r10909: Give better shutdown messages
[Samba/nascimento.git] / source3 / rpc_server / srv_spoolss_nt.c
blob5233d6c252df040734f2a77bea58473b1bee2d53
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-2004,
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 extern userdom_struct current_user_info;
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
38 #endif
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 /* Table to map the driver version */
45 /* to OS */
46 static const char * drv_ver_to_os[] = {
47 "WIN9X", /* driver version/cversion 0 */
48 "", /* unused ? */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
53 static const char *get_drv_ver_to_os(int ver)
55 if (ver < 0 || ver > 3)
56 return "";
57 return drv_ver_to_os[ver];
60 struct table_node {
61 const char *long_archi;
62 const char *short_archi;
63 int version;
66 static Printer_entry *printers_list;
68 typedef struct _counter_printer_0 {
69 struct _counter_printer_0 *next;
70 struct _counter_printer_0 *prev;
72 int snum;
73 uint32 counter;
74 } counter_printer_0;
76 static counter_printer_0 *counter_list;
78 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
79 static uint32 smb_connections=0;
82 /* in printing/nt_printing.c */
84 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
86 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
87 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v)
92 switch (v) {
93 case LPQ_QUEUED:
94 return 0;
95 case LPQ_PAUSED:
96 return JOB_STATUS_PAUSED;
97 case LPQ_SPOOLING:
98 return JOB_STATUS_SPOOLING;
99 case LPQ_PRINTING:
100 return JOB_STATUS_PRINTING;
101 case LPQ_ERROR:
102 return JOB_STATUS_ERROR;
103 case LPQ_DELETING:
104 return JOB_STATUS_DELETING;
105 case LPQ_OFFLINE:
106 return JOB_STATUS_OFFLINE;
107 case LPQ_PAPEROUT:
108 return JOB_STATUS_PAPEROUT;
109 case LPQ_PRINTED:
110 return JOB_STATUS_PRINTED;
111 case LPQ_DELETED:
112 return JOB_STATUS_DELETED;
113 case LPQ_BLOCKED:
114 return JOB_STATUS_BLOCKED;
115 case LPQ_USER_INTERVENTION:
116 return JOB_STATUS_USER_INTERVENTION;
118 return 0;
121 static int nt_printq_status(int v)
123 switch (v) {
124 case LPQ_PAUSED:
125 return PRINTER_STATUS_PAUSED;
126 case LPQ_QUEUED:
127 case LPQ_SPOOLING:
128 case LPQ_PRINTING:
129 return 0;
131 return 0;
134 /****************************************************************************
135 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
136 ****************************************************************************/
138 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
140 if (*pp == NULL)
141 return;
143 SAFE_FREE((*pp)->ctr.type);
144 SAFE_FREE(*pp);
147 /***************************************************************************
148 Disconnect from the client
149 ****************************************************************************/
151 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
153 WERROR result;
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
166 return;
169 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
171 if (!W_ERROR_IS_OK(result))
172 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
173 dos_errstr(result)));
175 /* if it's the last connection, deconnect the IPC$ share */
176 if (smb_connections==1) {
177 cli_shutdown(notify_cli_pipe->cli);
178 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
179 message_deregister(MSG_PRINTER_NOTIFY2);
181 /* Tell the connections db we're no longer interested in
182 * printer notify messages. */
184 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
187 smb_connections--;
190 /****************************************************************************
191 Functions to free a printer entry datastruct.
192 ****************************************************************************/
194 static void free_printer_entry(void *ptr)
196 Printer_entry *Printer = (Printer_entry *)ptr;
198 if (Printer->notify.client_connected==True) {
199 int snum = -1;
201 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
202 snum = -1;
203 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
204 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
205 snum = print_queue_snum(Printer->sharename);
206 if (snum != -1)
207 srv_spoolss_replycloseprinter(snum,
208 &Printer->notify.client_hnd);
212 Printer->notify.flags=0;
213 Printer->notify.options=0;
214 Printer->notify.localmachine[0]='\0';
215 Printer->notify.printerlocal=0;
216 free_spool_notify_option(&Printer->notify.option);
217 Printer->notify.option=NULL;
218 Printer->notify.client_connected=False;
220 free_nt_devicemode( &Printer->nt_devmode );
221 free_a_printer( &Printer->printer_info, 2 );
223 talloc_destroy( Printer->ctx );
225 /* Remove from the internal list. */
226 DLIST_REMOVE(printers_list, Printer);
228 SAFE_FREE(Printer);
231 /****************************************************************************
232 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
233 ****************************************************************************/
235 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
237 SPOOL_NOTIFY_OPTION *new_sp = NULL;
239 if (!sp)
240 return NULL;
242 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
243 if (!new_sp)
244 return NULL;
246 *new_sp = *sp;
248 if (sp->ctr.count) {
249 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
251 if (!new_sp->ctr.type) {
252 SAFE_FREE(new_sp);
253 return NULL;
257 return new_sp;
260 /****************************************************************************
261 find printer index by handle
262 ****************************************************************************/
264 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
266 Printer_entry *find_printer = NULL;
268 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
269 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
270 return NULL;
273 return find_printer;
276 /****************************************************************************
277 Close printer index by handle.
278 ****************************************************************************/
280 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
282 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
284 if (!Printer) {
285 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
286 return False;
289 close_policy_hnd(p, hnd);
291 return True;
294 /****************************************************************************
295 Delete a printer given a handle.
296 ****************************************************************************/
297 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
299 char *cmd = lp_deleteprinter_cmd();
300 pstring command;
301 int ret;
302 SE_PRIV se_printop = SE_PRINT_OPERATOR;
303 BOOL is_print_op = False;
305 /* can't fail if we don't try */
307 if ( !*cmd )
308 return WERR_OK;
310 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
312 if ( token )
313 is_print_op = user_has_privileges( token, &se_printop );
315 DEBUG(10,("Running [%s]\n", command));
317 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
319 if ( is_print_op )
320 become_root();
322 if ( (ret = smbrun(command, NULL)) == 0 ) {
323 /* Tell everyone we updated smb.conf. */
324 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
327 if ( is_print_op )
328 unbecome_root();
330 /********** END SePrintOperatorPrivlege BLOCK **********/
332 DEBUGADD(10,("returned [%d]\n", ret));
334 if (ret != 0)
335 return WERR_BADFID; /* What to return here? */
337 /* go ahead and re-read the services immediately */
338 reload_services( False );
340 if ( lp_servicenumber( sharename ) < 0 )
341 return WERR_ACCESS_DENIED;
343 return WERR_OK;
346 /****************************************************************************
347 Delete a printer given a handle.
348 ****************************************************************************/
350 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
352 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
354 if (!Printer) {
355 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
356 return WERR_BADFID;
360 * It turns out that Windows allows delete printer on a handle
361 * opened by an admin user, then used on a pipe handle created
362 * by an anonymous user..... but they're working on security.... riiight !
363 * JRA.
366 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
367 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
368 return WERR_ACCESS_DENIED;
371 /* this does not need a become root since the access check has been
372 done on the handle already */
374 if (del_a_printer( Printer->sharename ) != 0) {
375 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
376 return WERR_BADFID;
379 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
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->sharename));
398 *number = print_queue_snum(Printer->sharename);
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, *printername;
444 const char *servername;
445 fstring sname;
446 BOOL found=False;
447 NT_PRINTER_INFO_LEVEL *printer;
448 WERROR result;
450 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
452 aprinter = handlename;
453 if ( *handlename == '\\' ) {
454 servername = handlename + 2;
455 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
456 *aprinter = '\0';
457 aprinter++;
460 else {
461 servername = "";
464 /* save the servername to fill in replies on this handle */
466 if ( !is_myname_or_ipaddr( servername ) )
467 return False;
469 fstrcpy( Printer->servername, servername );
471 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
472 return True;
474 if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
475 return False;
477 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
479 /* Search all sharenames first as this is easier than pulling
480 the printer_info_2 off of disk */
482 snum = find_service(aprinter);
484 if ( lp_snum_ok(snum) && lp_print_ok(snum) ) {
485 found = True;
486 fstrcpy( sname, aprinter );
489 /* do another loop to look for printernames */
491 for (snum=0; !found && snum<n_services; snum++) {
493 /* no point in checking if this is not a printer or
494 we aren't allowing printername != sharename */
496 if ( !(lp_snum_ok(snum)
497 && lp_print_ok(snum)
498 && !lp_force_printername(snum)) )
500 continue;
503 fstrcpy(sname, lp_servicename(snum));
505 printer = NULL;
506 result = get_a_printer( NULL, &printer, 2, sname );
507 if ( !W_ERROR_IS_OK(result) ) {
508 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
509 sname, dos_errstr(result)));
510 continue;
513 /* printername is always returned as \\server\printername */
514 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
515 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
516 printer->info_2->printername));
517 free_a_printer( &printer, 2);
518 continue;
521 printername++;
523 if ( strequal(printername, aprinter) ) {
524 found = True;
527 DEBUGADD(10, ("printername: %s\n", printername));
529 free_a_printer( &printer, 2);
532 if ( !found ) {
533 DEBUGADD(4,("Printer not found\n"));
534 return False;
537 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
539 fstrcpy(Printer->sharename, sname);
541 return True;
544 /****************************************************************************
545 Find first available printer slot. creates a printer handle for you.
546 ****************************************************************************/
548 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
550 Printer_entry *new_printer;
552 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
554 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
555 return False;
557 ZERO_STRUCTP(new_printer);
559 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
560 SAFE_FREE(new_printer);
561 return False;
564 /* Add to the internal list. */
565 DLIST_ADD(printers_list, new_printer);
567 new_printer->notify.option=NULL;
569 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
570 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
571 close_printer_handle(p, hnd);
572 return False;
575 if (!set_printer_hnd_printertype(new_printer, name)) {
576 close_printer_handle(p, hnd);
577 return False;
580 if (!set_printer_hnd_name(new_printer, name)) {
581 close_printer_handle(p, hnd);
582 return False;
585 new_printer->access_granted = access_granted;
587 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
589 return True;
592 /***************************************************************************
593 check to see if the client motify handle is monitoring the notification
594 given by (notify_type, notify_field).
595 **************************************************************************/
597 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
598 uint16 notify_field)
600 return True;
603 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
604 uint16 notify_field)
606 SPOOL_NOTIFY_OPTION *option = p->notify.option;
607 uint32 i, j;
610 * Flags should always be zero when the change notify
611 * is registered by the client's spooler. A user Win32 app
612 * might use the flags though instead of the NOTIFY_OPTION_INFO
613 * --jerry
616 if (!option) {
617 return False;
620 if (p->notify.flags)
621 return is_monitoring_event_flags(
622 p->notify.flags, notify_type, notify_field);
624 for (i = 0; i < option->count; i++) {
626 /* Check match for notify_type */
628 if (option->ctr.type[i].type != notify_type)
629 continue;
631 /* Check match for field */
633 for (j = 0; j < option->ctr.type[i].count; j++) {
634 if (option->ctr.type[i].fields[j] == notify_field) {
635 return True;
640 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
641 p->servername, p->sharename, notify_type, notify_field));
643 return False;
646 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
648 static void notify_one_value(struct spoolss_notify_msg *msg,
649 SPOOL_NOTIFY_INFO_DATA *data,
650 TALLOC_CTX *mem_ctx)
652 data->notify_data.value[0] = msg->notify.value[0];
653 data->notify_data.value[1] = 0;
656 static void notify_string(struct spoolss_notify_msg *msg,
657 SPOOL_NOTIFY_INFO_DATA *data,
658 TALLOC_CTX *mem_ctx)
660 UNISTR2 unistr;
662 /* The length of the message includes the trailing \0 */
664 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
666 data->notify_data.data.length = msg->len * 2;
667 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
669 if (!data->notify_data.data.string) {
670 data->notify_data.data.length = 0;
671 return;
674 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
677 static void notify_system_time(struct spoolss_notify_msg *msg,
678 SPOOL_NOTIFY_INFO_DATA *data,
679 TALLOC_CTX *mem_ctx)
681 SYSTEMTIME systime;
682 prs_struct ps;
684 if (msg->len != sizeof(time_t)) {
685 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
686 msg->len));
687 return;
690 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
691 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
692 return;
695 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
696 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
697 return;
700 if (!spoolss_io_system_time("", &ps, 0, &systime))
701 return;
703 data->notify_data.data.length = prs_offset(&ps);
704 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
706 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
708 prs_mem_free(&ps);
711 struct notify2_message_table {
712 const char *name;
713 void (*fn)(struct spoolss_notify_msg *msg,
714 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
717 static struct notify2_message_table printer_notify_table[] = {
718 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
719 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
720 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
721 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
722 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
723 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
724 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
725 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
726 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
727 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
728 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
729 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
730 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
731 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
732 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
733 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
734 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
735 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
736 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
739 static struct notify2_message_table job_notify_table[] = {
740 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
741 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
742 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
743 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
744 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
745 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
746 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
747 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
748 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
749 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
750 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
751 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
752 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
753 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
754 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
755 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
756 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
757 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
758 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
759 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
760 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
761 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
762 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
763 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
767 /***********************************************************************
768 Allocate talloc context for container object
769 **********************************************************************/
771 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
773 if ( !ctr )
774 return;
776 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
778 return;
781 /***********************************************************************
782 release all allocated memory and zero out structure
783 **********************************************************************/
785 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
787 if ( !ctr )
788 return;
790 if ( ctr->ctx )
791 talloc_destroy(ctr->ctx);
793 ZERO_STRUCTP(ctr);
795 return;
798 /***********************************************************************
799 **********************************************************************/
801 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
803 if ( !ctr )
804 return NULL;
806 return ctr->ctx;
809 /***********************************************************************
810 **********************************************************************/
812 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
814 if ( !ctr || !ctr->msg_groups )
815 return NULL;
817 if ( idx >= ctr->num_groups )
818 return NULL;
820 return &ctr->msg_groups[idx];
824 /***********************************************************************
825 How many groups of change messages do we have ?
826 **********************************************************************/
828 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
830 if ( !ctr )
831 return 0;
833 return ctr->num_groups;
836 /***********************************************************************
837 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
838 **********************************************************************/
840 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
842 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
843 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
844 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
845 int i, new_slot;
847 if ( !ctr || !msg )
848 return 0;
850 /* loop over all groups looking for a matching printer name */
852 for ( i=0; i<ctr->num_groups; i++ ) {
853 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
854 break;
857 /* add a new group? */
859 if ( i == ctr->num_groups ) {
860 ctr->num_groups++;
862 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
863 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
864 return 0;
866 ctr->msg_groups = groups;
868 /* clear the new entry and set the printer name */
870 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
871 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
874 /* add the change messages; 'i' is the correct index now regardless */
876 msg_grp = &ctr->msg_groups[i];
878 msg_grp->num_msgs++;
880 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
881 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
882 return 0;
884 msg_grp->msgs = msg_list;
886 new_slot = msg_grp->num_msgs-1;
887 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
889 /* need to allocate own copy of data */
891 if ( msg->len != 0 )
892 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
894 return ctr->num_groups;
897 /***********************************************************************
898 Send a change notication message on all handles which have a call
899 back registered
900 **********************************************************************/
902 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
904 Printer_entry *p;
905 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
906 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
907 SPOOLSS_NOTIFY_MSG *messages;
908 int sending_msg_count;
910 if ( !msg_group ) {
911 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
912 return;
915 messages = msg_group->msgs;
917 if ( !messages ) {
918 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
919 return;
922 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
924 /* loop over all printers */
926 for (p = printers_list; p; p = p->next) {
927 SPOOL_NOTIFY_INFO_DATA *data;
928 uint32 data_len = 0;
929 uint32 id;
930 int i;
932 /* Is there notification on this handle? */
934 if ( !p->notify.client_connected )
935 continue;
937 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
939 /* For this printer? Print servers always receive
940 notifications. */
942 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
943 ( !strequal(msg_group->printername, p->sharename) ) )
944 continue;
946 DEBUG(10,("Our printer\n"));
948 /* allocate the max entries possible */
950 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
951 ZERO_STRUCTP(data);
953 /* build the array of change notifications */
955 sending_msg_count = 0;
957 for ( i=0; i<msg_group->num_msgs; i++ ) {
958 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
960 /* Are we monitoring this event? */
962 if (!is_monitoring_event(p, msg->type, msg->field))
963 continue;
965 sending_msg_count++;
968 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
969 msg->type, msg->field, p->sharename));
972 * if the is a printer notification handle and not a job notification
973 * type, then set the id to 0. Other wise just use what was specified
974 * in the message.
976 * When registering change notification on a print server handle
977 * we always need to send back the id (snum) matching the printer
978 * for which the change took place. For change notify registered
979 * on a printer handle, this does not matter and the id should be 0.
981 * --jerry
984 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
985 id = 0;
986 else
987 id = msg->id;
990 /* Convert unix jobid to smb jobid */
992 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
993 id = sysjob_to_jobid(msg->id);
995 if (id == -1) {
996 DEBUG(3, ("no such unix jobid %d\n", msg->id));
997 goto done;
1001 construct_info_data( &data[data_len], msg->type, msg->field, id );
1003 switch(msg->type) {
1004 case PRINTER_NOTIFY_TYPE:
1005 if ( printer_notify_table[msg->field].fn )
1006 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1007 break;
1009 case JOB_NOTIFY_TYPE:
1010 if ( job_notify_table[msg->field].fn )
1011 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1012 break;
1014 default:
1015 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1016 goto done;
1019 data_len++;
1022 if ( sending_msg_count ) {
1023 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1024 data_len, data, p->notify.change, 0 );
1028 done:
1029 DEBUG(8,("send_notify2_changes: Exit...\n"));
1030 return;
1033 /***********************************************************************
1034 **********************************************************************/
1036 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1039 uint32 tv_sec, tv_usec;
1040 size_t offset = 0;
1042 /* Unpack message */
1044 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1045 msg->printer);
1047 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1048 &tv_sec, &tv_usec,
1049 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1051 if (msg->len == 0)
1052 tdb_unpack((char *)buf + offset, len - offset, "dd",
1053 &msg->notify.value[0], &msg->notify.value[1]);
1054 else
1055 tdb_unpack((char *)buf + offset, len - offset, "B",
1056 &msg->len, &msg->notify.data);
1058 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1059 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1061 tv->tv_sec = tv_sec;
1062 tv->tv_usec = tv_usec;
1064 if (msg->len == 0)
1065 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1066 msg->notify.value[1]));
1067 else
1068 dump_data(3, msg->notify.data, msg->len);
1070 return True;
1073 /********************************************************************
1074 Receive a notify2 message list
1075 ********************************************************************/
1077 static void receive_notify2_message_list(int msg_type, struct process_id src,
1078 void *msg, size_t len)
1080 size_t msg_count, i;
1081 char *buf = (char *)msg;
1082 char *msg_ptr;
1083 size_t msg_len;
1084 SPOOLSS_NOTIFY_MSG notify;
1085 SPOOLSS_NOTIFY_MSG_CTR messages;
1086 int num_groups;
1088 if (len < 4) {
1089 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1090 return;
1093 msg_count = IVAL(buf, 0);
1094 msg_ptr = buf + 4;
1096 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1098 if (msg_count == 0) {
1099 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1100 return;
1103 /* initialize the container */
1105 ZERO_STRUCT( messages );
1106 notify_msg_ctr_init( &messages );
1109 * build message groups for each printer identified
1110 * in a change_notify msg. Remember that a PCN message
1111 * includes the handle returned for the srv_spoolss_replyopenprinter()
1112 * call. Therefore messages are grouped according to printer handle.
1115 for ( i=0; i<msg_count; i++ ) {
1116 struct timeval msg_tv;
1118 if (msg_ptr + 4 - buf > len) {
1119 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1120 return;
1123 msg_len = IVAL(msg_ptr,0);
1124 msg_ptr += 4;
1126 if (msg_ptr + msg_len - buf > len) {
1127 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1128 return;
1131 /* unpack messages */
1133 ZERO_STRUCT( notify );
1134 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1135 msg_ptr += msg_len;
1137 /* add to correct list in container */
1139 notify_msg_ctr_addmsg( &messages, &notify );
1141 /* free memory that might have been allocated by notify2_unpack_msg() */
1143 if ( notify.len != 0 )
1144 SAFE_FREE( notify.notify.data );
1147 /* process each group of messages */
1149 num_groups = notify_msg_ctr_numgroups( &messages );
1150 for ( i=0; i<num_groups; i++ )
1151 send_notify2_changes( &messages, i );
1154 /* cleanup */
1156 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1158 notify_msg_ctr_destroy( &messages );
1160 return;
1163 /********************************************************************
1164 Send a message to ourself about new driver being installed
1165 so we can upgrade the information for each printer bound to this
1166 driver
1167 ********************************************************************/
1169 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1171 int len = strlen(drivername);
1173 if (!len)
1174 return False;
1176 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1177 drivername));
1179 message_send_pid(pid_to_procid(sys_getpid()),
1180 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1182 return True;
1185 /**********************************************************************
1186 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1187 over all printers, upgrading ones as necessary
1188 **********************************************************************/
1190 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1192 fstring drivername;
1193 int snum;
1194 int n_services = lp_numservices();
1196 len = MIN(len,sizeof(drivername)-1);
1197 strncpy(drivername, buf, len);
1199 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1201 /* Iterate the printer list */
1203 for (snum=0; snum<n_services; snum++)
1205 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1207 WERROR result;
1208 NT_PRINTER_INFO_LEVEL *printer = NULL;
1210 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1211 if (!W_ERROR_IS_OK(result))
1212 continue;
1214 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1216 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1218 /* all we care about currently is the change_id */
1220 result = mod_a_printer(printer, 2);
1221 if (!W_ERROR_IS_OK(result)) {
1222 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1223 dos_errstr(result)));
1227 free_a_printer(&printer, 2);
1231 /* all done */
1234 /********************************************************************
1235 Update the cache for all printq's with a registered client
1236 connection
1237 ********************************************************************/
1239 void update_monitored_printq_cache( void )
1241 Printer_entry *printer = printers_list;
1242 int snum;
1244 /* loop through all printers and update the cache where
1245 client_connected == True */
1246 while ( printer )
1248 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1249 && printer->notify.client_connected )
1251 snum = print_queue_snum(printer->sharename);
1252 print_queue_status( snum, NULL, NULL );
1255 printer = printer->next;
1258 return;
1260 /********************************************************************
1261 Send a message to ourself about new driver being installed
1262 so we can upgrade the information for each printer bound to this
1263 driver
1264 ********************************************************************/
1266 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1268 int len = strlen(drivername);
1270 if (!len)
1271 return False;
1273 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1274 drivername));
1276 message_send_pid(pid_to_procid(sys_getpid()),
1277 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1279 return True;
1282 /**********************************************************************
1283 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1284 over all printers, resetting printer data as neessary
1285 **********************************************************************/
1287 void reset_all_printerdata(int msg_type, struct process_id src,
1288 void *buf, size_t len)
1290 fstring drivername;
1291 int snum;
1292 int n_services = lp_numservices();
1294 len = MIN( len, sizeof(drivername)-1 );
1295 strncpy( drivername, buf, len );
1297 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1299 /* Iterate the printer list */
1301 for ( snum=0; snum<n_services; snum++ )
1303 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1305 WERROR result;
1306 NT_PRINTER_INFO_LEVEL *printer = NULL;
1308 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1309 if ( !W_ERROR_IS_OK(result) )
1310 continue;
1313 * if the printer is bound to the driver,
1314 * then reset to the new driver initdata
1317 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1319 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1321 if ( !set_driver_init(printer, 2) ) {
1322 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1323 printer->info_2->printername, printer->info_2->drivername));
1326 result = mod_a_printer( printer, 2 );
1327 if ( !W_ERROR_IS_OK(result) ) {
1328 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1329 get_dos_error_msg(result)));
1333 free_a_printer( &printer, 2 );
1337 /* all done */
1339 return;
1342 /********************************************************************
1343 Copy routines used by convert_to_openprinterex()
1344 *******************************************************************/
1346 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1348 DEVICEMODE *d;
1349 int len;
1351 if (!devmode)
1352 return NULL;
1354 DEBUG (8,("dup_devmode\n"));
1356 /* bulk copy first */
1358 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1359 if (!d)
1360 return NULL;
1362 /* dup the pointer members separately */
1364 len = unistrlen(devmode->devicename.buffer);
1365 if (len != -1) {
1366 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1367 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1368 return NULL;
1372 len = unistrlen(devmode->formname.buffer);
1373 if (len != -1) {
1374 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1375 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1376 return NULL;
1379 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1381 return d;
1384 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1386 if (!new_ctr || !ctr)
1387 return;
1389 DEBUG(8,("copy_devmode_ctr\n"));
1391 new_ctr->size = ctr->size;
1392 new_ctr->devmode_ptr = ctr->devmode_ptr;
1394 if(ctr->devmode_ptr)
1395 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1398 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1400 if (!new_def || !def)
1401 return;
1403 DEBUG(8,("copy_printer_defaults\n"));
1405 new_def->datatype_ptr = def->datatype_ptr;
1407 if (def->datatype_ptr)
1408 copy_unistr2(&new_def->datatype, &def->datatype);
1410 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1412 new_def->access_required = def->access_required;
1415 /********************************************************************
1416 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1417 * SPOOL_Q_OPEN_PRINTER_EX structure
1418 ********************************************************************/
1420 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1422 if (!q_u_ex || !q_u)
1423 return WERR_OK;
1425 DEBUG(8,("convert_to_openprinterex\n"));
1427 if ( q_u->printername ) {
1428 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1429 if (q_u_ex->printername == NULL)
1430 return WERR_NOMEM;
1431 copy_unistr2(q_u_ex->printername, q_u->printername);
1434 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1436 return WERR_OK;
1439 /********************************************************************
1440 * spoolss_open_printer
1442 * called from the spoolss dispatcher
1443 ********************************************************************/
1445 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1447 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1448 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1450 if (!q_u || !r_u)
1451 return WERR_NOMEM;
1453 ZERO_STRUCT(q_u_ex);
1454 ZERO_STRUCT(r_u_ex);
1456 /* convert the OpenPrinter() call to OpenPrinterEx() */
1458 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1459 if (!W_ERROR_IS_OK(r_u_ex.status))
1460 return r_u_ex.status;
1462 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1464 /* convert back to OpenPrinter() */
1466 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1468 return r_u->status;
1471 /********************************************************************
1472 * spoolss_open_printer
1474 * If the openprinterex rpc call contains a devmode,
1475 * it's a per-user one. This per-user devmode is derivated
1476 * from the global devmode. Openprinterex() contains a per-user
1477 * devmode for when you do EMF printing and spooling.
1478 * In the EMF case, the NT workstation is only doing half the job
1479 * of rendering the page. The other half is done by running the printer
1480 * driver on the server.
1481 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1482 * The EMF file only contains what is to be printed on the page.
1483 * So in order for the server to know how to print, the NT client sends
1484 * a devicemode attached to the openprinterex call.
1485 * But this devicemode is short lived, it's only valid for the current print job.
1487 * If Samba would have supported EMF spooling, this devicemode would
1488 * have been attached to the handle, to sent it to the driver to correctly
1489 * rasterize the EMF file.
1491 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1492 * we just act as a pass-thru between windows and the printer.
1494 * In order to know that Samba supports only RAW spooling, NT has to call
1495 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1496 * and until NT sends a RAW job, we refuse it.
1498 * But to call getprinter() or startdoc(), you first need a valid handle,
1499 * and to get an handle you have to call openprintex(). Hence why you have
1500 * a devicemode in the openprinterex() call.
1503 * Differences between NT4 and NT 2000.
1504 * NT4:
1505 * ---
1506 * On NT4, you only have a global devicemode. This global devicemode can be changed
1507 * by the administrator (or by a user with enough privs). Everytime a user
1508 * wants to print, the devicemode is resetted to the default. In Word, everytime
1509 * you print, the printer's characteristics are always reset to the global devicemode.
1511 * NT 2000:
1512 * -------
1513 * In W2K, there is the notion of per-user devicemode. The first time you use
1514 * a printer, a per-user devicemode is build from the global devicemode.
1515 * If you change your per-user devicemode, it is saved in the registry, under the
1516 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1517 * printer preferences available.
1519 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1520 * on the General Tab of the printer properties windows.
1522 * To change the global devicemode: it's the "Printing Defaults..." button
1523 * on the Advanced Tab of the printer properties window.
1525 * JFM.
1526 ********************************************************************/
1528 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1530 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1531 POLICY_HND *handle = &r_u->handle;
1533 fstring name;
1534 int snum;
1535 struct current_user user;
1536 Printer_entry *Printer=NULL;
1538 if ( !q_u->printername )
1539 return WERR_INVALID_PRINTER_NAME;
1541 /* some sanity check because you can open a printer or a print server */
1542 /* aka: \\server\printer or \\server */
1544 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1546 DEBUGADD(3,("checking name: %s\n",name));
1548 if (!open_printer_hnd(p, handle, name, 0))
1549 return WERR_INVALID_PRINTER_NAME;
1551 Printer=find_printer_index_by_hnd(p, handle);
1552 if ( !Printer ) {
1553 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1554 "handle we created for printer %s\n", name ));
1555 close_printer_handle(p,handle);
1556 return WERR_INVALID_PRINTER_NAME;
1559 get_current_user(&user, p);
1562 * First case: the user is opening the print server:
1564 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1565 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1567 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1568 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1569 * or if the user is listed in the smb.conf printer admin parameter.
1571 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1572 * client view printer folder, but does not show the MSAPW.
1574 * Note: this test needs code to check access rights here too. Jeremy
1575 * could you look at this?
1577 * Second case: the user is opening a printer:
1578 * NT doesn't let us connect to a printer if the connecting user
1579 * doesn't have print permission.
1582 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1584 /* Printserver handles use global struct... */
1586 snum = -1;
1588 /* Map standard access rights to object specific access rights */
1590 se_map_standard(&printer_default->access_required,
1591 &printserver_std_mapping);
1593 /* Deny any object specific bits that don't apply to print
1594 servers (i.e printer and job specific bits) */
1596 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1598 if (printer_default->access_required &
1599 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1600 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1601 close_printer_handle(p, handle);
1602 return WERR_ACCESS_DENIED;
1605 /* Allow admin access */
1607 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1609 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1611 if (!lp_ms_add_printer_wizard()) {
1612 close_printer_handle(p, handle);
1613 return WERR_ACCESS_DENIED;
1616 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1617 and not a printer admin, then fail */
1619 if ( user.uid != 0
1620 && !user_has_privileges( user.nt_user_token, &se_printop )
1621 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1623 close_printer_handle(p, handle);
1624 return WERR_ACCESS_DENIED;
1627 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1629 else
1631 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1634 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1635 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1637 /* We fall through to return WERR_OK */
1640 else
1642 /* NT doesn't let us connect to a printer if the connecting user
1643 doesn't have print permission. */
1645 if (!get_printer_snum(p, handle, &snum)) {
1646 close_printer_handle(p, handle);
1647 return WERR_BADFID;
1650 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1652 /* map an empty access mask to the minimum access mask */
1653 if (printer_default->access_required == 0x0)
1654 printer_default->access_required = PRINTER_ACCESS_USE;
1657 * If we are not serving the printer driver for this printer,
1658 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1659 * will keep NT clients happy --jerry
1662 if (lp_use_client_driver(snum)
1663 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1665 printer_default->access_required = PRINTER_ACCESS_USE;
1668 /* check smb.conf parameters and the the sec_desc */
1670 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1671 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1672 return WERR_ACCESS_DENIED;
1675 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1676 DEBUG(3, ("access DENIED for printer open\n"));
1677 close_printer_handle(p, handle);
1678 return WERR_ACCESS_DENIED;
1681 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1682 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1683 close_printer_handle(p, handle);
1684 return WERR_ACCESS_DENIED;
1687 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1688 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1689 else
1690 printer_default->access_required = PRINTER_ACCESS_USE;
1692 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1693 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1697 Printer->access_granted = printer_default->access_required;
1700 * If the client sent a devmode in the OpenPrinter() call, then
1701 * save it here in case we get a job submission on this handle
1704 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1705 && q_u->printer_default.devmode_cont.devmode_ptr )
1707 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1708 &Printer->nt_devmode );
1711 #if 0 /* JERRY -- I'm doubtful this is really effective */
1712 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1713 optimization in Windows 2000 clients --jerry */
1715 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1716 && (RA_WIN2K == get_remote_arch()) )
1718 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1719 sys_usleep( 500000 );
1721 #endif
1723 return WERR_OK;
1726 /****************************************************************************
1727 ****************************************************************************/
1729 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1730 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1732 BOOL ret = True;
1734 switch (level) {
1735 case 2:
1736 /* printer->info_2 is already a valid printer */
1737 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1738 printer->info_2->setuptime = time(NULL);
1740 break;
1741 default:
1742 break;
1745 return ret;
1748 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1749 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1751 BOOL result = True;
1753 switch (level) {
1754 case 3:
1755 printer->info_3=NULL;
1756 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1757 result = False;
1758 break;
1759 case 6:
1760 printer->info_6=NULL;
1761 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1762 result = False;
1763 break;
1764 default:
1765 break;
1768 return result;
1771 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1772 NT_DEVICEMODE **pp_nt_devmode)
1774 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1777 * Ensure nt_devmode is a valid pointer
1778 * as we will be overwriting it.
1781 if (nt_devmode == NULL) {
1782 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1783 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1784 return False;
1787 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1788 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1790 nt_devmode->specversion=devmode->specversion;
1791 nt_devmode->driverversion=devmode->driverversion;
1792 nt_devmode->size=devmode->size;
1793 nt_devmode->fields=devmode->fields;
1794 nt_devmode->orientation=devmode->orientation;
1795 nt_devmode->papersize=devmode->papersize;
1796 nt_devmode->paperlength=devmode->paperlength;
1797 nt_devmode->paperwidth=devmode->paperwidth;
1798 nt_devmode->scale=devmode->scale;
1799 nt_devmode->copies=devmode->copies;
1800 nt_devmode->defaultsource=devmode->defaultsource;
1801 nt_devmode->printquality=devmode->printquality;
1802 nt_devmode->color=devmode->color;
1803 nt_devmode->duplex=devmode->duplex;
1804 nt_devmode->yresolution=devmode->yresolution;
1805 nt_devmode->ttoption=devmode->ttoption;
1806 nt_devmode->collate=devmode->collate;
1808 nt_devmode->logpixels=devmode->logpixels;
1809 nt_devmode->bitsperpel=devmode->bitsperpel;
1810 nt_devmode->pelswidth=devmode->pelswidth;
1811 nt_devmode->pelsheight=devmode->pelsheight;
1812 nt_devmode->displayflags=devmode->displayflags;
1813 nt_devmode->displayfrequency=devmode->displayfrequency;
1814 nt_devmode->icmmethod=devmode->icmmethod;
1815 nt_devmode->icmintent=devmode->icmintent;
1816 nt_devmode->mediatype=devmode->mediatype;
1817 nt_devmode->dithertype=devmode->dithertype;
1818 nt_devmode->reserved1=devmode->reserved1;
1819 nt_devmode->reserved2=devmode->reserved2;
1820 nt_devmode->panningwidth=devmode->panningwidth;
1821 nt_devmode->panningheight=devmode->panningheight;
1824 * Only change private and driverextra if the incoming devmode
1825 * has a new one. JRA.
1828 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1829 SAFE_FREE(nt_devmode->nt_dev_private);
1830 nt_devmode->driverextra=devmode->driverextra;
1831 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1832 return False;
1833 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1836 *pp_nt_devmode = nt_devmode;
1838 return True;
1841 /********************************************************************
1842 * _spoolss_enddocprinter_internal.
1843 ********************************************************************/
1845 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1847 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1848 int snum;
1850 if (!Printer) {
1851 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1852 return WERR_BADFID;
1855 if (!get_printer_snum(p, handle, &snum))
1856 return WERR_BADFID;
1858 Printer->document_started=False;
1859 print_job_end(snum, Printer->jobid,True);
1860 /* error codes unhandled so far ... */
1862 return WERR_OK;
1865 /********************************************************************
1866 * api_spoolss_closeprinter
1867 ********************************************************************/
1869 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1871 POLICY_HND *handle = &q_u->handle;
1873 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1875 if (Printer && Printer->document_started)
1876 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1878 if (!close_printer_handle(p, handle))
1879 return WERR_BADFID;
1881 /* clear the returned printer handle. Observed behavior
1882 from Win2k server. Don't think this really matters.
1883 Previous code just copied the value of the closed
1884 handle. --jerry */
1886 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1888 return WERR_OK;
1891 /********************************************************************
1892 * api_spoolss_deleteprinter
1894 ********************************************************************/
1896 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1898 POLICY_HND *handle = &q_u->handle;
1899 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1900 WERROR result;
1902 if (Printer && Printer->document_started)
1903 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1905 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1907 result = delete_printer_handle(p, handle);
1909 update_c_setprinter(False);
1911 return result;
1914 /*******************************************************************
1915 * static function to lookup the version id corresponding to an
1916 * long architecture string
1917 ******************************************************************/
1919 static int get_version_id (char * arch)
1921 int i;
1922 struct table_node archi_table[]= {
1924 {"Windows 4.0", "WIN40", 0 },
1925 {"Windows NT x86", "W32X86", 2 },
1926 {"Windows NT R4000", "W32MIPS", 2 },
1927 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1928 {"Windows NT PowerPC", "W32PPC", 2 },
1929 {"Windows IA64", "IA64", 3 },
1930 {"Windows x64", "x64", 3 },
1931 {NULL, "", -1 }
1934 for (i=0; archi_table[i].long_archi != NULL; i++)
1936 if (strcmp(arch, archi_table[i].long_archi) == 0)
1937 return (archi_table[i].version);
1940 return -1;
1943 /********************************************************************
1944 * _spoolss_deleteprinterdriver
1945 ********************************************************************/
1947 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1949 fstring driver;
1950 fstring arch;
1951 NT_PRINTER_DRIVER_INFO_LEVEL info;
1952 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1953 int version;
1954 struct current_user user;
1955 WERROR status;
1956 WERROR status_win2k = WERR_ACCESS_DENIED;
1958 get_current_user(&user, p);
1960 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1961 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1963 /* check that we have a valid driver name first */
1965 if ((version=get_version_id(arch)) == -1)
1966 return WERR_INVALID_ENVIRONMENT;
1968 ZERO_STRUCT(info);
1969 ZERO_STRUCT(info_win2k);
1971 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1973 /* try for Win2k driver if "Windows NT x86" */
1975 if ( version == 2 ) {
1976 version = 3;
1977 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1978 status = WERR_UNKNOWN_PRINTER_DRIVER;
1979 goto done;
1982 /* otherwise it was a failure */
1983 else {
1984 status = WERR_UNKNOWN_PRINTER_DRIVER;
1985 goto done;
1990 if (printer_driver_in_use(info.info_3)) {
1991 status = WERR_PRINTER_DRIVER_IN_USE;
1992 goto done;
1995 if ( version == 2 )
1997 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
1999 /* if we get to here, we now have 2 driver info structures to remove */
2000 /* remove the Win2k driver first*/
2002 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2003 free_a_printer_driver( info_win2k, 3 );
2005 /* this should not have failed---if it did, report to client */
2006 if ( !W_ERROR_IS_OK(status_win2k) )
2008 status = status_win2k;
2009 goto done;
2014 status = delete_printer_driver(info.info_3, &user, version, False);
2016 /* if at least one of the deletes succeeded return OK */
2018 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2019 status = WERR_OK;
2021 done:
2022 free_a_printer_driver( info, 3 );
2024 return status;
2027 /********************************************************************
2028 * spoolss_deleteprinterdriverex
2029 ********************************************************************/
2031 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2033 fstring driver;
2034 fstring arch;
2035 NT_PRINTER_DRIVER_INFO_LEVEL info;
2036 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2037 int version;
2038 uint32 flags = q_u->delete_flags;
2039 BOOL delete_files;
2040 struct current_user user;
2041 WERROR status;
2042 WERROR status_win2k = WERR_ACCESS_DENIED;
2044 get_current_user(&user, p);
2046 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2047 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2049 /* check that we have a valid driver name first */
2050 if ((version=get_version_id(arch)) == -1) {
2051 /* this is what NT returns */
2052 return WERR_INVALID_ENVIRONMENT;
2055 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2056 version = q_u->version;
2058 ZERO_STRUCT(info);
2059 ZERO_STRUCT(info_win2k);
2061 status = get_a_printer_driver(&info, 3, driver, arch, version);
2063 if ( !W_ERROR_IS_OK(status) )
2066 * if the client asked for a specific version,
2067 * or this is something other than Windows NT x86,
2068 * then we've failed
2071 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2072 goto done;
2074 /* try for Win2k driver if "Windows NT x86" */
2076 version = 3;
2077 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2078 status = WERR_UNKNOWN_PRINTER_DRIVER;
2079 goto done;
2083 if ( printer_driver_in_use(info.info_3) ) {
2084 status = WERR_PRINTER_DRIVER_IN_USE;
2085 goto done;
2089 * we have a couple of cases to consider.
2090 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2091 * then the delete should fail if **any** files overlap with
2092 * other drivers
2093 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2094 * non-overlapping files
2095 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2096 * is set, the do not delete any files
2097 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2100 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2102 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2104 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2105 /* no idea of the correct error here */
2106 status = WERR_ACCESS_DENIED;
2107 goto done;
2111 /* also check for W32X86/3 if necessary; maybe we already have? */
2113 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2114 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2117 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2118 /* no idea of the correct error here */
2119 free_a_printer_driver( info_win2k, 3 );
2120 status = WERR_ACCESS_DENIED;
2121 goto done;
2124 /* if we get to here, we now have 2 driver info structures to remove */
2125 /* remove the Win2k driver first*/
2127 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2128 free_a_printer_driver( info_win2k, 3 );
2130 /* this should not have failed---if it did, report to client */
2132 if ( !W_ERROR_IS_OK(status_win2k) )
2133 goto done;
2137 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2139 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2140 status = WERR_OK;
2141 done:
2142 free_a_printer_driver( info, 3 );
2144 return status;
2148 /****************************************************************************
2149 Internal routine for retreiving printerdata
2150 ***************************************************************************/
2152 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2153 const char *key, const char *value, uint32 *type, uint8 **data,
2154 uint32 *needed, uint32 in_size )
2156 REGISTRY_VALUE *val;
2157 uint32 size;
2158 int data_len;
2160 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2161 return WERR_BADFILE;
2163 *type = regval_type( val );
2165 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2167 size = regval_size( val );
2169 /* copy the min(in_size, len) */
2171 if ( in_size ) {
2172 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2174 /* special case for 0 length values */
2175 if ( data_len ) {
2176 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2177 return WERR_NOMEM;
2179 else {
2180 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2181 return WERR_NOMEM;
2184 else
2185 *data = NULL;
2187 *needed = size;
2189 DEBUG(5,("get_printer_dataex: copy done\n"));
2191 return WERR_OK;
2194 /****************************************************************************
2195 Internal routine for removing printerdata
2196 ***************************************************************************/
2198 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2200 return delete_printer_data( printer->info_2, key, value );
2203 /****************************************************************************
2204 Internal routine for storing printerdata
2205 ***************************************************************************/
2207 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2208 uint32 type, uint8 *data, int real_len )
2210 /* the registry objects enforce uniqueness based on value name */
2212 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2215 /********************************************************************
2216 GetPrinterData on a printer server Handle.
2217 ********************************************************************/
2219 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2221 int i;
2223 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2225 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2226 *type = REG_DWORD;
2227 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2228 return WERR_NOMEM;
2229 *needed = 0x4;
2230 return WERR_OK;
2233 if (!StrCaseCmp(value, "BeepEnabled")) {
2234 *type = REG_DWORD;
2235 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2236 return WERR_NOMEM;
2237 SIVAL(*data, 0, 0x00);
2238 *needed = 0x4;
2239 return WERR_OK;
2242 if (!StrCaseCmp(value, "EventLog")) {
2243 *type = REG_DWORD;
2244 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2245 return WERR_NOMEM;
2246 /* formally was 0x1b */
2247 SIVAL(*data, 0, 0x0);
2248 *needed = 0x4;
2249 return WERR_OK;
2252 if (!StrCaseCmp(value, "NetPopup")) {
2253 *type = REG_DWORD;
2254 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2255 return WERR_NOMEM;
2256 SIVAL(*data, 0, 0x00);
2257 *needed = 0x4;
2258 return WERR_OK;
2261 if (!StrCaseCmp(value, "MajorVersion")) {
2262 *type = REG_DWORD;
2263 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2264 return WERR_NOMEM;
2266 /* Windows NT 4.0 seems to not allow uploading of drivers
2267 to a server that reports 0x3 as the MajorVersion.
2268 need to investigate more how Win2k gets around this .
2269 -- jerry */
2271 if ( RA_WINNT == get_remote_arch() )
2272 SIVAL(*data, 0, 2);
2273 else
2274 SIVAL(*data, 0, 3);
2276 *needed = 0x4;
2277 return WERR_OK;
2280 if (!StrCaseCmp(value, "MinorVersion")) {
2281 *type = REG_DWORD;
2282 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2283 return WERR_NOMEM;
2284 SIVAL(*data, 0, 0);
2285 *needed = 0x4;
2286 return WERR_OK;
2289 /* REG_BINARY
2290 * uint32 size = 0x114
2291 * uint32 major = 5
2292 * uint32 minor = [0|1]
2293 * uint32 build = [2195|2600]
2294 * extra unicode string = e.g. "Service Pack 3"
2296 if (!StrCaseCmp(value, "OSVersion")) {
2297 *type = REG_BINARY;
2298 *needed = 0x114;
2300 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2301 return WERR_NOMEM;
2303 SIVAL(*data, 0, *needed); /* size */
2304 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2305 SIVAL(*data, 8, 0);
2306 SIVAL(*data, 12, 2195); /* build */
2308 /* leave extra string empty */
2310 return WERR_OK;
2314 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2315 const char *string="C:\\PRINTERS";
2316 *type = REG_SZ;
2317 *needed = 2*(strlen(string)+1);
2318 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2319 return WERR_NOMEM;
2320 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2322 /* it's done by hand ready to go on the wire */
2323 for (i=0; i<strlen(string); i++) {
2324 (*data)[2*i]=string[i];
2325 (*data)[2*i+1]='\0';
2327 return WERR_OK;
2330 if (!StrCaseCmp(value, "Architecture")) {
2331 const char *string="Windows NT x86";
2332 *type = REG_SZ;
2333 *needed = 2*(strlen(string)+1);
2334 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2335 return WERR_NOMEM;
2336 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2337 for (i=0; i<strlen(string); i++) {
2338 (*data)[2*i]=string[i];
2339 (*data)[2*i+1]='\0';
2341 return WERR_OK;
2344 if (!StrCaseCmp(value, "DsPresent")) {
2345 *type = REG_DWORD;
2346 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2347 return WERR_NOMEM;
2349 /* only show the publish check box if we are a
2350 memeber of a AD domain */
2352 if ( lp_security() == SEC_ADS )
2353 SIVAL(*data, 0, 0x01);
2354 else
2355 SIVAL(*data, 0, 0x00);
2357 *needed = 0x4;
2358 return WERR_OK;
2361 if (!StrCaseCmp(value, "DNSMachineName")) {
2362 pstring hostname;
2364 if (!get_mydnsfullname(hostname))
2365 return WERR_BADFILE;
2366 *type = REG_SZ;
2367 *needed = 2*(strlen(hostname)+1);
2368 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2369 return WERR_NOMEM;
2370 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2371 for (i=0; i<strlen(hostname); i++) {
2372 (*data)[2*i]=hostname[i];
2373 (*data)[2*i+1]='\0';
2375 return WERR_OK;
2379 return WERR_BADFILE;
2382 /********************************************************************
2383 * spoolss_getprinterdata
2384 ********************************************************************/
2386 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2388 POLICY_HND *handle = &q_u->handle;
2389 UNISTR2 *valuename = &q_u->valuename;
2390 uint32 in_size = q_u->size;
2391 uint32 *type = &r_u->type;
2392 uint32 *out_size = &r_u->size;
2393 uint8 **data = &r_u->data;
2394 uint32 *needed = &r_u->needed;
2395 WERROR status;
2396 fstring value;
2397 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2398 NT_PRINTER_INFO_LEVEL *printer = NULL;
2399 int snum = 0;
2402 * Reminder: when it's a string, the length is in BYTES
2403 * even if UNICODE is negociated.
2405 * JFM, 4/19/1999
2408 *out_size = in_size;
2410 /* in case of problem, return some default values */
2412 *needed = 0;
2413 *type = 0;
2415 DEBUG(4,("_spoolss_getprinterdata\n"));
2417 if ( !Printer ) {
2418 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2419 status = WERR_BADFID;
2420 goto done;
2423 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2425 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2426 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2427 else
2429 if ( !get_printer_snum(p,handle, &snum) ) {
2430 status = WERR_BADFID;
2431 goto done;
2434 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2435 if ( !W_ERROR_IS_OK(status) )
2436 goto done;
2438 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2440 if ( strequal(value, "ChangeId") ) {
2441 *type = REG_DWORD;
2442 *needed = sizeof(uint32);
2443 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2444 status = WERR_NOMEM;
2445 goto done;
2447 SIVAL( *data, 0, printer->info_2->changeid );
2448 status = WERR_OK;
2450 else
2451 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2454 if (*needed > *out_size)
2455 status = WERR_MORE_DATA;
2457 done:
2458 if ( !W_ERROR_IS_OK(status) )
2460 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2462 /* reply this param doesn't exist */
2464 if ( *out_size ) {
2465 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2466 if ( printer )
2467 free_a_printer( &printer, 2 );
2468 return WERR_NOMEM;
2471 else {
2472 *data = NULL;
2476 /* cleanup & exit */
2478 if ( printer )
2479 free_a_printer( &printer, 2 );
2481 return status;
2484 /*********************************************************
2485 Connect to the client machine.
2486 **********************************************************/
2488 static BOOL spoolss_connect_to_client(struct cli_state *the_cli, struct rpc_pipe_client **pp_pipe,
2489 struct in_addr *client_ip, const char *remote_machine)
2491 NTSTATUS ret;
2492 ZERO_STRUCTP(the_cli);
2494 if(cli_initialise(the_cli) == NULL) {
2495 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2496 return False;
2499 if ( is_zero_ip(*client_ip) ) {
2500 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2501 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2502 cli_shutdown(the_cli);
2503 return False;
2506 if (ismyip(the_cli->dest_ip)) {
2507 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2508 cli_shutdown(the_cli);
2509 return False;
2512 else {
2513 the_cli->dest_ip.s_addr = client_ip->s_addr;
2514 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2515 inet_ntoa(*client_ip) ));
2518 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2519 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) ));
2520 cli_shutdown(the_cli);
2521 return False;
2524 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2525 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2526 remote_machine));
2527 cli_shutdown(the_cli);
2528 return False;
2531 the_cli->protocol = PROTOCOL_NT1;
2532 cli_setup_signing_state(the_cli, lp_client_signing());
2534 if (!cli_negprot(the_cli)) {
2535 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2536 cli_shutdown(the_cli);
2537 return False;
2540 if (the_cli->protocol != PROTOCOL_NT1) {
2541 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2542 cli_shutdown(the_cli);
2543 return False;
2547 * Do an anonymous session setup.
2550 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2551 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2552 cli_shutdown(the_cli);
2553 return False;
2556 if (!(the_cli->sec_mode & 1)) {
2557 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2558 cli_shutdown(the_cli);
2559 return False;
2562 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2563 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) ));
2564 cli_shutdown(the_cli);
2565 return False;
2569 * Ok - we have an anonymous connection to the IPC$ share.
2570 * Now start the NT Domain stuff :-).
2573 *pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret);
2574 if(!*pp_pipe) {
2575 DEBUG(0,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2576 remote_machine, nt_errstr(ret)));
2577 cli_shutdown(the_cli);
2578 return False;
2581 return True;
2584 /***************************************************************************
2585 Connect to the client.
2586 ****************************************************************************/
2588 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2589 uint32 localprinter, uint32 type,
2590 POLICY_HND *handle, struct in_addr *client_ip)
2592 WERROR result;
2595 * If it's the first connection, contact the client
2596 * and connect to the IPC$ share anonymously
2598 if (smb_connections==0) {
2599 struct cli_state notify_cli; /* print notify back-channel */
2600 fstring unix_printer;
2602 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2604 ZERO_STRUCT(notify_cli);
2606 if(!spoolss_connect_to_client(&notify_cli, &notify_cli_pipe, client_ip, unix_printer))
2607 return False;
2609 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2610 /* Tell the connections db we're now interested in printer
2611 * notify messages. */
2612 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2616 * Tell the specific printing tdb we want messages for this printer
2617 * by registering our PID.
2620 if (!print_notify_register_pid(snum))
2621 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2623 smb_connections++;
2625 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2626 type, handle);
2628 if (!W_ERROR_IS_OK(result))
2629 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2630 dos_errstr(result)));
2632 return (W_ERROR_IS_OK(result));
2635 /********************************************************************
2636 * _spoolss_rffpcnex
2637 * ReplyFindFirstPrinterChangeNotifyEx
2639 * before replying OK: status=0 a rpc call is made to the workstation
2640 * asking ReplyOpenPrinter
2642 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2643 * called from api_spoolss_rffpcnex
2644 ********************************************************************/
2646 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2648 POLICY_HND *handle = &q_u->handle;
2649 uint32 flags = q_u->flags;
2650 uint32 options = q_u->options;
2651 UNISTR2 *localmachine = &q_u->localmachine;
2652 uint32 printerlocal = q_u->printerlocal;
2653 int snum = -1;
2654 SPOOL_NOTIFY_OPTION *option = q_u->option;
2655 struct in_addr client_ip;
2657 /* store the notify value in the printer struct */
2659 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2661 if (!Printer) {
2662 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2663 return WERR_BADFID;
2666 Printer->notify.flags=flags;
2667 Printer->notify.options=options;
2668 Printer->notify.printerlocal=printerlocal;
2670 if (Printer->notify.option)
2671 free_spool_notify_option(&Printer->notify.option);
2673 Printer->notify.option=dup_spool_notify_option(option);
2675 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2676 sizeof(Printer->notify.localmachine)-1);
2678 /* Connect to the client machine and send a ReplyOpenPrinter */
2680 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2681 snum = -1;
2682 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2683 !get_printer_snum(p, handle, &snum) )
2684 return WERR_BADFID;
2686 client_ip.s_addr = inet_addr(p->conn->client_address);
2688 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2689 Printer->notify.printerlocal, 1,
2690 &Printer->notify.client_hnd, &client_ip))
2691 return WERR_SERVER_UNAVAILABLE;
2693 Printer->notify.client_connected=True;
2695 return WERR_OK;
2698 /*******************************************************************
2699 * fill a notify_info_data with the servername
2700 ********************************************************************/
2702 void spoolss_notify_server_name(int snum,
2703 SPOOL_NOTIFY_INFO_DATA *data,
2704 print_queue_struct *queue,
2705 NT_PRINTER_INFO_LEVEL *printer,
2706 TALLOC_CTX *mem_ctx)
2708 pstring temp;
2709 uint32 len;
2711 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2713 data->notify_data.data.length = len;
2714 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2716 if (!data->notify_data.data.string) {
2717 data->notify_data.data.length = 0;
2718 return;
2721 memcpy(data->notify_data.data.string, temp, len);
2724 /*******************************************************************
2725 * fill a notify_info_data with the printername (not including the servername).
2726 ********************************************************************/
2728 void spoolss_notify_printer_name(int snum,
2729 SPOOL_NOTIFY_INFO_DATA *data,
2730 print_queue_struct *queue,
2731 NT_PRINTER_INFO_LEVEL *printer,
2732 TALLOC_CTX *mem_ctx)
2734 pstring temp;
2735 uint32 len;
2737 /* the notify name should not contain the \\server\ part */
2738 char *p = strrchr(printer->info_2->printername, '\\');
2740 if (!p) {
2741 p = printer->info_2->printername;
2742 } else {
2743 p++;
2746 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2748 data->notify_data.data.length = len;
2749 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2751 if (!data->notify_data.data.string) {
2752 data->notify_data.data.length = 0;
2753 return;
2756 memcpy(data->notify_data.data.string, temp, len);
2759 /*******************************************************************
2760 * fill a notify_info_data with the servicename
2761 ********************************************************************/
2763 void spoolss_notify_share_name(int snum,
2764 SPOOL_NOTIFY_INFO_DATA *data,
2765 print_queue_struct *queue,
2766 NT_PRINTER_INFO_LEVEL *printer,
2767 TALLOC_CTX *mem_ctx)
2769 pstring temp;
2770 uint32 len;
2772 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2774 data->notify_data.data.length = len;
2775 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2777 if (!data->notify_data.data.string) {
2778 data->notify_data.data.length = 0;
2779 return;
2782 memcpy(data->notify_data.data.string, temp, len);
2785 /*******************************************************************
2786 * fill a notify_info_data with the port name
2787 ********************************************************************/
2789 void spoolss_notify_port_name(int snum,
2790 SPOOL_NOTIFY_INFO_DATA *data,
2791 print_queue_struct *queue,
2792 NT_PRINTER_INFO_LEVEL *printer,
2793 TALLOC_CTX *mem_ctx)
2795 pstring temp;
2796 uint32 len;
2798 /* even if it's strange, that's consistant in all the code */
2800 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2802 data->notify_data.data.length = len;
2803 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2805 if (!data->notify_data.data.string) {
2806 data->notify_data.data.length = 0;
2807 return;
2810 memcpy(data->notify_data.data.string, temp, len);
2813 /*******************************************************************
2814 * fill a notify_info_data with the printername
2815 * but it doesn't exist, have to see what to do
2816 ********************************************************************/
2818 void spoolss_notify_driver_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 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2829 data->notify_data.data.length = len;
2830 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2832 if (!data->notify_data.data.string) {
2833 data->notify_data.data.length = 0;
2834 return;
2837 memcpy(data->notify_data.data.string, temp, len);
2840 /*******************************************************************
2841 * fill a notify_info_data with the comment
2842 ********************************************************************/
2844 void spoolss_notify_comment(int snum,
2845 SPOOL_NOTIFY_INFO_DATA *data,
2846 print_queue_struct *queue,
2847 NT_PRINTER_INFO_LEVEL *printer,
2848 TALLOC_CTX *mem_ctx)
2850 pstring temp;
2851 uint32 len;
2853 if (*printer->info_2->comment == '\0')
2854 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2855 else
2856 len = rpcstr_push(temp, printer->info_2->comment, 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 * location = "Room 1, floor 2, building 3"
2872 ********************************************************************/
2874 void spoolss_notify_location(int snum,
2875 SPOOL_NOTIFY_INFO_DATA *data,
2876 print_queue_struct *queue,
2877 NT_PRINTER_INFO_LEVEL *printer,
2878 TALLOC_CTX *mem_ctx)
2880 pstring temp;
2881 uint32 len;
2883 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2885 data->notify_data.data.length = len;
2886 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2888 if (!data->notify_data.data.string) {
2889 data->notify_data.data.length = 0;
2890 return;
2893 memcpy(data->notify_data.data.string, temp, len);
2896 /*******************************************************************
2897 * fill a notify_info_data with the device mode
2898 * jfm:xxxx don't to it for know but that's a real problem !!!
2899 ********************************************************************/
2901 static void spoolss_notify_devmode(int snum,
2902 SPOOL_NOTIFY_INFO_DATA *data,
2903 print_queue_struct *queue,
2904 NT_PRINTER_INFO_LEVEL *printer,
2905 TALLOC_CTX *mem_ctx)
2909 /*******************************************************************
2910 * fill a notify_info_data with the separator file name
2911 ********************************************************************/
2913 void spoolss_notify_sepfile(int snum,
2914 SPOOL_NOTIFY_INFO_DATA *data,
2915 print_queue_struct *queue,
2916 NT_PRINTER_INFO_LEVEL *printer,
2917 TALLOC_CTX *mem_ctx)
2919 pstring temp;
2920 uint32 len;
2922 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2924 data->notify_data.data.length = len;
2925 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2927 if (!data->notify_data.data.string) {
2928 data->notify_data.data.length = 0;
2929 return;
2932 memcpy(data->notify_data.data.string, temp, len);
2935 /*******************************************************************
2936 * fill a notify_info_data with the print processor
2937 * jfm:xxxx return always winprint to indicate we don't do anything to it
2938 ********************************************************************/
2940 void spoolss_notify_print_processor(int snum,
2941 SPOOL_NOTIFY_INFO_DATA *data,
2942 print_queue_struct *queue,
2943 NT_PRINTER_INFO_LEVEL *printer,
2944 TALLOC_CTX *mem_ctx)
2946 pstring temp;
2947 uint32 len;
2949 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2951 data->notify_data.data.length = len;
2952 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2954 if (!data->notify_data.data.string) {
2955 data->notify_data.data.length = 0;
2956 return;
2959 memcpy(data->notify_data.data.string, temp, len);
2962 /*******************************************************************
2963 * fill a notify_info_data with the print processor options
2964 * jfm:xxxx send an empty string
2965 ********************************************************************/
2967 void spoolss_notify_parameters(int snum,
2968 SPOOL_NOTIFY_INFO_DATA *data,
2969 print_queue_struct *queue,
2970 NT_PRINTER_INFO_LEVEL *printer,
2971 TALLOC_CTX *mem_ctx)
2973 pstring temp;
2974 uint32 len;
2976 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2978 data->notify_data.data.length = len;
2979 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2981 if (!data->notify_data.data.string) {
2982 data->notify_data.data.length = 0;
2983 return;
2986 memcpy(data->notify_data.data.string, temp, len);
2989 /*******************************************************************
2990 * fill a notify_info_data with the data type
2991 * jfm:xxxx always send RAW as data type
2992 ********************************************************************/
2994 void spoolss_notify_datatype(int snum,
2995 SPOOL_NOTIFY_INFO_DATA *data,
2996 print_queue_struct *queue,
2997 NT_PRINTER_INFO_LEVEL *printer,
2998 TALLOC_CTX *mem_ctx)
3000 pstring temp;
3001 uint32 len;
3003 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3005 data->notify_data.data.length = len;
3006 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3008 if (!data->notify_data.data.string) {
3009 data->notify_data.data.length = 0;
3010 return;
3013 memcpy(data->notify_data.data.string, temp, len);
3016 /*******************************************************************
3017 * fill a notify_info_data with the security descriptor
3018 * jfm:xxxx send an null pointer to say no security desc
3019 * have to implement security before !
3020 ********************************************************************/
3022 static void spoolss_notify_security_desc(int snum,
3023 SPOOL_NOTIFY_INFO_DATA *data,
3024 print_queue_struct *queue,
3025 NT_PRINTER_INFO_LEVEL *printer,
3026 TALLOC_CTX *mem_ctx)
3028 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3029 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3032 /*******************************************************************
3033 * fill a notify_info_data with the attributes
3034 * jfm:xxxx a samba printer is always shared
3035 ********************************************************************/
3037 void spoolss_notify_attributes(int snum,
3038 SPOOL_NOTIFY_INFO_DATA *data,
3039 print_queue_struct *queue,
3040 NT_PRINTER_INFO_LEVEL *printer,
3041 TALLOC_CTX *mem_ctx)
3043 data->notify_data.value[0] = printer->info_2->attributes;
3044 data->notify_data.value[1] = 0;
3047 /*******************************************************************
3048 * fill a notify_info_data with the priority
3049 ********************************************************************/
3051 static void spoolss_notify_priority(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.value[0] = printer->info_2->priority;
3058 data->notify_data.value[1] = 0;
3061 /*******************************************************************
3062 * fill a notify_info_data with the default priority
3063 ********************************************************************/
3065 static void spoolss_notify_default_priority(int snum,
3066 SPOOL_NOTIFY_INFO_DATA *data,
3067 print_queue_struct *queue,
3068 NT_PRINTER_INFO_LEVEL *printer,
3069 TALLOC_CTX *mem_ctx)
3071 data->notify_data.value[0] = printer->info_2->default_priority;
3072 data->notify_data.value[1] = 0;
3075 /*******************************************************************
3076 * fill a notify_info_data with the start time
3077 ********************************************************************/
3079 static void spoolss_notify_start_time(int snum,
3080 SPOOL_NOTIFY_INFO_DATA *data,
3081 print_queue_struct *queue,
3082 NT_PRINTER_INFO_LEVEL *printer,
3083 TALLOC_CTX *mem_ctx)
3085 data->notify_data.value[0] = printer->info_2->starttime;
3086 data->notify_data.value[1] = 0;
3089 /*******************************************************************
3090 * fill a notify_info_data with the until time
3091 ********************************************************************/
3093 static void spoolss_notify_until_time(int snum,
3094 SPOOL_NOTIFY_INFO_DATA *data,
3095 print_queue_struct *queue,
3096 NT_PRINTER_INFO_LEVEL *printer,
3097 TALLOC_CTX *mem_ctx)
3099 data->notify_data.value[0] = printer->info_2->untiltime;
3100 data->notify_data.value[1] = 0;
3103 /*******************************************************************
3104 * fill a notify_info_data with the status
3105 ********************************************************************/
3107 static void spoolss_notify_status(int snum,
3108 SPOOL_NOTIFY_INFO_DATA *data,
3109 print_queue_struct *queue,
3110 NT_PRINTER_INFO_LEVEL *printer,
3111 TALLOC_CTX *mem_ctx)
3113 print_status_struct status;
3115 print_queue_length(snum, &status);
3116 data->notify_data.value[0]=(uint32) status.status;
3117 data->notify_data.value[1] = 0;
3120 /*******************************************************************
3121 * fill a notify_info_data with the number of jobs queued
3122 ********************************************************************/
3124 void spoolss_notify_cjobs(int snum,
3125 SPOOL_NOTIFY_INFO_DATA *data,
3126 print_queue_struct *queue,
3127 NT_PRINTER_INFO_LEVEL *printer,
3128 TALLOC_CTX *mem_ctx)
3130 data->notify_data.value[0] = print_queue_length(snum, NULL);
3131 data->notify_data.value[1] = 0;
3134 /*******************************************************************
3135 * fill a notify_info_data with the average ppm
3136 ********************************************************************/
3138 static void spoolss_notify_average_ppm(int snum,
3139 SPOOL_NOTIFY_INFO_DATA *data,
3140 print_queue_struct *queue,
3141 NT_PRINTER_INFO_LEVEL *printer,
3142 TALLOC_CTX *mem_ctx)
3144 /* always respond 8 pages per minutes */
3145 /* a little hard ! */
3146 data->notify_data.value[0] = printer->info_2->averageppm;
3147 data->notify_data.value[1] = 0;
3150 /*******************************************************************
3151 * fill a notify_info_data with username
3152 ********************************************************************/
3154 static void spoolss_notify_username(int snum,
3155 SPOOL_NOTIFY_INFO_DATA *data,
3156 print_queue_struct *queue,
3157 NT_PRINTER_INFO_LEVEL *printer,
3158 TALLOC_CTX *mem_ctx)
3160 pstring temp;
3161 uint32 len;
3163 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3165 data->notify_data.data.length = len;
3166 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3168 if (!data->notify_data.data.string) {
3169 data->notify_data.data.length = 0;
3170 return;
3173 memcpy(data->notify_data.data.string, temp, len);
3176 /*******************************************************************
3177 * fill a notify_info_data with job status
3178 ********************************************************************/
3180 static void spoolss_notify_job_status(int snum,
3181 SPOOL_NOTIFY_INFO_DATA *data,
3182 print_queue_struct *queue,
3183 NT_PRINTER_INFO_LEVEL *printer,
3184 TALLOC_CTX *mem_ctx)
3186 data->notify_data.value[0]=nt_printj_status(queue->status);
3187 data->notify_data.value[1] = 0;
3190 /*******************************************************************
3191 * fill a notify_info_data with job name
3192 ********************************************************************/
3194 static void spoolss_notify_job_name(int snum,
3195 SPOOL_NOTIFY_INFO_DATA *data,
3196 print_queue_struct *queue,
3197 NT_PRINTER_INFO_LEVEL *printer,
3198 TALLOC_CTX *mem_ctx)
3200 pstring temp;
3201 uint32 len;
3203 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3205 data->notify_data.data.length = len;
3206 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3208 if (!data->notify_data.data.string) {
3209 data->notify_data.data.length = 0;
3210 return;
3213 memcpy(data->notify_data.data.string, temp, len);
3216 /*******************************************************************
3217 * fill a notify_info_data with job status
3218 ********************************************************************/
3220 static void spoolss_notify_job_status_string(int snum,
3221 SPOOL_NOTIFY_INFO_DATA *data,
3222 print_queue_struct *queue,
3223 NT_PRINTER_INFO_LEVEL *printer,
3224 TALLOC_CTX *mem_ctx)
3227 * Now we're returning job status codes we just return a "" here. JRA.
3230 const char *p = "";
3231 pstring temp;
3232 uint32 len;
3234 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3235 p = "unknown";
3237 switch (queue->status) {
3238 case LPQ_QUEUED:
3239 p = "Queued";
3240 break;
3241 case LPQ_PAUSED:
3242 p = ""; /* NT provides the paused string */
3243 break;
3244 case LPQ_SPOOLING:
3245 p = "Spooling";
3246 break;
3247 case LPQ_PRINTING:
3248 p = "Printing";
3249 break;
3251 #endif /* NO LONGER NEEDED. */
3253 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3255 data->notify_data.data.length = len;
3256 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3258 if (!data->notify_data.data.string) {
3259 data->notify_data.data.length = 0;
3260 return;
3263 memcpy(data->notify_data.data.string, temp, len);
3266 /*******************************************************************
3267 * fill a notify_info_data with job time
3268 ********************************************************************/
3270 static void spoolss_notify_job_time(int snum,
3271 SPOOL_NOTIFY_INFO_DATA *data,
3272 print_queue_struct *queue,
3273 NT_PRINTER_INFO_LEVEL *printer,
3274 TALLOC_CTX *mem_ctx)
3276 data->notify_data.value[0]=0x0;
3277 data->notify_data.value[1]=0;
3280 /*******************************************************************
3281 * fill a notify_info_data with job size
3282 ********************************************************************/
3284 static void spoolss_notify_job_size(int snum,
3285 SPOOL_NOTIFY_INFO_DATA *data,
3286 print_queue_struct *queue,
3287 NT_PRINTER_INFO_LEVEL *printer,
3288 TALLOC_CTX *mem_ctx)
3290 data->notify_data.value[0]=queue->size;
3291 data->notify_data.value[1]=0;
3294 /*******************************************************************
3295 * fill a notify_info_data with page info
3296 ********************************************************************/
3297 static void spoolss_notify_total_pages(int snum,
3298 SPOOL_NOTIFY_INFO_DATA *data,
3299 print_queue_struct *queue,
3300 NT_PRINTER_INFO_LEVEL *printer,
3301 TALLOC_CTX *mem_ctx)
3303 data->notify_data.value[0]=queue->page_count;
3304 data->notify_data.value[1]=0;
3307 /*******************************************************************
3308 * fill a notify_info_data with pages printed info.
3309 ********************************************************************/
3310 static void spoolss_notify_pages_printed(int snum,
3311 SPOOL_NOTIFY_INFO_DATA *data,
3312 print_queue_struct *queue,
3313 NT_PRINTER_INFO_LEVEL *printer,
3314 TALLOC_CTX *mem_ctx)
3316 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3317 data->notify_data.value[1]=0;
3320 /*******************************************************************
3321 Fill a notify_info_data with job position.
3322 ********************************************************************/
3324 static void spoolss_notify_job_position(int snum,
3325 SPOOL_NOTIFY_INFO_DATA *data,
3326 print_queue_struct *queue,
3327 NT_PRINTER_INFO_LEVEL *printer,
3328 TALLOC_CTX *mem_ctx)
3330 data->notify_data.value[0]=queue->job;
3331 data->notify_data.value[1]=0;
3334 /*******************************************************************
3335 Fill a notify_info_data with submitted time.
3336 ********************************************************************/
3338 static void spoolss_notify_submitted_time(int snum,
3339 SPOOL_NOTIFY_INFO_DATA *data,
3340 print_queue_struct *queue,
3341 NT_PRINTER_INFO_LEVEL *printer,
3342 TALLOC_CTX *mem_ctx)
3344 struct tm *t;
3345 uint32 len;
3346 SYSTEMTIME st;
3347 char *p;
3349 t=gmtime(&queue->time);
3351 len = sizeof(SYSTEMTIME);
3353 data->notify_data.data.length = len;
3354 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3356 if (!data->notify_data.data.string) {
3357 data->notify_data.data.length = 0;
3358 return;
3361 make_systemtime(&st, t);
3364 * Systemtime must be linearized as a set of UINT16's.
3365 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3368 p = (char *)data->notify_data.data.string;
3369 SSVAL(p, 0, st.year);
3370 SSVAL(p, 2, st.month);
3371 SSVAL(p, 4, st.dayofweek);
3372 SSVAL(p, 6, st.day);
3373 SSVAL(p, 8, st.hour);
3374 SSVAL(p, 10, st.minute);
3375 SSVAL(p, 12, st.second);
3376 SSVAL(p, 14, st.milliseconds);
3379 struct s_notify_info_data_table
3381 uint16 type;
3382 uint16 field;
3383 const char *name;
3384 uint32 size;
3385 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3386 print_queue_struct *queue,
3387 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3390 /* A table describing the various print notification constants and
3391 whether the notification data is a pointer to a variable sized
3392 buffer, a one value uint32 or a two value uint32. */
3394 static const struct s_notify_info_data_table notify_info_data_table[] =
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3440 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3442 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3443 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3444 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3445 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3448 /*******************************************************************
3449 Return the size of info_data structure.
3450 ********************************************************************/
3452 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3454 int i=0;
3456 for (i = 0; i < sizeof(notify_info_data_table); i++)
3458 if ( (notify_info_data_table[i].type == type)
3459 && (notify_info_data_table[i].field == field) )
3461 switch(notify_info_data_table[i].size)
3463 case NOTIFY_ONE_VALUE:
3464 case NOTIFY_TWO_VALUE:
3465 return 1;
3466 case NOTIFY_STRING:
3467 return 2;
3469 /* The only pointer notify data I have seen on
3470 the wire is the submitted time and this has
3471 the notify size set to 4. -tpot */
3473 case NOTIFY_POINTER:
3474 return 4;
3476 case NOTIFY_SECDESC:
3477 return 5;
3482 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3484 return 0;
3487 /*******************************************************************
3488 Return the type of notify_info_data.
3489 ********************************************************************/
3491 static int type_of_notify_info_data(uint16 type, uint16 field)
3493 int i=0;
3495 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3496 if (notify_info_data_table[i].type == type &&
3497 notify_info_data_table[i].field == field)
3498 return notify_info_data_table[i].size;
3501 return False;
3504 /****************************************************************************
3505 ****************************************************************************/
3507 static int search_notify(uint16 type, uint16 field, int *value)
3509 int i;
3511 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3512 if (notify_info_data_table[i].type == type &&
3513 notify_info_data_table[i].field == field &&
3514 notify_info_data_table[i].fn != NULL) {
3515 *value = i;
3516 return True;
3520 return False;
3523 /****************************************************************************
3524 ****************************************************************************/
3526 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3528 info_data->type = type;
3529 info_data->field = field;
3530 info_data->reserved = 0;
3532 info_data->size = size_of_notify_info_data(type, field);
3533 info_data->enc_type = type_of_notify_info_data(type, field);
3535 info_data->id = id;
3540 /*******************************************************************
3542 * fill a notify_info struct with info asked
3544 ********************************************************************/
3546 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3547 snum, SPOOL_NOTIFY_OPTION_TYPE
3548 *option_type, uint32 id,
3549 TALLOC_CTX *mem_ctx)
3551 int field_num,j;
3552 uint16 type;
3553 uint16 field;
3555 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3556 NT_PRINTER_INFO_LEVEL *printer = NULL;
3557 print_queue_struct *queue=NULL;
3559 type=option_type->type;
3561 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3562 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3563 option_type->count, lp_servicename(snum)));
3565 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3566 return False;
3568 for(field_num=0; field_num<option_type->count; field_num++) {
3569 field = option_type->fields[field_num];
3571 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3573 if (!search_notify(type, field, &j) )
3574 continue;
3576 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3577 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3578 return False;
3579 } else
3580 info->data = tid;
3582 current_data = &info->data[info->count];
3584 construct_info_data(current_data, type, field, id);
3586 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3587 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3589 notify_info_data_table[j].fn(snum, current_data, queue,
3590 printer, mem_ctx);
3592 info->count++;
3595 free_a_printer(&printer, 2);
3596 return True;
3599 /*******************************************************************
3601 * fill a notify_info struct with info asked
3603 ********************************************************************/
3605 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3606 SPOOL_NOTIFY_INFO *info,
3607 NT_PRINTER_INFO_LEVEL *printer,
3608 int snum, SPOOL_NOTIFY_OPTION_TYPE
3609 *option_type, uint32 id,
3610 TALLOC_CTX *mem_ctx)
3612 int field_num,j;
3613 uint16 type;
3614 uint16 field;
3616 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3618 DEBUG(4,("construct_notify_jobs_info\n"));
3620 type = option_type->type;
3622 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3623 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3624 option_type->count));
3626 for(field_num=0; field_num<option_type->count; field_num++) {
3627 field = option_type->fields[field_num];
3629 if (!search_notify(type, field, &j) )
3630 continue;
3632 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3633 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3634 return False;
3636 else info->data = tid;
3638 current_data=&(info->data[info->count]);
3640 construct_info_data(current_data, type, field, id);
3641 notify_info_data_table[j].fn(snum, current_data, queue,
3642 printer, mem_ctx);
3643 info->count++;
3646 return True;
3650 * JFM: The enumeration is not that simple, it's even non obvious.
3652 * let's take an example: I want to monitor the PRINTER SERVER for
3653 * the printer's name and the number of jobs currently queued.
3654 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3655 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3657 * I have 3 printers on the back of my server.
3659 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3660 * structures.
3661 * Number Data Id
3662 * 1 printer 1 name 1
3663 * 2 printer 1 cjob 1
3664 * 3 printer 2 name 2
3665 * 4 printer 2 cjob 2
3666 * 5 printer 3 name 3
3667 * 6 printer 3 name 3
3669 * that's the print server case, the printer case is even worse.
3672 /*******************************************************************
3674 * enumerate all printers on the printserver
3675 * fill a notify_info struct with info asked
3677 ********************************************************************/
3679 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3680 SPOOL_NOTIFY_INFO *info,
3681 TALLOC_CTX *mem_ctx)
3683 int snum;
3684 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3685 int n_services=lp_numservices();
3686 int i;
3687 SPOOL_NOTIFY_OPTION *option;
3688 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3690 DEBUG(4,("printserver_notify_info\n"));
3692 if (!Printer)
3693 return WERR_BADFID;
3695 option=Printer->notify.option;
3696 info->version=2;
3697 info->data=NULL;
3698 info->count=0;
3700 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3701 sending a ffpcn() request first */
3703 if ( !option )
3704 return WERR_BADFID;
3706 for (i=0; i<option->count; i++) {
3707 option_type=&(option->ctr.type[i]);
3709 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3710 continue;
3712 for (snum=0; snum<n_services; snum++)
3714 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3715 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3719 #if 0
3721 * Debugging information, don't delete.
3724 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3725 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3726 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3728 for (i=0; i<info->count; i++) {
3729 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3730 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3731 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3733 #endif
3735 return WERR_OK;
3738 /*******************************************************************
3740 * fill a notify_info struct with info asked
3742 ********************************************************************/
3744 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3745 TALLOC_CTX *mem_ctx)
3747 int snum;
3748 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3749 int i;
3750 uint32 id;
3751 SPOOL_NOTIFY_OPTION *option;
3752 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3753 int count,j;
3754 print_queue_struct *queue=NULL;
3755 print_status_struct status;
3757 DEBUG(4,("printer_notify_info\n"));
3759 if (!Printer)
3760 return WERR_BADFID;
3762 option=Printer->notify.option;
3763 id = 0x0;
3764 info->version=2;
3765 info->data=NULL;
3766 info->count=0;
3768 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3769 sending a ffpcn() request first */
3771 if ( !option )
3772 return WERR_BADFID;
3774 get_printer_snum(p, hnd, &snum);
3776 for (i=0; i<option->count; i++) {
3777 option_type=&option->ctr.type[i];
3779 switch ( option_type->type ) {
3780 case PRINTER_NOTIFY_TYPE:
3781 if(construct_notify_printer_info(Printer, info, snum,
3782 option_type, id,
3783 mem_ctx))
3784 id--;
3785 break;
3787 case JOB_NOTIFY_TYPE: {
3788 NT_PRINTER_INFO_LEVEL *printer = NULL;
3790 count = print_queue_status(snum, &queue, &status);
3792 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3793 goto done;
3795 for (j=0; j<count; j++) {
3796 construct_notify_jobs_info(&queue[j], info,
3797 printer, snum,
3798 option_type,
3799 queue[j].job,
3800 mem_ctx);
3803 free_a_printer(&printer, 2);
3805 done:
3806 SAFE_FREE(queue);
3807 break;
3813 * Debugging information, don't delete.
3816 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3817 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3818 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3820 for (i=0; i<info->count; i++) {
3821 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3822 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3823 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3826 return WERR_OK;
3829 /********************************************************************
3830 * spoolss_rfnpcnex
3831 ********************************************************************/
3833 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3835 POLICY_HND *handle = &q_u->handle;
3836 SPOOL_NOTIFY_INFO *info = &r_u->info;
3838 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3839 WERROR result = WERR_BADFID;
3841 /* we always have a NOTIFY_INFO struct */
3842 r_u->info_ptr=0x1;
3844 if (!Printer) {
3845 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3846 OUR_HANDLE(handle)));
3847 goto done;
3850 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3853 * We are now using the change value, and
3854 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3855 * I don't have a global notification system, I'm sending back all the
3856 * informations even when _NOTHING_ has changed.
3859 /* We need to keep track of the change value to send back in
3860 RRPCN replies otherwise our updates are ignored. */
3862 Printer->notify.fnpcn = True;
3864 if (Printer->notify.client_connected) {
3865 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3866 Printer->notify.change = q_u->change;
3869 /* just ignore the SPOOL_NOTIFY_OPTION */
3871 switch (Printer->printer_type) {
3872 case PRINTER_HANDLE_IS_PRINTSERVER:
3873 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3874 break;
3876 case PRINTER_HANDLE_IS_PRINTER:
3877 result = printer_notify_info(p, handle, info, p->mem_ctx);
3878 break;
3881 Printer->notify.fnpcn = False;
3883 done:
3884 return result;
3887 /********************************************************************
3888 * construct_printer_info_0
3889 * fill a printer_info_0 struct
3890 ********************************************************************/
3892 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3894 pstring chaine;
3895 int count;
3896 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3897 counter_printer_0 *session_counter;
3898 uint32 global_counter;
3899 struct tm *t;
3900 time_t setuptime;
3901 print_status_struct status;
3903 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3904 return False;
3906 count = print_queue_length(snum, &status);
3908 /* check if we already have a counter for this printer */
3909 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3910 if (session_counter->snum == snum)
3911 break;
3914 /* it's the first time, add it to the list */
3915 if (session_counter==NULL) {
3916 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3917 free_a_printer(&ntprinter, 2);
3918 return False;
3920 ZERO_STRUCTP(session_counter);
3921 session_counter->snum=snum;
3922 session_counter->counter=0;
3923 DLIST_ADD(counter_list, session_counter);
3926 /* increment it */
3927 session_counter->counter++;
3929 /* JFM:
3930 * the global_counter should be stored in a TDB as it's common to all the clients
3931 * and should be zeroed on samba startup
3933 global_counter=session_counter->counter;
3935 pstrcpy(chaine,ntprinter->info_2->printername);
3937 init_unistr(&printer->printername, chaine);
3939 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3940 init_unistr(&printer->servername, chaine);
3942 printer->cjobs = count;
3943 printer->total_jobs = 0;
3944 printer->total_bytes = 0;
3946 setuptime = (time_t)ntprinter->info_2->setuptime;
3947 t=gmtime(&setuptime);
3949 printer->year = t->tm_year+1900;
3950 printer->month = t->tm_mon+1;
3951 printer->dayofweek = t->tm_wday;
3952 printer->day = t->tm_mday;
3953 printer->hour = t->tm_hour;
3954 printer->minute = t->tm_min;
3955 printer->second = t->tm_sec;
3956 printer->milliseconds = 0;
3958 printer->global_counter = global_counter;
3959 printer->total_pages = 0;
3961 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3962 printer->major_version = 0x0005; /* NT 5 */
3963 printer->build_version = 0x0893; /* build 2195 */
3965 printer->unknown7 = 0x1;
3966 printer->unknown8 = 0x0;
3967 printer->unknown9 = 0x0;
3968 printer->session_counter = session_counter->counter;
3969 printer->unknown11 = 0x0;
3970 printer->printer_errors = 0x0; /* number of print failure */
3971 printer->unknown13 = 0x0;
3972 printer->unknown14 = 0x1;
3973 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3974 printer->unknown16 = 0x0;
3975 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3976 printer->unknown18 = 0x0;
3977 printer->status = nt_printq_status(status.status);
3978 printer->unknown20 = 0x0;
3979 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3980 printer->unknown22 = 0x0;
3981 printer->unknown23 = 0x6; /* 6 ???*/
3982 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3983 printer->unknown25 = 0;
3984 printer->unknown26 = 0;
3985 printer->unknown27 = 0;
3986 printer->unknown28 = 0;
3987 printer->unknown29 = 0;
3989 free_a_printer(&ntprinter,2);
3990 return (True);
3993 /********************************************************************
3994 * construct_printer_info_1
3995 * fill a printer_info_1 struct
3996 ********************************************************************/
3997 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3999 pstring chaine;
4000 pstring chaine2;
4001 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4003 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4004 return False;
4006 printer->flags=flags;
4008 if (*ntprinter->info_2->comment == '\0') {
4009 init_unistr(&printer->comment, lp_comment(snum));
4010 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4011 ntprinter->info_2->drivername, lp_comment(snum));
4013 else {
4014 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4015 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4016 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4019 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4021 init_unistr(&printer->description, chaine);
4022 init_unistr(&printer->name, chaine2);
4024 free_a_printer(&ntprinter,2);
4026 return True;
4029 /****************************************************************************
4030 Free a DEVMODE struct.
4031 ****************************************************************************/
4033 static void free_dev_mode(DEVICEMODE *dev)
4035 if (dev == NULL)
4036 return;
4038 SAFE_FREE(dev->dev_private);
4039 SAFE_FREE(dev);
4043 /****************************************************************************
4044 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4045 should be valid upon entry
4046 ****************************************************************************/
4048 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4050 if ( !devmode || !ntdevmode )
4051 return False;
4053 init_unistr(&devmode->devicename, ntdevmode->devicename);
4055 init_unistr(&devmode->formname, ntdevmode->formname);
4057 devmode->specversion = ntdevmode->specversion;
4058 devmode->driverversion = ntdevmode->driverversion;
4059 devmode->size = ntdevmode->size;
4060 devmode->driverextra = ntdevmode->driverextra;
4061 devmode->fields = ntdevmode->fields;
4063 devmode->orientation = ntdevmode->orientation;
4064 devmode->papersize = ntdevmode->papersize;
4065 devmode->paperlength = ntdevmode->paperlength;
4066 devmode->paperwidth = ntdevmode->paperwidth;
4067 devmode->scale = ntdevmode->scale;
4068 devmode->copies = ntdevmode->copies;
4069 devmode->defaultsource = ntdevmode->defaultsource;
4070 devmode->printquality = ntdevmode->printquality;
4071 devmode->color = ntdevmode->color;
4072 devmode->duplex = ntdevmode->duplex;
4073 devmode->yresolution = ntdevmode->yresolution;
4074 devmode->ttoption = ntdevmode->ttoption;
4075 devmode->collate = ntdevmode->collate;
4076 devmode->icmmethod = ntdevmode->icmmethod;
4077 devmode->icmintent = ntdevmode->icmintent;
4078 devmode->mediatype = ntdevmode->mediatype;
4079 devmode->dithertype = ntdevmode->dithertype;
4081 if (ntdevmode->nt_dev_private != NULL) {
4082 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4083 return False;
4086 return True;
4089 /****************************************************************************
4090 Create a DEVMODE struct. Returns malloced memory.
4091 ****************************************************************************/
4093 DEVICEMODE *construct_dev_mode(int snum)
4095 NT_PRINTER_INFO_LEVEL *printer = NULL;
4096 DEVICEMODE *devmode = NULL;
4098 DEBUG(7,("construct_dev_mode\n"));
4100 DEBUGADD(8,("getting printer characteristics\n"));
4102 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4103 return NULL;
4105 if ( !printer->info_2->devmode ) {
4106 DEBUG(5, ("BONG! There was no device mode!\n"));
4107 goto done;
4110 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4111 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4112 goto done;
4115 ZERO_STRUCTP(devmode);
4117 DEBUGADD(8,("loading DEVICEMODE\n"));
4119 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4120 free_dev_mode( devmode );
4121 devmode = NULL;
4124 done:
4125 free_a_printer(&printer,2);
4127 return devmode;
4130 /********************************************************************
4131 * construct_printer_info_2
4132 * fill a printer_info_2 struct
4133 ********************************************************************/
4135 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4137 int count;
4138 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4140 print_status_struct status;
4142 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4143 return False;
4145 count = print_queue_length(snum, &status);
4147 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4148 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4149 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4150 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4151 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4153 if (*ntprinter->info_2->comment == '\0')
4154 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4155 else
4156 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4158 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4159 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4160 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4161 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4162 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4164 printer->attributes = ntprinter->info_2->attributes;
4166 printer->priority = ntprinter->info_2->priority; /* priority */
4167 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4168 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4169 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4170 printer->status = nt_printq_status(status.status); /* status */
4171 printer->cjobs = count; /* jobs */
4172 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4174 if ( !(printer->devmode = construct_dev_mode(snum)) )
4175 DEBUG(8, ("Returning NULL Devicemode!\n"));
4177 printer->secdesc = NULL;
4179 if ( ntprinter->info_2->secdesc_buf
4180 && ntprinter->info_2->secdesc_buf->len != 0 )
4182 /* don't use talloc_steal() here unless you do a deep steal of all
4183 the SEC_DESC members */
4185 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4186 ntprinter->info_2->secdesc_buf->sec );
4189 free_a_printer(&ntprinter, 2);
4191 return True;
4194 /********************************************************************
4195 * construct_printer_info_3
4196 * fill a printer_info_3 struct
4197 ********************************************************************/
4199 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4201 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4202 PRINTER_INFO_3 *printer = NULL;
4204 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4205 return False;
4207 *pp_printer = NULL;
4208 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4209 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4210 return False;
4213 ZERO_STRUCTP(printer);
4215 /* These are the components of the SD we are returning. */
4217 printer->flags = 0x4;
4219 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4220 /* don't use talloc_steal() here unless you do a deep steal of all
4221 the SEC_DESC members */
4223 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4224 ntprinter->info_2->secdesc_buf->sec );
4227 free_a_printer(&ntprinter, 2);
4229 *pp_printer = printer;
4230 return True;
4233 /********************************************************************
4234 * construct_printer_info_4
4235 * fill a printer_info_4 struct
4236 ********************************************************************/
4238 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4240 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4242 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4243 return False;
4245 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4246 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4247 printer->attributes = ntprinter->info_2->attributes;
4249 free_a_printer(&ntprinter, 2);
4250 return True;
4253 /********************************************************************
4254 * construct_printer_info_5
4255 * fill a printer_info_5 struct
4256 ********************************************************************/
4258 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4260 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4262 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4263 return False;
4265 init_unistr(&printer->printername, ntprinter->info_2->printername);
4266 init_unistr(&printer->portname, ntprinter->info_2->portname);
4267 printer->attributes = ntprinter->info_2->attributes;
4269 /* these two are not used by NT+ according to MSDN */
4271 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4272 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4274 free_a_printer(&ntprinter, 2);
4276 return True;
4279 /********************************************************************
4280 * construct_printer_info_7
4281 * fill a printer_info_7 struct
4282 ********************************************************************/
4284 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4286 char *guid_str = NULL;
4287 struct uuid guid;
4289 if (is_printer_published(print_hnd, snum, &guid)) {
4290 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4291 strupper_m(guid_str);
4292 init_unistr(&printer->guid, guid_str);
4293 printer->action = SPOOL_DS_PUBLISH;
4294 } else {
4295 init_unistr(&printer->guid, "");
4296 printer->action = SPOOL_DS_UNPUBLISH;
4299 return True;
4302 /********************************************************************
4303 Spoolss_enumprinters.
4304 ********************************************************************/
4306 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4308 int snum;
4309 int i;
4310 int n_services=lp_numservices();
4311 PRINTER_INFO_1 *tp, *printers=NULL;
4312 PRINTER_INFO_1 current_prt;
4313 WERROR result = WERR_OK;
4315 DEBUG(4,("enum_all_printers_info_1\n"));
4317 for (snum=0; snum<n_services; snum++) {
4318 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4319 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4321 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4322 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4323 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4324 SAFE_FREE(printers);
4325 *returned=0;
4326 return WERR_NOMEM;
4328 else printers = tp;
4329 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4331 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4332 (*returned)++;
4337 /* check the required size. */
4338 for (i=0; i<*returned; i++)
4339 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4341 if (*needed > offered) {
4342 result = WERR_INSUFFICIENT_BUFFER;
4343 goto out;
4346 if (!rpcbuf_alloc_size(buffer, *needed)) {
4347 result = WERR_NOMEM;
4348 goto out;
4351 /* fill the buffer with the structures */
4352 for (i=0; i<*returned; i++)
4353 smb_io_printer_info_1("", buffer, &printers[i], 0);
4355 out:
4356 /* clear memory */
4358 SAFE_FREE(printers);
4360 if ( !W_ERROR_IS_OK(result) )
4361 *returned = 0;
4363 return result;
4366 /********************************************************************
4367 enum_all_printers_info_1_local.
4368 *********************************************************************/
4370 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4372 DEBUG(4,("enum_all_printers_info_1_local\n"));
4374 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4377 /********************************************************************
4378 enum_all_printers_info_1_name.
4379 *********************************************************************/
4381 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4383 char *s = name;
4385 DEBUG(4,("enum_all_printers_info_1_name\n"));
4387 if ((name[0] == '\\') && (name[1] == '\\'))
4388 s = name + 2;
4390 if (is_myname_or_ipaddr(s)) {
4391 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4393 else
4394 return WERR_INVALID_NAME;
4397 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4398 /********************************************************************
4399 enum_all_printers_info_1_remote.
4400 *********************************************************************/
4402 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4404 PRINTER_INFO_1 *printer;
4405 fstring printername;
4406 fstring desc;
4407 fstring comment;
4408 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4409 WERROR result = WERR_OK;
4411 /* JFM: currently it's more a place holder than anything else.
4412 * In the spooler world there is a notion of server registration.
4413 * the print servers are registered on the PDC (in the same domain)
4415 * We should have a TDB here. The registration is done thru an
4416 * undocumented RPC call.
4419 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4420 return WERR_NOMEM;
4422 *returned=1;
4424 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4425 slprintf(desc, sizeof(desc)-1,"%s", name);
4426 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4428 init_unistr(&printer->description, desc);
4429 init_unistr(&printer->name, printername);
4430 init_unistr(&printer->comment, comment);
4431 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4433 /* check the required size. */
4434 *needed += spoolss_size_printer_info_1(printer);
4436 if (*needed > offered) {
4437 result = WERR_INSUFFICIENT_BUFFER;
4438 goto out;
4441 if (!rpcbuf_alloc_size(buffer, *needed)) {
4442 result = WERR_NOMEM;
4443 goto out;
4446 /* fill the buffer with the structures */
4447 smb_io_printer_info_1("", buffer, printer, 0);
4449 out:
4450 /* clear memory */
4451 SAFE_FREE(printer);
4453 if ( !W_ERROR_IS_OK(result) )
4454 *returned = 0;
4456 return result;
4459 #endif
4461 /********************************************************************
4462 enum_all_printers_info_1_network.
4463 *********************************************************************/
4465 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4467 char *s = name;
4469 DEBUG(4,("enum_all_printers_info_1_network\n"));
4471 /* If we respond to a enum_printers level 1 on our name with flags
4472 set to PRINTER_ENUM_REMOTE with a list of printers then these
4473 printers incorrectly appear in the APW browse list.
4474 Specifically the printers for the server appear at the workgroup
4475 level where all the other servers in the domain are
4476 listed. Windows responds to this call with a
4477 WERR_CAN_NOT_COMPLETE so we should do the same. */
4479 if (name[0] == '\\' && name[1] == '\\')
4480 s = name + 2;
4482 if (is_myname_or_ipaddr(s))
4483 return WERR_CAN_NOT_COMPLETE;
4485 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4488 /********************************************************************
4489 * api_spoolss_enumprinters
4491 * called from api_spoolss_enumprinters (see this to understand)
4492 ********************************************************************/
4494 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4496 int snum;
4497 int i;
4498 int n_services=lp_numservices();
4499 PRINTER_INFO_2 *tp, *printers=NULL;
4500 PRINTER_INFO_2 current_prt;
4501 WERROR result = WERR_OK;
4503 for (snum=0; snum<n_services; snum++) {
4504 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4505 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4507 if (construct_printer_info_2(NULL, &current_prt, snum))
4509 if ( !(tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4510 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4511 SAFE_FREE(printers);
4512 *returned = 0;
4513 return WERR_NOMEM;
4516 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4518 printers = tp;
4519 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4521 (*returned)++;
4526 /* check the required size. */
4527 for (i=0; i<*returned; i++)
4528 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4530 if (*needed > offered) {
4531 result = WERR_INSUFFICIENT_BUFFER;
4532 goto out;
4535 if (!rpcbuf_alloc_size(buffer, *needed)) {
4536 result = WERR_NOMEM;
4537 goto out;
4540 /* fill the buffer with the structures */
4541 for (i=0; i<*returned; i++)
4542 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4544 out:
4545 /* clear memory */
4547 for (i=0; i<*returned; i++)
4548 free_devmode(printers[i].devmode);
4550 SAFE_FREE(printers);
4552 if ( !W_ERROR_IS_OK(result) )
4553 *returned = 0;
4555 return result;
4558 /********************************************************************
4559 * handle enumeration of printers at level 1
4560 ********************************************************************/
4562 static WERROR enumprinters_level1( uint32 flags, fstring name,
4563 RPC_BUFFER *buffer, uint32 offered,
4564 uint32 *needed, uint32 *returned)
4566 /* Not all the flags are equals */
4568 if (flags & PRINTER_ENUM_LOCAL)
4569 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4571 if (flags & PRINTER_ENUM_NAME)
4572 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4574 #if 0 /* JERRY - disabled for now */
4575 if (flags & PRINTER_ENUM_REMOTE)
4576 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4577 #endif
4579 if (flags & PRINTER_ENUM_NETWORK)
4580 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4582 return WERR_OK; /* NT4sp5 does that */
4585 /********************************************************************
4586 * handle enumeration of printers at level 2
4587 ********************************************************************/
4589 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4590 RPC_BUFFER *buffer, uint32 offered,
4591 uint32 *needed, uint32 *returned)
4593 char *s = servername;
4595 if (flags & PRINTER_ENUM_LOCAL) {
4596 return enum_all_printers_info_2(buffer, offered, needed, returned);
4599 if (flags & PRINTER_ENUM_NAME) {
4600 if ((servername[0] == '\\') && (servername[1] == '\\'))
4601 s = servername + 2;
4602 if (is_myname_or_ipaddr(s))
4603 return enum_all_printers_info_2(buffer, offered, needed, returned);
4604 else
4605 return WERR_INVALID_NAME;
4608 if (flags & PRINTER_ENUM_REMOTE)
4609 return WERR_UNKNOWN_LEVEL;
4611 return WERR_OK;
4614 /********************************************************************
4615 * handle enumeration of printers at level 5
4616 ********************************************************************/
4618 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4619 RPC_BUFFER *buffer, uint32 offered,
4620 uint32 *needed, uint32 *returned)
4622 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4623 return WERR_OK;
4626 /********************************************************************
4627 * api_spoolss_enumprinters
4629 * called from api_spoolss_enumprinters (see this to understand)
4630 ********************************************************************/
4632 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4634 uint32 flags = q_u->flags;
4635 UNISTR2 *servername = &q_u->servername;
4636 uint32 level = q_u->level;
4637 RPC_BUFFER *buffer = NULL;
4638 uint32 offered = q_u->offered;
4639 uint32 *needed = &r_u->needed;
4640 uint32 *returned = &r_u->returned;
4642 fstring name;
4644 /* that's an [in out] buffer */
4646 if ( q_u->buffer ) {
4647 rpcbuf_move(q_u->buffer, &r_u->buffer);
4648 buffer = r_u->buffer;
4651 DEBUG(4,("_spoolss_enumprinters\n"));
4653 *needed=0;
4654 *returned=0;
4657 * Level 1:
4658 * flags==PRINTER_ENUM_NAME
4659 * if name=="" then enumerates all printers
4660 * if name!="" then enumerate the printer
4661 * flags==PRINTER_ENUM_REMOTE
4662 * name is NULL, enumerate printers
4663 * Level 2: name!="" enumerates printers, name can't be NULL
4664 * Level 3: doesn't exist
4665 * Level 4: does a local registry lookup
4666 * Level 5: same as Level 2
4669 unistr2_to_ascii(name, servername, sizeof(name)-1);
4670 strupper_m(name);
4672 switch (level) {
4673 case 1:
4674 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4675 case 2:
4676 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4677 case 5:
4678 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4679 case 3:
4680 case 4:
4681 break;
4683 return WERR_UNKNOWN_LEVEL;
4686 /****************************************************************************
4687 ****************************************************************************/
4689 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4691 PRINTER_INFO_0 *printer=NULL;
4692 WERROR result = WERR_OK;
4694 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4695 return WERR_NOMEM;
4697 construct_printer_info_0(print_hnd, printer, snum);
4699 /* check the required size. */
4700 *needed += spoolss_size_printer_info_0(printer);
4702 if (*needed > offered) {
4703 result = WERR_INSUFFICIENT_BUFFER;
4704 goto out;
4707 if (!rpcbuf_alloc_size(buffer, *needed)) {
4708 result = WERR_NOMEM;
4709 goto out;
4712 /* fill the buffer with the structures */
4713 smb_io_printer_info_0("", buffer, printer, 0);
4715 out:
4716 /* clear memory */
4718 SAFE_FREE(printer);
4720 return result;
4723 /****************************************************************************
4724 ****************************************************************************/
4726 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4728 PRINTER_INFO_1 *printer=NULL;
4729 WERROR result = WERR_OK;
4731 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4732 return WERR_NOMEM;
4734 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4736 /* check the required size. */
4737 *needed += spoolss_size_printer_info_1(printer);
4739 if (*needed > offered) {
4740 result = WERR_INSUFFICIENT_BUFFER;
4741 goto out;
4744 if (!rpcbuf_alloc_size(buffer, *needed)) {
4745 result = WERR_NOMEM;
4746 goto out;
4749 /* fill the buffer with the structures */
4750 smb_io_printer_info_1("", buffer, printer, 0);
4752 out:
4753 /* clear memory */
4754 SAFE_FREE(printer);
4756 return result;
4759 /****************************************************************************
4760 ****************************************************************************/
4762 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4764 PRINTER_INFO_2 *printer=NULL;
4765 WERROR result = WERR_OK;
4767 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4768 return WERR_NOMEM;
4770 construct_printer_info_2(print_hnd, printer, snum);
4772 /* check the required size. */
4773 *needed += spoolss_size_printer_info_2(printer);
4775 if (*needed > offered) {
4776 result = WERR_INSUFFICIENT_BUFFER;
4777 goto out;
4780 if (!rpcbuf_alloc_size(buffer, *needed)) {
4781 result = WERR_NOMEM;
4782 goto out;
4785 /* fill the buffer with the structures */
4786 if (!smb_io_printer_info_2("", buffer, printer, 0))
4787 result = WERR_NOMEM;
4789 out:
4790 /* clear memory */
4791 free_printer_info_2(printer);
4793 return result;
4796 /****************************************************************************
4797 ****************************************************************************/
4799 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4801 PRINTER_INFO_3 *printer=NULL;
4802 WERROR result = WERR_OK;
4804 if (!construct_printer_info_3(print_hnd, &printer, snum))
4805 return WERR_NOMEM;
4807 /* check the required size. */
4808 *needed += spoolss_size_printer_info_3(printer);
4810 if (*needed > offered) {
4811 result = WERR_INSUFFICIENT_BUFFER;
4812 goto out;
4815 if (!rpcbuf_alloc_size(buffer, *needed)) {
4816 result = WERR_NOMEM;
4817 goto out;
4820 /* fill the buffer with the structures */
4821 smb_io_printer_info_3("", buffer, printer, 0);
4823 out:
4824 /* clear memory */
4825 free_printer_info_3(printer);
4827 return result;
4830 /****************************************************************************
4831 ****************************************************************************/
4833 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4835 PRINTER_INFO_4 *printer=NULL;
4836 WERROR result = WERR_OK;
4838 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4839 return WERR_NOMEM;
4841 if (!construct_printer_info_4(print_hnd, printer, snum))
4842 return WERR_NOMEM;
4844 /* check the required size. */
4845 *needed += spoolss_size_printer_info_4(printer);
4847 if (*needed > offered) {
4848 result = WERR_INSUFFICIENT_BUFFER;
4849 goto out;
4852 if (!rpcbuf_alloc_size(buffer, *needed)) {
4853 result = WERR_NOMEM;
4854 goto out;
4857 /* fill the buffer with the structures */
4858 smb_io_printer_info_4("", buffer, printer, 0);
4860 out:
4861 /* clear memory */
4862 free_printer_info_4(printer);
4864 return result;
4867 /****************************************************************************
4868 ****************************************************************************/
4870 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4872 PRINTER_INFO_5 *printer=NULL;
4873 WERROR result = WERR_OK;
4875 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4876 return WERR_NOMEM;
4878 if (!construct_printer_info_5(print_hnd, printer, snum))
4879 return WERR_NOMEM;
4881 /* check the required size. */
4882 *needed += spoolss_size_printer_info_5(printer);
4884 if (*needed > offered) {
4885 result = WERR_INSUFFICIENT_BUFFER;
4886 goto out;
4889 if (!rpcbuf_alloc_size(buffer, *needed)) {
4890 result = WERR_NOMEM;
4891 goto out;
4894 /* fill the buffer with the structures */
4895 smb_io_printer_info_5("", buffer, printer, 0);
4897 out:
4898 /* clear memory */
4899 free_printer_info_5(printer);
4901 return result;
4904 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4906 PRINTER_INFO_7 *printer=NULL;
4907 WERROR result = WERR_OK;
4909 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4910 return WERR_NOMEM;
4912 if (!construct_printer_info_7(print_hnd, printer, snum))
4913 return WERR_NOMEM;
4915 /* check the required size. */
4916 *needed += spoolss_size_printer_info_7(printer);
4918 if (*needed > offered) {
4919 result = WERR_INSUFFICIENT_BUFFER;
4920 goto out;
4923 if (!rpcbuf_alloc_size(buffer, *needed)) {
4924 result = WERR_NOMEM;
4925 goto out;
4929 /* fill the buffer with the structures */
4930 smb_io_printer_info_7("", buffer, printer, 0);
4932 out:
4933 /* clear memory */
4934 free_printer_info_7(printer);
4936 return result;
4939 /****************************************************************************
4940 ****************************************************************************/
4942 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4944 POLICY_HND *handle = &q_u->handle;
4945 uint32 level = q_u->level;
4946 RPC_BUFFER *buffer = NULL;
4947 uint32 offered = q_u->offered;
4948 uint32 *needed = &r_u->needed;
4949 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4951 int snum;
4953 /* that's an [in out] buffer */
4955 if ( q_u->buffer ) {
4956 rpcbuf_move(q_u->buffer, &r_u->buffer);
4957 buffer = r_u->buffer;
4960 *needed=0;
4962 if (!get_printer_snum(p, handle, &snum))
4963 return WERR_BADFID;
4965 switch (level) {
4966 case 0:
4967 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4968 case 1:
4969 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4970 case 2:
4971 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4972 case 3:
4973 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4974 case 4:
4975 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4976 case 5:
4977 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4978 case 7:
4979 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4981 return WERR_UNKNOWN_LEVEL;
4984 /********************************************************************
4985 * fill a DRIVER_INFO_1 struct
4986 ********************************************************************/
4988 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4990 init_unistr( &info->name, driver.info_3->name);
4993 /********************************************************************
4994 * construct_printer_driver_info_1
4995 ********************************************************************/
4997 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4999 NT_PRINTER_INFO_LEVEL *printer = NULL;
5000 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5002 ZERO_STRUCT(driver);
5004 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5005 return WERR_INVALID_PRINTER_NAME;
5007 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5008 return WERR_UNKNOWN_PRINTER_DRIVER;
5010 fill_printer_driver_info_1(info, driver, servername, architecture);
5012 free_a_printer(&printer,2);
5014 return WERR_OK;
5017 /********************************************************************
5018 * construct_printer_driver_info_2
5019 * fill a printer_info_2 struct
5020 ********************************************************************/
5022 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5024 pstring temp;
5026 info->version=driver.info_3->cversion;
5028 init_unistr( &info->name, driver.info_3->name );
5029 init_unistr( &info->architecture, driver.info_3->environment );
5032 if (strlen(driver.info_3->driverpath)) {
5033 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5034 init_unistr( &info->driverpath, temp );
5035 } else
5036 init_unistr( &info->driverpath, "" );
5038 if (strlen(driver.info_3->datafile)) {
5039 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5040 init_unistr( &info->datafile, temp );
5041 } else
5042 init_unistr( &info->datafile, "" );
5044 if (strlen(driver.info_3->configfile)) {
5045 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5046 init_unistr( &info->configfile, temp );
5047 } else
5048 init_unistr( &info->configfile, "" );
5051 /********************************************************************
5052 * construct_printer_driver_info_2
5053 * fill a printer_info_2 struct
5054 ********************************************************************/
5056 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5058 NT_PRINTER_INFO_LEVEL *printer = NULL;
5059 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5061 ZERO_STRUCT(printer);
5062 ZERO_STRUCT(driver);
5064 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5065 return WERR_INVALID_PRINTER_NAME;
5067 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5068 return WERR_UNKNOWN_PRINTER_DRIVER;
5070 fill_printer_driver_info_2(info, driver, servername);
5072 free_a_printer(&printer,2);
5074 return WERR_OK;
5077 /********************************************************************
5078 * copy a strings array and convert to UNICODE
5080 * convert an array of ascii string to a UNICODE string
5081 ********************************************************************/
5083 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5085 int i=0;
5086 int j=0;
5087 const char *v;
5088 pstring line;
5089 uint16 *tuary;
5091 DEBUG(6,("init_unistr_array\n"));
5092 *uni_array=NULL;
5094 while (True)
5096 if ( !char_array )
5097 v = "";
5098 else
5100 v = char_array[i];
5101 if (!v)
5102 v = ""; /* hack to handle null lists */
5105 /* hack to allow this to be used in places other than when generating
5106 the list of dependent files */
5108 if ( servername )
5109 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5110 else
5111 pstrcpy( line, v );
5113 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5115 /* add one extra unit16 for the second terminating NULL */
5117 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5118 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5119 return 0;
5120 } else
5121 *uni_array = tuary;
5123 if ( !strlen(v) )
5124 break;
5126 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5127 i++;
5130 if (*uni_array) {
5131 /* special case for ""; we need to add both NULL's here */
5132 if (!j)
5133 (*uni_array)[j++]=0x0000;
5134 (*uni_array)[j]=0x0000;
5137 DEBUGADD(6,("last one:done\n"));
5139 /* return size of array in uint16's */
5141 return j+1;
5144 /********************************************************************
5145 * construct_printer_info_3
5146 * fill a printer_info_3 struct
5147 ********************************************************************/
5149 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5151 pstring temp;
5153 ZERO_STRUCTP(info);
5155 info->version=driver.info_3->cversion;
5157 init_unistr( &info->name, driver.info_3->name );
5158 init_unistr( &info->architecture, driver.info_3->environment );
5160 if (strlen(driver.info_3->driverpath)) {
5161 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5162 init_unistr( &info->driverpath, temp );
5163 } else
5164 init_unistr( &info->driverpath, "" );
5166 if (strlen(driver.info_3->datafile)) {
5167 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5168 init_unistr( &info->datafile, temp );
5169 } else
5170 init_unistr( &info->datafile, "" );
5172 if (strlen(driver.info_3->configfile)) {
5173 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5174 init_unistr( &info->configfile, temp );
5175 } else
5176 init_unistr( &info->configfile, "" );
5178 if (strlen(driver.info_3->helpfile)) {
5179 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5180 init_unistr( &info->helpfile, temp );
5181 } else
5182 init_unistr( &info->helpfile, "" );
5184 init_unistr( &info->monitorname, driver.info_3->monitorname );
5185 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5187 info->dependentfiles=NULL;
5188 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5191 /********************************************************************
5192 * construct_printer_info_3
5193 * fill a printer_info_3 struct
5194 ********************************************************************/
5196 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5198 NT_PRINTER_INFO_LEVEL *printer = NULL;
5199 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5200 WERROR status;
5201 ZERO_STRUCT(driver);
5203 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5204 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5205 if (!W_ERROR_IS_OK(status))
5206 return WERR_INVALID_PRINTER_NAME;
5208 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5209 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5211 #if 0 /* JERRY */
5214 * I put this code in during testing. Helpful when commenting out the
5215 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5216 * as win2k always queries the driver using an infor level of 6.
5217 * I've left it in (but ifdef'd out) because I'll probably
5218 * use it in experimentation again in the future. --jerry 22/01/2002
5221 if (!W_ERROR_IS_OK(status)) {
5223 * Is this a W2k client ?
5225 if (version == 3) {
5226 /* Yes - try again with a WinNT driver. */
5227 version = 2;
5228 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5229 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5231 #endif
5233 if (!W_ERROR_IS_OK(status)) {
5234 free_a_printer(&printer,2);
5235 return WERR_UNKNOWN_PRINTER_DRIVER;
5238 #if 0 /* JERRY */
5240 #endif
5243 fill_printer_driver_info_3(info, driver, servername);
5245 free_a_printer(&printer,2);
5247 return WERR_OK;
5250 /********************************************************************
5251 * construct_printer_info_6
5252 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5253 ********************************************************************/
5255 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5257 pstring temp;
5258 fstring nullstr;
5260 ZERO_STRUCTP(info);
5261 memset(&nullstr, '\0', sizeof(fstring));
5263 info->version=driver.info_3->cversion;
5265 init_unistr( &info->name, driver.info_3->name );
5266 init_unistr( &info->architecture, driver.info_3->environment );
5268 if (strlen(driver.info_3->driverpath)) {
5269 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5270 init_unistr( &info->driverpath, temp );
5271 } else
5272 init_unistr( &info->driverpath, "" );
5274 if (strlen(driver.info_3->datafile)) {
5275 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5276 init_unistr( &info->datafile, temp );
5277 } else
5278 init_unistr( &info->datafile, "" );
5280 if (strlen(driver.info_3->configfile)) {
5281 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5282 init_unistr( &info->configfile, temp );
5283 } else
5284 init_unistr( &info->configfile, "" );
5286 if (strlen(driver.info_3->helpfile)) {
5287 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5288 init_unistr( &info->helpfile, temp );
5289 } else
5290 init_unistr( &info->helpfile, "" );
5292 init_unistr( &info->monitorname, driver.info_3->monitorname );
5293 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5295 info->dependentfiles = NULL;
5296 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5298 info->previousdrivernames=NULL;
5299 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5301 info->driver_date.low=0;
5302 info->driver_date.high=0;
5304 info->padding=0;
5305 info->driver_version_low=0;
5306 info->driver_version_high=0;
5308 init_unistr( &info->mfgname, "");
5309 init_unistr( &info->oem_url, "");
5310 init_unistr( &info->hardware_id, "");
5311 init_unistr( &info->provider, "");
5314 /********************************************************************
5315 * construct_printer_info_6
5316 * fill a printer_info_6 struct
5317 ********************************************************************/
5319 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5320 fstring servername, fstring architecture, uint32 version)
5322 NT_PRINTER_INFO_LEVEL *printer = NULL;
5323 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5324 WERROR status;
5326 ZERO_STRUCT(driver);
5328 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5330 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5332 if (!W_ERROR_IS_OK(status))
5333 return WERR_INVALID_PRINTER_NAME;
5335 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5337 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5339 if (!W_ERROR_IS_OK(status))
5342 * Is this a W2k client ?
5345 if (version < 3) {
5346 free_a_printer(&printer,2);
5347 return WERR_UNKNOWN_PRINTER_DRIVER;
5350 /* Yes - try again with a WinNT driver. */
5351 version = 2;
5352 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5353 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5354 if (!W_ERROR_IS_OK(status)) {
5355 free_a_printer(&printer,2);
5356 return WERR_UNKNOWN_PRINTER_DRIVER;
5360 fill_printer_driver_info_6(info, driver, servername);
5362 free_a_printer(&printer,2);
5363 free_a_printer_driver(driver, 3);
5365 return WERR_OK;
5368 /****************************************************************************
5369 ****************************************************************************/
5371 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5373 SAFE_FREE(info->dependentfiles);
5376 /****************************************************************************
5377 ****************************************************************************/
5379 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5381 SAFE_FREE(info->dependentfiles);
5384 /****************************************************************************
5385 ****************************************************************************/
5387 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5389 DRIVER_INFO_1 *info=NULL;
5390 WERROR result;
5392 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5393 return WERR_NOMEM;
5395 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5396 if (!W_ERROR_IS_OK(result))
5397 goto out;
5399 /* check the required size. */
5400 *needed += spoolss_size_printer_driver_info_1(info);
5402 if (*needed > offered) {
5403 result = WERR_INSUFFICIENT_BUFFER;
5404 goto out;
5407 if (!rpcbuf_alloc_size(buffer, *needed)) {
5408 result = WERR_NOMEM;
5409 goto out;
5412 /* fill the buffer with the structures */
5413 smb_io_printer_driver_info_1("", buffer, info, 0);
5415 out:
5416 /* clear memory */
5417 SAFE_FREE(info);
5419 return result;
5422 /****************************************************************************
5423 ****************************************************************************/
5425 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5427 DRIVER_INFO_2 *info=NULL;
5428 WERROR result;
5430 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5431 return WERR_NOMEM;
5433 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5434 if (!W_ERROR_IS_OK(result))
5435 goto out;
5437 /* check the required size. */
5438 *needed += spoolss_size_printer_driver_info_2(info);
5440 if (*needed > offered) {
5441 result = WERR_INSUFFICIENT_BUFFER;
5442 goto out;
5445 if (!rpcbuf_alloc_size(buffer, *needed)) {
5446 result = WERR_NOMEM;
5447 goto out;
5450 /* fill the buffer with the structures */
5451 smb_io_printer_driver_info_2("", buffer, info, 0);
5453 out:
5454 /* clear memory */
5455 SAFE_FREE(info);
5457 return result;
5460 /****************************************************************************
5461 ****************************************************************************/
5463 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5465 DRIVER_INFO_3 info;
5466 WERROR result;
5468 ZERO_STRUCT(info);
5470 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5471 if (!W_ERROR_IS_OK(result))
5472 goto out;
5474 /* check the required size. */
5475 *needed += spoolss_size_printer_driver_info_3(&info);
5477 if (*needed > offered) {
5478 result = WERR_INSUFFICIENT_BUFFER;
5479 goto out;
5482 if (!rpcbuf_alloc_size(buffer, *needed)) {
5483 result = WERR_NOMEM;
5484 goto out;
5487 /* fill the buffer with the structures */
5488 smb_io_printer_driver_info_3("", buffer, &info, 0);
5490 out:
5491 free_printer_driver_info_3(&info);
5493 return result;
5496 /****************************************************************************
5497 ****************************************************************************/
5499 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5501 DRIVER_INFO_6 info;
5502 WERROR result;
5504 ZERO_STRUCT(info);
5506 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5507 if (!W_ERROR_IS_OK(result))
5508 goto out;
5510 /* check the required size. */
5511 *needed += spoolss_size_printer_driver_info_6(&info);
5513 if (*needed > offered) {
5514 result = WERR_INSUFFICIENT_BUFFER;
5515 goto out;
5518 if (!rpcbuf_alloc_size(buffer, *needed)) {
5519 result = WERR_NOMEM;
5520 goto out;
5523 /* fill the buffer with the structures */
5524 smb_io_printer_driver_info_6("", buffer, &info, 0);
5526 out:
5527 free_printer_driver_info_6(&info);
5529 return result;
5532 /****************************************************************************
5533 ****************************************************************************/
5535 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5537 POLICY_HND *handle = &q_u->handle;
5538 UNISTR2 *uni_arch = &q_u->architecture;
5539 uint32 level = q_u->level;
5540 uint32 clientmajorversion = q_u->clientmajorversion;
5541 RPC_BUFFER *buffer = NULL;
5542 uint32 offered = q_u->offered;
5543 uint32 *needed = &r_u->needed;
5544 uint32 *servermajorversion = &r_u->servermajorversion;
5545 uint32 *serverminorversion = &r_u->serverminorversion;
5546 Printer_entry *printer;
5548 fstring servername;
5549 fstring architecture;
5550 int snum;
5552 /* that's an [in out] buffer */
5554 if ( q_u->buffer ) {
5555 rpcbuf_move(q_u->buffer, &r_u->buffer);
5556 buffer = r_u->buffer;
5559 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5561 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5562 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5563 return WERR_INVALID_PRINTER_NAME;
5566 *needed = 0;
5567 *servermajorversion = 0;
5568 *serverminorversion = 0;
5570 fstrcpy(servername, get_server_name( printer ));
5571 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5573 if (!get_printer_snum(p, handle, &snum))
5574 return WERR_BADFID;
5576 switch (level) {
5577 case 1:
5578 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5579 case 2:
5580 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5581 case 3:
5582 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5583 case 6:
5584 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5585 #if 0 /* JERRY */
5586 case 101:
5587 /* apparently this call is the equivalent of
5588 EnumPrinterDataEx() for the DsDriver key */
5589 break;
5590 #endif
5593 return WERR_UNKNOWN_LEVEL;
5596 /****************************************************************************
5597 ****************************************************************************/
5599 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5601 POLICY_HND *handle = &q_u->handle;
5603 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5605 if (!Printer) {
5606 DEBUG(3,("Error in startpageprinter printer handle\n"));
5607 return WERR_BADFID;
5610 Printer->page_started=True;
5611 return WERR_OK;
5614 /****************************************************************************
5615 ****************************************************************************/
5617 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5619 POLICY_HND *handle = &q_u->handle;
5620 int snum;
5622 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5624 if (!Printer) {
5625 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5626 return WERR_BADFID;
5629 if (!get_printer_snum(p, handle, &snum))
5630 return WERR_BADFID;
5632 Printer->page_started=False;
5633 print_job_endpage(snum, Printer->jobid);
5635 return WERR_OK;
5638 /********************************************************************
5639 * api_spoolss_getprinter
5640 * called from the spoolss dispatcher
5642 ********************************************************************/
5644 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5646 POLICY_HND *handle = &q_u->handle;
5647 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5648 uint32 *jobid = &r_u->jobid;
5650 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5651 int snum;
5652 pstring jobname;
5653 fstring datatype;
5654 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5655 struct current_user user;
5657 if (!Printer) {
5658 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5659 return WERR_BADFID;
5662 get_current_user(&user, p);
5665 * a nice thing with NT is it doesn't listen to what you tell it.
5666 * when asked to send _only_ RAW datas, it tries to send datas
5667 * in EMF format.
5669 * So I add checks like in NT Server ...
5672 if (info_1->p_datatype != 0) {
5673 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5674 if (strcmp(datatype, "RAW") != 0) {
5675 (*jobid)=0;
5676 return WERR_INVALID_DATATYPE;
5680 /* get the share number of the printer */
5681 if (!get_printer_snum(p, handle, &snum)) {
5682 return WERR_BADFID;
5685 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5687 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5689 /* An error occured in print_job_start() so return an appropriate
5690 NT error code. */
5692 if (Printer->jobid == -1) {
5693 return map_werror_from_unix(errno);
5696 Printer->document_started=True;
5697 (*jobid) = Printer->jobid;
5699 return WERR_OK;
5702 /********************************************************************
5703 * api_spoolss_getprinter
5704 * called from the spoolss dispatcher
5706 ********************************************************************/
5708 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5710 POLICY_HND *handle = &q_u->handle;
5712 return _spoolss_enddocprinter_internal(p, handle);
5715 /****************************************************************************
5716 ****************************************************************************/
5718 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5720 POLICY_HND *handle = &q_u->handle;
5721 uint32 buffer_size = q_u->buffer_size;
5722 uint8 *buffer = q_u->buffer;
5723 uint32 *buffer_written = &q_u->buffer_size2;
5724 int snum;
5725 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5727 if (!Printer) {
5728 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5729 r_u->buffer_written = q_u->buffer_size2;
5730 return WERR_BADFID;
5733 if (!get_printer_snum(p, handle, &snum))
5734 return WERR_BADFID;
5736 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5737 (SMB_OFF_T)-1, (size_t)buffer_size);
5738 if (*buffer_written == (uint32)-1) {
5739 r_u->buffer_written = 0;
5740 if (errno == ENOSPC)
5741 return WERR_NO_SPOOL_SPACE;
5742 else
5743 return WERR_ACCESS_DENIED;
5746 r_u->buffer_written = q_u->buffer_size2;
5748 return WERR_OK;
5751 /********************************************************************
5752 * api_spoolss_getprinter
5753 * called from the spoolss dispatcher
5755 ********************************************************************/
5757 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5758 pipes_struct *p)
5760 struct current_user user;
5761 int snum;
5762 WERROR errcode = WERR_BADFUNC;
5763 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5765 get_current_user(&user, p);
5767 if (!Printer) {
5768 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5769 return WERR_BADFID;
5772 if (!get_printer_snum(p, handle, &snum))
5773 return WERR_BADFID;
5775 switch (command) {
5776 case PRINTER_CONTROL_PAUSE:
5777 if (print_queue_pause(&user, snum, &errcode)) {
5778 errcode = WERR_OK;
5780 break;
5781 case PRINTER_CONTROL_RESUME:
5782 case PRINTER_CONTROL_UNPAUSE:
5783 if (print_queue_resume(&user, snum, &errcode)) {
5784 errcode = WERR_OK;
5786 break;
5787 case PRINTER_CONTROL_PURGE:
5788 if (print_queue_purge(&user, snum, &errcode)) {
5789 errcode = WERR_OK;
5791 break;
5792 default:
5793 return WERR_UNKNOWN_LEVEL;
5796 return errcode;
5799 /********************************************************************
5800 * api_spoolss_abortprinter
5801 * From MSDN: "Deletes printer's spool file if printer is configured
5802 * for spooling"
5803 ********************************************************************/
5805 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5807 POLICY_HND *handle = &q_u->handle;
5808 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5809 int snum;
5810 struct current_user user;
5811 WERROR errcode = WERR_OK;
5813 if (!Printer) {
5814 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5815 return WERR_BADFID;
5818 if (!get_printer_snum(p, handle, &snum))
5819 return WERR_BADFID;
5821 get_current_user( &user, p );
5823 print_job_delete( &user, snum, Printer->jobid, &errcode );
5825 return errcode;
5828 /********************************************************************
5829 * called by spoolss_api_setprinter
5830 * when updating a printer description
5831 ********************************************************************/
5833 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5834 const SPOOL_PRINTER_INFO_LEVEL *info,
5835 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5837 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5838 WERROR result;
5839 int snum;
5841 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5843 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5844 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5845 OUR_HANDLE(handle)));
5847 result = WERR_BADFID;
5848 goto done;
5851 /* Check the user has permissions to change the security
5852 descriptor. By experimentation with two NT machines, the user
5853 requires Full Access to the printer to change security
5854 information. */
5856 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5857 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5858 result = WERR_ACCESS_DENIED;
5859 goto done;
5862 /* NT seems to like setting the security descriptor even though
5863 nothing may have actually changed. */
5865 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5867 if (DEBUGLEVEL >= 10) {
5868 SEC_ACL *the_acl;
5869 int i;
5871 the_acl = old_secdesc_ctr->sec->dacl;
5872 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5873 PRINTERNAME(snum), the_acl->num_aces));
5875 for (i = 0; i < the_acl->num_aces; i++) {
5876 fstring sid_str;
5878 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5880 DEBUG(10, ("%s 0x%08x\n", sid_str,
5881 the_acl->ace[i].info.mask));
5884 the_acl = secdesc_ctr->sec->dacl;
5886 if (the_acl) {
5887 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5888 PRINTERNAME(snum), the_acl->num_aces));
5890 for (i = 0; i < the_acl->num_aces; i++) {
5891 fstring sid_str;
5893 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5895 DEBUG(10, ("%s 0x%08x\n", sid_str,
5896 the_acl->ace[i].info.mask));
5898 } else {
5899 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5903 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5905 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5906 result = WERR_OK;
5907 goto done;
5910 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5912 done:
5914 return result;
5917 /********************************************************************
5918 Canonicalize printer info from a client
5920 ATTN: It does not matter what we set the servername to hear
5921 since we do the necessary work in get_a_printer() to set it to
5922 the correct value based on what the client sent in the
5923 _spoolss_open_printer_ex().
5924 ********************************************************************/
5926 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5928 fstring printername;
5929 const char *p;
5931 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5932 "portname=%s drivername=%s comment=%s location=%s\n",
5933 info->servername, info->printername, info->sharename,
5934 info->portname, info->drivername, info->comment, info->location));
5936 /* we force some elements to "correct" values */
5937 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5938 fstrcpy(info->sharename, lp_servicename(snum));
5940 /* check to see if we allow printername != sharename */
5942 if ( lp_force_printername(snum) ) {
5943 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5944 global_myname(), info->sharename );
5945 } else {
5947 /* make sure printername is in \\server\printername format */
5949 fstrcpy( printername, info->printername );
5950 p = printername;
5951 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5952 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5953 p++;
5956 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5957 global_myname(), p );
5960 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5961 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5965 return True;
5968 /****************************************************************************
5969 ****************************************************************************/
5971 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5973 char *cmd = lp_addprinter_cmd();
5974 char **qlines;
5975 pstring command;
5976 int numlines;
5977 int ret;
5978 int fd;
5979 fstring remote_machine = "%m";
5980 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5981 BOOL is_print_op = False;
5983 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5985 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5986 cmd, printer->info_2->printername, printer->info_2->sharename,
5987 printer->info_2->portname, printer->info_2->drivername,
5988 printer->info_2->location, printer->info_2->comment, remote_machine);
5990 if ( token )
5991 is_print_op = user_has_privileges( token, &se_printop );
5993 DEBUG(10,("Running [%s]\n", command));
5995 /********* BEGIN SePrintOperatorPrivilege **********/
5997 if ( is_print_op )
5998 become_root();
6000 if ( (ret = smbrun(command, &fd)) == 0 ) {
6001 /* Tell everyone we updated smb.conf. */
6002 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6005 if ( is_print_op )
6006 unbecome_root();
6008 /********* END SePrintOperatorPrivilege **********/
6010 DEBUGADD(10,("returned [%d]\n", ret));
6012 if ( ret != 0 ) {
6013 if (fd != -1)
6014 close(fd);
6015 return False;
6018 /* reload our services immediately */
6019 reload_services( False );
6021 numlines = 0;
6022 /* Get lines and convert them back to dos-codepage */
6023 qlines = fd_lines_load(fd, &numlines);
6024 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6025 close(fd);
6027 /* Set the portname to what the script says the portname should be. */
6028 /* but don't require anything to be return from the script exit a good error code */
6030 if (numlines) {
6031 /* Set the portname to what the script says the portname should be. */
6032 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6033 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6036 file_lines_free(qlines);
6037 return True;
6040 /********************************************************************
6041 * Called by spoolss_api_setprinter
6042 * when updating a printer description.
6043 ********************************************************************/
6045 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6046 const SPOOL_PRINTER_INFO_LEVEL *info,
6047 DEVICEMODE *devmode)
6049 int snum;
6050 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6051 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6052 WERROR result;
6053 UNISTR2 buffer;
6054 fstring asc_buffer;
6056 DEBUG(8,("update_printer\n"));
6058 result = WERR_OK;
6060 if (!Printer) {
6061 result = WERR_BADFID;
6062 goto done;
6065 if (!get_printer_snum(p, handle, &snum)) {
6066 result = WERR_BADFID;
6067 goto done;
6070 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6071 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6072 result = WERR_BADFID;
6073 goto done;
6076 DEBUGADD(8,("Converting info_2 struct\n"));
6079 * convert_printer_info converts the incoming
6080 * info from the client and overwrites the info
6081 * just read from the tdb in the pointer 'printer'.
6084 if (!convert_printer_info(info, printer, level)) {
6085 result = WERR_NOMEM;
6086 goto done;
6089 if (devmode) {
6090 /* we have a valid devmode
6091 convert it and link it*/
6093 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6094 if (!convert_devicemode(printer->info_2->printername, devmode,
6095 &printer->info_2->devmode)) {
6096 result = WERR_NOMEM;
6097 goto done;
6101 /* Do sanity check on the requested changes for Samba */
6103 if (!check_printer_ok(printer->info_2, snum)) {
6104 result = WERR_INVALID_PARAM;
6105 goto done;
6108 /* FIXME!!! If the driver has changed we really should verify that
6109 it is installed before doing much else --jerry */
6111 /* Check calling user has permission to update printer description */
6113 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6114 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6115 result = WERR_ACCESS_DENIED;
6116 goto done;
6119 /* Call addprinter hook */
6120 /* Check changes to see if this is really needed */
6122 if ( *lp_addprinter_cmd()
6123 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6124 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6125 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6126 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6128 /* add_printer_hook() will call reload_services() */
6130 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6131 result = WERR_ACCESS_DENIED;
6132 goto done;
6137 * When a *new* driver is bound to a printer, the drivername is used to
6138 * lookup previously saved driver initialization info, which is then
6139 * bound to the printer, simulating what happens in the Windows arch.
6141 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6143 if (!set_driver_init(printer, 2))
6145 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6146 printer->info_2->drivername));
6149 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6150 printer->info_2->drivername));
6152 notify_printer_driver(snum, printer->info_2->drivername);
6156 * flag which changes actually occured. This is a small subset of
6157 * all the possible changes. We also have to update things in the
6158 * DsSpooler key.
6161 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6162 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6163 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6164 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6166 notify_printer_comment(snum, printer->info_2->comment);
6169 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6170 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6171 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6172 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6174 notify_printer_sharename(snum, printer->info_2->sharename);
6177 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6178 char *pname;
6180 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6181 pname++;
6182 else
6183 pname = printer->info_2->printername;
6186 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6187 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6188 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6190 notify_printer_printername( snum, pname );
6193 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6194 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6195 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6196 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6198 notify_printer_port(snum, printer->info_2->portname);
6201 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6202 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6203 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6204 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6206 notify_printer_location(snum, printer->info_2->location);
6209 /* here we need to update some more DsSpooler keys */
6210 /* uNCName, serverName, shortServerName */
6212 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6213 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6214 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6215 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6216 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6218 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6219 global_myname(), printer->info_2->sharename );
6220 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6221 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6222 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6224 /* Update printer info */
6225 result = mod_a_printer(printer, 2);
6227 done:
6228 free_a_printer(&printer, 2);
6229 free_a_printer(&old_printer, 2);
6232 return result;
6235 /****************************************************************************
6236 ****************************************************************************/
6237 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6238 const SPOOL_PRINTER_INFO_LEVEL *info)
6240 #ifdef HAVE_ADS
6241 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6242 int snum;
6243 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6245 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6247 if (!Printer)
6248 return WERR_BADFID;
6250 if (!get_printer_snum(p, handle, &snum))
6251 return WERR_BADFID;
6253 nt_printer_publish(Printer, snum, info7->action);
6255 return WERR_OK;
6256 #else
6257 return WERR_UNKNOWN_LEVEL;
6258 #endif
6260 /****************************************************************************
6261 ****************************************************************************/
6263 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6265 POLICY_HND *handle = &q_u->handle;
6266 uint32 level = q_u->level;
6267 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6268 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6269 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6270 uint32 command = q_u->command;
6271 WERROR result;
6273 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6275 if (!Printer) {
6276 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6277 return WERR_BADFID;
6280 /* check the level */
6281 switch (level) {
6282 case 0:
6283 return control_printer(handle, command, p);
6284 case 2:
6285 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6286 if (!W_ERROR_IS_OK(result))
6287 return result;
6288 if (secdesc_ctr)
6289 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6290 return result;
6291 case 3:
6292 return update_printer_sec(handle, level, info, p,
6293 secdesc_ctr);
6294 case 7:
6295 return publish_or_unpublish_printer(p, handle, info);
6296 default:
6297 return WERR_UNKNOWN_LEVEL;
6301 /****************************************************************************
6302 ****************************************************************************/
6304 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6306 POLICY_HND *handle = &q_u->handle;
6307 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6309 if (!Printer) {
6310 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6311 return WERR_BADFID;
6314 if (Printer->notify.client_connected==True) {
6315 int snum = -1;
6317 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6318 snum = -1;
6319 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6320 !get_printer_snum(p, handle, &snum) )
6321 return WERR_BADFID;
6323 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6326 Printer->notify.flags=0;
6327 Printer->notify.options=0;
6328 Printer->notify.localmachine[0]='\0';
6329 Printer->notify.printerlocal=0;
6330 if (Printer->notify.option)
6331 free_spool_notify_option(&Printer->notify.option);
6332 Printer->notify.client_connected=False;
6334 return WERR_OK;
6337 /****************************************************************************
6338 ****************************************************************************/
6340 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6342 /* that's an [in out] buffer */
6344 if ( q_u->buffer )
6345 rpcbuf_move(q_u->buffer, &r_u->buffer);
6347 r_u->needed = 0;
6348 return WERR_INVALID_PARAM; /* this is what a NT server
6349 returns for AddJob. AddJob
6350 must fail on non-local
6351 printers */
6354 /****************************************************************************
6355 ****************************************************************************/
6357 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6358 int position, int snum,
6359 NT_PRINTER_INFO_LEVEL *ntprinter)
6361 struct tm *t;
6363 t=gmtime(&queue->time);
6365 job_info->jobid=queue->job;
6366 init_unistr(&job_info->printername, lp_servicename(snum));
6367 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6368 init_unistr(&job_info->username, queue->fs_user);
6369 init_unistr(&job_info->document, queue->fs_file);
6370 init_unistr(&job_info->datatype, "RAW");
6371 init_unistr(&job_info->text_status, "");
6372 job_info->status=nt_printj_status(queue->status);
6373 job_info->priority=queue->priority;
6374 job_info->position=position;
6375 job_info->totalpages=queue->page_count;
6376 job_info->pagesprinted=0;
6378 make_systemtime(&job_info->submitted, t);
6381 /****************************************************************************
6382 ****************************************************************************/
6384 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6385 int position, int snum,
6386 NT_PRINTER_INFO_LEVEL *ntprinter,
6387 DEVICEMODE *devmode)
6389 struct tm *t;
6391 t=gmtime(&queue->time);
6393 job_info->jobid=queue->job;
6395 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6397 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6398 init_unistr(&job_info->username, queue->fs_user);
6399 init_unistr(&job_info->document, queue->fs_file);
6400 init_unistr(&job_info->notifyname, queue->fs_user);
6401 init_unistr(&job_info->datatype, "RAW");
6402 init_unistr(&job_info->printprocessor, "winprint");
6403 init_unistr(&job_info->parameters, "");
6404 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6405 init_unistr(&job_info->text_status, "");
6407 /* and here the security descriptor */
6409 job_info->status=nt_printj_status(queue->status);
6410 job_info->priority=queue->priority;
6411 job_info->position=position;
6412 job_info->starttime=0;
6413 job_info->untiltime=0;
6414 job_info->totalpages=queue->page_count;
6415 job_info->size=queue->size;
6416 make_systemtime(&(job_info->submitted), t);
6417 job_info->timeelapsed=0;
6418 job_info->pagesprinted=0;
6420 job_info->devmode = devmode;
6422 return (True);
6425 /****************************************************************************
6426 Enumjobs at level 1.
6427 ****************************************************************************/
6429 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6430 NT_PRINTER_INFO_LEVEL *ntprinter,
6431 RPC_BUFFER *buffer, uint32 offered,
6432 uint32 *needed, uint32 *returned)
6434 JOB_INFO_1 *info;
6435 int i;
6436 WERROR result = WERR_OK;
6438 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6439 if (info==NULL) {
6440 SAFE_FREE(queue);
6441 *returned=0;
6442 return WERR_NOMEM;
6445 for (i=0; i<*returned; i++)
6446 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6448 SAFE_FREE(queue);
6450 /* check the required size. */
6451 for (i=0; i<*returned; i++)
6452 (*needed) += spoolss_size_job_info_1(&info[i]);
6454 if (*needed > offered) {
6455 result = WERR_INSUFFICIENT_BUFFER;
6456 goto out;
6459 if (!rpcbuf_alloc_size(buffer, *needed)) {
6460 result = WERR_NOMEM;
6461 goto out;
6464 /* fill the buffer with the structures */
6465 for (i=0; i<*returned; i++)
6466 smb_io_job_info_1("", buffer, &info[i], 0);
6468 out:
6469 /* clear memory */
6470 SAFE_FREE(info);
6472 if ( !W_ERROR_IS_OK(result) )
6473 *returned = 0;
6475 return result;
6478 /****************************************************************************
6479 Enumjobs at level 2.
6480 ****************************************************************************/
6482 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6483 NT_PRINTER_INFO_LEVEL *ntprinter,
6484 RPC_BUFFER *buffer, uint32 offered,
6485 uint32 *needed, uint32 *returned)
6487 JOB_INFO_2 *info = NULL;
6488 int i;
6489 WERROR result = WERR_OK;
6490 DEVICEMODE *devmode = NULL;
6492 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6493 *returned=0;
6494 return WERR_NOMEM;
6497 /* this should not be a failure condition if the devmode is NULL */
6499 devmode = construct_dev_mode(snum);
6501 for (i=0; i<*returned; i++)
6502 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6504 free_a_printer(&ntprinter, 2);
6505 SAFE_FREE(queue);
6507 /* check the required size. */
6508 for (i=0; i<*returned; i++)
6509 (*needed) += spoolss_size_job_info_2(&info[i]);
6511 if (*needed > offered) {
6512 result = WERR_INSUFFICIENT_BUFFER;
6513 goto out;
6516 if (!rpcbuf_alloc_size(buffer, *needed)) {
6517 result = WERR_NOMEM;
6518 goto out;
6521 /* fill the buffer with the structures */
6522 for (i=0; i<*returned; i++)
6523 smb_io_job_info_2("", buffer, &info[i], 0);
6525 out:
6526 free_devmode(devmode);
6527 SAFE_FREE(info);
6529 if ( !W_ERROR_IS_OK(result) )
6530 *returned = 0;
6532 return result;
6536 /****************************************************************************
6537 Enumjobs.
6538 ****************************************************************************/
6540 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6542 POLICY_HND *handle = &q_u->handle;
6543 uint32 level = q_u->level;
6544 RPC_BUFFER *buffer = NULL;
6545 uint32 offered = q_u->offered;
6546 uint32 *needed = &r_u->needed;
6547 uint32 *returned = &r_u->returned;
6548 WERROR wret;
6549 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6550 int snum;
6551 print_status_struct prt_status;
6552 print_queue_struct *queue=NULL;
6554 /* that's an [in out] buffer */
6556 if ( q_u->buffer ) {
6557 rpcbuf_move(q_u->buffer, &r_u->buffer);
6558 buffer = r_u->buffer;
6561 DEBUG(4,("_spoolss_enumjobs\n"));
6563 *needed=0;
6564 *returned=0;
6566 /* lookup the printer snum and tdb entry */
6568 if (!get_printer_snum(p, handle, &snum))
6569 return WERR_BADFID;
6571 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6572 if ( !W_ERROR_IS_OK(wret) )
6573 return wret;
6575 *returned = print_queue_status(snum, &queue, &prt_status);
6576 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6578 if (*returned == 0) {
6579 SAFE_FREE(queue);
6580 return WERR_OK;
6583 switch (level) {
6584 case 1:
6585 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6586 return wret;
6587 case 2:
6588 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6589 return wret;
6590 default:
6591 SAFE_FREE(queue);
6592 *returned=0;
6593 wret = WERR_UNKNOWN_LEVEL;
6596 free_a_printer( &ntprinter, 2 );
6597 return wret;
6600 /****************************************************************************
6601 ****************************************************************************/
6603 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6605 return WERR_OK;
6608 /****************************************************************************
6609 ****************************************************************************/
6611 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6613 POLICY_HND *handle = &q_u->handle;
6614 uint32 jobid = q_u->jobid;
6615 uint32 command = q_u->command;
6617 struct current_user user;
6618 int snum;
6619 WERROR errcode = WERR_BADFUNC;
6621 if (!get_printer_snum(p, handle, &snum)) {
6622 return WERR_BADFID;
6625 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6626 return WERR_INVALID_PRINTER_NAME;
6629 get_current_user(&user, p);
6631 switch (command) {
6632 case JOB_CONTROL_CANCEL:
6633 case JOB_CONTROL_DELETE:
6634 if (print_job_delete(&user, snum, jobid, &errcode)) {
6635 errcode = WERR_OK;
6637 break;
6638 case JOB_CONTROL_PAUSE:
6639 if (print_job_pause(&user, snum, jobid, &errcode)) {
6640 errcode = WERR_OK;
6642 break;
6643 case JOB_CONTROL_RESTART:
6644 case JOB_CONTROL_RESUME:
6645 if (print_job_resume(&user, snum, jobid, &errcode)) {
6646 errcode = WERR_OK;
6648 break;
6649 default:
6650 return WERR_UNKNOWN_LEVEL;
6653 return errcode;
6656 /****************************************************************************
6657 Enumerates all printer drivers at level 1.
6658 ****************************************************************************/
6660 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6662 int i;
6663 int ndrivers;
6664 uint32 version;
6665 fstring *list = NULL;
6666 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6667 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6668 WERROR result = WERR_OK;
6670 *returned=0;
6672 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6673 list=NULL;
6674 ndrivers=get_ntdrivers(&list, architecture, version);
6675 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6677 if(ndrivers == -1)
6678 return WERR_NOMEM;
6680 if(ndrivers != 0) {
6681 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6682 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6683 SAFE_FREE(driver_info_1);
6684 SAFE_FREE(list);
6685 return WERR_NOMEM;
6687 else driver_info_1 = tdi1;
6690 for (i=0; i<ndrivers; i++) {
6691 WERROR status;
6692 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6693 ZERO_STRUCT(driver);
6694 status = get_a_printer_driver(&driver, 3, list[i],
6695 architecture, version);
6696 if (!W_ERROR_IS_OK(status)) {
6697 SAFE_FREE(list);
6698 return status;
6700 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6701 free_a_printer_driver(driver, 3);
6704 *returned+=ndrivers;
6705 SAFE_FREE(list);
6708 /* check the required size. */
6709 for (i=0; i<*returned; i++) {
6710 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6711 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6714 if (*needed > offered) {
6715 result = WERR_INSUFFICIENT_BUFFER;
6716 goto out;
6719 if (!rpcbuf_alloc_size(buffer, *needed)) {
6720 result = WERR_NOMEM;
6721 goto out;
6724 /* fill the buffer with the driver structures */
6725 for (i=0; i<*returned; i++) {
6726 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6727 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6730 out:
6731 SAFE_FREE(driver_info_1);
6733 if ( !W_ERROR_IS_OK(result) )
6734 *returned = 0;
6736 return result;
6739 /****************************************************************************
6740 Enumerates all printer drivers at level 2.
6741 ****************************************************************************/
6743 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6745 int i;
6746 int ndrivers;
6747 uint32 version;
6748 fstring *list = NULL;
6749 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6750 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6751 WERROR result = WERR_OK;
6753 *returned=0;
6755 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6756 list=NULL;
6757 ndrivers=get_ntdrivers(&list, architecture, version);
6758 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6760 if(ndrivers == -1)
6761 return WERR_NOMEM;
6763 if(ndrivers != 0) {
6764 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6765 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6766 SAFE_FREE(driver_info_2);
6767 SAFE_FREE(list);
6768 return WERR_NOMEM;
6770 else driver_info_2 = tdi2;
6773 for (i=0; i<ndrivers; i++) {
6774 WERROR status;
6776 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6777 ZERO_STRUCT(driver);
6778 status = get_a_printer_driver(&driver, 3, list[i],
6779 architecture, version);
6780 if (!W_ERROR_IS_OK(status)) {
6781 SAFE_FREE(list);
6782 return status;
6784 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6785 free_a_printer_driver(driver, 3);
6788 *returned+=ndrivers;
6789 SAFE_FREE(list);
6792 /* check the required size. */
6793 for (i=0; i<*returned; i++) {
6794 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6795 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6798 if (*needed > offered) {
6799 result = WERR_INSUFFICIENT_BUFFER;
6800 goto out;
6803 if (!rpcbuf_alloc_size(buffer, *needed)) {
6804 result = WERR_NOMEM;
6805 goto out;
6808 /* fill the buffer with the form structures */
6809 for (i=0; i<*returned; i++) {
6810 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6811 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6814 out:
6815 SAFE_FREE(driver_info_2);
6817 if ( !W_ERROR_IS_OK(result) )
6818 *returned = 0;
6820 return result;
6823 /****************************************************************************
6824 Enumerates all printer drivers at level 3.
6825 ****************************************************************************/
6827 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6829 int i;
6830 int ndrivers;
6831 uint32 version;
6832 fstring *list = NULL;
6833 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6834 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6835 WERROR result = WERR_OK;
6837 *returned=0;
6839 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6840 list=NULL;
6841 ndrivers=get_ntdrivers(&list, architecture, version);
6842 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6844 if(ndrivers == -1)
6845 return WERR_NOMEM;
6847 if(ndrivers != 0) {
6848 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6849 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6850 SAFE_FREE(driver_info_3);
6851 SAFE_FREE(list);
6852 return WERR_NOMEM;
6854 else driver_info_3 = tdi3;
6857 for (i=0; i<ndrivers; i++) {
6858 WERROR status;
6860 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6861 ZERO_STRUCT(driver);
6862 status = get_a_printer_driver(&driver, 3, list[i],
6863 architecture, version);
6864 if (!W_ERROR_IS_OK(status)) {
6865 SAFE_FREE(list);
6866 return status;
6868 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6869 free_a_printer_driver(driver, 3);
6872 *returned+=ndrivers;
6873 SAFE_FREE(list);
6876 /* check the required size. */
6877 for (i=0; i<*returned; i++) {
6878 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6879 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6882 if (*needed > offered) {
6883 result = WERR_INSUFFICIENT_BUFFER;
6884 goto out;
6887 if (!rpcbuf_alloc_size(buffer, *needed)) {
6888 result = WERR_NOMEM;
6889 goto out;
6892 /* fill the buffer with the driver structures */
6893 for (i=0; i<*returned; i++) {
6894 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6895 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6898 out:
6899 for (i=0; i<*returned; i++)
6900 SAFE_FREE(driver_info_3[i].dependentfiles);
6902 SAFE_FREE(driver_info_3);
6904 if ( !W_ERROR_IS_OK(result) )
6905 *returned = 0;
6907 return result;
6910 /****************************************************************************
6911 Enumerates all printer drivers.
6912 ****************************************************************************/
6914 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6916 uint32 level = q_u->level;
6917 RPC_BUFFER *buffer = NULL;
6918 uint32 offered = q_u->offered;
6919 uint32 *needed = &r_u->needed;
6920 uint32 *returned = &r_u->returned;
6922 fstring servername;
6923 fstring architecture;
6925 /* that's an [in out] buffer */
6927 if ( q_u->buffer ) {
6928 rpcbuf_move(q_u->buffer, &r_u->buffer);
6929 buffer = r_u->buffer;
6932 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6934 *needed = 0;
6935 *returned = 0;
6937 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6938 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6940 if ( !is_myname_or_ipaddr( servername ) )
6941 return WERR_UNKNOWN_PRINTER_DRIVER;
6943 switch (level) {
6944 case 1:
6945 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6946 case 2:
6947 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6948 case 3:
6949 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6950 default:
6951 return WERR_UNKNOWN_LEVEL;
6955 /****************************************************************************
6956 ****************************************************************************/
6958 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6960 form->flag=list->flag;
6961 init_unistr(&form->name, list->name);
6962 form->width=list->width;
6963 form->length=list->length;
6964 form->left=list->left;
6965 form->top=list->top;
6966 form->right=list->right;
6967 form->bottom=list->bottom;
6970 /****************************************************************************
6971 ****************************************************************************/
6973 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6975 uint32 level = q_u->level;
6976 RPC_BUFFER *buffer = NULL;
6977 uint32 offered = q_u->offered;
6978 uint32 *needed = &r_u->needed;
6979 uint32 *numofforms = &r_u->numofforms;
6980 uint32 numbuiltinforms;
6982 nt_forms_struct *list=NULL;
6983 nt_forms_struct *builtinlist=NULL;
6984 FORM_1 *forms_1;
6985 int buffer_size=0;
6986 int i;
6988 /* that's an [in out] buffer */
6990 if ( q_u->buffer ) {
6991 rpcbuf_move(q_u->buffer, &r_u->buffer);
6992 buffer = r_u->buffer;
6995 DEBUG(4,("_spoolss_enumforms\n"));
6996 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6997 DEBUGADD(5,("Info level [%d]\n", level));
6999 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7000 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7001 *numofforms = get_ntforms(&list);
7002 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7003 *numofforms += numbuiltinforms;
7005 if (*numofforms == 0)
7006 return WERR_NO_MORE_ITEMS;
7008 switch (level) {
7009 case 1:
7010 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7011 *numofforms=0;
7012 return WERR_NOMEM;
7015 /* construct the list of form structures */
7016 for (i=0; i<numbuiltinforms; i++) {
7017 DEBUGADD(6,("Filling form number [%d]\n",i));
7018 fill_form_1(&forms_1[i], &builtinlist[i]);
7021 SAFE_FREE(builtinlist);
7023 for (; i<*numofforms; i++) {
7024 DEBUGADD(6,("Filling form number [%d]\n",i));
7025 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7028 SAFE_FREE(list);
7030 /* check the required size. */
7031 for (i=0; i<numbuiltinforms; i++) {
7032 DEBUGADD(6,("adding form [%d]'s size\n",i));
7033 buffer_size += spoolss_size_form_1(&forms_1[i]);
7035 for (; i<*numofforms; i++) {
7036 DEBUGADD(6,("adding form [%d]'s size\n",i));
7037 buffer_size += spoolss_size_form_1(&forms_1[i]);
7040 *needed=buffer_size;
7042 if (*needed > offered) {
7043 SAFE_FREE(forms_1);
7044 *numofforms=0;
7045 return WERR_INSUFFICIENT_BUFFER;
7048 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7049 SAFE_FREE(forms_1);
7050 *numofforms=0;
7051 return WERR_NOMEM;
7054 /* fill the buffer with the form structures */
7055 for (i=0; i<numbuiltinforms; i++) {
7056 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7057 smb_io_form_1("", buffer, &forms_1[i], 0);
7059 for (; i<*numofforms; i++) {
7060 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7061 smb_io_form_1("", buffer, &forms_1[i], 0);
7064 SAFE_FREE(forms_1);
7066 return WERR_OK;
7068 default:
7069 SAFE_FREE(list);
7070 SAFE_FREE(builtinlist);
7071 return WERR_UNKNOWN_LEVEL;
7076 /****************************************************************************
7077 ****************************************************************************/
7079 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7081 uint32 level = q_u->level;
7082 UNISTR2 *uni_formname = &q_u->formname;
7083 RPC_BUFFER *buffer = NULL;
7084 uint32 offered = q_u->offered;
7085 uint32 *needed = &r_u->needed;
7087 nt_forms_struct *list=NULL;
7088 nt_forms_struct builtin_form;
7089 BOOL foundBuiltin;
7090 FORM_1 form_1;
7091 fstring form_name;
7092 int buffer_size=0;
7093 int numofforms=0, i=0;
7095 /* that's an [in out] buffer */
7097 if ( q_u->buffer ) {
7098 rpcbuf_move(q_u->buffer, &r_u->buffer);
7099 buffer = r_u->buffer;
7102 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7104 DEBUG(4,("_spoolss_getform\n"));
7105 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7106 DEBUGADD(5,("Info level [%d]\n", level));
7108 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7109 if (!foundBuiltin) {
7110 numofforms = get_ntforms(&list);
7111 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7113 if (numofforms == 0)
7114 return WERR_BADFID;
7117 switch (level) {
7118 case 1:
7119 if (foundBuiltin) {
7120 fill_form_1(&form_1, &builtin_form);
7121 } else {
7123 /* Check if the requested name is in the list of form structures */
7124 for (i=0; i<numofforms; i++) {
7126 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7128 if (strequal(form_name, list[i].name)) {
7129 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7130 fill_form_1(&form_1, &list[i]);
7131 break;
7135 SAFE_FREE(list);
7136 if (i == numofforms) {
7137 return WERR_BADFID;
7140 /* check the required size. */
7142 *needed=spoolss_size_form_1(&form_1);
7144 if (*needed > offered)
7145 return WERR_INSUFFICIENT_BUFFER;
7147 if (!rpcbuf_alloc_size(buffer, buffer_size))
7148 return WERR_NOMEM;
7150 /* fill the buffer with the form structures */
7151 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7152 smb_io_form_1("", buffer, &form_1, 0);
7154 return WERR_OK;
7156 default:
7157 SAFE_FREE(list);
7158 return WERR_UNKNOWN_LEVEL;
7162 /****************************************************************************
7163 ****************************************************************************/
7165 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7167 init_unistr(&port->port_name, name);
7170 /****************************************************************************
7171 ****************************************************************************/
7173 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7175 init_unistr(&port->port_name, name);
7176 init_unistr(&port->monitor_name, "Local Monitor");
7177 init_unistr(&port->description, "Local Port");
7178 port->port_type=PORT_TYPE_WRITE;
7179 port->reserved=0x0;
7183 /****************************************************************************
7184 wrapper around the enumer ports command
7185 ****************************************************************************/
7187 WERROR enumports_hook( int *count, char ***lines )
7189 char *cmd = lp_enumports_cmd();
7190 char **qlines;
7191 pstring command;
7192 int numlines;
7193 int ret;
7194 int fd;
7197 /* if no hook then just fill in the default port */
7199 if ( !*cmd ) {
7200 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7201 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7202 qlines[1] = NULL;
7203 numlines = 1;
7205 else {
7206 /* we have a valid enumport command */
7208 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7210 DEBUG(10,("Running [%s]\n", command));
7211 ret = smbrun(command, &fd);
7212 DEBUG(10,("Returned [%d]\n", ret));
7213 if (ret != 0) {
7214 if (fd != -1)
7215 close(fd);
7217 return WERR_ACCESS_DENIED;
7220 numlines = 0;
7221 qlines = fd_lines_load(fd, &numlines);
7222 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7223 close(fd);
7226 *count = numlines;
7227 *lines = qlines;
7229 return WERR_OK;
7232 /****************************************************************************
7233 enumports level 1.
7234 ****************************************************************************/
7236 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7238 PORT_INFO_1 *ports=NULL;
7239 int i=0;
7240 WERROR result = WERR_OK;
7241 char **qlines;
7242 int numlines;
7244 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7245 return result;
7247 if(numlines) {
7248 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7249 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7250 dos_errstr(WERR_NOMEM)));
7251 file_lines_free(qlines);
7252 return WERR_NOMEM;
7255 for (i=0; i<numlines; i++) {
7256 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7257 fill_port_1(&ports[i], qlines[i]);
7260 file_lines_free(qlines);
7263 *returned = numlines;
7265 /* check the required size. */
7266 for (i=0; i<*returned; i++) {
7267 DEBUGADD(6,("adding port [%d]'s size\n", i));
7268 *needed += spoolss_size_port_info_1(&ports[i]);
7271 if (*needed > offered) {
7272 result = WERR_INSUFFICIENT_BUFFER;
7273 goto out;
7276 if (!rpcbuf_alloc_size(buffer, *needed)) {
7277 result = WERR_NOMEM;
7278 goto out;
7281 /* fill the buffer with the ports structures */
7282 for (i=0; i<*returned; i++) {
7283 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7284 smb_io_port_1("", buffer, &ports[i], 0);
7287 out:
7288 SAFE_FREE(ports);
7290 if ( !W_ERROR_IS_OK(result) )
7291 *returned = 0;
7293 return result;
7296 /****************************************************************************
7297 enumports level 2.
7298 ****************************************************************************/
7300 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7302 PORT_INFO_2 *ports=NULL;
7303 int i=0;
7304 WERROR result = WERR_OK;
7305 char **qlines;
7306 int numlines;
7308 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7309 return result;
7312 if(numlines) {
7313 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7314 file_lines_free(qlines);
7315 return WERR_NOMEM;
7318 for (i=0; i<numlines; i++) {
7319 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7320 fill_port_2(&(ports[i]), qlines[i]);
7323 file_lines_free(qlines);
7326 *returned = numlines;
7328 /* check the required size. */
7329 for (i=0; i<*returned; i++) {
7330 DEBUGADD(6,("adding port [%d]'s size\n", i));
7331 *needed += spoolss_size_port_info_2(&ports[i]);
7334 if (*needed > offered) {
7335 result = WERR_INSUFFICIENT_BUFFER;
7336 goto out;
7339 if (!rpcbuf_alloc_size(buffer, *needed)) {
7340 result = WERR_NOMEM;
7341 goto out;
7344 /* fill the buffer with the ports structures */
7345 for (i=0; i<*returned; i++) {
7346 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7347 smb_io_port_2("", buffer, &ports[i], 0);
7350 out:
7351 SAFE_FREE(ports);
7353 if ( !W_ERROR_IS_OK(result) )
7354 *returned = 0;
7356 return result;
7359 /****************************************************************************
7360 enumports.
7361 ****************************************************************************/
7363 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7365 uint32 level = q_u->level;
7366 RPC_BUFFER *buffer = NULL;
7367 uint32 offered = q_u->offered;
7368 uint32 *needed = &r_u->needed;
7369 uint32 *returned = &r_u->returned;
7371 /* that's an [in out] buffer */
7373 if ( q_u->buffer ) {
7374 rpcbuf_move(q_u->buffer, &r_u->buffer);
7375 buffer = r_u->buffer;
7378 DEBUG(4,("_spoolss_enumports\n"));
7380 *returned=0;
7381 *needed=0;
7383 switch (level) {
7384 case 1:
7385 return enumports_level_1(buffer, offered, needed, returned);
7386 case 2:
7387 return enumports_level_2(buffer, offered, needed, returned);
7388 default:
7389 return WERR_UNKNOWN_LEVEL;
7393 /****************************************************************************
7394 ****************************************************************************/
7396 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7397 const SPOOL_PRINTER_INFO_LEVEL *info,
7398 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7399 uint32 user_switch, const SPOOL_USER_CTR *user,
7400 POLICY_HND *handle)
7402 NT_PRINTER_INFO_LEVEL *printer = NULL;
7403 fstring name;
7404 int snum;
7405 WERROR err = WERR_OK;
7407 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7408 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7409 return WERR_NOMEM;
7412 ZERO_STRUCTP(printer);
7414 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7415 if (!convert_printer_info(info, printer, 2)) {
7416 free_a_printer(&printer, 2);
7417 return WERR_NOMEM;
7420 /* check to see if the printer already exists */
7422 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7423 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7424 printer->info_2->sharename));
7425 free_a_printer(&printer, 2);
7426 return WERR_PRINTER_ALREADY_EXISTS;
7429 /* FIXME!!! smbd should check to see if the driver is installed before
7430 trying to add a printer like this --jerry */
7432 if (*lp_addprinter_cmd() ) {
7433 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7434 free_a_printer(&printer,2);
7435 return WERR_ACCESS_DENIED;
7437 } else {
7438 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7439 "smb.conf parameter \"addprinter command\" is defined. This"
7440 "parameter must exist for this call to succeed\n",
7441 printer->info_2->sharename ));
7444 /* use our primary netbios name since get_a_printer() will convert
7445 it to what the client expects on a case by case basis */
7447 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7448 printer->info_2->sharename);
7451 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7452 free_a_printer(&printer,2);
7453 return WERR_ACCESS_DENIED;
7456 /* you must be a printer admin to add a new printer */
7457 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7458 free_a_printer(&printer,2);
7459 return WERR_ACCESS_DENIED;
7463 * Do sanity check on the requested changes for Samba.
7466 if (!check_printer_ok(printer->info_2, snum)) {
7467 free_a_printer(&printer,2);
7468 return WERR_INVALID_PARAM;
7472 * When a printer is created, the drivername bound to the printer is used
7473 * to lookup previously saved driver initialization info, which is then
7474 * bound to the new printer, simulating what happens in the Windows arch.
7477 if (!devmode)
7479 set_driver_init(printer, 2);
7481 else
7483 /* A valid devmode was included, convert and link it
7485 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7487 if (!convert_devicemode(printer->info_2->printername, devmode,
7488 &printer->info_2->devmode))
7489 return WERR_NOMEM;
7492 /* write the ASCII on disk */
7493 err = mod_a_printer(printer, 2);
7494 if (!W_ERROR_IS_OK(err)) {
7495 free_a_printer(&printer,2);
7496 return err;
7499 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7500 /* Handle open failed - remove addition. */
7501 del_a_printer(printer->info_2->sharename);
7502 free_a_printer(&printer,2);
7503 return WERR_ACCESS_DENIED;
7506 update_c_setprinter(False);
7507 free_a_printer(&printer,2);
7509 return WERR_OK;
7512 /****************************************************************************
7513 ****************************************************************************/
7515 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7517 UNISTR2 *uni_srv_name = q_u->server_name;
7518 uint32 level = q_u->level;
7519 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7520 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7521 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7522 uint32 user_switch = q_u->user_switch;
7523 SPOOL_USER_CTR *user = &q_u->user_ctr;
7524 POLICY_HND *handle = &r_u->handle;
7526 switch (level) {
7527 case 1:
7528 /* we don't handle yet */
7529 /* but I know what to do ... */
7530 return WERR_UNKNOWN_LEVEL;
7531 case 2:
7532 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7533 devmode, sdb,
7534 user_switch, user, handle);
7535 default:
7536 return WERR_UNKNOWN_LEVEL;
7540 /****************************************************************************
7541 ****************************************************************************/
7543 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7545 uint32 level = q_u->level;
7546 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7547 WERROR err = WERR_OK;
7548 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7549 struct current_user user;
7550 fstring driver_name;
7551 uint32 version;
7553 ZERO_STRUCT(driver);
7555 get_current_user(&user, p);
7557 if (!convert_printer_driver_info(info, &driver, level)) {
7558 err = WERR_NOMEM;
7559 goto done;
7562 DEBUG(5,("Cleaning driver's information\n"));
7563 err = clean_up_driver_struct(driver, level, &user);
7564 if (!W_ERROR_IS_OK(err))
7565 goto done;
7567 DEBUG(5,("Moving driver to final destination\n"));
7568 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7569 goto done;
7572 if (add_a_printer_driver(driver, level)!=0) {
7573 err = WERR_ACCESS_DENIED;
7574 goto done;
7577 /* BEGIN_ADMIN_LOG */
7578 switch(level) {
7579 case 3:
7580 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7581 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7582 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7583 break;
7584 case 6:
7585 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7586 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7587 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7588 break;
7590 /* END_ADMIN_LOG */
7593 * I think this is where he DrvUpgradePrinter() hook would be
7594 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7595 * server. Right now, we just need to send ourselves a message
7596 * to update each printer bound to this driver. --jerry
7599 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7600 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7601 driver_name));
7605 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7606 * decide if the driver init data should be deleted. The rules are:
7607 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7608 * 2) delete init data only if there is no 2k/Xp driver
7609 * 3) always delete init data
7610 * The generalized rule is always use init data from the highest order driver.
7611 * It is necessary to follow the driver install by an initialization step to
7612 * finish off this process.
7614 if (level == 3)
7615 version = driver.info_3->cversion;
7616 else if (level == 6)
7617 version = driver.info_6->version;
7618 else
7619 version = -1;
7620 switch (version) {
7622 * 9x printer driver - never delete init data
7624 case 0:
7625 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7626 driver_name));
7627 break;
7630 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7631 * there is no 2k/Xp driver init data for this driver name.
7633 case 2:
7635 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7637 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7639 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7641 if (!del_driver_init(driver_name))
7642 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7643 } else {
7645 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7647 free_a_printer_driver(driver1,3);
7648 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7649 driver_name));
7652 break;
7655 * 2k or Xp printer driver - always delete init data
7657 case 3:
7658 if (!del_driver_init(driver_name))
7659 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7660 break;
7662 default:
7663 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7664 break;
7668 done:
7669 free_a_printer_driver(driver, level);
7670 return err;
7673 /********************************************************************
7674 * spoolss_addprinterdriverex
7675 ********************************************************************/
7677 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7679 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7680 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7683 * we only support the semantics of AddPrinterDriver()
7684 * i.e. only copy files that are newer than existing ones
7687 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7688 return WERR_ACCESS_DENIED;
7690 ZERO_STRUCT(q_u_local);
7691 ZERO_STRUCT(r_u_local);
7693 /* just pass the information off to _spoolss_addprinterdriver() */
7694 q_u_local.server_name_ptr = q_u->server_name_ptr;
7695 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7696 q_u_local.level = q_u->level;
7697 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7699 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7702 /****************************************************************************
7703 ****************************************************************************/
7705 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7707 init_unistr(&info->name, name);
7710 /****************************************************************************
7711 ****************************************************************************/
7713 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7715 pstring path;
7716 pstring long_archi;
7717 fstring servername;
7718 char *pservername;
7719 const char *short_archi;
7720 DRIVER_DIRECTORY_1 *info=NULL;
7721 WERROR result = WERR_OK;
7723 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7724 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7726 /* check for beginning double '\'s and that the server
7727 long enough */
7729 pservername = servername;
7730 if ( *pservername == '\\' && strlen(servername)>2 ) {
7731 pservername += 2;
7734 if ( !is_myname_or_ipaddr( pservername ) )
7735 return WERR_INVALID_PARAM;
7737 if (!(short_archi = get_short_archi(long_archi)))
7738 return WERR_INVALID_ENVIRONMENT;
7740 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7741 return WERR_NOMEM;
7743 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7745 DEBUG(4,("printer driver directory: [%s]\n", path));
7747 fill_driverdir_1(info, path);
7749 *needed += spoolss_size_driverdir_info_1(info);
7751 if (*needed > offered) {
7752 result = WERR_INSUFFICIENT_BUFFER;
7753 goto out;
7756 if (!rpcbuf_alloc_size(buffer, *needed)) {
7757 result = WERR_NOMEM;
7758 goto out;
7761 smb_io_driverdir_1("", buffer, info, 0);
7763 out:
7764 SAFE_FREE(info);
7766 return result;
7769 /****************************************************************************
7770 ****************************************************************************/
7772 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7774 UNISTR2 *name = &q_u->name;
7775 UNISTR2 *uni_environment = &q_u->environment;
7776 uint32 level = q_u->level;
7777 RPC_BUFFER *buffer = NULL;
7778 uint32 offered = q_u->offered;
7779 uint32 *needed = &r_u->needed;
7781 /* that's an [in out] buffer */
7783 if ( q_u->buffer ) {
7784 rpcbuf_move(q_u->buffer, &r_u->buffer);
7785 buffer = r_u->buffer;
7788 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7790 *needed=0;
7792 switch(level) {
7793 case 1:
7794 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7795 default:
7796 return WERR_UNKNOWN_LEVEL;
7800 /****************************************************************************
7801 ****************************************************************************/
7803 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7805 POLICY_HND *handle = &q_u->handle;
7806 uint32 idx = q_u->index;
7807 uint32 in_value_len = q_u->valuesize;
7808 uint32 in_data_len = q_u->datasize;
7809 uint32 *out_max_value_len = &r_u->valuesize;
7810 uint16 **out_value = &r_u->value;
7811 uint32 *out_value_len = &r_u->realvaluesize;
7812 uint32 *out_type = &r_u->type;
7813 uint32 *out_max_data_len = &r_u->datasize;
7814 uint8 **data_out = &r_u->data;
7815 uint32 *out_data_len = &r_u->realdatasize;
7817 NT_PRINTER_INFO_LEVEL *printer = NULL;
7819 uint32 biggest_valuesize;
7820 uint32 biggest_datasize;
7821 uint32 data_len;
7822 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7823 int snum;
7824 WERROR result;
7825 REGISTRY_VALUE *val = NULL;
7826 NT_PRINTER_DATA *p_data;
7827 int i, key_index, num_values;
7828 int name_length;
7830 *out_type = 0;
7832 *out_max_data_len = 0;
7833 *data_out = NULL;
7834 *out_data_len = 0;
7836 DEBUG(5,("spoolss_enumprinterdata\n"));
7838 if (!Printer) {
7839 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7840 return WERR_BADFID;
7843 if (!get_printer_snum(p,handle, &snum))
7844 return WERR_BADFID;
7846 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7847 if (!W_ERROR_IS_OK(result))
7848 return result;
7850 p_data = printer->info_2->data;
7851 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7853 result = WERR_OK;
7856 * The NT machine wants to know the biggest size of value and data
7858 * cf: MSDN EnumPrinterData remark section
7861 if ( !in_value_len && !in_data_len && (key_index != -1) )
7863 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7865 biggest_valuesize = 0;
7866 biggest_datasize = 0;
7868 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7870 for ( i=0; i<num_values; i++ )
7872 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7874 name_length = strlen(val->valuename);
7875 if ( strlen(val->valuename) > biggest_valuesize )
7876 biggest_valuesize = name_length;
7878 if ( val->size > biggest_datasize )
7879 biggest_datasize = val->size;
7881 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7882 biggest_datasize));
7885 /* the value is an UNICODE string but real_value_size is the length
7886 in bytes including the trailing 0 */
7888 *out_value_len = 2 * (1+biggest_valuesize);
7889 *out_data_len = biggest_datasize;
7891 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7893 goto done;
7897 * the value len is wrong in NT sp3
7898 * that's the number of bytes not the number of unicode chars
7901 if ( key_index != -1 )
7902 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7904 if ( !val )
7907 /* out_value should default to "" or else NT4 has
7908 problems unmarshalling the response */
7910 *out_max_value_len=(in_value_len/sizeof(uint16));
7912 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7914 result = WERR_NOMEM;
7915 goto done;
7918 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7920 /* the data is counted in bytes */
7922 *out_max_data_len = in_data_len;
7923 *out_data_len = in_data_len;
7925 /* only allocate when given a non-zero data_len */
7927 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7929 result = WERR_NOMEM;
7930 goto done;
7933 result = WERR_NO_MORE_ITEMS;
7935 else
7938 * the value is:
7939 * - counted in bytes in the request
7940 * - counted in UNICODE chars in the max reply
7941 * - counted in bytes in the real size
7943 * take a pause *before* coding not *during* coding
7946 /* name */
7947 *out_max_value_len=(in_value_len/sizeof(uint16));
7948 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7950 result = WERR_NOMEM;
7951 goto done;
7954 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7956 /* type */
7958 *out_type = regval_type( val );
7960 /* data - counted in bytes */
7962 *out_max_data_len = in_data_len;
7963 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7965 result = WERR_NOMEM;
7966 goto done;
7968 data_len = regval_size(val);
7969 if ( *data_out )
7970 memcpy( *data_out, regval_data_p(val), data_len );
7971 *out_data_len = data_len;
7974 done:
7975 free_a_printer(&printer, 2);
7976 return result;
7979 /****************************************************************************
7980 ****************************************************************************/
7982 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7984 POLICY_HND *handle = &q_u->handle;
7985 UNISTR2 *value = &q_u->value;
7986 uint32 type = q_u->type;
7987 uint8 *data = q_u->data;
7988 uint32 real_len = q_u->real_len;
7990 NT_PRINTER_INFO_LEVEL *printer = NULL;
7991 int snum=0;
7992 WERROR status = WERR_OK;
7993 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7994 fstring valuename;
7996 DEBUG(5,("spoolss_setprinterdata\n"));
7998 if (!Printer) {
7999 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8000 return WERR_BADFID;
8003 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8004 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8005 return WERR_INVALID_PARAM;
8008 if (!get_printer_snum(p,handle, &snum))
8009 return WERR_BADFID;
8012 * Access check : NT returns "access denied" if you make a
8013 * SetPrinterData call without the necessary privildge.
8014 * we were originally returning OK if nothing changed
8015 * which made Win2k issue **a lot** of SetPrinterData
8016 * when connecting to a printer --jerry
8019 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8021 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8022 status = WERR_ACCESS_DENIED;
8023 goto done;
8026 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8027 if (!W_ERROR_IS_OK(status))
8028 return status;
8030 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8033 * When client side code sets a magic printer data key, detect it and save
8034 * the current printer data and the magic key's data (its the DEVMODE) for
8035 * future printer/driver initializations.
8037 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8039 /* Set devmode and printer initialization info */
8040 status = save_driver_init( printer, 2, data, real_len );
8042 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8044 else
8046 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8047 type, data, real_len );
8048 if ( W_ERROR_IS_OK(status) )
8049 status = mod_a_printer(printer, 2);
8052 done:
8053 free_a_printer(&printer, 2);
8055 return status;
8058 /****************************************************************************
8059 ****************************************************************************/
8061 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8063 POLICY_HND *handle = &q_u->handle;
8064 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8065 int snum;
8067 DEBUG(5,("_spoolss_resetprinter\n"));
8070 * All we do is to check to see if the handle and queue is valid.
8071 * This call really doesn't mean anything to us because we only
8072 * support RAW printing. --jerry
8075 if (!Printer) {
8076 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8077 return WERR_BADFID;
8080 if (!get_printer_snum(p,handle, &snum))
8081 return WERR_BADFID;
8084 /* blindly return success */
8085 return WERR_OK;
8089 /****************************************************************************
8090 ****************************************************************************/
8092 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8094 POLICY_HND *handle = &q_u->handle;
8095 UNISTR2 *value = &q_u->valuename;
8097 NT_PRINTER_INFO_LEVEL *printer = NULL;
8098 int snum=0;
8099 WERROR status = WERR_OK;
8100 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8101 pstring valuename;
8103 DEBUG(5,("spoolss_deleteprinterdata\n"));
8105 if (!Printer) {
8106 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8107 return WERR_BADFID;
8110 if (!get_printer_snum(p, handle, &snum))
8111 return WERR_BADFID;
8113 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8114 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8115 return WERR_ACCESS_DENIED;
8118 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8119 if (!W_ERROR_IS_OK(status))
8120 return status;
8122 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8124 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8126 if ( W_ERROR_IS_OK(status) )
8127 mod_a_printer( printer, 2 );
8129 free_a_printer(&printer, 2);
8131 return status;
8134 /****************************************************************************
8135 ****************************************************************************/
8137 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8139 POLICY_HND *handle = &q_u->handle;
8140 FORM *form = &q_u->form;
8141 nt_forms_struct tmpForm;
8142 int snum;
8143 WERROR status = WERR_OK;
8144 NT_PRINTER_INFO_LEVEL *printer = NULL;
8146 int count=0;
8147 nt_forms_struct *list=NULL;
8148 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8150 DEBUG(5,("spoolss_addform\n"));
8152 if (!Printer) {
8153 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8154 return WERR_BADFID;
8158 /* forms can be added 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_addform: denied by handle permissions.\n"));
8172 status = WERR_ACCESS_DENIED;
8173 goto done;
8176 /* can't add if builtin */
8178 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8179 status = WERR_ALREADY_EXISTS;
8180 goto done;
8183 count = get_ntforms(&list);
8185 if(!add_a_form(&list, form, &count)) {
8186 status = WERR_NOMEM;
8187 goto done;
8190 write_ntforms(&list, count);
8193 * ChangeID must always be set if this is a printer
8196 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8197 status = mod_a_printer(printer, 2);
8199 done:
8200 if ( printer )
8201 free_a_printer(&printer, 2);
8202 SAFE_FREE(list);
8204 return status;
8207 /****************************************************************************
8208 ****************************************************************************/
8210 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8212 POLICY_HND *handle = &q_u->handle;
8213 UNISTR2 *form_name = &q_u->name;
8214 nt_forms_struct tmpForm;
8215 int count=0;
8216 nt_forms_struct *list=NULL;
8217 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8218 int snum;
8219 WERROR status = WERR_OK;
8220 NT_PRINTER_INFO_LEVEL *printer = NULL;
8222 DEBUG(5,("spoolss_deleteform\n"));
8224 if (!Printer) {
8225 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8226 return WERR_BADFID;
8229 /* forms can be deleted on printer of on the print server handle */
8231 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8233 if (!get_printer_snum(p,handle, &snum))
8234 return WERR_BADFID;
8236 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8237 if (!W_ERROR_IS_OK(status))
8238 goto done;
8241 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8242 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8243 status = WERR_ACCESS_DENIED;
8244 goto done;
8247 /* can't delete if builtin */
8249 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8250 status = WERR_INVALID_PARAM;
8251 goto done;
8254 count = get_ntforms(&list);
8256 if ( !delete_a_form(&list, form_name, &count, &status ))
8257 goto done;
8260 * ChangeID must always be set if this is a printer
8263 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8264 status = mod_a_printer(printer, 2);
8266 done:
8267 if ( printer )
8268 free_a_printer(&printer, 2);
8269 SAFE_FREE(list);
8271 return status;
8274 /****************************************************************************
8275 ****************************************************************************/
8277 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8279 POLICY_HND *handle = &q_u->handle;
8280 FORM *form = &q_u->form;
8281 nt_forms_struct tmpForm;
8282 int snum;
8283 WERROR status = WERR_OK;
8284 NT_PRINTER_INFO_LEVEL *printer = NULL;
8286 int count=0;
8287 nt_forms_struct *list=NULL;
8288 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8290 DEBUG(5,("spoolss_setform\n"));
8292 if (!Printer) {
8293 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8294 return WERR_BADFID;
8297 /* forms can be modified on printer of on the print server handle */
8299 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8301 if (!get_printer_snum(p,handle, &snum))
8302 return WERR_BADFID;
8304 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8305 if (!W_ERROR_IS_OK(status))
8306 goto done;
8309 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8310 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8311 status = WERR_ACCESS_DENIED;
8312 goto done;
8315 /* can't set if builtin */
8316 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8317 status = WERR_INVALID_PARAM;
8318 goto done;
8321 count = get_ntforms(&list);
8322 update_a_form(&list, form, count);
8323 write_ntforms(&list, count);
8326 * ChangeID must always be set if this is a printer
8329 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8330 status = mod_a_printer(printer, 2);
8333 done:
8334 if ( printer )
8335 free_a_printer(&printer, 2);
8336 SAFE_FREE(list);
8338 return status;
8341 /****************************************************************************
8342 enumprintprocessors level 1.
8343 ****************************************************************************/
8345 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8347 PRINTPROCESSOR_1 *info_1=NULL;
8348 WERROR result = WERR_OK;
8350 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8351 return WERR_NOMEM;
8353 (*returned) = 0x1;
8355 init_unistr(&info_1->name, "winprint");
8357 *needed += spoolss_size_printprocessor_info_1(info_1);
8359 if (*needed > offered) {
8360 result = WERR_INSUFFICIENT_BUFFER;
8361 goto out;
8364 if (!rpcbuf_alloc_size(buffer, *needed)) {
8365 result = WERR_NOMEM;
8366 goto out;
8369 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8371 out:
8372 SAFE_FREE(info_1);
8374 if ( !W_ERROR_IS_OK(result) )
8375 *returned = 0;
8377 return result;
8380 /****************************************************************************
8381 ****************************************************************************/
8383 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8385 uint32 level = q_u->level;
8386 RPC_BUFFER *buffer = NULL;
8387 uint32 offered = q_u->offered;
8388 uint32 *needed = &r_u->needed;
8389 uint32 *returned = &r_u->returned;
8391 /* that's an [in out] buffer */
8393 if ( q_u->buffer ) {
8394 rpcbuf_move(q_u->buffer, &r_u->buffer);
8395 buffer = r_u->buffer;
8398 DEBUG(5,("spoolss_enumprintprocessors\n"));
8401 * Enumerate the print processors ...
8403 * Just reply with "winprint", to keep NT happy
8404 * and I can use my nice printer checker.
8407 *returned=0;
8408 *needed=0;
8410 switch (level) {
8411 case 1:
8412 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8413 default:
8414 return WERR_UNKNOWN_LEVEL;
8418 /****************************************************************************
8419 enumprintprocdatatypes level 1.
8420 ****************************************************************************/
8422 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8424 PRINTPROCDATATYPE_1 *info_1=NULL;
8425 WERROR result = WERR_NOMEM;
8427 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8428 return WERR_NOMEM;
8430 (*returned) = 0x1;
8432 init_unistr(&info_1->name, "RAW");
8434 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8436 if (*needed > offered) {
8437 result = WERR_INSUFFICIENT_BUFFER;
8438 goto out;
8441 if (!rpcbuf_alloc_size(buffer, *needed)) {
8442 result = WERR_NOMEM;
8443 goto out;
8446 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8448 out:
8449 SAFE_FREE(info_1);
8451 if ( !W_ERROR_IS_OK(result) )
8452 *returned = 0;
8454 return result;
8457 /****************************************************************************
8458 ****************************************************************************/
8460 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8462 uint32 level = q_u->level;
8463 RPC_BUFFER *buffer = NULL;
8464 uint32 offered = q_u->offered;
8465 uint32 *needed = &r_u->needed;
8466 uint32 *returned = &r_u->returned;
8468 /* that's an [in out] buffer */
8470 if ( q_u->buffer ) {
8471 rpcbuf_move(q_u->buffer, &r_u->buffer);
8472 buffer = r_u->buffer;
8475 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8477 *returned=0;
8478 *needed=0;
8480 switch (level) {
8481 case 1:
8482 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8483 default:
8484 return WERR_UNKNOWN_LEVEL;
8488 /****************************************************************************
8489 enumprintmonitors level 1.
8490 ****************************************************************************/
8492 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8494 PRINTMONITOR_1 *info_1=NULL;
8495 WERROR result = WERR_OK;
8497 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8498 return WERR_NOMEM;
8500 (*returned) = 0x1;
8502 init_unistr(&info_1->name, "Local Port");
8504 *needed += spoolss_size_printmonitor_info_1(info_1);
8506 if (*needed > offered) {
8507 result = WERR_INSUFFICIENT_BUFFER;
8508 goto out;
8511 if (!rpcbuf_alloc_size(buffer, *needed)) {
8512 result = WERR_NOMEM;
8513 goto out;
8516 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8518 out:
8519 SAFE_FREE(info_1);
8521 if ( !W_ERROR_IS_OK(result) )
8522 *returned = 0;
8524 return result;
8527 /****************************************************************************
8528 enumprintmonitors level 2.
8529 ****************************************************************************/
8531 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8533 PRINTMONITOR_2 *info_2=NULL;
8534 WERROR result = WERR_OK;
8536 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8537 return WERR_NOMEM;
8539 (*returned) = 0x1;
8541 init_unistr(&info_2->name, "Local Port");
8542 init_unistr(&info_2->environment, "Windows NT X86");
8543 init_unistr(&info_2->dll_name, "localmon.dll");
8545 *needed += spoolss_size_printmonitor_info_2(info_2);
8547 if (*needed > offered) {
8548 result = WERR_INSUFFICIENT_BUFFER;
8549 goto out;
8552 if (!rpcbuf_alloc_size(buffer, *needed)) {
8553 result = WERR_NOMEM;
8554 goto out;
8557 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8559 out:
8560 SAFE_FREE(info_2);
8562 if ( !W_ERROR_IS_OK(result) )
8563 *returned = 0;
8565 return result;
8568 /****************************************************************************
8569 ****************************************************************************/
8571 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8573 uint32 level = q_u->level;
8574 RPC_BUFFER *buffer = NULL;
8575 uint32 offered = q_u->offered;
8576 uint32 *needed = &r_u->needed;
8577 uint32 *returned = &r_u->returned;
8579 /* that's an [in out] buffer */
8581 if ( q_u->buffer ) {
8582 rpcbuf_move(q_u->buffer, &r_u->buffer);
8583 buffer = r_u->buffer;
8586 DEBUG(5,("spoolss_enumprintmonitors\n"));
8589 * Enumerate the print monitors ...
8591 * Just reply with "Local Port", to keep NT happy
8592 * and I can use my nice printer checker.
8595 *returned=0;
8596 *needed=0;
8598 switch (level) {
8599 case 1:
8600 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8601 case 2:
8602 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8603 default:
8604 return WERR_UNKNOWN_LEVEL;
8608 /****************************************************************************
8609 ****************************************************************************/
8611 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8612 NT_PRINTER_INFO_LEVEL *ntprinter,
8613 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8614 uint32 *needed)
8616 int i=0;
8617 BOOL found=False;
8618 JOB_INFO_1 *info_1=NULL;
8619 WERROR result = WERR_OK;
8621 info_1=SMB_MALLOC_P(JOB_INFO_1);
8623 if (info_1 == NULL) {
8624 return WERR_NOMEM;
8627 for (i=0; i<count && found==False; i++) {
8628 if ((*queue)[i].job==(int)jobid)
8629 found=True;
8632 if (found==False) {
8633 SAFE_FREE(info_1);
8634 /* NT treats not found as bad param... yet another bad choice */
8635 return WERR_INVALID_PARAM;
8638 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8640 *needed += spoolss_size_job_info_1(info_1);
8642 if (*needed > offered) {
8643 result = WERR_INSUFFICIENT_BUFFER;
8644 goto out;
8647 if (!rpcbuf_alloc_size(buffer, *needed)) {
8648 result = WERR_NOMEM;
8649 goto out;
8652 smb_io_job_info_1("", buffer, info_1, 0);
8654 out:
8655 SAFE_FREE(info_1);
8657 return result;
8660 /****************************************************************************
8661 ****************************************************************************/
8663 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8664 NT_PRINTER_INFO_LEVEL *ntprinter,
8665 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8666 uint32 *needed)
8668 int i = 0;
8669 BOOL found = False;
8670 JOB_INFO_2 *info_2;
8671 WERROR result;
8672 DEVICEMODE *devmode = NULL;
8673 NT_DEVICEMODE *nt_devmode = NULL;
8675 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8676 return WERR_NOMEM;
8678 ZERO_STRUCTP(info_2);
8680 for ( i=0; i<count && found==False; i++ )
8682 if ((*queue)[i].job == (int)jobid)
8683 found = True;
8686 if ( !found ) {
8687 /* NT treats not found as bad param... yet another bad
8688 choice */
8689 result = WERR_INVALID_PARAM;
8690 goto done;
8694 * if the print job does not have a DEVMODE associated with it,
8695 * just use the one for the printer. A NULL devicemode is not
8696 * a failure condition
8699 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8700 devmode = construct_dev_mode(snum);
8701 else {
8702 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8703 ZERO_STRUCTP( devmode );
8704 convert_nt_devicemode( devmode, nt_devmode );
8708 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8710 *needed += spoolss_size_job_info_2(info_2);
8712 if (*needed > offered) {
8713 result = WERR_INSUFFICIENT_BUFFER;
8714 goto done;
8717 if (!rpcbuf_alloc_size(buffer, *needed)) {
8718 result = WERR_NOMEM;
8719 goto done;
8722 smb_io_job_info_2("", buffer, info_2, 0);
8724 result = WERR_OK;
8726 done:
8727 /* Cleanup allocated memory */
8729 free_job_info_2(info_2); /* Also frees devmode */
8730 SAFE_FREE(info_2);
8732 return result;
8735 /****************************************************************************
8736 ****************************************************************************/
8738 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8740 POLICY_HND *handle = &q_u->handle;
8741 uint32 jobid = q_u->jobid;
8742 uint32 level = q_u->level;
8743 RPC_BUFFER *buffer = NULL;
8744 uint32 offered = q_u->offered;
8745 uint32 *needed = &r_u->needed;
8746 WERROR wstatus = WERR_OK;
8747 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8748 int snum;
8749 int count;
8750 print_queue_struct *queue = NULL;
8751 print_status_struct prt_status;
8753 /* that's an [in out] buffer */
8755 if ( q_u->buffer ) {
8756 rpcbuf_move(q_u->buffer, &r_u->buffer);
8757 buffer = r_u->buffer;
8760 DEBUG(5,("spoolss_getjob\n"));
8762 *needed = 0;
8764 if (!get_printer_snum(p, handle, &snum))
8765 return WERR_BADFID;
8767 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8768 if ( !W_ERROR_IS_OK(wstatus) )
8769 return wstatus;
8771 count = print_queue_status(snum, &queue, &prt_status);
8773 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8774 count, prt_status.status, prt_status.message));
8776 switch ( level ) {
8777 case 1:
8778 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8779 buffer, offered, needed);
8780 break;
8781 case 2:
8782 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8783 buffer, offered, needed);
8784 break;
8785 default:
8786 wstatus = WERR_UNKNOWN_LEVEL;
8787 break;
8790 SAFE_FREE(queue);
8791 free_a_printer( &ntprinter, 2 );
8793 return wstatus;
8796 /********************************************************************
8797 spoolss_getprinterdataex
8799 From MSDN documentation of GetPrinterDataEx: pass request
8800 to GetPrinterData if key is "PrinterDriverData".
8801 ********************************************************************/
8803 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8805 POLICY_HND *handle = &q_u->handle;
8806 uint32 in_size = q_u->size;
8807 uint32 *type = &r_u->type;
8808 uint32 *out_size = &r_u->size;
8809 uint8 **data = &r_u->data;
8810 uint32 *needed = &r_u->needed;
8811 fstring keyname, valuename;
8813 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8815 NT_PRINTER_INFO_LEVEL *printer = NULL;
8816 int snum = 0;
8817 WERROR status = WERR_OK;
8819 DEBUG(4,("_spoolss_getprinterdataex\n"));
8821 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8822 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8824 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8825 keyname, valuename));
8827 /* in case of problem, return some default values */
8829 *needed = 0;
8830 *type = 0;
8831 *out_size = in_size;
8833 if (!Printer) {
8834 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8835 status = WERR_BADFID;
8836 goto done;
8839 /* Is the handle to a printer or to the server? */
8841 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8842 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8843 status = WERR_INVALID_PARAM;
8844 goto done;
8847 if ( !get_printer_snum(p,handle, &snum) )
8848 return WERR_BADFID;
8850 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8851 if ( !W_ERROR_IS_OK(status) )
8852 goto done;
8854 /* check to see if the keyname is valid */
8855 if ( !strlen(keyname) ) {
8856 status = WERR_INVALID_PARAM;
8857 goto done;
8860 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8861 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8862 free_a_printer( &printer, 2 );
8863 status = WERR_BADFILE;
8864 goto done;
8867 /* When given a new keyname, we should just create it */
8869 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8871 if (*needed > *out_size)
8872 status = WERR_MORE_DATA;
8874 done:
8875 if ( !W_ERROR_IS_OK(status) )
8877 DEBUG(5, ("error: allocating %d\n", *out_size));
8879 /* reply this param doesn't exist */
8881 if ( *out_size )
8883 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8884 status = WERR_NOMEM;
8885 goto done;
8888 else {
8889 *data = NULL;
8893 if ( printer )
8894 free_a_printer( &printer, 2 );
8896 return status;
8899 /********************************************************************
8900 * spoolss_setprinterdataex
8901 ********************************************************************/
8903 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8905 POLICY_HND *handle = &q_u->handle;
8906 uint32 type = q_u->type;
8907 uint8 *data = q_u->data;
8908 uint32 real_len = q_u->real_len;
8910 NT_PRINTER_INFO_LEVEL *printer = NULL;
8911 int snum = 0;
8912 WERROR status = WERR_OK;
8913 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8914 fstring valuename;
8915 fstring keyname;
8916 char *oid_string;
8918 DEBUG(4,("_spoolss_setprinterdataex\n"));
8920 /* From MSDN documentation of SetPrinterDataEx: pass request to
8921 SetPrinterData if key is "PrinterDriverData" */
8923 if (!Printer) {
8924 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8925 return WERR_BADFID;
8928 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8929 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8930 return WERR_INVALID_PARAM;
8933 if ( !get_printer_snum(p,handle, &snum) )
8934 return WERR_BADFID;
8937 * Access check : NT returns "access denied" if you make a
8938 * SetPrinterData call without the necessary privildge.
8939 * we were originally returning OK if nothing changed
8940 * which made Win2k issue **a lot** of SetPrinterData
8941 * when connecting to a printer --jerry
8944 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8946 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8947 return WERR_ACCESS_DENIED;
8950 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8951 if (!W_ERROR_IS_OK(status))
8952 return status;
8954 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8955 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8957 /* check for OID in valuename */
8959 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8961 *oid_string = '\0';
8962 oid_string++;
8965 /* save the registry data */
8967 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8969 if ( W_ERROR_IS_OK(status) )
8971 /* save the OID if one was specified */
8972 if ( oid_string ) {
8973 fstrcat( keyname, "\\" );
8974 fstrcat( keyname, SPOOL_OID_KEY );
8977 * I'm not checking the status here on purpose. Don't know
8978 * if this is right, but I'm returning the status from the
8979 * previous set_printer_dataex() call. I have no idea if
8980 * this is right. --jerry
8983 set_printer_dataex( printer, keyname, valuename,
8984 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8987 status = mod_a_printer(printer, 2);
8990 free_a_printer(&printer, 2);
8992 return status;
8996 /********************************************************************
8997 * spoolss_deleteprinterdataex
8998 ********************************************************************/
9000 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9002 POLICY_HND *handle = &q_u->handle;
9003 UNISTR2 *value = &q_u->valuename;
9004 UNISTR2 *key = &q_u->keyname;
9006 NT_PRINTER_INFO_LEVEL *printer = NULL;
9007 int snum=0;
9008 WERROR status = WERR_OK;
9009 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9010 pstring valuename, keyname;
9012 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9014 if (!Printer) {
9015 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9016 return WERR_BADFID;
9019 if (!get_printer_snum(p, handle, &snum))
9020 return WERR_BADFID;
9022 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9023 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9024 return WERR_ACCESS_DENIED;
9027 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9028 if (!W_ERROR_IS_OK(status))
9029 return status;
9031 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9032 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9034 status = delete_printer_dataex( printer, keyname, valuename );
9036 if ( W_ERROR_IS_OK(status) )
9037 mod_a_printer( printer, 2 );
9039 free_a_printer(&printer, 2);
9041 return status;
9044 /********************************************************************
9045 * spoolss_enumprinterkey
9046 ********************************************************************/
9049 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9051 fstring key;
9052 fstring *keynames = NULL;
9053 uint16 *enumkeys = NULL;
9054 int num_keys;
9055 int printerkey_len;
9056 POLICY_HND *handle = &q_u->handle;
9057 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9058 NT_PRINTER_DATA *data;
9059 NT_PRINTER_INFO_LEVEL *printer = NULL;
9060 int snum = 0;
9061 WERROR status = WERR_BADFILE;
9064 DEBUG(4,("_spoolss_enumprinterkey\n"));
9066 if (!Printer) {
9067 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9068 return WERR_BADFID;
9071 if ( !get_printer_snum(p,handle, &snum) )
9072 return WERR_BADFID;
9074 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9075 if (!W_ERROR_IS_OK(status))
9076 return status;
9078 /* get the list of subkey names */
9080 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9081 data = printer->info_2->data;
9083 num_keys = get_printer_subkeys( data, key, &keynames );
9085 if ( num_keys == -1 ) {
9086 status = WERR_BADFILE;
9087 goto done;
9090 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9092 r_u->needed = printerkey_len*2;
9094 if ( q_u->size < r_u->needed ) {
9095 status = WERR_MORE_DATA;
9096 goto done;
9099 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9100 status = WERR_NOMEM;
9101 goto done;
9104 status = WERR_OK;
9106 if ( q_u->size < r_u->needed )
9107 status = WERR_MORE_DATA;
9109 done:
9110 free_a_printer( &printer, 2 );
9111 SAFE_FREE( keynames );
9113 return status;
9116 /********************************************************************
9117 * spoolss_deleteprinterkey
9118 ********************************************************************/
9120 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9122 POLICY_HND *handle = &q_u->handle;
9123 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9124 fstring key;
9125 NT_PRINTER_INFO_LEVEL *printer = NULL;
9126 int snum=0;
9127 WERROR status;
9129 DEBUG(5,("spoolss_deleteprinterkey\n"));
9131 if (!Printer) {
9132 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9133 return WERR_BADFID;
9136 /* if keyname == NULL, return error */
9138 if ( !q_u->keyname.buffer )
9139 return WERR_INVALID_PARAM;
9141 if (!get_printer_snum(p, handle, &snum))
9142 return WERR_BADFID;
9144 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9145 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9146 return WERR_ACCESS_DENIED;
9149 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9150 if (!W_ERROR_IS_OK(status))
9151 return status;
9153 /* delete the key and all subneys */
9155 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9157 status = delete_all_printer_data( printer->info_2, key );
9159 if ( W_ERROR_IS_OK(status) )
9160 status = mod_a_printer(printer, 2);
9162 free_a_printer( &printer, 2 );
9164 return status;
9168 /********************************************************************
9169 * spoolss_enumprinterdataex
9170 ********************************************************************/
9172 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9174 POLICY_HND *handle = &q_u->handle;
9175 uint32 in_size = q_u->size;
9176 uint32 num_entries,
9177 needed;
9178 NT_PRINTER_INFO_LEVEL *printer = NULL;
9179 PRINTER_ENUM_VALUES *enum_values = NULL;
9180 NT_PRINTER_DATA *p_data;
9181 fstring key;
9182 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9183 int snum;
9184 WERROR result;
9185 int key_index;
9186 int i;
9187 REGISTRY_VALUE *val;
9188 char *value_name;
9189 uint32 data_len;
9192 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9194 if (!Printer) {
9195 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9196 return WERR_BADFID;
9200 * first check for a keyname of NULL or "". Win2k seems to send
9201 * this a lot and we should send back WERR_INVALID_PARAM
9202 * no need to spend time looking up the printer in this case.
9203 * --jerry
9206 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9207 if ( !strlen(key) ) {
9208 result = WERR_INVALID_PARAM;
9209 goto done;
9212 /* get the printer off of disk */
9214 if (!get_printer_snum(p,handle, &snum))
9215 return WERR_BADFID;
9217 ZERO_STRUCT(printer);
9218 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9219 if (!W_ERROR_IS_OK(result))
9220 return result;
9222 /* now look for a match on the key name */
9224 p_data = printer->info_2->data;
9226 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9227 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9229 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9230 result = WERR_INVALID_PARAM;
9231 goto done;
9234 result = WERR_OK;
9235 needed = 0;
9237 /* allocate the memory for the array of pointers -- if necessary */
9239 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9240 if ( num_entries )
9242 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9244 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9245 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9246 result = WERR_NOMEM;
9247 goto done;
9250 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9254 * loop through all params and build the array to pass
9255 * back to the client
9258 for ( i=0; i<num_entries; i++ )
9260 /* lookup the registry value */
9262 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9263 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9265 /* copy the data */
9267 value_name = regval_name( val );
9268 init_unistr( &enum_values[i].valuename, value_name );
9269 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9270 enum_values[i].type = regval_type( val );
9272 data_len = regval_size( val );
9273 if ( data_len ) {
9274 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9276 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9277 data_len ));
9278 result = WERR_NOMEM;
9279 goto done;
9282 enum_values[i].data_len = data_len;
9284 /* keep track of the size of the array in bytes */
9286 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9289 /* housekeeping information in the reply */
9291 r_u->needed = needed;
9292 r_u->returned = num_entries;
9294 if (needed > in_size) {
9295 result = WERR_MORE_DATA;
9296 goto done;
9299 /* copy data into the reply */
9301 r_u->ctr.size = r_u->needed;
9302 r_u->ctr.size_of_array = r_u->returned;
9303 r_u->ctr.values = enum_values;
9307 done:
9308 if ( printer )
9309 free_a_printer(&printer, 2);
9311 return result;
9314 /****************************************************************************
9315 ****************************************************************************/
9317 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9319 init_unistr(&info->name, name);
9322 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9323 UNISTR2 *environment,
9324 RPC_BUFFER *buffer,
9325 uint32 offered,
9326 uint32 *needed)
9328 pstring path;
9329 pstring long_archi;
9330 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9331 WERROR result = WERR_OK;
9333 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9335 if (!get_short_archi(long_archi))
9336 return WERR_INVALID_ENVIRONMENT;
9338 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9339 return WERR_NOMEM;
9341 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9343 fill_printprocessordirectory_1(info, path);
9345 *needed += spoolss_size_printprocessordirectory_info_1(info);
9347 if (*needed > offered) {
9348 result = WERR_INSUFFICIENT_BUFFER;
9349 goto out;
9352 if (!rpcbuf_alloc_size(buffer, *needed)) {
9353 result = WERR_INSUFFICIENT_BUFFER;
9354 goto out;
9357 smb_io_printprocessordirectory_1("", buffer, info, 0);
9359 out:
9360 SAFE_FREE(info);
9362 return result;
9365 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9367 uint32 level = q_u->level;
9368 RPC_BUFFER *buffer = NULL;
9369 uint32 offered = q_u->offered;
9370 uint32 *needed = &r_u->needed;
9371 WERROR result;
9373 /* that's an [in out] buffer */
9375 if ( q_u->buffer ) {
9376 rpcbuf_move(q_u->buffer, &r_u->buffer);
9377 buffer = r_u->buffer;
9380 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9382 *needed=0;
9384 switch(level) {
9385 case 1:
9386 result = getprintprocessordirectory_level_1
9387 (&q_u->name, &q_u->environment, buffer, offered, needed);
9388 break;
9389 default:
9390 result = WERR_UNKNOWN_LEVEL;
9393 return result;
9396 #if 0
9398 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9399 SPOOL_R_REPLYOPENPRINTER *r_u)
9401 DEBUG(5,("_spoolss_replyopenprinter\n"));
9403 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9405 return WERR_OK;
9408 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9409 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9411 DEBUG(5,("_spoolss_replycloseprinter\n"));
9412 return WERR_OK;
9415 #endif