r9268: bumping version to 3.0.20rc3
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob5391ac5f41a8e977acabe822597de8646dd1f305
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 cli_state notify_cli; /* print notify back-channel */
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 = cli_spoolss_reply_close_printer(&notify_cli, notify_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_nt_session_close(&notify_cli);
178 cli_ulogoff(&notify_cli);
179 cli_shutdown(&notify_cli);
180 message_deregister(MSG_PRINTER_NOTIFY2);
182 /* Tell the connections db we're no longer interested in
183 * printer notify messages. */
185 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
188 smb_connections--;
191 /****************************************************************************
192 Functions to free a printer entry datastruct.
193 ****************************************************************************/
195 static void free_printer_entry(void *ptr)
197 Printer_entry *Printer = (Printer_entry *)ptr;
199 if (Printer->notify.client_connected==True) {
200 int snum = -1;
202 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
203 snum = -1;
204 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
205 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
206 snum = print_queue_snum(Printer->sharename);
207 if (snum != -1)
208 srv_spoolss_replycloseprinter(snum,
209 &Printer->notify.client_hnd);
213 Printer->notify.flags=0;
214 Printer->notify.options=0;
215 Printer->notify.localmachine[0]='\0';
216 Printer->notify.printerlocal=0;
217 free_spool_notify_option(&Printer->notify.option);
218 Printer->notify.option=NULL;
219 Printer->notify.client_connected=False;
221 free_nt_devicemode( &Printer->nt_devmode );
222 free_a_printer( &Printer->printer_info, 2 );
224 talloc_destroy( Printer->ctx );
226 /* Remove from the internal list. */
227 DLIST_REMOVE(printers_list, Printer);
229 SAFE_FREE(Printer);
232 /****************************************************************************
233 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
234 ****************************************************************************/
236 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
238 SPOOL_NOTIFY_OPTION *new_sp = NULL;
240 if (!sp)
241 return NULL;
243 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
244 if (!new_sp)
245 return NULL;
247 *new_sp = *sp;
249 if (sp->ctr.count) {
250 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
252 if (!new_sp->ctr.type) {
253 SAFE_FREE(new_sp);
254 return NULL;
258 return new_sp;
261 /****************************************************************************
262 find printer index by handle
263 ****************************************************************************/
265 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
267 Printer_entry *find_printer = NULL;
269 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
270 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
271 return NULL;
274 return find_printer;
277 #ifdef ENABLE_PRINT_HND_OBJECT_CACHE
278 /****************************************************************************
279 look for a printer object cached on an open printer handle
280 ****************************************************************************/
282 WERROR find_printer_in_print_hnd_cache( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 **info2,
283 const char *servername, const char *printername )
285 Printer_entry *p;
287 DEBUG(10,("find_printer_in_print_hnd_cache: printer [\\\\%s\\%s]\n",
288 servername, printername));
290 for ( p=printers_list; p; p=p->next )
292 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
293 && p->printer_info
294 && strequal( p->sharename, printername )
295 && strequal( p->servername, servername ) )
297 DEBUG(10,("Found printer\n"));
298 *info2 = dup_printer_2( ctx, p->printer_info->info_2 );
299 if ( *info2 )
300 return WERR_OK;
304 return WERR_INVALID_PRINTER_NAME;
307 /****************************************************************************
308 destroy any cached printer_info_2 structures on open handles
309 ****************************************************************************/
311 void invalidate_printer_hnd_cache( char *printername )
313 Printer_entry *p;
315 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
317 for ( p=printers_list; p; p=p->next )
319 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
320 && p->printer_info
321 && StrCaseCmp(p->sharename, printername)==0)
323 DEBUG(10,("invalidating printer_info cache for handl:\n"));
324 free_a_printer( &p->printer_info, 2 );
325 p->printer_info = NULL;
329 return;
331 #endif
333 /****************************************************************************
334 Close printer index by handle.
335 ****************************************************************************/
337 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
339 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
341 if (!Printer) {
342 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
343 return False;
346 close_policy_hnd(p, hnd);
348 return True;
351 /****************************************************************************
352 Delete a printer given a handle.
353 ****************************************************************************/
354 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
356 char *cmd = lp_deleteprinter_cmd();
357 pstring command;
358 int ret;
359 SE_PRIV se_printop = SE_PRINT_OPERATOR;
360 BOOL is_print_op = False;
362 /* can't fail if we don't try */
364 if ( !*cmd )
365 return WERR_OK;
367 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
369 if ( token )
370 is_print_op = user_has_privileges( token, &se_printop );
372 DEBUG(10,("Running [%s]\n", command));
374 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
376 if ( is_print_op )
377 become_root();
379 if ( (ret = smbrun(command, NULL)) == 0 ) {
380 /* Tell everyone we updated smb.conf. */
381 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
384 if ( is_print_op )
385 unbecome_root();
387 /********** END SePrintOperatorPrivlege BLOCK **********/
389 DEBUGADD(10,("returned [%d]\n", ret));
391 if (ret != 0)
392 return WERR_BADFID; /* What to return here? */
394 /* go ahead and re-read the services immediately */
395 reload_services( False );
397 if ( lp_servicenumber( sharename ) < 0 )
398 return WERR_ACCESS_DENIED;
400 return WERR_OK;
403 /****************************************************************************
404 Delete a printer given a handle.
405 ****************************************************************************/
407 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
409 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
411 if (!Printer) {
412 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
413 return WERR_BADFID;
417 * It turns out that Windows allows delete printer on a handle
418 * opened by an admin user, then used on a pipe handle created
419 * by an anonymous user..... but they're working on security.... riiight !
420 * JRA.
423 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
424 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
425 return WERR_ACCESS_DENIED;
428 /* this does not need a become root since the access check has been
429 done on the handle already */
431 if (del_a_printer( Printer->sharename ) != 0) {
432 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
433 return WERR_BADFID;
436 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
439 /****************************************************************************
440 Return the snum of a printer corresponding to an handle.
441 ****************************************************************************/
443 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
445 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
447 if (!Printer) {
448 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
449 return False;
452 switch (Printer->printer_type) {
453 case PRINTER_HANDLE_IS_PRINTER:
454 DEBUG(4,("short name:%s\n", Printer->sharename));
455 *number = print_queue_snum(Printer->sharename);
456 return (*number != -1);
457 case PRINTER_HANDLE_IS_PRINTSERVER:
458 return False;
459 default:
460 return False;
464 /****************************************************************************
465 Set printer handle type.
466 Check if it's \\server or \\server\printer
467 ****************************************************************************/
469 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
471 DEBUG(3,("Setting printer type=%s\n", handlename));
473 if ( strlen(handlename) < 3 ) {
474 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
475 return False;
478 /* it's a print server */
479 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
480 DEBUGADD(4,("Printer is a print server\n"));
481 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
483 /* it's a printer */
484 else {
485 DEBUGADD(4,("Printer is a printer\n"));
486 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
489 return True;
492 /****************************************************************************
493 Set printer handle name.
494 ****************************************************************************/
496 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
498 int snum;
499 int n_services=lp_numservices();
500 char *aprinter, *printername;
501 const char *servername;
502 fstring sname;
503 BOOL found=False;
504 NT_PRINTER_INFO_LEVEL *printer;
505 WERROR result;
507 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
509 aprinter = handlename;
510 if ( *handlename == '\\' ) {
511 servername = handlename + 2;
512 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
513 *aprinter = '\0';
514 aprinter++;
517 else {
518 servername = "";
521 /* save the servername to fill in replies on this handle */
523 if ( !is_myname_or_ipaddr( servername ) )
524 return False;
526 fstrcpy( Printer->servername, servername );
528 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
529 return True;
531 if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
532 return False;
534 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
536 /* Search all sharenames first as this is easier than pulling
537 the printer_info_2 off of disk */
539 snum = find_service(aprinter);
541 if ( lp_snum_ok(snum) && lp_print_ok(snum) ) {
542 found = True;
543 fstrcpy( sname, aprinter );
546 /* do another loop to look for printernames */
548 for (snum=0; !found && snum<n_services; snum++) {
550 /* no point in checking if this is not a printer or
551 we aren't allowing printername != sharename */
553 if ( !(lp_snum_ok(snum)
554 && lp_print_ok(snum)
555 && !lp_force_printername(snum)) )
557 continue;
560 fstrcpy(sname, lp_servicename(snum));
562 printer = NULL;
563 result = get_a_printer( NULL, &printer, 2, sname );
564 if ( !W_ERROR_IS_OK(result) ) {
565 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
566 sname, dos_errstr(result)));
567 continue;
570 /* printername is always returned as \\server\printername */
571 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
572 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
573 printer->info_2->printername));
574 free_a_printer( &printer, 2);
575 continue;
578 printername++;
580 if ( strequal(printername, aprinter) ) {
581 found = True;
584 DEBUGADD(10, ("printername: %s\n", printername));
586 free_a_printer( &printer, 2);
589 if ( !found ) {
590 DEBUGADD(4,("Printer not found\n"));
591 return False;
594 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
596 fstrcpy(Printer->sharename, sname);
598 return True;
601 /****************************************************************************
602 Find first available printer slot. creates a printer handle for you.
603 ****************************************************************************/
605 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
607 Printer_entry *new_printer;
609 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
611 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
612 return False;
614 ZERO_STRUCTP(new_printer);
616 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
617 SAFE_FREE(new_printer);
618 return False;
621 /* Add to the internal list. */
622 DLIST_ADD(printers_list, new_printer);
624 new_printer->notify.option=NULL;
626 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
627 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
628 close_printer_handle(p, hnd);
629 return False;
632 if (!set_printer_hnd_printertype(new_printer, name)) {
633 close_printer_handle(p, hnd);
634 return False;
637 if (!set_printer_hnd_name(new_printer, name)) {
638 close_printer_handle(p, hnd);
639 return False;
642 new_printer->access_granted = access_granted;
644 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
646 return True;
649 /***************************************************************************
650 check to see if the client motify handle is monitoring the notification
651 given by (notify_type, notify_field).
652 **************************************************************************/
654 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
655 uint16 notify_field)
657 return True;
660 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
661 uint16 notify_field)
663 SPOOL_NOTIFY_OPTION *option = p->notify.option;
664 uint32 i, j;
667 * Flags should always be zero when the change notify
668 * is registered by the client's spooler. A user Win32 app
669 * might use the flags though instead of the NOTIFY_OPTION_INFO
670 * --jerry
673 if (!option) {
674 return False;
677 if (p->notify.flags)
678 return is_monitoring_event_flags(
679 p->notify.flags, notify_type, notify_field);
681 for (i = 0; i < option->count; i++) {
683 /* Check match for notify_type */
685 if (option->ctr.type[i].type != notify_type)
686 continue;
688 /* Check match for field */
690 for (j = 0; j < option->ctr.type[i].count; j++) {
691 if (option->ctr.type[i].fields[j] == notify_field) {
692 return True;
697 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
698 p->servername, p->sharename, notify_type, notify_field));
700 return False;
703 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
705 static void notify_one_value(struct spoolss_notify_msg *msg,
706 SPOOL_NOTIFY_INFO_DATA *data,
707 TALLOC_CTX *mem_ctx)
709 data->notify_data.value[0] = msg->notify.value[0];
710 data->notify_data.value[1] = 0;
713 static void notify_string(struct spoolss_notify_msg *msg,
714 SPOOL_NOTIFY_INFO_DATA *data,
715 TALLOC_CTX *mem_ctx)
717 UNISTR2 unistr;
719 /* The length of the message includes the trailing \0 */
721 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
723 data->notify_data.data.length = msg->len * 2;
724 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
726 if (!data->notify_data.data.string) {
727 data->notify_data.data.length = 0;
728 return;
731 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
734 static void notify_system_time(struct spoolss_notify_msg *msg,
735 SPOOL_NOTIFY_INFO_DATA *data,
736 TALLOC_CTX *mem_ctx)
738 SYSTEMTIME systime;
739 prs_struct ps;
741 if (msg->len != sizeof(time_t)) {
742 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
743 msg->len));
744 return;
747 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
748 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
749 return;
752 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
753 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
754 return;
757 if (!spoolss_io_system_time("", &ps, 0, &systime))
758 return;
760 data->notify_data.data.length = prs_offset(&ps);
761 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
763 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
765 prs_mem_free(&ps);
768 struct notify2_message_table {
769 const char *name;
770 void (*fn)(struct spoolss_notify_msg *msg,
771 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
774 static struct notify2_message_table printer_notify_table[] = {
775 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
776 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
777 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
778 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
779 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
780 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
781 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
782 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
783 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
784 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
785 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
786 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
787 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
788 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
789 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
790 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
791 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
792 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
793 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
796 static struct notify2_message_table job_notify_table[] = {
797 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
798 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
799 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
800 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
801 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
802 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
803 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
804 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
805 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
806 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
807 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
808 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
809 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
810 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
811 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
812 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
813 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
814 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
815 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
816 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
817 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
818 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
819 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
820 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
824 /***********************************************************************
825 Allocate talloc context for container object
826 **********************************************************************/
828 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
830 if ( !ctr )
831 return;
833 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
835 return;
838 /***********************************************************************
839 release all allocated memory and zero out structure
840 **********************************************************************/
842 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
844 if ( !ctr )
845 return;
847 if ( ctr->ctx )
848 talloc_destroy(ctr->ctx);
850 ZERO_STRUCTP(ctr);
852 return;
855 /***********************************************************************
856 **********************************************************************/
858 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
860 if ( !ctr )
861 return NULL;
863 return ctr->ctx;
866 /***********************************************************************
867 **********************************************************************/
869 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
871 if ( !ctr || !ctr->msg_groups )
872 return NULL;
874 if ( idx >= ctr->num_groups )
875 return NULL;
877 return &ctr->msg_groups[idx];
881 /***********************************************************************
882 How many groups of change messages do we have ?
883 **********************************************************************/
885 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
887 if ( !ctr )
888 return 0;
890 return ctr->num_groups;
893 /***********************************************************************
894 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
895 **********************************************************************/
897 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
899 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
900 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
901 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
902 int i, new_slot;
904 if ( !ctr || !msg )
905 return 0;
907 /* loop over all groups looking for a matching printer name */
909 for ( i=0; i<ctr->num_groups; i++ ) {
910 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
911 break;
914 /* add a new group? */
916 if ( i == ctr->num_groups ) {
917 ctr->num_groups++;
919 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
920 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
921 return 0;
923 ctr->msg_groups = groups;
925 /* clear the new entry and set the printer name */
927 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
928 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
931 /* add the change messages; 'i' is the correct index now regardless */
933 msg_grp = &ctr->msg_groups[i];
935 msg_grp->num_msgs++;
937 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
938 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
939 return 0;
941 msg_grp->msgs = msg_list;
943 new_slot = msg_grp->num_msgs-1;
944 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
946 /* need to allocate own copy of data */
948 if ( msg->len != 0 )
949 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
951 return ctr->num_groups;
954 /***********************************************************************
955 Send a change notication message on all handles which have a call
956 back registered
957 **********************************************************************/
959 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
961 Printer_entry *p;
962 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
963 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
964 SPOOLSS_NOTIFY_MSG *messages;
965 int sending_msg_count;
967 if ( !msg_group ) {
968 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
969 return;
972 messages = msg_group->msgs;
974 if ( !messages ) {
975 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
976 return;
979 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
981 /* loop over all printers */
983 for (p = printers_list; p; p = p->next) {
984 SPOOL_NOTIFY_INFO_DATA *data;
985 uint32 data_len = 0;
986 uint32 id;
987 int i;
989 /* Is there notification on this handle? */
991 if ( !p->notify.client_connected )
992 continue;
994 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
996 /* For this printer? Print servers always receive
997 notifications. */
999 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
1000 ( !strequal(msg_group->printername, p->sharename) ) )
1001 continue;
1003 DEBUG(10,("Our printer\n"));
1005 /* allocate the max entries possible */
1007 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
1008 ZERO_STRUCTP(data);
1010 /* build the array of change notifications */
1012 sending_msg_count = 0;
1014 for ( i=0; i<msg_group->num_msgs; i++ ) {
1015 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1017 /* Are we monitoring this event? */
1019 if (!is_monitoring_event(p, msg->type, msg->field))
1020 continue;
1022 sending_msg_count++;
1025 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1026 msg->type, msg->field, p->sharename));
1029 * if the is a printer notification handle and not a job notification
1030 * type, then set the id to 0. Other wise just use what was specified
1031 * in the message.
1033 * When registering change notification on a print server handle
1034 * we always need to send back the id (snum) matching the printer
1035 * for which the change took place. For change notify registered
1036 * on a printer handle, this does not matter and the id should be 0.
1038 * --jerry
1041 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1042 id = 0;
1043 else
1044 id = msg->id;
1047 /* Convert unix jobid to smb jobid */
1049 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1050 id = sysjob_to_jobid(msg->id);
1052 if (id == -1) {
1053 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1054 goto done;
1058 construct_info_data( &data[data_len], msg->type, msg->field, id );
1060 switch(msg->type) {
1061 case PRINTER_NOTIFY_TYPE:
1062 if ( printer_notify_table[msg->field].fn )
1063 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1064 break;
1066 case JOB_NOTIFY_TYPE:
1067 if ( job_notify_table[msg->field].fn )
1068 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1069 break;
1071 default:
1072 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1073 goto done;
1076 data_len++;
1079 if ( sending_msg_count ) {
1080 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
1081 data_len, data, p->notify.change, 0 );
1085 done:
1086 DEBUG(8,("send_notify2_changes: Exit...\n"));
1087 return;
1090 /***********************************************************************
1091 **********************************************************************/
1093 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1096 uint32 tv_sec, tv_usec;
1097 size_t offset = 0;
1099 /* Unpack message */
1101 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1102 msg->printer);
1104 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1105 &tv_sec, &tv_usec,
1106 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1108 if (msg->len == 0)
1109 tdb_unpack((char *)buf + offset, len - offset, "dd",
1110 &msg->notify.value[0], &msg->notify.value[1]);
1111 else
1112 tdb_unpack((char *)buf + offset, len - offset, "B",
1113 &msg->len, &msg->notify.data);
1115 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1116 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1118 tv->tv_sec = tv_sec;
1119 tv->tv_usec = tv_usec;
1121 if (msg->len == 0)
1122 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1123 msg->notify.value[1]));
1124 else
1125 dump_data(3, msg->notify.data, msg->len);
1127 return True;
1130 /********************************************************************
1131 Receive a notify2 message list
1132 ********************************************************************/
1134 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1136 size_t msg_count, i;
1137 char *buf = (char *)msg;
1138 char *msg_ptr;
1139 size_t msg_len;
1140 SPOOLSS_NOTIFY_MSG notify;
1141 SPOOLSS_NOTIFY_MSG_CTR messages;
1142 int num_groups;
1144 if (len < 4) {
1145 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1146 return;
1149 msg_count = IVAL(buf, 0);
1150 msg_ptr = buf + 4;
1152 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1154 if (msg_count == 0) {
1155 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1156 return;
1159 /* initialize the container */
1161 ZERO_STRUCT( messages );
1162 notify_msg_ctr_init( &messages );
1165 * build message groups for each printer identified
1166 * in a change_notify msg. Remember that a PCN message
1167 * includes the handle returned for the srv_spoolss_replyopenprinter()
1168 * call. Therefore messages are grouped according to printer handle.
1171 for ( i=0; i<msg_count; i++ ) {
1172 struct timeval msg_tv;
1174 if (msg_ptr + 4 - buf > len) {
1175 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1176 return;
1179 msg_len = IVAL(msg_ptr,0);
1180 msg_ptr += 4;
1182 if (msg_ptr + msg_len - buf > len) {
1183 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1184 return;
1187 /* unpack messages */
1189 ZERO_STRUCT( notify );
1190 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1191 msg_ptr += msg_len;
1193 /* add to correct list in container */
1195 notify_msg_ctr_addmsg( &messages, &notify );
1197 /* free memory that might have been allocated by notify2_unpack_msg() */
1199 if ( notify.len != 0 )
1200 SAFE_FREE( notify.notify.data );
1203 /* process each group of messages */
1205 num_groups = notify_msg_ctr_numgroups( &messages );
1206 for ( i=0; i<num_groups; i++ )
1207 send_notify2_changes( &messages, i );
1210 /* cleanup */
1212 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1214 notify_msg_ctr_destroy( &messages );
1216 return;
1219 #ifdef ENABLE_PRINT_HND_OBJECT_CACHE
1220 /********************************************************************
1221 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1222 one smbd, all of processes must clear their printer cache immediately.
1223 ********************************************************************/
1225 void receive_printer_mod_msg(int msg_type, pid_t src, void *buf, size_t len)
1227 fstring printername;
1229 fstrcpy( printername, buf );
1231 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername ));
1233 invalidate_printer_hnd_cache( printername );
1235 #endif
1237 /********************************************************************
1238 Send a message to ourself about new driver being installed
1239 so we can upgrade the information for each printer bound to this
1240 driver
1241 ********************************************************************/
1243 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1245 int len = strlen(drivername);
1247 if (!len)
1248 return False;
1250 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1251 drivername));
1253 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1255 return True;
1258 /**********************************************************************
1259 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1260 over all printers, upgrading ones as necessary
1261 **********************************************************************/
1263 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1265 fstring drivername;
1266 int snum;
1267 int n_services = lp_numservices();
1269 len = MIN(len,sizeof(drivername)-1);
1270 strncpy(drivername, buf, len);
1272 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1274 /* Iterate the printer list */
1276 for (snum=0; snum<n_services; snum++)
1278 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1280 WERROR result;
1281 NT_PRINTER_INFO_LEVEL *printer = NULL;
1283 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1284 if (!W_ERROR_IS_OK(result))
1285 continue;
1287 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1289 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1291 /* all we care about currently is the change_id */
1293 result = mod_a_printer(printer, 2);
1294 if (!W_ERROR_IS_OK(result)) {
1295 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1296 dos_errstr(result)));
1300 free_a_printer(&printer, 2);
1304 /* all done */
1307 /********************************************************************
1308 Update the cache for all printq's with a registered client
1309 connection
1310 ********************************************************************/
1312 void update_monitored_printq_cache( void )
1314 Printer_entry *printer = printers_list;
1315 int snum;
1317 /* loop through all printers and update the cache where
1318 client_connected == True */
1319 while ( printer )
1321 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1322 && printer->notify.client_connected )
1324 snum = print_queue_snum(printer->sharename);
1325 print_queue_status( snum, NULL, NULL );
1328 printer = printer->next;
1331 return;
1333 /********************************************************************
1334 Send a message to ourself about new driver being installed
1335 so we can upgrade the information for each printer bound to this
1336 driver
1337 ********************************************************************/
1339 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1341 int len = strlen(drivername);
1343 if (!len)
1344 return False;
1346 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1347 drivername));
1349 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1351 return True;
1354 /**********************************************************************
1355 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1356 over all printers, resetting printer data as neessary
1357 **********************************************************************/
1359 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1361 fstring drivername;
1362 int snum;
1363 int n_services = lp_numservices();
1365 len = MIN( len, sizeof(drivername)-1 );
1366 strncpy( drivername, buf, len );
1368 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1370 /* Iterate the printer list */
1372 for ( snum=0; snum<n_services; snum++ )
1374 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1376 WERROR result;
1377 NT_PRINTER_INFO_LEVEL *printer = NULL;
1379 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1380 if ( !W_ERROR_IS_OK(result) )
1381 continue;
1384 * if the printer is bound to the driver,
1385 * then reset to the new driver initdata
1388 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1390 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1392 if ( !set_driver_init(printer, 2) ) {
1393 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1394 printer->info_2->printername, printer->info_2->drivername));
1397 result = mod_a_printer( printer, 2 );
1398 if ( !W_ERROR_IS_OK(result) ) {
1399 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1400 get_dos_error_msg(result)));
1404 free_a_printer( &printer, 2 );
1408 /* all done */
1410 return;
1413 /********************************************************************
1414 Copy routines used by convert_to_openprinterex()
1415 *******************************************************************/
1417 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1419 DEVICEMODE *d;
1420 int len;
1422 if (!devmode)
1423 return NULL;
1425 DEBUG (8,("dup_devmode\n"));
1427 /* bulk copy first */
1429 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1430 if (!d)
1431 return NULL;
1433 /* dup the pointer members separately */
1435 len = unistrlen(devmode->devicename.buffer);
1436 if (len != -1) {
1437 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1438 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1439 return NULL;
1443 len = unistrlen(devmode->formname.buffer);
1444 if (len != -1) {
1445 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1446 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1447 return NULL;
1450 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1452 return d;
1455 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1457 if (!new_ctr || !ctr)
1458 return;
1460 DEBUG(8,("copy_devmode_ctr\n"));
1462 new_ctr->size = ctr->size;
1463 new_ctr->devmode_ptr = ctr->devmode_ptr;
1465 if(ctr->devmode_ptr)
1466 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1469 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1471 if (!new_def || !def)
1472 return;
1474 DEBUG(8,("copy_printer_defaults\n"));
1476 new_def->datatype_ptr = def->datatype_ptr;
1478 if (def->datatype_ptr)
1479 copy_unistr2(&new_def->datatype, &def->datatype);
1481 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1483 new_def->access_required = def->access_required;
1486 /********************************************************************
1487 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1488 * SPOOL_Q_OPEN_PRINTER_EX structure
1489 ********************************************************************/
1491 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1493 if (!q_u_ex || !q_u)
1494 return WERR_OK;
1496 DEBUG(8,("convert_to_openprinterex\n"));
1498 if ( q_u->printername ) {
1499 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1500 if (q_u_ex->printername == NULL)
1501 return WERR_NOMEM;
1502 copy_unistr2(q_u_ex->printername, q_u->printername);
1505 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1507 return WERR_OK;
1510 /********************************************************************
1511 * spoolss_open_printer
1513 * called from the spoolss dispatcher
1514 ********************************************************************/
1516 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1518 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1519 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1521 if (!q_u || !r_u)
1522 return WERR_NOMEM;
1524 ZERO_STRUCT(q_u_ex);
1525 ZERO_STRUCT(r_u_ex);
1527 /* convert the OpenPrinter() call to OpenPrinterEx() */
1529 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1530 if (!W_ERROR_IS_OK(r_u_ex.status))
1531 return r_u_ex.status;
1533 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1535 /* convert back to OpenPrinter() */
1537 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1539 return r_u->status;
1542 /********************************************************************
1543 * spoolss_open_printer
1545 * If the openprinterex rpc call contains a devmode,
1546 * it's a per-user one. This per-user devmode is derivated
1547 * from the global devmode. Openprinterex() contains a per-user
1548 * devmode for when you do EMF printing and spooling.
1549 * In the EMF case, the NT workstation is only doing half the job
1550 * of rendering the page. The other half is done by running the printer
1551 * driver on the server.
1552 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1553 * The EMF file only contains what is to be printed on the page.
1554 * So in order for the server to know how to print, the NT client sends
1555 * a devicemode attached to the openprinterex call.
1556 * But this devicemode is short lived, it's only valid for the current print job.
1558 * If Samba would have supported EMF spooling, this devicemode would
1559 * have been attached to the handle, to sent it to the driver to correctly
1560 * rasterize the EMF file.
1562 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1563 * we just act as a pass-thru between windows and the printer.
1565 * In order to know that Samba supports only RAW spooling, NT has to call
1566 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1567 * and until NT sends a RAW job, we refuse it.
1569 * But to call getprinter() or startdoc(), you first need a valid handle,
1570 * and to get an handle you have to call openprintex(). Hence why you have
1571 * a devicemode in the openprinterex() call.
1574 * Differences between NT4 and NT 2000.
1575 * NT4:
1576 * ---
1577 * On NT4, you only have a global devicemode. This global devicemode can be changed
1578 * by the administrator (or by a user with enough privs). Everytime a user
1579 * wants to print, the devicemode is resetted to the default. In Word, everytime
1580 * you print, the printer's characteristics are always reset to the global devicemode.
1582 * NT 2000:
1583 * -------
1584 * In W2K, there is the notion of per-user devicemode. The first time you use
1585 * a printer, a per-user devicemode is build from the global devicemode.
1586 * If you change your per-user devicemode, it is saved in the registry, under the
1587 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1588 * printer preferences available.
1590 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1591 * on the General Tab of the printer properties windows.
1593 * To change the global devicemode: it's the "Printing Defaults..." button
1594 * on the Advanced Tab of the printer properties window.
1596 * JFM.
1597 ********************************************************************/
1599 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1601 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1602 POLICY_HND *handle = &r_u->handle;
1604 fstring name;
1605 int snum;
1606 struct current_user user;
1607 Printer_entry *Printer=NULL;
1609 if ( !q_u->printername )
1610 return WERR_INVALID_PRINTER_NAME;
1612 /* some sanity check because you can open a printer or a print server */
1613 /* aka: \\server\printer or \\server */
1615 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1617 DEBUGADD(3,("checking name: %s\n",name));
1619 if (!open_printer_hnd(p, handle, name, 0))
1620 return WERR_INVALID_PRINTER_NAME;
1622 Printer=find_printer_index_by_hnd(p, handle);
1623 if ( !Printer ) {
1624 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1625 "handle we created for printer %s\n", name ));
1626 close_printer_handle(p,handle);
1627 return WERR_INVALID_PRINTER_NAME;
1630 get_current_user(&user, p);
1633 * First case: the user is opening the print server:
1635 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1636 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1638 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1639 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1640 * or if the user is listed in the smb.conf printer admin parameter.
1642 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1643 * client view printer folder, but does not show the MSAPW.
1645 * Note: this test needs code to check access rights here too. Jeremy
1646 * could you look at this?
1648 * Second case: the user is opening a printer:
1649 * NT doesn't let us connect to a printer if the connecting user
1650 * doesn't have print permission.
1653 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1655 /* Printserver handles use global struct... */
1657 snum = -1;
1659 /* Map standard access rights to object specific access rights */
1661 se_map_standard(&printer_default->access_required,
1662 &printserver_std_mapping);
1664 /* Deny any object specific bits that don't apply to print
1665 servers (i.e printer and job specific bits) */
1667 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1669 if (printer_default->access_required &
1670 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1671 DEBUG(3, ("access DENIED for non-printserver bits"));
1672 close_printer_handle(p, handle);
1673 return WERR_ACCESS_DENIED;
1676 /* Allow admin access */
1678 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1680 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1682 if (!lp_ms_add_printer_wizard()) {
1683 close_printer_handle(p, handle);
1684 return WERR_ACCESS_DENIED;
1687 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1688 and not a printer admin, then fail */
1690 if ( user.uid != 0
1691 && !user_has_privileges( user.nt_user_token, &se_printop )
1692 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1694 close_printer_handle(p, handle);
1695 return WERR_ACCESS_DENIED;
1698 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1700 else
1702 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1705 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1706 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1708 /* We fall through to return WERR_OK */
1711 else
1713 /* NT doesn't let us connect to a printer if the connecting user
1714 doesn't have print permission. */
1716 if (!get_printer_snum(p, handle, &snum)) {
1717 close_printer_handle(p, handle);
1718 return WERR_BADFID;
1721 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1723 /* map an empty access mask to the minimum access mask */
1724 if (printer_default->access_required == 0x0)
1725 printer_default->access_required = PRINTER_ACCESS_USE;
1728 * If we are not serving the printer driver for this printer,
1729 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1730 * will keep NT clients happy --jerry
1733 if (lp_use_client_driver(snum)
1734 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1736 printer_default->access_required = PRINTER_ACCESS_USE;
1739 /* check smb.conf parameters and the the sec_desc */
1741 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1742 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1743 return WERR_ACCESS_DENIED;
1746 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1747 DEBUG(3, ("access DENIED for printer open\n"));
1748 close_printer_handle(p, handle);
1749 return WERR_ACCESS_DENIED;
1752 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1753 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1754 close_printer_handle(p, handle);
1755 return WERR_ACCESS_DENIED;
1758 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1759 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1760 else
1761 printer_default->access_required = PRINTER_ACCESS_USE;
1763 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1764 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1768 Printer->access_granted = printer_default->access_required;
1771 * If the client sent a devmode in the OpenPrinter() call, then
1772 * save it here in case we get a job submission on this handle
1775 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1776 && q_u->printer_default.devmode_cont.devmode_ptr )
1778 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1779 &Printer->nt_devmode );
1782 #if 0 /* JERRY -- I'm doubtful this is really effective */
1783 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1784 optimization in Windows 2000 clients --jerry */
1786 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1787 && (RA_WIN2K == get_remote_arch()) )
1789 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1790 sys_usleep( 500000 );
1792 #endif
1794 return WERR_OK;
1797 /****************************************************************************
1798 ****************************************************************************/
1800 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1801 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1803 BOOL ret = True;
1805 switch (level) {
1806 case 2:
1807 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1808 break;
1809 default:
1810 break;
1813 return ret;
1816 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1817 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1819 BOOL result = True;
1821 switch (level) {
1822 case 3:
1823 printer->info_3=NULL;
1824 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1825 result = False;
1826 break;
1827 case 6:
1828 printer->info_6=NULL;
1829 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1830 result = False;
1831 break;
1832 default:
1833 break;
1836 return result;
1839 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1840 NT_DEVICEMODE **pp_nt_devmode)
1842 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1845 * Ensure nt_devmode is a valid pointer
1846 * as we will be overwriting it.
1849 if (nt_devmode == NULL) {
1850 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1851 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1852 return False;
1855 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1856 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1858 nt_devmode->specversion=devmode->specversion;
1859 nt_devmode->driverversion=devmode->driverversion;
1860 nt_devmode->size=devmode->size;
1861 nt_devmode->fields=devmode->fields;
1862 nt_devmode->orientation=devmode->orientation;
1863 nt_devmode->papersize=devmode->papersize;
1864 nt_devmode->paperlength=devmode->paperlength;
1865 nt_devmode->paperwidth=devmode->paperwidth;
1866 nt_devmode->scale=devmode->scale;
1867 nt_devmode->copies=devmode->copies;
1868 nt_devmode->defaultsource=devmode->defaultsource;
1869 nt_devmode->printquality=devmode->printquality;
1870 nt_devmode->color=devmode->color;
1871 nt_devmode->duplex=devmode->duplex;
1872 nt_devmode->yresolution=devmode->yresolution;
1873 nt_devmode->ttoption=devmode->ttoption;
1874 nt_devmode->collate=devmode->collate;
1876 nt_devmode->logpixels=devmode->logpixels;
1877 nt_devmode->bitsperpel=devmode->bitsperpel;
1878 nt_devmode->pelswidth=devmode->pelswidth;
1879 nt_devmode->pelsheight=devmode->pelsheight;
1880 nt_devmode->displayflags=devmode->displayflags;
1881 nt_devmode->displayfrequency=devmode->displayfrequency;
1882 nt_devmode->icmmethod=devmode->icmmethod;
1883 nt_devmode->icmintent=devmode->icmintent;
1884 nt_devmode->mediatype=devmode->mediatype;
1885 nt_devmode->dithertype=devmode->dithertype;
1886 nt_devmode->reserved1=devmode->reserved1;
1887 nt_devmode->reserved2=devmode->reserved2;
1888 nt_devmode->panningwidth=devmode->panningwidth;
1889 nt_devmode->panningheight=devmode->panningheight;
1892 * Only change private and driverextra if the incoming devmode
1893 * has a new one. JRA.
1896 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1897 SAFE_FREE(nt_devmode->nt_dev_private);
1898 nt_devmode->driverextra=devmode->driverextra;
1899 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1900 return False;
1901 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1904 *pp_nt_devmode = nt_devmode;
1906 return True;
1909 /********************************************************************
1910 * _spoolss_enddocprinter_internal.
1911 ********************************************************************/
1913 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1915 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1916 int snum;
1918 if (!Printer) {
1919 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1920 return WERR_BADFID;
1923 if (!get_printer_snum(p, handle, &snum))
1924 return WERR_BADFID;
1926 Printer->document_started=False;
1927 print_job_end(snum, Printer->jobid,True);
1928 /* error codes unhandled so far ... */
1930 return WERR_OK;
1933 /********************************************************************
1934 * api_spoolss_closeprinter
1935 ********************************************************************/
1937 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1939 POLICY_HND *handle = &q_u->handle;
1941 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1943 if (Printer && Printer->document_started)
1944 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1946 if (!close_printer_handle(p, handle))
1947 return WERR_BADFID;
1949 /* clear the returned printer handle. Observed behavior
1950 from Win2k server. Don't think this really matters.
1951 Previous code just copied the value of the closed
1952 handle. --jerry */
1954 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1956 return WERR_OK;
1959 /********************************************************************
1960 * api_spoolss_deleteprinter
1962 ********************************************************************/
1964 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1966 POLICY_HND *handle = &q_u->handle;
1967 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1968 WERROR result;
1970 if (Printer && Printer->document_started)
1971 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1973 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1975 result = delete_printer_handle(p, handle);
1977 update_c_setprinter(False);
1979 return result;
1982 /*******************************************************************
1983 * static function to lookup the version id corresponding to an
1984 * long architecture string
1985 ******************************************************************/
1987 static int get_version_id (char * arch)
1989 int i;
1990 struct table_node archi_table[]= {
1992 {"Windows 4.0", "WIN40", 0 },
1993 {"Windows NT x86", "W32X86", 2 },
1994 {"Windows NT R4000", "W32MIPS", 2 },
1995 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1996 {"Windows NT PowerPC", "W32PPC", 2 },
1997 {"Windows IA64", "IA64", 3 },
1998 {"Windows x64", "x64", 3 },
1999 {NULL, "", -1 }
2002 for (i=0; archi_table[i].long_archi != NULL; i++)
2004 if (strcmp(arch, archi_table[i].long_archi) == 0)
2005 return (archi_table[i].version);
2008 return -1;
2011 /********************************************************************
2012 * _spoolss_deleteprinterdriver
2013 ********************************************************************/
2015 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2017 fstring driver;
2018 fstring arch;
2019 NT_PRINTER_DRIVER_INFO_LEVEL info;
2020 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2021 int version;
2022 struct current_user user;
2023 WERROR status;
2024 WERROR status_win2k = WERR_ACCESS_DENIED;
2026 get_current_user(&user, p);
2028 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2029 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2031 /* check that we have a valid driver name first */
2033 if ((version=get_version_id(arch)) == -1)
2034 return WERR_INVALID_ENVIRONMENT;
2036 ZERO_STRUCT(info);
2037 ZERO_STRUCT(info_win2k);
2039 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2041 /* try for Win2k driver if "Windows NT x86" */
2043 if ( version == 2 ) {
2044 version = 3;
2045 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2046 status = WERR_UNKNOWN_PRINTER_DRIVER;
2047 goto done;
2050 /* otherwise it was a failure */
2051 else {
2052 status = WERR_UNKNOWN_PRINTER_DRIVER;
2053 goto done;
2058 if (printer_driver_in_use(info.info_3)) {
2059 status = WERR_PRINTER_DRIVER_IN_USE;
2060 goto done;
2063 if ( version == 2 )
2065 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2067 /* if we get to here, we now have 2 driver info structures to remove */
2068 /* remove the Win2k driver first*/
2070 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2071 free_a_printer_driver( info_win2k, 3 );
2073 /* this should not have failed---if it did, report to client */
2074 if ( !W_ERROR_IS_OK(status_win2k) )
2075 goto done;
2079 status = delete_printer_driver(info.info_3, &user, version, False);
2081 /* if at least one of the deletes succeeded return OK */
2083 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2084 status = WERR_OK;
2086 done:
2087 free_a_printer_driver( info, 3 );
2089 return status;
2092 /********************************************************************
2093 * spoolss_deleteprinterdriverex
2094 ********************************************************************/
2096 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2098 fstring driver;
2099 fstring arch;
2100 NT_PRINTER_DRIVER_INFO_LEVEL info;
2101 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2102 int version;
2103 uint32 flags = q_u->delete_flags;
2104 BOOL delete_files;
2105 struct current_user user;
2106 WERROR status;
2107 WERROR status_win2k = WERR_ACCESS_DENIED;
2109 get_current_user(&user, p);
2111 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2112 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2114 /* check that we have a valid driver name first */
2115 if ((version=get_version_id(arch)) == -1) {
2116 /* this is what NT returns */
2117 return WERR_INVALID_ENVIRONMENT;
2120 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2121 version = q_u->version;
2123 ZERO_STRUCT(info);
2124 ZERO_STRUCT(info_win2k);
2126 status = get_a_printer_driver(&info, 3, driver, arch, version);
2128 if ( !W_ERROR_IS_OK(status) )
2131 * if the client asked for a specific version,
2132 * or this is something other than Windows NT x86,
2133 * then we've failed
2136 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2137 goto done;
2139 /* try for Win2k driver if "Windows NT x86" */
2141 version = 3;
2142 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2143 status = WERR_UNKNOWN_PRINTER_DRIVER;
2144 goto done;
2148 if ( printer_driver_in_use(info.info_3) ) {
2149 status = WERR_PRINTER_DRIVER_IN_USE;
2150 goto done;
2154 * we have a couple of cases to consider.
2155 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2156 * then the delete should fail if **any** files overlap with
2157 * other drivers
2158 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2159 * non-overlapping files
2160 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2161 * is set, the do not delete any files
2162 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2165 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2167 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2169 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2170 /* no idea of the correct error here */
2171 status = WERR_ACCESS_DENIED;
2172 goto done;
2176 /* also check for W32X86/3 if necessary; maybe we already have? */
2178 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2179 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2182 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2183 /* no idea of the correct error here */
2184 free_a_printer_driver( info_win2k, 3 );
2185 status = WERR_ACCESS_DENIED;
2186 goto done;
2189 /* if we get to here, we now have 2 driver info structures to remove */
2190 /* remove the Win2k driver first*/
2192 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2193 free_a_printer_driver( info_win2k, 3 );
2195 /* this should not have failed---if it did, report to client */
2197 if ( !W_ERROR_IS_OK(status_win2k) )
2198 goto done;
2202 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2204 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2205 status = WERR_OK;
2206 done:
2207 free_a_printer_driver( info, 3 );
2209 return status;
2213 /****************************************************************************
2214 Internal routine for retreiving printerdata
2215 ***************************************************************************/
2217 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2218 const char *key, const char *value, uint32 *type, uint8 **data,
2219 uint32 *needed, uint32 in_size )
2221 REGISTRY_VALUE *val;
2222 uint32 size;
2223 int data_len;
2225 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2226 return WERR_BADFILE;
2228 *type = regval_type( val );
2230 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2232 size = regval_size( val );
2234 /* copy the min(in_size, len) */
2236 if ( in_size ) {
2237 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2239 /* special case for 0 length values */
2240 if ( data_len ) {
2241 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2242 return WERR_NOMEM;
2244 else {
2245 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2246 return WERR_NOMEM;
2249 else
2250 *data = NULL;
2252 *needed = size;
2254 DEBUG(5,("get_printer_dataex: copy done\n"));
2256 return WERR_OK;
2259 /****************************************************************************
2260 Internal routine for removing printerdata
2261 ***************************************************************************/
2263 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2265 return delete_printer_data( printer->info_2, key, value );
2268 /****************************************************************************
2269 Internal routine for storing printerdata
2270 ***************************************************************************/
2272 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2273 uint32 type, uint8 *data, int real_len )
2275 delete_printer_data( printer->info_2, key, value );
2277 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2280 /********************************************************************
2281 GetPrinterData on a printer server Handle.
2282 ********************************************************************/
2284 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2286 int i;
2288 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2290 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2291 *type = REG_DWORD;
2292 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2293 return WERR_NOMEM;
2294 *needed = 0x4;
2295 return WERR_OK;
2298 if (!StrCaseCmp(value, "BeepEnabled")) {
2299 *type = REG_DWORD;
2300 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2301 return WERR_NOMEM;
2302 SIVAL(*data, 0, 0x00);
2303 *needed = 0x4;
2304 return WERR_OK;
2307 if (!StrCaseCmp(value, "EventLog")) {
2308 *type = REG_DWORD;
2309 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2310 return WERR_NOMEM;
2311 /* formally was 0x1b */
2312 SIVAL(*data, 0, 0x0);
2313 *needed = 0x4;
2314 return WERR_OK;
2317 if (!StrCaseCmp(value, "NetPopup")) {
2318 *type = REG_DWORD;
2319 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2320 return WERR_NOMEM;
2321 SIVAL(*data, 0, 0x00);
2322 *needed = 0x4;
2323 return WERR_OK;
2326 if (!StrCaseCmp(value, "MajorVersion")) {
2327 *type = REG_DWORD;
2328 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2329 return WERR_NOMEM;
2331 /* Windows NT 4.0 seems to not allow uploading of drivers
2332 to a server that reports 0x3 as the MajorVersion.
2333 need to investigate more how Win2k gets around this .
2334 -- jerry */
2336 if ( RA_WINNT == get_remote_arch() )
2337 SIVAL(*data, 0, 2);
2338 else
2339 SIVAL(*data, 0, 3);
2341 *needed = 0x4;
2342 return WERR_OK;
2345 if (!StrCaseCmp(value, "MinorVersion")) {
2346 *type = REG_DWORD;
2347 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2348 return WERR_NOMEM;
2349 SIVAL(*data, 0, 0);
2350 *needed = 0x4;
2351 return WERR_OK;
2354 /* REG_BINARY
2355 * uint32 size = 0x114
2356 * uint32 major = 5
2357 * uint32 minor = [0|1]
2358 * uint32 build = [2195|2600]
2359 * extra unicode string = e.g. "Service Pack 3"
2361 if (!StrCaseCmp(value, "OSVersion")) {
2362 *type = REG_BINARY;
2363 *needed = 0x114;
2365 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2366 return WERR_NOMEM;
2368 SIVAL(*data, 0, *needed); /* size */
2369 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2370 SIVAL(*data, 8, 0);
2371 SIVAL(*data, 12, 2195); /* build */
2373 /* leave extra string empty */
2375 return WERR_OK;
2379 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2380 const char *string="C:\\PRINTERS";
2381 *type = REG_SZ;
2382 *needed = 2*(strlen(string)+1);
2383 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2384 return WERR_NOMEM;
2385 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2387 /* it's done by hand ready to go on the wire */
2388 for (i=0; i<strlen(string); i++) {
2389 (*data)[2*i]=string[i];
2390 (*data)[2*i+1]='\0';
2392 return WERR_OK;
2395 if (!StrCaseCmp(value, "Architecture")) {
2396 const char *string="Windows NT x86";
2397 *type = REG_SZ;
2398 *needed = 2*(strlen(string)+1);
2399 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2400 return WERR_NOMEM;
2401 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2402 for (i=0; i<strlen(string); i++) {
2403 (*data)[2*i]=string[i];
2404 (*data)[2*i+1]='\0';
2406 return WERR_OK;
2409 if (!StrCaseCmp(value, "DsPresent")) {
2410 *type = REG_DWORD;
2411 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2412 return WERR_NOMEM;
2414 /* only show the publish check box if we are a
2415 memeber of a AD domain */
2417 if ( lp_security() == SEC_ADS )
2418 SIVAL(*data, 0, 0x01);
2419 else
2420 SIVAL(*data, 0, 0x00);
2422 *needed = 0x4;
2423 return WERR_OK;
2426 if (!StrCaseCmp(value, "DNSMachineName")) {
2427 pstring hostname;
2429 if (!get_mydnsfullname(hostname))
2430 return WERR_BADFILE;
2431 *type = REG_SZ;
2432 *needed = 2*(strlen(hostname)+1);
2433 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2434 return WERR_NOMEM;
2435 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2436 for (i=0; i<strlen(hostname); i++) {
2437 (*data)[2*i]=hostname[i];
2438 (*data)[2*i+1]='\0';
2440 return WERR_OK;
2444 return WERR_BADFILE;
2447 /********************************************************************
2448 * spoolss_getprinterdata
2449 ********************************************************************/
2451 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2453 POLICY_HND *handle = &q_u->handle;
2454 UNISTR2 *valuename = &q_u->valuename;
2455 uint32 in_size = q_u->size;
2456 uint32 *type = &r_u->type;
2457 uint32 *out_size = &r_u->size;
2458 uint8 **data = &r_u->data;
2459 uint32 *needed = &r_u->needed;
2460 WERROR status;
2461 fstring value;
2462 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2463 NT_PRINTER_INFO_LEVEL *printer = NULL;
2464 int snum = 0;
2467 * Reminder: when it's a string, the length is in BYTES
2468 * even if UNICODE is negociated.
2470 * JFM, 4/19/1999
2473 *out_size = in_size;
2475 /* in case of problem, return some default values */
2477 *needed = 0;
2478 *type = 0;
2480 DEBUG(4,("_spoolss_getprinterdata\n"));
2482 if ( !Printer ) {
2483 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2484 status = WERR_BADFID;
2485 goto done;
2488 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2490 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2491 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2492 else
2494 if ( !get_printer_snum(p,handle, &snum) ) {
2495 status = WERR_BADFID;
2496 goto done;
2499 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2500 if ( !W_ERROR_IS_OK(status) )
2501 goto done;
2503 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2505 if ( strequal(value, "ChangeId") ) {
2506 *type = REG_DWORD;
2507 *needed = sizeof(uint32);
2508 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2509 status = WERR_NOMEM;
2510 goto done;
2512 SIVAL( *data, 0, printer->info_2->changeid );
2513 status = WERR_OK;
2515 else
2516 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2519 if (*needed > *out_size)
2520 status = WERR_MORE_DATA;
2522 done:
2523 if ( !W_ERROR_IS_OK(status) )
2525 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2527 /* reply this param doesn't exist */
2529 if ( *out_size ) {
2530 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2531 if ( printer )
2532 free_a_printer( &printer, 2 );
2533 return WERR_NOMEM;
2536 else {
2537 *data = NULL;
2541 /* cleanup & exit */
2543 if ( printer )
2544 free_a_printer( &printer, 2 );
2546 return status;
2549 /*********************************************************
2550 Connect to the client machine.
2551 **********************************************************/
2553 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2554 struct in_addr *client_ip, const char *remote_machine)
2556 ZERO_STRUCTP(the_cli);
2558 if(cli_initialise(the_cli) == NULL) {
2559 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2560 return False;
2563 if ( is_zero_ip(*client_ip) ) {
2564 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2565 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2566 cli_shutdown(the_cli);
2567 return False;
2570 if (ismyip(the_cli->dest_ip)) {
2571 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2572 cli_shutdown(the_cli);
2573 return False;
2576 else {
2577 the_cli->dest_ip.s_addr = client_ip->s_addr;
2578 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2579 inet_ntoa(*client_ip) ));
2582 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2583 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) ));
2584 cli_shutdown(the_cli);
2585 return False;
2588 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2589 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2590 remote_machine));
2591 cli_shutdown(the_cli);
2592 return False;
2595 the_cli->protocol = PROTOCOL_NT1;
2596 cli_setup_signing_state(the_cli, lp_client_signing());
2598 if (!cli_negprot(the_cli)) {
2599 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2600 cli_shutdown(the_cli);
2601 return False;
2604 if (the_cli->protocol != PROTOCOL_NT1) {
2605 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2606 cli_shutdown(the_cli);
2607 return False;
2611 * Do an anonymous session setup.
2614 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2615 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2616 cli_shutdown(the_cli);
2617 return False;
2620 if (!(the_cli->sec_mode & 1)) {
2621 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2622 cli_shutdown(the_cli);
2623 return False;
2626 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2627 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) ));
2628 cli_shutdown(the_cli);
2629 return False;
2633 * Ok - we have an anonymous connection to the IPC$ share.
2634 * Now start the NT Domain stuff :-).
2637 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2638 DEBUG(0,("spoolss_connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
2639 cli_nt_session_close(the_cli);
2640 cli_ulogoff(the_cli);
2641 cli_shutdown(the_cli);
2642 return False;
2645 return True;
2648 /***************************************************************************
2649 Connect to the client.
2650 ****************************************************************************/
2652 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2653 uint32 localprinter, uint32 type,
2654 POLICY_HND *handle, struct in_addr *client_ip)
2656 WERROR result;
2659 * If it's the first connection, contact the client
2660 * and connect to the IPC$ share anonymously
2662 if (smb_connections==0) {
2663 fstring unix_printer;
2665 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2667 ZERO_STRUCT(notify_cli);
2669 if(!spoolss_connect_to_client(&notify_cli, client_ip, unix_printer))
2670 return False;
2672 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2673 /* Tell the connections db we're now interested in printer
2674 * notify messages. */
2675 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2679 * Tell the specific printing tdb we want messages for this printer
2680 * by registering our PID.
2683 if (!print_notify_register_pid(snum))
2684 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2686 smb_connections++;
2688 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2689 type, handle);
2691 if (!W_ERROR_IS_OK(result))
2692 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2693 dos_errstr(result)));
2695 return (W_ERROR_IS_OK(result));
2698 /********************************************************************
2699 * _spoolss_rffpcnex
2700 * ReplyFindFirstPrinterChangeNotifyEx
2702 * before replying OK: status=0 a rpc call is made to the workstation
2703 * asking ReplyOpenPrinter
2705 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2706 * called from api_spoolss_rffpcnex
2707 ********************************************************************/
2709 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2711 POLICY_HND *handle = &q_u->handle;
2712 uint32 flags = q_u->flags;
2713 uint32 options = q_u->options;
2714 UNISTR2 *localmachine = &q_u->localmachine;
2715 uint32 printerlocal = q_u->printerlocal;
2716 int snum = -1;
2717 SPOOL_NOTIFY_OPTION *option = q_u->option;
2718 struct in_addr client_ip;
2720 /* store the notify value in the printer struct */
2722 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2724 if (!Printer) {
2725 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2726 return WERR_BADFID;
2729 Printer->notify.flags=flags;
2730 Printer->notify.options=options;
2731 Printer->notify.printerlocal=printerlocal;
2733 if (Printer->notify.option)
2734 free_spool_notify_option(&Printer->notify.option);
2736 Printer->notify.option=dup_spool_notify_option(option);
2738 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2739 sizeof(Printer->notify.localmachine)-1);
2741 /* Connect to the client machine and send a ReplyOpenPrinter */
2743 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2744 snum = -1;
2745 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2746 !get_printer_snum(p, handle, &snum) )
2747 return WERR_BADFID;
2749 client_ip.s_addr = inet_addr(p->conn->client_address);
2751 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2752 Printer->notify.printerlocal, 1,
2753 &Printer->notify.client_hnd, &client_ip))
2754 return WERR_SERVER_UNAVAILABLE;
2756 Printer->notify.client_connected=True;
2758 return WERR_OK;
2761 /*******************************************************************
2762 * fill a notify_info_data with the servername
2763 ********************************************************************/
2765 void spoolss_notify_server_name(int snum,
2766 SPOOL_NOTIFY_INFO_DATA *data,
2767 print_queue_struct *queue,
2768 NT_PRINTER_INFO_LEVEL *printer,
2769 TALLOC_CTX *mem_ctx)
2771 pstring temp;
2772 uint32 len;
2774 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2776 data->notify_data.data.length = len;
2777 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2779 if (!data->notify_data.data.string) {
2780 data->notify_data.data.length = 0;
2781 return;
2784 memcpy(data->notify_data.data.string, temp, len);
2787 /*******************************************************************
2788 * fill a notify_info_data with the printername (not including the servername).
2789 ********************************************************************/
2791 void spoolss_notify_printer_name(int snum,
2792 SPOOL_NOTIFY_INFO_DATA *data,
2793 print_queue_struct *queue,
2794 NT_PRINTER_INFO_LEVEL *printer,
2795 TALLOC_CTX *mem_ctx)
2797 pstring temp;
2798 uint32 len;
2800 /* the notify name should not contain the \\server\ part */
2801 char *p = strrchr(printer->info_2->printername, '\\');
2803 if (!p) {
2804 p = printer->info_2->printername;
2805 } else {
2806 p++;
2809 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2811 data->notify_data.data.length = len;
2812 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2814 if (!data->notify_data.data.string) {
2815 data->notify_data.data.length = 0;
2816 return;
2819 memcpy(data->notify_data.data.string, temp, len);
2822 /*******************************************************************
2823 * fill a notify_info_data with the servicename
2824 ********************************************************************/
2826 void spoolss_notify_share_name(int snum,
2827 SPOOL_NOTIFY_INFO_DATA *data,
2828 print_queue_struct *queue,
2829 NT_PRINTER_INFO_LEVEL *printer,
2830 TALLOC_CTX *mem_ctx)
2832 pstring temp;
2833 uint32 len;
2835 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2837 data->notify_data.data.length = len;
2838 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2840 if (!data->notify_data.data.string) {
2841 data->notify_data.data.length = 0;
2842 return;
2845 memcpy(data->notify_data.data.string, temp, len);
2848 /*******************************************************************
2849 * fill a notify_info_data with the port name
2850 ********************************************************************/
2852 void spoolss_notify_port_name(int snum,
2853 SPOOL_NOTIFY_INFO_DATA *data,
2854 print_queue_struct *queue,
2855 NT_PRINTER_INFO_LEVEL *printer,
2856 TALLOC_CTX *mem_ctx)
2858 pstring temp;
2859 uint32 len;
2861 /* even if it's strange, that's consistant in all the code */
2863 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2865 data->notify_data.data.length = len;
2866 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2868 if (!data->notify_data.data.string) {
2869 data->notify_data.data.length = 0;
2870 return;
2873 memcpy(data->notify_data.data.string, temp, len);
2876 /*******************************************************************
2877 * fill a notify_info_data with the printername
2878 * but it doesn't exist, have to see what to do
2879 ********************************************************************/
2881 void spoolss_notify_driver_name(int snum,
2882 SPOOL_NOTIFY_INFO_DATA *data,
2883 print_queue_struct *queue,
2884 NT_PRINTER_INFO_LEVEL *printer,
2885 TALLOC_CTX *mem_ctx)
2887 pstring temp;
2888 uint32 len;
2890 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2892 data->notify_data.data.length = len;
2893 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2895 if (!data->notify_data.data.string) {
2896 data->notify_data.data.length = 0;
2897 return;
2900 memcpy(data->notify_data.data.string, temp, len);
2903 /*******************************************************************
2904 * fill a notify_info_data with the comment
2905 ********************************************************************/
2907 void spoolss_notify_comment(int snum,
2908 SPOOL_NOTIFY_INFO_DATA *data,
2909 print_queue_struct *queue,
2910 NT_PRINTER_INFO_LEVEL *printer,
2911 TALLOC_CTX *mem_ctx)
2913 pstring temp;
2914 uint32 len;
2916 if (*printer->info_2->comment == '\0')
2917 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2918 else
2919 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2921 data->notify_data.data.length = len;
2922 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2924 if (!data->notify_data.data.string) {
2925 data->notify_data.data.length = 0;
2926 return;
2929 memcpy(data->notify_data.data.string, temp, len);
2932 /*******************************************************************
2933 * fill a notify_info_data with the comment
2934 * location = "Room 1, floor 2, building 3"
2935 ********************************************************************/
2937 void spoolss_notify_location(int snum,
2938 SPOOL_NOTIFY_INFO_DATA *data,
2939 print_queue_struct *queue,
2940 NT_PRINTER_INFO_LEVEL *printer,
2941 TALLOC_CTX *mem_ctx)
2943 pstring temp;
2944 uint32 len;
2946 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2948 data->notify_data.data.length = len;
2949 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2951 if (!data->notify_data.data.string) {
2952 data->notify_data.data.length = 0;
2953 return;
2956 memcpy(data->notify_data.data.string, temp, len);
2959 /*******************************************************************
2960 * fill a notify_info_data with the device mode
2961 * jfm:xxxx don't to it for know but that's a real problem !!!
2962 ********************************************************************/
2964 static void spoolss_notify_devmode(int snum,
2965 SPOOL_NOTIFY_INFO_DATA *data,
2966 print_queue_struct *queue,
2967 NT_PRINTER_INFO_LEVEL *printer,
2968 TALLOC_CTX *mem_ctx)
2972 /*******************************************************************
2973 * fill a notify_info_data with the separator file name
2974 ********************************************************************/
2976 void spoolss_notify_sepfile(int snum,
2977 SPOOL_NOTIFY_INFO_DATA *data,
2978 print_queue_struct *queue,
2979 NT_PRINTER_INFO_LEVEL *printer,
2980 TALLOC_CTX *mem_ctx)
2982 pstring temp;
2983 uint32 len;
2985 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2987 data->notify_data.data.length = len;
2988 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2990 if (!data->notify_data.data.string) {
2991 data->notify_data.data.length = 0;
2992 return;
2995 memcpy(data->notify_data.data.string, temp, len);
2998 /*******************************************************************
2999 * fill a notify_info_data with the print processor
3000 * jfm:xxxx return always winprint to indicate we don't do anything to it
3001 ********************************************************************/
3003 void spoolss_notify_print_processor(int snum,
3004 SPOOL_NOTIFY_INFO_DATA *data,
3005 print_queue_struct *queue,
3006 NT_PRINTER_INFO_LEVEL *printer,
3007 TALLOC_CTX *mem_ctx)
3009 pstring temp;
3010 uint32 len;
3012 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3014 data->notify_data.data.length = len;
3015 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3017 if (!data->notify_data.data.string) {
3018 data->notify_data.data.length = 0;
3019 return;
3022 memcpy(data->notify_data.data.string, temp, len);
3025 /*******************************************************************
3026 * fill a notify_info_data with the print processor options
3027 * jfm:xxxx send an empty string
3028 ********************************************************************/
3030 void spoolss_notify_parameters(int snum,
3031 SPOOL_NOTIFY_INFO_DATA *data,
3032 print_queue_struct *queue,
3033 NT_PRINTER_INFO_LEVEL *printer,
3034 TALLOC_CTX *mem_ctx)
3036 pstring temp;
3037 uint32 len;
3039 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3041 data->notify_data.data.length = len;
3042 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3044 if (!data->notify_data.data.string) {
3045 data->notify_data.data.length = 0;
3046 return;
3049 memcpy(data->notify_data.data.string, temp, len);
3052 /*******************************************************************
3053 * fill a notify_info_data with the data type
3054 * jfm:xxxx always send RAW as data type
3055 ********************************************************************/
3057 void spoolss_notify_datatype(int snum,
3058 SPOOL_NOTIFY_INFO_DATA *data,
3059 print_queue_struct *queue,
3060 NT_PRINTER_INFO_LEVEL *printer,
3061 TALLOC_CTX *mem_ctx)
3063 pstring temp;
3064 uint32 len;
3066 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3068 data->notify_data.data.length = len;
3069 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3071 if (!data->notify_data.data.string) {
3072 data->notify_data.data.length = 0;
3073 return;
3076 memcpy(data->notify_data.data.string, temp, len);
3079 /*******************************************************************
3080 * fill a notify_info_data with the security descriptor
3081 * jfm:xxxx send an null pointer to say no security desc
3082 * have to implement security before !
3083 ********************************************************************/
3085 static void spoolss_notify_security_desc(int snum,
3086 SPOOL_NOTIFY_INFO_DATA *data,
3087 print_queue_struct *queue,
3088 NT_PRINTER_INFO_LEVEL *printer,
3089 TALLOC_CTX *mem_ctx)
3091 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3092 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3095 /*******************************************************************
3096 * fill a notify_info_data with the attributes
3097 * jfm:xxxx a samba printer is always shared
3098 ********************************************************************/
3100 void spoolss_notify_attributes(int snum,
3101 SPOOL_NOTIFY_INFO_DATA *data,
3102 print_queue_struct *queue,
3103 NT_PRINTER_INFO_LEVEL *printer,
3104 TALLOC_CTX *mem_ctx)
3106 data->notify_data.value[0] = printer->info_2->attributes;
3107 data->notify_data.value[1] = 0;
3110 /*******************************************************************
3111 * fill a notify_info_data with the priority
3112 ********************************************************************/
3114 static void spoolss_notify_priority(int snum,
3115 SPOOL_NOTIFY_INFO_DATA *data,
3116 print_queue_struct *queue,
3117 NT_PRINTER_INFO_LEVEL *printer,
3118 TALLOC_CTX *mem_ctx)
3120 data->notify_data.value[0] = printer->info_2->priority;
3121 data->notify_data.value[1] = 0;
3124 /*******************************************************************
3125 * fill a notify_info_data with the default priority
3126 ********************************************************************/
3128 static void spoolss_notify_default_priority(int snum,
3129 SPOOL_NOTIFY_INFO_DATA *data,
3130 print_queue_struct *queue,
3131 NT_PRINTER_INFO_LEVEL *printer,
3132 TALLOC_CTX *mem_ctx)
3134 data->notify_data.value[0] = printer->info_2->default_priority;
3135 data->notify_data.value[1] = 0;
3138 /*******************************************************************
3139 * fill a notify_info_data with the start time
3140 ********************************************************************/
3142 static void spoolss_notify_start_time(int snum,
3143 SPOOL_NOTIFY_INFO_DATA *data,
3144 print_queue_struct *queue,
3145 NT_PRINTER_INFO_LEVEL *printer,
3146 TALLOC_CTX *mem_ctx)
3148 data->notify_data.value[0] = printer->info_2->starttime;
3149 data->notify_data.value[1] = 0;
3152 /*******************************************************************
3153 * fill a notify_info_data with the until time
3154 ********************************************************************/
3156 static void spoolss_notify_until_time(int snum,
3157 SPOOL_NOTIFY_INFO_DATA *data,
3158 print_queue_struct *queue,
3159 NT_PRINTER_INFO_LEVEL *printer,
3160 TALLOC_CTX *mem_ctx)
3162 data->notify_data.value[0] = printer->info_2->untiltime;
3163 data->notify_data.value[1] = 0;
3166 /*******************************************************************
3167 * fill a notify_info_data with the status
3168 ********************************************************************/
3170 static void spoolss_notify_status(int snum,
3171 SPOOL_NOTIFY_INFO_DATA *data,
3172 print_queue_struct *queue,
3173 NT_PRINTER_INFO_LEVEL *printer,
3174 TALLOC_CTX *mem_ctx)
3176 print_status_struct status;
3178 print_queue_length(snum, &status);
3179 data->notify_data.value[0]=(uint32) status.status;
3180 data->notify_data.value[1] = 0;
3183 /*******************************************************************
3184 * fill a notify_info_data with the number of jobs queued
3185 ********************************************************************/
3187 void spoolss_notify_cjobs(int snum,
3188 SPOOL_NOTIFY_INFO_DATA *data,
3189 print_queue_struct *queue,
3190 NT_PRINTER_INFO_LEVEL *printer,
3191 TALLOC_CTX *mem_ctx)
3193 data->notify_data.value[0] = print_queue_length(snum, NULL);
3194 data->notify_data.value[1] = 0;
3197 /*******************************************************************
3198 * fill a notify_info_data with the average ppm
3199 ********************************************************************/
3201 static void spoolss_notify_average_ppm(int snum,
3202 SPOOL_NOTIFY_INFO_DATA *data,
3203 print_queue_struct *queue,
3204 NT_PRINTER_INFO_LEVEL *printer,
3205 TALLOC_CTX *mem_ctx)
3207 /* always respond 8 pages per minutes */
3208 /* a little hard ! */
3209 data->notify_data.value[0] = printer->info_2->averageppm;
3210 data->notify_data.value[1] = 0;
3213 /*******************************************************************
3214 * fill a notify_info_data with username
3215 ********************************************************************/
3217 static void spoolss_notify_username(int snum,
3218 SPOOL_NOTIFY_INFO_DATA *data,
3219 print_queue_struct *queue,
3220 NT_PRINTER_INFO_LEVEL *printer,
3221 TALLOC_CTX *mem_ctx)
3223 pstring temp;
3224 uint32 len;
3226 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3228 data->notify_data.data.length = len;
3229 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3231 if (!data->notify_data.data.string) {
3232 data->notify_data.data.length = 0;
3233 return;
3236 memcpy(data->notify_data.data.string, temp, len);
3239 /*******************************************************************
3240 * fill a notify_info_data with job status
3241 ********************************************************************/
3243 static void spoolss_notify_job_status(int snum,
3244 SPOOL_NOTIFY_INFO_DATA *data,
3245 print_queue_struct *queue,
3246 NT_PRINTER_INFO_LEVEL *printer,
3247 TALLOC_CTX *mem_ctx)
3249 data->notify_data.value[0]=nt_printj_status(queue->status);
3250 data->notify_data.value[1] = 0;
3253 /*******************************************************************
3254 * fill a notify_info_data with job name
3255 ********************************************************************/
3257 static void spoolss_notify_job_name(int snum,
3258 SPOOL_NOTIFY_INFO_DATA *data,
3259 print_queue_struct *queue,
3260 NT_PRINTER_INFO_LEVEL *printer,
3261 TALLOC_CTX *mem_ctx)
3263 pstring temp;
3264 uint32 len;
3266 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3268 data->notify_data.data.length = len;
3269 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3271 if (!data->notify_data.data.string) {
3272 data->notify_data.data.length = 0;
3273 return;
3276 memcpy(data->notify_data.data.string, temp, len);
3279 /*******************************************************************
3280 * fill a notify_info_data with job status
3281 ********************************************************************/
3283 static void spoolss_notify_job_status_string(int snum,
3284 SPOOL_NOTIFY_INFO_DATA *data,
3285 print_queue_struct *queue,
3286 NT_PRINTER_INFO_LEVEL *printer,
3287 TALLOC_CTX *mem_ctx)
3290 * Now we're returning job status codes we just return a "" here. JRA.
3293 const char *p = "";
3294 pstring temp;
3295 uint32 len;
3297 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3298 p = "unknown";
3300 switch (queue->status) {
3301 case LPQ_QUEUED:
3302 p = "Queued";
3303 break;
3304 case LPQ_PAUSED:
3305 p = ""; /* NT provides the paused string */
3306 break;
3307 case LPQ_SPOOLING:
3308 p = "Spooling";
3309 break;
3310 case LPQ_PRINTING:
3311 p = "Printing";
3312 break;
3314 #endif /* NO LONGER NEEDED. */
3316 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3318 data->notify_data.data.length = len;
3319 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3321 if (!data->notify_data.data.string) {
3322 data->notify_data.data.length = 0;
3323 return;
3326 memcpy(data->notify_data.data.string, temp, len);
3329 /*******************************************************************
3330 * fill a notify_info_data with job time
3331 ********************************************************************/
3333 static void spoolss_notify_job_time(int snum,
3334 SPOOL_NOTIFY_INFO_DATA *data,
3335 print_queue_struct *queue,
3336 NT_PRINTER_INFO_LEVEL *printer,
3337 TALLOC_CTX *mem_ctx)
3339 data->notify_data.value[0]=0x0;
3340 data->notify_data.value[1]=0;
3343 /*******************************************************************
3344 * fill a notify_info_data with job size
3345 ********************************************************************/
3347 static void spoolss_notify_job_size(int snum,
3348 SPOOL_NOTIFY_INFO_DATA *data,
3349 print_queue_struct *queue,
3350 NT_PRINTER_INFO_LEVEL *printer,
3351 TALLOC_CTX *mem_ctx)
3353 data->notify_data.value[0]=queue->size;
3354 data->notify_data.value[1]=0;
3357 /*******************************************************************
3358 * fill a notify_info_data with page info
3359 ********************************************************************/
3360 static void spoolss_notify_total_pages(int snum,
3361 SPOOL_NOTIFY_INFO_DATA *data,
3362 print_queue_struct *queue,
3363 NT_PRINTER_INFO_LEVEL *printer,
3364 TALLOC_CTX *mem_ctx)
3366 data->notify_data.value[0]=queue->page_count;
3367 data->notify_data.value[1]=0;
3370 /*******************************************************************
3371 * fill a notify_info_data with pages printed info.
3372 ********************************************************************/
3373 static void spoolss_notify_pages_printed(int snum,
3374 SPOOL_NOTIFY_INFO_DATA *data,
3375 print_queue_struct *queue,
3376 NT_PRINTER_INFO_LEVEL *printer,
3377 TALLOC_CTX *mem_ctx)
3379 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3380 data->notify_data.value[1]=0;
3383 /*******************************************************************
3384 Fill a notify_info_data with job position.
3385 ********************************************************************/
3387 static void spoolss_notify_job_position(int snum,
3388 SPOOL_NOTIFY_INFO_DATA *data,
3389 print_queue_struct *queue,
3390 NT_PRINTER_INFO_LEVEL *printer,
3391 TALLOC_CTX *mem_ctx)
3393 data->notify_data.value[0]=queue->job;
3394 data->notify_data.value[1]=0;
3397 /*******************************************************************
3398 Fill a notify_info_data with submitted time.
3399 ********************************************************************/
3401 static void spoolss_notify_submitted_time(int snum,
3402 SPOOL_NOTIFY_INFO_DATA *data,
3403 print_queue_struct *queue,
3404 NT_PRINTER_INFO_LEVEL *printer,
3405 TALLOC_CTX *mem_ctx)
3407 struct tm *t;
3408 uint32 len;
3409 SYSTEMTIME st;
3410 char *p;
3412 t=gmtime(&queue->time);
3414 len = sizeof(SYSTEMTIME);
3416 data->notify_data.data.length = len;
3417 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3419 if (!data->notify_data.data.string) {
3420 data->notify_data.data.length = 0;
3421 return;
3424 make_systemtime(&st, t);
3427 * Systemtime must be linearized as a set of UINT16's.
3428 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3431 p = (char *)data->notify_data.data.string;
3432 SSVAL(p, 0, st.year);
3433 SSVAL(p, 2, st.month);
3434 SSVAL(p, 4, st.dayofweek);
3435 SSVAL(p, 6, st.day);
3436 SSVAL(p, 8, st.hour);
3437 SSVAL(p, 10, st.minute);
3438 SSVAL(p, 12, st.second);
3439 SSVAL(p, 14, st.milliseconds);
3442 struct s_notify_info_data_table
3444 uint16 type;
3445 uint16 field;
3446 const char *name;
3447 uint32 size;
3448 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3449 print_queue_struct *queue,
3450 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3453 /* A table describing the various print notification constants and
3454 whether the notification data is a pointer to a variable sized
3455 buffer, a one value uint32 or a two value uint32. */
3457 static const struct s_notify_info_data_table notify_info_data_table[] =
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3508 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3511 /*******************************************************************
3512 Return the size of info_data structure.
3513 ********************************************************************/
3515 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3517 int i=0;
3519 for (i = 0; i < sizeof(notify_info_data_table); i++)
3521 if ( (notify_info_data_table[i].type == type)
3522 && (notify_info_data_table[i].field == field) )
3524 switch(notify_info_data_table[i].size)
3526 case NOTIFY_ONE_VALUE:
3527 case NOTIFY_TWO_VALUE:
3528 return 1;
3529 case NOTIFY_STRING:
3530 return 2;
3532 /* The only pointer notify data I have seen on
3533 the wire is the submitted time and this has
3534 the notify size set to 4. -tpot */
3536 case NOTIFY_POINTER:
3537 return 4;
3539 case NOTIFY_SECDESC:
3540 return 5;
3545 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3547 return 0;
3550 /*******************************************************************
3551 Return the type of notify_info_data.
3552 ********************************************************************/
3554 static int type_of_notify_info_data(uint16 type, uint16 field)
3556 int i=0;
3558 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3559 if (notify_info_data_table[i].type == type &&
3560 notify_info_data_table[i].field == field)
3561 return notify_info_data_table[i].size;
3564 return False;
3567 /****************************************************************************
3568 ****************************************************************************/
3570 static int search_notify(uint16 type, uint16 field, int *value)
3572 int i;
3574 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3575 if (notify_info_data_table[i].type == type &&
3576 notify_info_data_table[i].field == field &&
3577 notify_info_data_table[i].fn != NULL) {
3578 *value = i;
3579 return True;
3583 return False;
3586 /****************************************************************************
3587 ****************************************************************************/
3589 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3591 info_data->type = type;
3592 info_data->field = field;
3593 info_data->reserved = 0;
3595 info_data->size = size_of_notify_info_data(type, field);
3596 info_data->enc_type = type_of_notify_info_data(type, field);
3598 info_data->id = id;
3603 /*******************************************************************
3605 * fill a notify_info struct with info asked
3607 ********************************************************************/
3609 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3610 snum, SPOOL_NOTIFY_OPTION_TYPE
3611 *option_type, uint32 id,
3612 TALLOC_CTX *mem_ctx)
3614 int field_num,j;
3615 uint16 type;
3616 uint16 field;
3618 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3619 NT_PRINTER_INFO_LEVEL *printer = NULL;
3620 print_queue_struct *queue=NULL;
3622 type=option_type->type;
3624 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3625 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3626 option_type->count, lp_servicename(snum)));
3628 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3629 return False;
3631 for(field_num=0; field_num<option_type->count; field_num++) {
3632 field = option_type->fields[field_num];
3634 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3636 if (!search_notify(type, field, &j) )
3637 continue;
3639 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3640 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3641 return False;
3642 } else
3643 info->data = tid;
3645 current_data = &info->data[info->count];
3647 construct_info_data(current_data, type, field, id);
3649 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3650 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3652 notify_info_data_table[j].fn(snum, current_data, queue,
3653 printer, mem_ctx);
3655 info->count++;
3658 free_a_printer(&printer, 2);
3659 return True;
3662 /*******************************************************************
3664 * fill a notify_info struct with info asked
3666 ********************************************************************/
3668 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3669 SPOOL_NOTIFY_INFO *info,
3670 NT_PRINTER_INFO_LEVEL *printer,
3671 int snum, SPOOL_NOTIFY_OPTION_TYPE
3672 *option_type, uint32 id,
3673 TALLOC_CTX *mem_ctx)
3675 int field_num,j;
3676 uint16 type;
3677 uint16 field;
3679 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3681 DEBUG(4,("construct_notify_jobs_info\n"));
3683 type = option_type->type;
3685 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3686 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3687 option_type->count));
3689 for(field_num=0; field_num<option_type->count; field_num++) {
3690 field = option_type->fields[field_num];
3692 if (!search_notify(type, field, &j) )
3693 continue;
3695 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3696 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3697 return False;
3699 else info->data = tid;
3701 current_data=&(info->data[info->count]);
3703 construct_info_data(current_data, type, field, id);
3704 notify_info_data_table[j].fn(snum, current_data, queue,
3705 printer, mem_ctx);
3706 info->count++;
3709 return True;
3713 * JFM: The enumeration is not that simple, it's even non obvious.
3715 * let's take an example: I want to monitor the PRINTER SERVER for
3716 * the printer's name and the number of jobs currently queued.
3717 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3718 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3720 * I have 3 printers on the back of my server.
3722 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3723 * structures.
3724 * Number Data Id
3725 * 1 printer 1 name 1
3726 * 2 printer 1 cjob 1
3727 * 3 printer 2 name 2
3728 * 4 printer 2 cjob 2
3729 * 5 printer 3 name 3
3730 * 6 printer 3 name 3
3732 * that's the print server case, the printer case is even worse.
3735 /*******************************************************************
3737 * enumerate all printers on the printserver
3738 * fill a notify_info struct with info asked
3740 ********************************************************************/
3742 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3743 SPOOL_NOTIFY_INFO *info,
3744 TALLOC_CTX *mem_ctx)
3746 int snum;
3747 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3748 int n_services=lp_numservices();
3749 int i;
3750 SPOOL_NOTIFY_OPTION *option;
3751 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3753 DEBUG(4,("printserver_notify_info\n"));
3755 if (!Printer)
3756 return WERR_BADFID;
3758 option=Printer->notify.option;
3759 info->version=2;
3760 info->data=NULL;
3761 info->count=0;
3763 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3764 sending a ffpcn() request first */
3766 if ( !option )
3767 return WERR_BADFID;
3769 for (i=0; i<option->count; i++) {
3770 option_type=&(option->ctr.type[i]);
3772 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3773 continue;
3775 for (snum=0; snum<n_services; snum++)
3777 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3778 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3782 #if 0
3784 * Debugging information, don't delete.
3787 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3788 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3789 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3791 for (i=0; i<info->count; i++) {
3792 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3793 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3794 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3796 #endif
3798 return WERR_OK;
3801 /*******************************************************************
3803 * fill a notify_info struct with info asked
3805 ********************************************************************/
3807 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3808 TALLOC_CTX *mem_ctx)
3810 int snum;
3811 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3812 int i;
3813 uint32 id;
3814 SPOOL_NOTIFY_OPTION *option;
3815 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3816 int count,j;
3817 print_queue_struct *queue=NULL;
3818 print_status_struct status;
3820 DEBUG(4,("printer_notify_info\n"));
3822 if (!Printer)
3823 return WERR_BADFID;
3825 option=Printer->notify.option;
3826 id = 0x0;
3827 info->version=2;
3828 info->data=NULL;
3829 info->count=0;
3831 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3832 sending a ffpcn() request first */
3834 if ( !option )
3835 return WERR_BADFID;
3837 get_printer_snum(p, hnd, &snum);
3839 for (i=0; i<option->count; i++) {
3840 option_type=&option->ctr.type[i];
3842 switch ( option_type->type ) {
3843 case PRINTER_NOTIFY_TYPE:
3844 if(construct_notify_printer_info(Printer, info, snum,
3845 option_type, id,
3846 mem_ctx))
3847 id--;
3848 break;
3850 case JOB_NOTIFY_TYPE: {
3851 NT_PRINTER_INFO_LEVEL *printer = NULL;
3853 count = print_queue_status(snum, &queue, &status);
3855 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3856 goto done;
3858 for (j=0; j<count; j++) {
3859 construct_notify_jobs_info(&queue[j], info,
3860 printer, snum,
3861 option_type,
3862 queue[j].job,
3863 mem_ctx);
3866 free_a_printer(&printer, 2);
3868 done:
3869 SAFE_FREE(queue);
3870 break;
3876 * Debugging information, don't delete.
3879 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3880 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3881 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3883 for (i=0; i<info->count; i++) {
3884 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3885 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3886 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3889 return WERR_OK;
3892 /********************************************************************
3893 * spoolss_rfnpcnex
3894 ********************************************************************/
3896 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3898 POLICY_HND *handle = &q_u->handle;
3899 SPOOL_NOTIFY_INFO *info = &r_u->info;
3901 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3902 WERROR result = WERR_BADFID;
3904 /* we always have a NOTIFY_INFO struct */
3905 r_u->info_ptr=0x1;
3907 if (!Printer) {
3908 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3909 OUR_HANDLE(handle)));
3910 goto done;
3913 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3916 * We are now using the change value, and
3917 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3918 * I don't have a global notification system, I'm sending back all the
3919 * informations even when _NOTHING_ has changed.
3922 /* We need to keep track of the change value to send back in
3923 RRPCN replies otherwise our updates are ignored. */
3925 Printer->notify.fnpcn = True;
3927 if (Printer->notify.client_connected) {
3928 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3929 Printer->notify.change = q_u->change;
3932 /* just ignore the SPOOL_NOTIFY_OPTION */
3934 switch (Printer->printer_type) {
3935 case PRINTER_HANDLE_IS_PRINTSERVER:
3936 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3937 break;
3939 case PRINTER_HANDLE_IS_PRINTER:
3940 result = printer_notify_info(p, handle, info, p->mem_ctx);
3941 break;
3944 Printer->notify.fnpcn = False;
3946 done:
3947 return result;
3950 /********************************************************************
3951 * construct_printer_info_0
3952 * fill a printer_info_0 struct
3953 ********************************************************************/
3955 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3957 pstring chaine;
3958 int count;
3959 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3960 counter_printer_0 *session_counter;
3961 uint32 global_counter;
3962 struct tm *t;
3963 time_t setuptime;
3964 print_status_struct status;
3966 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3967 return False;
3969 count = print_queue_length(snum, &status);
3971 /* check if we already have a counter for this printer */
3972 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3973 if (session_counter->snum == snum)
3974 break;
3977 /* it's the first time, add it to the list */
3978 if (session_counter==NULL) {
3979 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3980 free_a_printer(&ntprinter, 2);
3981 return False;
3983 ZERO_STRUCTP(session_counter);
3984 session_counter->snum=snum;
3985 session_counter->counter=0;
3986 DLIST_ADD(counter_list, session_counter);
3989 /* increment it */
3990 session_counter->counter++;
3992 /* JFM:
3993 * the global_counter should be stored in a TDB as it's common to all the clients
3994 * and should be zeroed on samba startup
3996 global_counter=session_counter->counter;
3998 pstrcpy(chaine,ntprinter->info_2->printername);
4000 init_unistr(&printer->printername, chaine);
4002 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
4003 init_unistr(&printer->servername, chaine);
4005 printer->cjobs = count;
4006 printer->total_jobs = 0;
4007 printer->total_bytes = 0;
4009 setuptime = (time_t)ntprinter->info_2->setuptime;
4010 t=gmtime(&setuptime);
4012 printer->year = t->tm_year+1900;
4013 printer->month = t->tm_mon+1;
4014 printer->dayofweek = t->tm_wday;
4015 printer->day = t->tm_mday;
4016 printer->hour = t->tm_hour;
4017 printer->minute = t->tm_min;
4018 printer->second = t->tm_sec;
4019 printer->milliseconds = 0;
4021 printer->global_counter = global_counter;
4022 printer->total_pages = 0;
4024 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4025 printer->major_version = 0x0005; /* NT 5 */
4026 printer->build_version = 0x0893; /* build 2195 */
4028 printer->unknown7 = 0x1;
4029 printer->unknown8 = 0x0;
4030 printer->unknown9 = 0x0;
4031 printer->session_counter = session_counter->counter;
4032 printer->unknown11 = 0x0;
4033 printer->printer_errors = 0x0; /* number of print failure */
4034 printer->unknown13 = 0x0;
4035 printer->unknown14 = 0x1;
4036 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4037 printer->unknown16 = 0x0;
4038 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4039 printer->unknown18 = 0x0;
4040 printer->status = nt_printq_status(status.status);
4041 printer->unknown20 = 0x0;
4042 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4043 printer->unknown22 = 0x0;
4044 printer->unknown23 = 0x6; /* 6 ???*/
4045 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4046 printer->unknown25 = 0;
4047 printer->unknown26 = 0;
4048 printer->unknown27 = 0;
4049 printer->unknown28 = 0;
4050 printer->unknown29 = 0;
4052 free_a_printer(&ntprinter,2);
4053 return (True);
4056 /********************************************************************
4057 * construct_printer_info_1
4058 * fill a printer_info_1 struct
4059 ********************************************************************/
4060 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4062 pstring chaine;
4063 pstring chaine2;
4064 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4066 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4067 return False;
4069 printer->flags=flags;
4071 if (*ntprinter->info_2->comment == '\0') {
4072 init_unistr(&printer->comment, lp_comment(snum));
4073 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4074 ntprinter->info_2->drivername, lp_comment(snum));
4076 else {
4077 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4078 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4079 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4082 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4084 init_unistr(&printer->description, chaine);
4085 init_unistr(&printer->name, chaine2);
4087 free_a_printer(&ntprinter,2);
4089 return True;
4092 /****************************************************************************
4093 Free a DEVMODE struct.
4094 ****************************************************************************/
4096 static void free_dev_mode(DEVICEMODE *dev)
4098 if (dev == NULL)
4099 return;
4101 SAFE_FREE(dev->dev_private);
4102 SAFE_FREE(dev);
4106 /****************************************************************************
4107 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4108 should be valid upon entry
4109 ****************************************************************************/
4111 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4113 if ( !devmode || !ntdevmode )
4114 return False;
4116 init_unistr(&devmode->devicename, ntdevmode->devicename);
4118 init_unistr(&devmode->formname, ntdevmode->formname);
4120 devmode->specversion = ntdevmode->specversion;
4121 devmode->driverversion = ntdevmode->driverversion;
4122 devmode->size = ntdevmode->size;
4123 devmode->driverextra = ntdevmode->driverextra;
4124 devmode->fields = ntdevmode->fields;
4126 devmode->orientation = ntdevmode->orientation;
4127 devmode->papersize = ntdevmode->papersize;
4128 devmode->paperlength = ntdevmode->paperlength;
4129 devmode->paperwidth = ntdevmode->paperwidth;
4130 devmode->scale = ntdevmode->scale;
4131 devmode->copies = ntdevmode->copies;
4132 devmode->defaultsource = ntdevmode->defaultsource;
4133 devmode->printquality = ntdevmode->printquality;
4134 devmode->color = ntdevmode->color;
4135 devmode->duplex = ntdevmode->duplex;
4136 devmode->yresolution = ntdevmode->yresolution;
4137 devmode->ttoption = ntdevmode->ttoption;
4138 devmode->collate = ntdevmode->collate;
4139 devmode->icmmethod = ntdevmode->icmmethod;
4140 devmode->icmintent = ntdevmode->icmintent;
4141 devmode->mediatype = ntdevmode->mediatype;
4142 devmode->dithertype = ntdevmode->dithertype;
4144 if (ntdevmode->nt_dev_private != NULL) {
4145 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4146 return False;
4149 return True;
4152 /****************************************************************************
4153 Create a DEVMODE struct. Returns malloced memory.
4154 ****************************************************************************/
4156 DEVICEMODE *construct_dev_mode(int snum)
4158 NT_PRINTER_INFO_LEVEL *printer = NULL;
4159 DEVICEMODE *devmode = NULL;
4161 DEBUG(7,("construct_dev_mode\n"));
4163 DEBUGADD(8,("getting printer characteristics\n"));
4165 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4166 return NULL;
4168 if ( !printer->info_2->devmode ) {
4169 DEBUG(5, ("BONG! There was no device mode!\n"));
4170 goto done;
4173 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4174 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4175 goto done;
4178 ZERO_STRUCTP(devmode);
4180 DEBUGADD(8,("loading DEVICEMODE\n"));
4182 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4183 free_dev_mode( devmode );
4184 devmode = NULL;
4187 done:
4188 free_a_printer(&printer,2);
4190 return devmode;
4193 /********************************************************************
4194 * construct_printer_info_2
4195 * fill a printer_info_2 struct
4196 ********************************************************************/
4198 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4200 int count;
4201 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4203 print_status_struct status;
4205 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4206 return False;
4208 count = print_queue_length(snum, &status);
4210 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4211 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4212 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4213 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4214 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4216 if (*ntprinter->info_2->comment == '\0')
4217 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4218 else
4219 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4221 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4222 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4223 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4224 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4225 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4227 printer->attributes = ntprinter->info_2->attributes;
4229 printer->priority = ntprinter->info_2->priority; /* priority */
4230 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4231 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4232 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4233 printer->status = nt_printq_status(status.status); /* status */
4234 printer->cjobs = count; /* jobs */
4235 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4237 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4238 DEBUG(8, ("Returning NULL Devicemode!\n"));
4241 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4242 /* steal the printer info sec_desc structure. [badly done]. */
4243 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4244 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4245 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4246 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4248 else {
4249 printer->secdesc = NULL;
4252 free_a_printer(&ntprinter, 2);
4253 return True;
4256 /********************************************************************
4257 * construct_printer_info_3
4258 * fill a printer_info_3 struct
4259 ********************************************************************/
4261 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4263 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4264 PRINTER_INFO_3 *printer = NULL;
4266 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4267 return False;
4269 *pp_printer = NULL;
4270 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4271 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4272 return False;
4275 ZERO_STRUCTP(printer);
4277 printer->flags = 4; /* These are the components of the SD we are returning. */
4278 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4279 /* steal the printer info sec_desc structure. [badly done]. */
4280 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4282 #if 0
4284 * Set the flags for the components we are returning.
4287 if (printer->secdesc->owner_sid)
4288 printer->flags |= OWNER_SECURITY_INFORMATION;
4290 if (printer->secdesc->grp_sid)
4291 printer->flags |= GROUP_SECURITY_INFORMATION;
4293 if (printer->secdesc->dacl)
4294 printer->flags |= DACL_SECURITY_INFORMATION;
4296 if (printer->secdesc->sacl)
4297 printer->flags |= SACL_SECURITY_INFORMATION;
4298 #endif
4300 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4301 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4302 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4305 free_a_printer(&ntprinter, 2);
4307 *pp_printer = printer;
4308 return True;
4311 /********************************************************************
4312 * construct_printer_info_4
4313 * fill a printer_info_4 struct
4314 ********************************************************************/
4316 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4318 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4320 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4321 return False;
4323 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4324 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4325 printer->attributes = ntprinter->info_2->attributes;
4327 free_a_printer(&ntprinter, 2);
4328 return True;
4331 /********************************************************************
4332 * construct_printer_info_5
4333 * fill a printer_info_5 struct
4334 ********************************************************************/
4336 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4338 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4340 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4341 return False;
4343 init_unistr(&printer->printername, ntprinter->info_2->printername);
4344 init_unistr(&printer->portname, ntprinter->info_2->portname);
4345 printer->attributes = ntprinter->info_2->attributes;
4347 /* these two are not used by NT+ according to MSDN */
4349 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4350 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4352 free_a_printer(&ntprinter, 2);
4354 return True;
4357 /********************************************************************
4358 * construct_printer_info_7
4359 * fill a printer_info_7 struct
4360 ********************************************************************/
4362 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4364 char *guid_str = NULL;
4365 struct uuid guid;
4367 if (is_printer_published(print_hnd, snum, &guid)) {
4368 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4369 strupper_m(guid_str);
4370 init_unistr(&printer->guid, guid_str);
4371 printer->action = SPOOL_DS_PUBLISH;
4372 } else {
4373 init_unistr(&printer->guid, "");
4374 printer->action = SPOOL_DS_UNPUBLISH;
4377 return True;
4380 /********************************************************************
4381 Spoolss_enumprinters.
4382 ********************************************************************/
4384 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4386 int snum;
4387 int i;
4388 int n_services=lp_numservices();
4389 PRINTER_INFO_1 *tp, *printers=NULL;
4390 PRINTER_INFO_1 current_prt;
4391 WERROR result = WERR_OK;
4393 DEBUG(4,("enum_all_printers_info_1\n"));
4395 for (snum=0; snum<n_services; snum++) {
4396 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4397 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4399 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4400 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4401 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4402 SAFE_FREE(printers);
4403 *returned=0;
4404 return WERR_NOMEM;
4406 else printers = tp;
4407 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4409 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4410 (*returned)++;
4415 /* check the required size. */
4416 for (i=0; i<*returned; i++)
4417 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4419 if (*needed > offered) {
4420 result = WERR_INSUFFICIENT_BUFFER;
4421 goto out;
4424 if (!rpcbuf_alloc_size(buffer, *needed)) {
4425 result = WERR_NOMEM;
4426 goto out;
4429 /* fill the buffer with the structures */
4430 for (i=0; i<*returned; i++)
4431 smb_io_printer_info_1("", buffer, &printers[i], 0);
4433 out:
4434 /* clear memory */
4436 SAFE_FREE(printers);
4438 if ( !W_ERROR_IS_OK(result) )
4439 *returned = 0;
4441 return result;
4444 /********************************************************************
4445 enum_all_printers_info_1_local.
4446 *********************************************************************/
4448 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4450 DEBUG(4,("enum_all_printers_info_1_local\n"));
4452 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4455 /********************************************************************
4456 enum_all_printers_info_1_name.
4457 *********************************************************************/
4459 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4461 char *s = name;
4463 DEBUG(4,("enum_all_printers_info_1_name\n"));
4465 if ((name[0] == '\\') && (name[1] == '\\'))
4466 s = name + 2;
4468 if (is_myname_or_ipaddr(s)) {
4469 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4471 else
4472 return WERR_INVALID_NAME;
4475 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4476 /********************************************************************
4477 enum_all_printers_info_1_remote.
4478 *********************************************************************/
4480 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4482 PRINTER_INFO_1 *printer;
4483 fstring printername;
4484 fstring desc;
4485 fstring comment;
4486 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4487 WERROR result = WERR_OK;
4489 /* JFM: currently it's more a place holder than anything else.
4490 * In the spooler world there is a notion of server registration.
4491 * the print servers are registered on the PDC (in the same domain)
4493 * We should have a TDB here. The registration is done thru an
4494 * undocumented RPC call.
4497 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4498 return WERR_NOMEM;
4500 *returned=1;
4502 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4503 slprintf(desc, sizeof(desc)-1,"%s", name);
4504 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4506 init_unistr(&printer->description, desc);
4507 init_unistr(&printer->name, printername);
4508 init_unistr(&printer->comment, comment);
4509 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4511 /* check the required size. */
4512 *needed += spoolss_size_printer_info_1(printer);
4514 if (*needed > offered) {
4515 result = WERR_INSUFFICIENT_BUFFER;
4516 goto out;
4519 if (!rpcbuf_alloc_size(buffer, *needed)) {
4520 result = WERR_NOMEM;
4521 goto out;
4524 /* fill the buffer with the structures */
4525 smb_io_printer_info_1("", buffer, printer, 0);
4527 out:
4528 /* clear memory */
4529 SAFE_FREE(printer);
4531 if ( !W_ERROR_IS_OK(result) )
4532 *returned = 0;
4534 return result;
4537 #endif
4539 /********************************************************************
4540 enum_all_printers_info_1_network.
4541 *********************************************************************/
4543 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4545 char *s = name;
4547 DEBUG(4,("enum_all_printers_info_1_network\n"));
4549 /* If we respond to a enum_printers level 1 on our name with flags
4550 set to PRINTER_ENUM_REMOTE with a list of printers then these
4551 printers incorrectly appear in the APW browse list.
4552 Specifically the printers for the server appear at the workgroup
4553 level where all the other servers in the domain are
4554 listed. Windows responds to this call with a
4555 WERR_CAN_NOT_COMPLETE so we should do the same. */
4557 if (name[0] == '\\' && name[1] == '\\')
4558 s = name + 2;
4560 if (is_myname_or_ipaddr(s))
4561 return WERR_CAN_NOT_COMPLETE;
4563 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4566 /********************************************************************
4567 * api_spoolss_enumprinters
4569 * called from api_spoolss_enumprinters (see this to understand)
4570 ********************************************************************/
4572 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4574 int snum;
4575 int i;
4576 int n_services=lp_numservices();
4577 PRINTER_INFO_2 *tp, *printers=NULL;
4578 PRINTER_INFO_2 current_prt;
4579 WERROR result = WERR_OK;
4581 for (snum=0; snum<n_services; snum++) {
4582 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4583 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4585 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4586 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) == NULL) {
4587 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4588 SAFE_FREE(printers);
4589 *returned = 0;
4590 return WERR_NOMEM;
4592 else printers = tp;
4593 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4594 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4595 (*returned)++;
4600 /* check the required size. */
4601 for (i=0; i<*returned; i++)
4602 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4604 if (*needed > offered) {
4605 result = WERR_INSUFFICIENT_BUFFER;
4606 goto out;
4609 if (!rpcbuf_alloc_size(buffer, *needed)) {
4610 result = WERR_NOMEM;
4611 goto out;
4614 /* fill the buffer with the structures */
4615 for (i=0; i<*returned; i++)
4616 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4618 out:
4619 /* clear memory */
4620 for (i=0; i<*returned; i++) {
4621 free_devmode(printers[i].devmode);
4623 SAFE_FREE(printers);
4625 if ( !W_ERROR_IS_OK(result) )
4626 *returned = 0;
4628 return result;
4631 /********************************************************************
4632 * handle enumeration of printers at level 1
4633 ********************************************************************/
4635 static WERROR enumprinters_level1( uint32 flags, fstring name,
4636 RPC_BUFFER *buffer, uint32 offered,
4637 uint32 *needed, uint32 *returned)
4639 /* Not all the flags are equals */
4641 if (flags & PRINTER_ENUM_LOCAL)
4642 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4644 if (flags & PRINTER_ENUM_NAME)
4645 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4647 #if 0 /* JERRY - disabled for now */
4648 if (flags & PRINTER_ENUM_REMOTE)
4649 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4650 #endif
4652 if (flags & PRINTER_ENUM_NETWORK)
4653 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4655 return WERR_OK; /* NT4sp5 does that */
4658 /********************************************************************
4659 * handle enumeration of printers at level 2
4660 ********************************************************************/
4662 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4663 RPC_BUFFER *buffer, uint32 offered,
4664 uint32 *needed, uint32 *returned)
4666 char *s = servername;
4668 if (flags & PRINTER_ENUM_LOCAL) {
4669 return enum_all_printers_info_2(buffer, offered, needed, returned);
4672 if (flags & PRINTER_ENUM_NAME) {
4673 if ((servername[0] == '\\') && (servername[1] == '\\'))
4674 s = servername + 2;
4675 if (is_myname_or_ipaddr(s))
4676 return enum_all_printers_info_2(buffer, offered, needed, returned);
4677 else
4678 return WERR_INVALID_NAME;
4681 if (flags & PRINTER_ENUM_REMOTE)
4682 return WERR_UNKNOWN_LEVEL;
4684 return WERR_OK;
4687 /********************************************************************
4688 * handle enumeration of printers at level 5
4689 ********************************************************************/
4691 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4692 RPC_BUFFER *buffer, uint32 offered,
4693 uint32 *needed, uint32 *returned)
4695 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4696 return WERR_OK;
4699 /********************************************************************
4700 * api_spoolss_enumprinters
4702 * called from api_spoolss_enumprinters (see this to understand)
4703 ********************************************************************/
4705 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4707 uint32 flags = q_u->flags;
4708 UNISTR2 *servername = &q_u->servername;
4709 uint32 level = q_u->level;
4710 RPC_BUFFER *buffer = NULL;
4711 uint32 offered = q_u->offered;
4712 uint32 *needed = &r_u->needed;
4713 uint32 *returned = &r_u->returned;
4715 fstring name;
4717 /* that's an [in out] buffer */
4719 if ( q_u->buffer ) {
4720 rpcbuf_move(q_u->buffer, &r_u->buffer);
4721 buffer = r_u->buffer;
4724 DEBUG(4,("_spoolss_enumprinters\n"));
4726 *needed=0;
4727 *returned=0;
4730 * Level 1:
4731 * flags==PRINTER_ENUM_NAME
4732 * if name=="" then enumerates all printers
4733 * if name!="" then enumerate the printer
4734 * flags==PRINTER_ENUM_REMOTE
4735 * name is NULL, enumerate printers
4736 * Level 2: name!="" enumerates printers, name can't be NULL
4737 * Level 3: doesn't exist
4738 * Level 4: does a local registry lookup
4739 * Level 5: same as Level 2
4742 unistr2_to_ascii(name, servername, sizeof(name)-1);
4743 strupper_m(name);
4745 switch (level) {
4746 case 1:
4747 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4748 case 2:
4749 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4750 case 5:
4751 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4752 case 3:
4753 case 4:
4754 break;
4756 return WERR_UNKNOWN_LEVEL;
4759 /****************************************************************************
4760 ****************************************************************************/
4762 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4764 PRINTER_INFO_0 *printer=NULL;
4765 WERROR result = WERR_OK;
4767 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4768 return WERR_NOMEM;
4770 construct_printer_info_0(print_hnd, printer, snum);
4772 /* check the required size. */
4773 *needed += spoolss_size_printer_info_0(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 smb_io_printer_info_0("", buffer, printer, 0);
4788 out:
4789 /* clear memory */
4791 SAFE_FREE(printer);
4793 return result;
4796 /****************************************************************************
4797 ****************************************************************************/
4799 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4801 PRINTER_INFO_1 *printer=NULL;
4802 WERROR result = WERR_OK;
4804 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4805 return WERR_NOMEM;
4807 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4809 /* check the required size. */
4810 *needed += spoolss_size_printer_info_1(printer);
4812 if (*needed > offered) {
4813 result = WERR_INSUFFICIENT_BUFFER;
4814 goto out;
4817 if (!rpcbuf_alloc_size(buffer, *needed)) {
4818 result = WERR_NOMEM;
4819 goto out;
4822 /* fill the buffer with the structures */
4823 smb_io_printer_info_1("", buffer, printer, 0);
4825 out:
4826 /* clear memory */
4827 SAFE_FREE(printer);
4829 return result;
4832 /****************************************************************************
4833 ****************************************************************************/
4835 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4837 PRINTER_INFO_2 *printer=NULL;
4838 WERROR result = WERR_OK;
4840 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4841 return WERR_NOMEM;
4843 construct_printer_info_2(print_hnd, printer, snum);
4845 /* check the required size. */
4846 *needed += spoolss_size_printer_info_2(printer);
4848 if (*needed > offered) {
4849 result = WERR_INSUFFICIENT_BUFFER;
4850 goto out;
4853 if (!rpcbuf_alloc_size(buffer, *needed)) {
4854 result = WERR_NOMEM;
4855 goto out;
4858 /* fill the buffer with the structures */
4859 if (!smb_io_printer_info_2("", buffer, printer, 0))
4860 result = WERR_NOMEM;
4862 out:
4863 /* clear memory */
4864 free_printer_info_2(printer);
4866 return result;
4869 /****************************************************************************
4870 ****************************************************************************/
4872 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4874 PRINTER_INFO_3 *printer=NULL;
4875 WERROR result = WERR_OK;
4877 if (!construct_printer_info_3(print_hnd, &printer, snum))
4878 return WERR_NOMEM;
4880 /* check the required size. */
4881 *needed += spoolss_size_printer_info_3(printer);
4883 if (*needed > offered) {
4884 result = WERR_INSUFFICIENT_BUFFER;
4885 goto out;
4888 if (!rpcbuf_alloc_size(buffer, *needed)) {
4889 result = WERR_NOMEM;
4890 goto out;
4893 /* fill the buffer with the structures */
4894 smb_io_printer_info_3("", buffer, printer, 0);
4896 out:
4897 /* clear memory */
4898 free_printer_info_3(printer);
4900 return result;
4903 /****************************************************************************
4904 ****************************************************************************/
4906 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4908 PRINTER_INFO_4 *printer=NULL;
4909 WERROR result = WERR_OK;
4911 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4912 return WERR_NOMEM;
4914 if (!construct_printer_info_4(print_hnd, printer, snum))
4915 return WERR_NOMEM;
4917 /* check the required size. */
4918 *needed += spoolss_size_printer_info_4(printer);
4920 if (*needed > offered) {
4921 result = WERR_INSUFFICIENT_BUFFER;
4922 goto out;
4925 if (!rpcbuf_alloc_size(buffer, *needed)) {
4926 result = WERR_NOMEM;
4927 goto out;
4930 /* fill the buffer with the structures */
4931 smb_io_printer_info_4("", buffer, printer, 0);
4933 out:
4934 /* clear memory */
4935 free_printer_info_4(printer);
4937 return result;
4940 /****************************************************************************
4941 ****************************************************************************/
4943 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4945 PRINTER_INFO_5 *printer=NULL;
4946 WERROR result = WERR_OK;
4948 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4949 return WERR_NOMEM;
4951 if (!construct_printer_info_5(print_hnd, printer, snum))
4952 return WERR_NOMEM;
4954 /* check the required size. */
4955 *needed += spoolss_size_printer_info_5(printer);
4957 if (*needed > offered) {
4958 result = WERR_INSUFFICIENT_BUFFER;
4959 goto out;
4962 if (!rpcbuf_alloc_size(buffer, *needed)) {
4963 result = WERR_NOMEM;
4964 goto out;
4967 /* fill the buffer with the structures */
4968 smb_io_printer_info_5("", buffer, printer, 0);
4970 out:
4971 /* clear memory */
4972 free_printer_info_5(printer);
4974 return result;
4977 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4979 PRINTER_INFO_7 *printer=NULL;
4980 WERROR result = WERR_OK;
4982 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4983 return WERR_NOMEM;
4985 if (!construct_printer_info_7(print_hnd, printer, snum))
4986 return WERR_NOMEM;
4988 /* check the required size. */
4989 *needed += spoolss_size_printer_info_7(printer);
4991 if (*needed > offered) {
4992 result = WERR_INSUFFICIENT_BUFFER;
4993 goto out;
4996 if (!rpcbuf_alloc_size(buffer, *needed)) {
4997 result = WERR_NOMEM;
4998 goto out;
5002 /* fill the buffer with the structures */
5003 smb_io_printer_info_7("", buffer, printer, 0);
5005 out:
5006 /* clear memory */
5007 free_printer_info_7(printer);
5009 return result;
5012 /****************************************************************************
5013 ****************************************************************************/
5015 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5017 POLICY_HND *handle = &q_u->handle;
5018 uint32 level = q_u->level;
5019 RPC_BUFFER *buffer = NULL;
5020 uint32 offered = q_u->offered;
5021 uint32 *needed = &r_u->needed;
5022 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5024 int snum;
5026 /* that's an [in out] buffer */
5028 if ( q_u->buffer ) {
5029 rpcbuf_move(q_u->buffer, &r_u->buffer);
5030 buffer = r_u->buffer;
5033 *needed=0;
5035 if (!get_printer_snum(p, handle, &snum))
5036 return WERR_BADFID;
5038 switch (level) {
5039 case 0:
5040 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5041 case 1:
5042 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5043 case 2:
5044 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5045 case 3:
5046 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5047 case 4:
5048 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5049 case 5:
5050 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5051 case 7:
5052 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5054 return WERR_UNKNOWN_LEVEL;
5057 /********************************************************************
5058 * fill a DRIVER_INFO_1 struct
5059 ********************************************************************/
5061 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5063 init_unistr( &info->name, driver.info_3->name);
5066 /********************************************************************
5067 * construct_printer_driver_info_1
5068 ********************************************************************/
5070 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5072 NT_PRINTER_INFO_LEVEL *printer = NULL;
5073 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5075 ZERO_STRUCT(driver);
5077 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5078 return WERR_INVALID_PRINTER_NAME;
5080 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5081 return WERR_UNKNOWN_PRINTER_DRIVER;
5083 fill_printer_driver_info_1(info, driver, servername, architecture);
5085 free_a_printer(&printer,2);
5087 return WERR_OK;
5090 /********************************************************************
5091 * construct_printer_driver_info_2
5092 * fill a printer_info_2 struct
5093 ********************************************************************/
5095 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5097 pstring temp;
5099 info->version=driver.info_3->cversion;
5101 init_unistr( &info->name, driver.info_3->name );
5102 init_unistr( &info->architecture, driver.info_3->environment );
5105 if (strlen(driver.info_3->driverpath)) {
5106 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5107 init_unistr( &info->driverpath, temp );
5108 } else
5109 init_unistr( &info->driverpath, "" );
5111 if (strlen(driver.info_3->datafile)) {
5112 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5113 init_unistr( &info->datafile, temp );
5114 } else
5115 init_unistr( &info->datafile, "" );
5117 if (strlen(driver.info_3->configfile)) {
5118 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5119 init_unistr( &info->configfile, temp );
5120 } else
5121 init_unistr( &info->configfile, "" );
5124 /********************************************************************
5125 * construct_printer_driver_info_2
5126 * fill a printer_info_2 struct
5127 ********************************************************************/
5129 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5131 NT_PRINTER_INFO_LEVEL *printer = NULL;
5132 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5134 ZERO_STRUCT(printer);
5135 ZERO_STRUCT(driver);
5137 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5138 return WERR_INVALID_PRINTER_NAME;
5140 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5141 return WERR_UNKNOWN_PRINTER_DRIVER;
5143 fill_printer_driver_info_2(info, driver, servername);
5145 free_a_printer(&printer,2);
5147 return WERR_OK;
5150 /********************************************************************
5151 * copy a strings array and convert to UNICODE
5153 * convert an array of ascii string to a UNICODE string
5154 ********************************************************************/
5156 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5158 int i=0;
5159 int j=0;
5160 const char *v;
5161 pstring line;
5162 uint16 *tuary;
5164 DEBUG(6,("init_unistr_array\n"));
5165 *uni_array=NULL;
5167 while (True)
5169 if ( !char_array )
5170 v = "";
5171 else
5173 v = char_array[i];
5174 if (!v)
5175 v = ""; /* hack to handle null lists */
5178 /* hack to allow this to be used in places other than when generating
5179 the list of dependent files */
5181 if ( servername )
5182 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5183 else
5184 pstrcpy( line, v );
5186 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5188 /* add one extra unit16 for the second terminating NULL */
5190 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5191 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5192 return 0;
5193 } else
5194 *uni_array = tuary;
5196 if ( !strlen(v) )
5197 break;
5199 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5200 i++;
5203 if (*uni_array) {
5204 /* special case for ""; we need to add both NULL's here */
5205 if (!j)
5206 (*uni_array)[j++]=0x0000;
5207 (*uni_array)[j]=0x0000;
5210 DEBUGADD(6,("last one:done\n"));
5212 /* return size of array in uint16's */
5214 return j+1;
5217 /********************************************************************
5218 * construct_printer_info_3
5219 * fill a printer_info_3 struct
5220 ********************************************************************/
5222 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5224 pstring temp;
5226 ZERO_STRUCTP(info);
5228 info->version=driver.info_3->cversion;
5230 init_unistr( &info->name, driver.info_3->name );
5231 init_unistr( &info->architecture, driver.info_3->environment );
5233 if (strlen(driver.info_3->driverpath)) {
5234 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5235 init_unistr( &info->driverpath, temp );
5236 } else
5237 init_unistr( &info->driverpath, "" );
5239 if (strlen(driver.info_3->datafile)) {
5240 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5241 init_unistr( &info->datafile, temp );
5242 } else
5243 init_unistr( &info->datafile, "" );
5245 if (strlen(driver.info_3->configfile)) {
5246 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5247 init_unistr( &info->configfile, temp );
5248 } else
5249 init_unistr( &info->configfile, "" );
5251 if (strlen(driver.info_3->helpfile)) {
5252 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5253 init_unistr( &info->helpfile, temp );
5254 } else
5255 init_unistr( &info->helpfile, "" );
5257 init_unistr( &info->monitorname, driver.info_3->monitorname );
5258 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5260 info->dependentfiles=NULL;
5261 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5264 /********************************************************************
5265 * construct_printer_info_3
5266 * fill a printer_info_3 struct
5267 ********************************************************************/
5269 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5271 NT_PRINTER_INFO_LEVEL *printer = NULL;
5272 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5273 WERROR status;
5274 ZERO_STRUCT(driver);
5276 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5277 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5278 if (!W_ERROR_IS_OK(status))
5279 return WERR_INVALID_PRINTER_NAME;
5281 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5282 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5284 #if 0 /* JERRY */
5287 * I put this code in during testing. Helpful when commenting out the
5288 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5289 * as win2k always queries the driver using an infor level of 6.
5290 * I've left it in (but ifdef'd out) because I'll probably
5291 * use it in experimentation again in the future. --jerry 22/01/2002
5294 if (!W_ERROR_IS_OK(status)) {
5296 * Is this a W2k client ?
5298 if (version == 3) {
5299 /* Yes - try again with a WinNT driver. */
5300 version = 2;
5301 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5302 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5304 #endif
5306 if (!W_ERROR_IS_OK(status)) {
5307 free_a_printer(&printer,2);
5308 return WERR_UNKNOWN_PRINTER_DRIVER;
5311 #if 0 /* JERRY */
5313 #endif
5316 fill_printer_driver_info_3(info, driver, servername);
5318 free_a_printer(&printer,2);
5320 return WERR_OK;
5323 /********************************************************************
5324 * construct_printer_info_6
5325 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5326 ********************************************************************/
5328 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5330 pstring temp;
5331 fstring nullstr;
5333 ZERO_STRUCTP(info);
5334 memset(&nullstr, '\0', sizeof(fstring));
5336 info->version=driver.info_3->cversion;
5338 init_unistr( &info->name, driver.info_3->name );
5339 init_unistr( &info->architecture, driver.info_3->environment );
5341 if (strlen(driver.info_3->driverpath)) {
5342 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5343 init_unistr( &info->driverpath, temp );
5344 } else
5345 init_unistr( &info->driverpath, "" );
5347 if (strlen(driver.info_3->datafile)) {
5348 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5349 init_unistr( &info->datafile, temp );
5350 } else
5351 init_unistr( &info->datafile, "" );
5353 if (strlen(driver.info_3->configfile)) {
5354 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5355 init_unistr( &info->configfile, temp );
5356 } else
5357 init_unistr( &info->configfile, "" );
5359 if (strlen(driver.info_3->helpfile)) {
5360 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5361 init_unistr( &info->helpfile, temp );
5362 } else
5363 init_unistr( &info->helpfile, "" );
5365 init_unistr( &info->monitorname, driver.info_3->monitorname );
5366 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5368 info->dependentfiles = NULL;
5369 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5371 info->previousdrivernames=NULL;
5372 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5374 info->driver_date.low=0;
5375 info->driver_date.high=0;
5377 info->padding=0;
5378 info->driver_version_low=0;
5379 info->driver_version_high=0;
5381 init_unistr( &info->mfgname, "");
5382 init_unistr( &info->oem_url, "");
5383 init_unistr( &info->hardware_id, "");
5384 init_unistr( &info->provider, "");
5387 /********************************************************************
5388 * construct_printer_info_6
5389 * fill a printer_info_6 struct
5390 ********************************************************************/
5392 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5393 fstring servername, fstring architecture, uint32 version)
5395 NT_PRINTER_INFO_LEVEL *printer = NULL;
5396 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5397 WERROR status;
5399 ZERO_STRUCT(driver);
5401 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5403 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5405 if (!W_ERROR_IS_OK(status))
5406 return WERR_INVALID_PRINTER_NAME;
5408 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5410 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5412 if (!W_ERROR_IS_OK(status))
5415 * Is this a W2k client ?
5418 if (version < 3) {
5419 free_a_printer(&printer,2);
5420 return WERR_UNKNOWN_PRINTER_DRIVER;
5423 /* Yes - try again with a WinNT driver. */
5424 version = 2;
5425 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5426 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5427 if (!W_ERROR_IS_OK(status)) {
5428 free_a_printer(&printer,2);
5429 return WERR_UNKNOWN_PRINTER_DRIVER;
5433 fill_printer_driver_info_6(info, driver, servername);
5435 free_a_printer(&printer,2);
5436 free_a_printer_driver(driver, 3);
5438 return WERR_OK;
5441 /****************************************************************************
5442 ****************************************************************************/
5444 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5446 SAFE_FREE(info->dependentfiles);
5449 /****************************************************************************
5450 ****************************************************************************/
5452 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5454 SAFE_FREE(info->dependentfiles);
5457 /****************************************************************************
5458 ****************************************************************************/
5460 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5462 DRIVER_INFO_1 *info=NULL;
5463 WERROR result;
5465 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5466 return WERR_NOMEM;
5468 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5469 if (!W_ERROR_IS_OK(result))
5470 goto out;
5472 /* check the required size. */
5473 *needed += spoolss_size_printer_driver_info_1(info);
5475 if (*needed > offered) {
5476 result = WERR_INSUFFICIENT_BUFFER;
5477 goto out;
5480 if (!rpcbuf_alloc_size(buffer, *needed)) {
5481 result = WERR_NOMEM;
5482 goto out;
5485 /* fill the buffer with the structures */
5486 smb_io_printer_driver_info_1("", buffer, info, 0);
5488 out:
5489 /* clear memory */
5490 SAFE_FREE(info);
5492 return result;
5495 /****************************************************************************
5496 ****************************************************************************/
5498 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5500 DRIVER_INFO_2 *info=NULL;
5501 WERROR result;
5503 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5504 return WERR_NOMEM;
5506 result = construct_printer_driver_info_2(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_2(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_2("", buffer, info, 0);
5526 out:
5527 /* clear memory */
5528 SAFE_FREE(info);
5530 return result;
5533 /****************************************************************************
5534 ****************************************************************************/
5536 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5538 DRIVER_INFO_3 info;
5539 WERROR result;
5541 ZERO_STRUCT(info);
5543 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5544 if (!W_ERROR_IS_OK(result))
5545 goto out;
5547 /* check the required size. */
5548 *needed += spoolss_size_printer_driver_info_3(&info);
5550 if (*needed > offered) {
5551 result = WERR_INSUFFICIENT_BUFFER;
5552 goto out;
5555 if (!rpcbuf_alloc_size(buffer, *needed)) {
5556 result = WERR_NOMEM;
5557 goto out;
5560 /* fill the buffer with the structures */
5561 smb_io_printer_driver_info_3("", buffer, &info, 0);
5563 out:
5564 free_printer_driver_info_3(&info);
5566 return result;
5569 /****************************************************************************
5570 ****************************************************************************/
5572 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5574 DRIVER_INFO_6 info;
5575 WERROR result;
5577 ZERO_STRUCT(info);
5579 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5580 if (!W_ERROR_IS_OK(result))
5581 goto out;
5583 /* check the required size. */
5584 *needed += spoolss_size_printer_driver_info_6(&info);
5586 if (*needed > offered) {
5587 result = WERR_INSUFFICIENT_BUFFER;
5588 goto out;
5591 if (!rpcbuf_alloc_size(buffer, *needed)) {
5592 result = WERR_NOMEM;
5593 goto out;
5596 /* fill the buffer with the structures */
5597 smb_io_printer_driver_info_6("", buffer, &info, 0);
5599 out:
5600 free_printer_driver_info_6(&info);
5602 return result;
5605 /****************************************************************************
5606 ****************************************************************************/
5608 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5610 POLICY_HND *handle = &q_u->handle;
5611 UNISTR2 *uni_arch = &q_u->architecture;
5612 uint32 level = q_u->level;
5613 uint32 clientmajorversion = q_u->clientmajorversion;
5614 RPC_BUFFER *buffer = NULL;
5615 uint32 offered = q_u->offered;
5616 uint32 *needed = &r_u->needed;
5617 uint32 *servermajorversion = &r_u->servermajorversion;
5618 uint32 *serverminorversion = &r_u->serverminorversion;
5619 Printer_entry *printer;
5621 fstring servername;
5622 fstring architecture;
5623 int snum;
5625 /* that's an [in out] buffer */
5627 if ( q_u->buffer ) {
5628 rpcbuf_move(q_u->buffer, &r_u->buffer);
5629 buffer = r_u->buffer;
5632 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5634 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5635 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5636 return WERR_INVALID_PRINTER_NAME;
5639 *needed = 0;
5640 *servermajorversion = 0;
5641 *serverminorversion = 0;
5643 fstrcpy(servername, get_server_name( printer ));
5644 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5646 if (!get_printer_snum(p, handle, &snum))
5647 return WERR_BADFID;
5649 switch (level) {
5650 case 1:
5651 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5652 case 2:
5653 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5654 case 3:
5655 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5656 case 6:
5657 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5658 #if 0 /* JERRY */
5659 case 101:
5660 /* apparently this call is the equivalent of
5661 EnumPrinterDataEx() for the DsDriver key */
5662 break;
5663 #endif
5666 return WERR_UNKNOWN_LEVEL;
5669 /****************************************************************************
5670 ****************************************************************************/
5672 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5674 POLICY_HND *handle = &q_u->handle;
5676 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5678 if (!Printer) {
5679 DEBUG(3,("Error in startpageprinter printer handle\n"));
5680 return WERR_BADFID;
5683 Printer->page_started=True;
5684 return WERR_OK;
5687 /****************************************************************************
5688 ****************************************************************************/
5690 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5692 POLICY_HND *handle = &q_u->handle;
5693 int snum;
5695 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5697 if (!Printer) {
5698 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5699 return WERR_BADFID;
5702 if (!get_printer_snum(p, handle, &snum))
5703 return WERR_BADFID;
5705 Printer->page_started=False;
5706 print_job_endpage(snum, Printer->jobid);
5708 return WERR_OK;
5711 /********************************************************************
5712 * api_spoolss_getprinter
5713 * called from the spoolss dispatcher
5715 ********************************************************************/
5717 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5719 POLICY_HND *handle = &q_u->handle;
5720 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5721 uint32 *jobid = &r_u->jobid;
5723 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5724 int snum;
5725 pstring jobname;
5726 fstring datatype;
5727 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5728 struct current_user user;
5730 if (!Printer) {
5731 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5732 return WERR_BADFID;
5735 get_current_user(&user, p);
5738 * a nice thing with NT is it doesn't listen to what you tell it.
5739 * when asked to send _only_ RAW datas, it tries to send datas
5740 * in EMF format.
5742 * So I add checks like in NT Server ...
5745 if (info_1->p_datatype != 0) {
5746 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5747 if (strcmp(datatype, "RAW") != 0) {
5748 (*jobid)=0;
5749 return WERR_INVALID_DATATYPE;
5753 /* get the share number of the printer */
5754 if (!get_printer_snum(p, handle, &snum)) {
5755 return WERR_BADFID;
5758 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5760 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5762 /* An error occured in print_job_start() so return an appropriate
5763 NT error code. */
5765 if (Printer->jobid == -1) {
5766 return map_werror_from_unix(errno);
5769 Printer->document_started=True;
5770 (*jobid) = Printer->jobid;
5772 return WERR_OK;
5775 /********************************************************************
5776 * api_spoolss_getprinter
5777 * called from the spoolss dispatcher
5779 ********************************************************************/
5781 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5783 POLICY_HND *handle = &q_u->handle;
5785 return _spoolss_enddocprinter_internal(p, handle);
5788 /****************************************************************************
5789 ****************************************************************************/
5791 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5793 POLICY_HND *handle = &q_u->handle;
5794 uint32 buffer_size = q_u->buffer_size;
5795 uint8 *buffer = q_u->buffer;
5796 uint32 *buffer_written = &q_u->buffer_size2;
5797 int snum;
5798 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5800 if (!Printer) {
5801 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5802 r_u->buffer_written = q_u->buffer_size2;
5803 return WERR_BADFID;
5806 if (!get_printer_snum(p, handle, &snum))
5807 return WERR_BADFID;
5809 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5810 (SMB_OFF_T)-1, (size_t)buffer_size);
5811 if (*buffer_written == (uint32)-1) {
5812 r_u->buffer_written = 0;
5813 if (errno == ENOSPC)
5814 return WERR_NO_SPOOL_SPACE;
5815 else
5816 return WERR_ACCESS_DENIED;
5819 r_u->buffer_written = q_u->buffer_size2;
5821 return WERR_OK;
5824 /********************************************************************
5825 * api_spoolss_getprinter
5826 * called from the spoolss dispatcher
5828 ********************************************************************/
5830 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5831 pipes_struct *p)
5833 struct current_user user;
5834 int snum;
5835 WERROR errcode = WERR_BADFUNC;
5836 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5838 get_current_user(&user, p);
5840 if (!Printer) {
5841 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5842 return WERR_BADFID;
5845 if (!get_printer_snum(p, handle, &snum))
5846 return WERR_BADFID;
5848 switch (command) {
5849 case PRINTER_CONTROL_PAUSE:
5850 if (print_queue_pause(&user, snum, &errcode)) {
5851 errcode = WERR_OK;
5853 break;
5854 case PRINTER_CONTROL_RESUME:
5855 case PRINTER_CONTROL_UNPAUSE:
5856 if (print_queue_resume(&user, snum, &errcode)) {
5857 errcode = WERR_OK;
5859 break;
5860 case PRINTER_CONTROL_PURGE:
5861 if (print_queue_purge(&user, snum, &errcode)) {
5862 errcode = WERR_OK;
5864 break;
5865 default:
5866 return WERR_UNKNOWN_LEVEL;
5869 return errcode;
5872 /********************************************************************
5873 * api_spoolss_abortprinter
5874 * From MSDN: "Deletes printer's spool file if printer is configured
5875 * for spooling"
5876 ********************************************************************/
5878 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5880 POLICY_HND *handle = &q_u->handle;
5881 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5882 int snum;
5883 struct current_user user;
5884 WERROR errcode = WERR_OK;
5886 if (!Printer) {
5887 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5888 return WERR_BADFID;
5891 if (!get_printer_snum(p, handle, &snum))
5892 return WERR_BADFID;
5894 get_current_user( &user, p );
5896 print_job_delete( &user, snum, Printer->jobid, &errcode );
5898 return errcode;
5901 /********************************************************************
5902 * called by spoolss_api_setprinter
5903 * when updating a printer description
5904 ********************************************************************/
5906 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5907 const SPOOL_PRINTER_INFO_LEVEL *info,
5908 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5910 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5911 WERROR result;
5912 int snum;
5914 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5916 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5917 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5918 OUR_HANDLE(handle)));
5920 result = WERR_BADFID;
5921 goto done;
5924 /* Check the user has permissions to change the security
5925 descriptor. By experimentation with two NT machines, the user
5926 requires Full Access to the printer to change security
5927 information. */
5929 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5930 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5931 result = WERR_ACCESS_DENIED;
5932 goto done;
5935 /* NT seems to like setting the security descriptor even though
5936 nothing may have actually changed. */
5938 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5940 if (DEBUGLEVEL >= 10) {
5941 SEC_ACL *the_acl;
5942 int i;
5944 the_acl = old_secdesc_ctr->sec->dacl;
5945 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5946 PRINTERNAME(snum), the_acl->num_aces));
5948 for (i = 0; i < the_acl->num_aces; i++) {
5949 fstring sid_str;
5951 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5953 DEBUG(10, ("%s 0x%08x\n", sid_str,
5954 the_acl->ace[i].info.mask));
5957 the_acl = secdesc_ctr->sec->dacl;
5959 if (the_acl) {
5960 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5961 PRINTERNAME(snum), the_acl->num_aces));
5963 for (i = 0; i < the_acl->num_aces; i++) {
5964 fstring sid_str;
5966 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5968 DEBUG(10, ("%s 0x%08x\n", sid_str,
5969 the_acl->ace[i].info.mask));
5971 } else {
5972 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5976 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5978 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5979 result = WERR_OK;
5980 goto done;
5983 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5985 done:
5987 return result;
5990 /********************************************************************
5991 Canonicalize printer info from a client
5993 ATTN: It does not matter what we set the servername to hear
5994 since we do the necessary work in get_a_printer() to set it to
5995 the correct value based on what the client sent in the
5996 _spoolss_open_printer_ex().
5997 ********************************************************************/
5999 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6001 fstring printername;
6002 const char *p;
6004 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6005 "portname=%s drivername=%s comment=%s location=%s\n",
6006 info->servername, info->printername, info->sharename,
6007 info->portname, info->drivername, info->comment, info->location));
6009 /* we force some elements to "correct" values */
6010 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6011 fstrcpy(info->sharename, lp_servicename(snum));
6013 /* check to see if we allow printername != sharename */
6015 if ( lp_force_printername(snum) ) {
6016 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6017 global_myname(), info->sharename );
6018 } else {
6020 /* make sure printername is in \\server\printername format */
6022 fstrcpy( printername, info->printername );
6023 p = printername;
6024 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6025 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6026 p++;
6029 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6030 global_myname(), p );
6033 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6034 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6038 return True;
6041 /****************************************************************************
6042 ****************************************************************************/
6044 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6046 char *cmd = lp_addprinter_cmd();
6047 char **qlines;
6048 pstring command;
6049 int numlines;
6050 int ret;
6051 int fd;
6052 fstring remote_machine = "%m";
6053 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6054 BOOL is_print_op = False;
6056 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6058 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6059 cmd, printer->info_2->printername, printer->info_2->sharename,
6060 printer->info_2->portname, printer->info_2->drivername,
6061 printer->info_2->location, printer->info_2->comment, remote_machine);
6063 if ( token )
6064 is_print_op = user_has_privileges( token, &se_printop );
6066 DEBUG(10,("Running [%s]\n", command));
6068 /********* BEGIN SePrintOperatorPrivilege **********/
6070 if ( is_print_op )
6071 become_root();
6073 if ( (ret = smbrun(command, &fd)) == 0 ) {
6074 /* Tell everyone we updated smb.conf. */
6075 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6078 if ( is_print_op )
6079 unbecome_root();
6081 /********* END SePrintOperatorPrivilege **********/
6083 DEBUGADD(10,("returned [%d]\n", ret));
6085 if ( ret != 0 ) {
6086 if (fd != -1)
6087 close(fd);
6088 return False;
6091 /* reload our services immediately */
6092 reload_services( False );
6094 numlines = 0;
6095 /* Get lines and convert them back to dos-codepage */
6096 qlines = fd_lines_load(fd, &numlines);
6097 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6098 close(fd);
6100 /* Set the portname to what the script says the portname should be. */
6101 /* but don't require anything to be return from the script exit a good error code */
6103 if (numlines) {
6104 /* Set the portname to what the script says the portname should be. */
6105 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6106 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6109 file_lines_free(qlines);
6110 return True;
6113 /********************************************************************
6114 * Called by spoolss_api_setprinter
6115 * when updating a printer description.
6116 ********************************************************************/
6118 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6119 const SPOOL_PRINTER_INFO_LEVEL *info,
6120 DEVICEMODE *devmode)
6122 int snum;
6123 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6124 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6125 WERROR result;
6126 UNISTR2 buffer;
6127 fstring asc_buffer;
6129 DEBUG(8,("update_printer\n"));
6131 result = WERR_OK;
6133 if (!Printer) {
6134 result = WERR_BADFID;
6135 goto done;
6138 if (!get_printer_snum(p, handle, &snum)) {
6139 result = WERR_BADFID;
6140 goto done;
6143 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6144 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6145 result = WERR_BADFID;
6146 goto done;
6149 DEBUGADD(8,("Converting info_2 struct\n"));
6152 * convert_printer_info converts the incoming
6153 * info from the client and overwrites the info
6154 * just read from the tdb in the pointer 'printer'.
6157 if (!convert_printer_info(info, printer, level)) {
6158 result = WERR_NOMEM;
6159 goto done;
6162 if (devmode) {
6163 /* we have a valid devmode
6164 convert it and link it*/
6166 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6167 if (!convert_devicemode(printer->info_2->printername, devmode,
6168 &printer->info_2->devmode)) {
6169 result = WERR_NOMEM;
6170 goto done;
6174 /* Do sanity check on the requested changes for Samba */
6176 if (!check_printer_ok(printer->info_2, snum)) {
6177 result = WERR_INVALID_PARAM;
6178 goto done;
6181 /* FIXME!!! If the driver has changed we really should verify that
6182 it is installed before doing much else --jerry */
6184 /* Check calling user has permission to update printer description */
6186 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6187 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6188 result = WERR_ACCESS_DENIED;
6189 goto done;
6192 /* Call addprinter hook */
6193 /* Check changes to see if this is really needed */
6195 if ( *lp_addprinter_cmd()
6196 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6197 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6198 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6199 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6201 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6202 result = WERR_ACCESS_DENIED;
6203 goto done;
6207 * make sure we actually reload the services after
6208 * this as smb.conf could have a new section in it
6209 * .... shouldn't .... but could
6211 reload_services(False);
6215 * When a *new* driver is bound to a printer, the drivername is used to
6216 * lookup previously saved driver initialization info, which is then
6217 * bound to the printer, simulating what happens in the Windows arch.
6219 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6221 if (!set_driver_init(printer, 2))
6223 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6224 printer->info_2->drivername));
6227 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6228 printer->info_2->drivername));
6230 notify_printer_driver(snum, printer->info_2->drivername);
6234 * flag which changes actually occured. This is a small subset of
6235 * all the possible changes. We also have to update things in the
6236 * DsSpooler key.
6239 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6240 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6241 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6242 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6244 notify_printer_comment(snum, printer->info_2->comment);
6247 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6248 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6249 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6250 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6252 notify_printer_sharename(snum, printer->info_2->sharename);
6255 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6256 char *pname;
6258 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6259 pname++;
6260 else
6261 pname = printer->info_2->printername;
6264 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6265 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6266 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6268 notify_printer_printername( snum, pname );
6271 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6272 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6273 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6274 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6276 notify_printer_port(snum, printer->info_2->portname);
6279 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6280 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6281 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6282 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6284 notify_printer_location(snum, printer->info_2->location);
6287 /* here we need to update some more DsSpooler keys */
6288 /* uNCName, serverName, shortServerName */
6290 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6291 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6292 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6293 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6294 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6296 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6297 global_myname(), printer->info_2->sharename );
6298 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6299 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6300 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6302 /* Update printer info */
6303 result = mod_a_printer(printer, 2);
6305 done:
6306 free_a_printer(&printer, 2);
6307 free_a_printer(&old_printer, 2);
6310 return result;
6313 /****************************************************************************
6314 ****************************************************************************/
6315 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6316 const SPOOL_PRINTER_INFO_LEVEL *info)
6318 #ifdef HAVE_ADS
6319 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6320 int snum;
6321 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6323 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6325 if (!Printer)
6326 return WERR_BADFID;
6328 if (!get_printer_snum(p, handle, &snum))
6329 return WERR_BADFID;
6331 nt_printer_publish(Printer, snum, info7->action);
6333 return WERR_OK;
6334 #else
6335 return WERR_UNKNOWN_LEVEL;
6336 #endif
6338 /****************************************************************************
6339 ****************************************************************************/
6341 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6343 POLICY_HND *handle = &q_u->handle;
6344 uint32 level = q_u->level;
6345 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6346 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6347 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6348 uint32 command = q_u->command;
6349 WERROR result;
6351 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6353 if (!Printer) {
6354 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6355 return WERR_BADFID;
6358 /* check the level */
6359 switch (level) {
6360 case 0:
6361 return control_printer(handle, command, p);
6362 case 2:
6363 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6364 if (!W_ERROR_IS_OK(result))
6365 return result;
6366 if (secdesc_ctr)
6367 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6368 return result;
6369 case 3:
6370 return update_printer_sec(handle, level, info, p,
6371 secdesc_ctr);
6372 case 7:
6373 return publish_or_unpublish_printer(p, handle, info);
6374 default:
6375 return WERR_UNKNOWN_LEVEL;
6379 /****************************************************************************
6380 ****************************************************************************/
6382 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6384 POLICY_HND *handle = &q_u->handle;
6385 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6387 if (!Printer) {
6388 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6389 return WERR_BADFID;
6392 if (Printer->notify.client_connected==True) {
6393 int snum = -1;
6395 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6396 snum = -1;
6397 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6398 !get_printer_snum(p, handle, &snum) )
6399 return WERR_BADFID;
6401 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6404 Printer->notify.flags=0;
6405 Printer->notify.options=0;
6406 Printer->notify.localmachine[0]='\0';
6407 Printer->notify.printerlocal=0;
6408 if (Printer->notify.option)
6409 free_spool_notify_option(&Printer->notify.option);
6410 Printer->notify.client_connected=False;
6412 return WERR_OK;
6415 /****************************************************************************
6416 ****************************************************************************/
6418 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6420 /* that's an [in out] buffer */
6422 if ( q_u->buffer )
6423 rpcbuf_move(q_u->buffer, &r_u->buffer);
6425 r_u->needed = 0;
6426 return WERR_INVALID_PARAM; /* this is what a NT server
6427 returns for AddJob. AddJob
6428 must fail on non-local
6429 printers */
6432 /****************************************************************************
6433 ****************************************************************************/
6435 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6436 int position, int snum,
6437 NT_PRINTER_INFO_LEVEL *ntprinter)
6439 struct tm *t;
6441 t=gmtime(&queue->time);
6443 job_info->jobid=queue->job;
6444 init_unistr(&job_info->printername, lp_servicename(snum));
6445 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6446 init_unistr(&job_info->username, queue->fs_user);
6447 init_unistr(&job_info->document, queue->fs_file);
6448 init_unistr(&job_info->datatype, "RAW");
6449 init_unistr(&job_info->text_status, "");
6450 job_info->status=nt_printj_status(queue->status);
6451 job_info->priority=queue->priority;
6452 job_info->position=position;
6453 job_info->totalpages=queue->page_count;
6454 job_info->pagesprinted=0;
6456 make_systemtime(&job_info->submitted, t);
6459 /****************************************************************************
6460 ****************************************************************************/
6462 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6463 int position, int snum,
6464 NT_PRINTER_INFO_LEVEL *ntprinter,
6465 DEVICEMODE *devmode)
6467 struct tm *t;
6469 t=gmtime(&queue->time);
6471 job_info->jobid=queue->job;
6473 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6475 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6476 init_unistr(&job_info->username, queue->fs_user);
6477 init_unistr(&job_info->document, queue->fs_file);
6478 init_unistr(&job_info->notifyname, queue->fs_user);
6479 init_unistr(&job_info->datatype, "RAW");
6480 init_unistr(&job_info->printprocessor, "winprint");
6481 init_unistr(&job_info->parameters, "");
6482 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6483 init_unistr(&job_info->text_status, "");
6485 /* and here the security descriptor */
6487 job_info->status=nt_printj_status(queue->status);
6488 job_info->priority=queue->priority;
6489 job_info->position=position;
6490 job_info->starttime=0;
6491 job_info->untiltime=0;
6492 job_info->totalpages=queue->page_count;
6493 job_info->size=queue->size;
6494 make_systemtime(&(job_info->submitted), t);
6495 job_info->timeelapsed=0;
6496 job_info->pagesprinted=0;
6498 job_info->devmode = devmode;
6500 return (True);
6503 /****************************************************************************
6504 Enumjobs at level 1.
6505 ****************************************************************************/
6507 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6508 NT_PRINTER_INFO_LEVEL *ntprinter,
6509 RPC_BUFFER *buffer, uint32 offered,
6510 uint32 *needed, uint32 *returned)
6512 JOB_INFO_1 *info;
6513 int i;
6514 WERROR result = WERR_OK;
6516 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6517 if (info==NULL) {
6518 SAFE_FREE(queue);
6519 *returned=0;
6520 return WERR_NOMEM;
6523 for (i=0; i<*returned; i++)
6524 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6526 SAFE_FREE(queue);
6528 /* check the required size. */
6529 for (i=0; i<*returned; i++)
6530 (*needed) += spoolss_size_job_info_1(&info[i]);
6532 if (*needed > offered) {
6533 result = WERR_INSUFFICIENT_BUFFER;
6534 goto out;
6537 if (!rpcbuf_alloc_size(buffer, *needed)) {
6538 result = WERR_NOMEM;
6539 goto out;
6542 /* fill the buffer with the structures */
6543 for (i=0; i<*returned; i++)
6544 smb_io_job_info_1("", buffer, &info[i], 0);
6546 out:
6547 /* clear memory */
6548 SAFE_FREE(info);
6550 if ( !W_ERROR_IS_OK(result) )
6551 *returned = 0;
6553 return result;
6556 /****************************************************************************
6557 Enumjobs at level 2.
6558 ****************************************************************************/
6560 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6561 NT_PRINTER_INFO_LEVEL *ntprinter,
6562 RPC_BUFFER *buffer, uint32 offered,
6563 uint32 *needed, uint32 *returned)
6565 JOB_INFO_2 *info = NULL;
6566 int i;
6567 WERROR result = WERR_OK;
6568 DEVICEMODE *devmode = NULL;
6570 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6571 *returned=0;
6572 return WERR_NOMEM;
6575 /* this should not be a failure condition if the devmode is NULL */
6577 devmode = construct_dev_mode(snum);
6579 for (i=0; i<*returned; i++)
6580 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6582 free_a_printer(&ntprinter, 2);
6583 SAFE_FREE(queue);
6585 /* check the required size. */
6586 for (i=0; i<*returned; i++)
6587 (*needed) += spoolss_size_job_info_2(&info[i]);
6589 if (*needed > offered) {
6590 result = WERR_INSUFFICIENT_BUFFER;
6591 goto out;
6594 if (!rpcbuf_alloc_size(buffer, *needed)) {
6595 result = WERR_NOMEM;
6596 goto out;
6599 /* fill the buffer with the structures */
6600 for (i=0; i<*returned; i++)
6601 smb_io_job_info_2("", buffer, &info[i], 0);
6603 out:
6604 free_devmode(devmode);
6605 SAFE_FREE(info);
6607 if ( !W_ERROR_IS_OK(result) )
6608 *returned = 0;
6610 return result;
6614 /****************************************************************************
6615 Enumjobs.
6616 ****************************************************************************/
6618 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6620 POLICY_HND *handle = &q_u->handle;
6621 uint32 level = q_u->level;
6622 RPC_BUFFER *buffer = NULL;
6623 uint32 offered = q_u->offered;
6624 uint32 *needed = &r_u->needed;
6625 uint32 *returned = &r_u->returned;
6626 WERROR wret;
6627 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6628 int snum;
6629 print_status_struct prt_status;
6630 print_queue_struct *queue=NULL;
6632 /* that's an [in out] buffer */
6634 if ( q_u->buffer ) {
6635 rpcbuf_move(q_u->buffer, &r_u->buffer);
6636 buffer = r_u->buffer;
6639 DEBUG(4,("_spoolss_enumjobs\n"));
6641 *needed=0;
6642 *returned=0;
6644 /* lookup the printer snum and tdb entry */
6646 if (!get_printer_snum(p, handle, &snum))
6647 return WERR_BADFID;
6649 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6650 if ( !W_ERROR_IS_OK(wret) )
6651 return wret;
6653 *returned = print_queue_status(snum, &queue, &prt_status);
6654 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6656 if (*returned == 0) {
6657 SAFE_FREE(queue);
6658 return WERR_OK;
6661 switch (level) {
6662 case 1:
6663 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6664 return wret;
6665 case 2:
6666 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6667 return wret;
6668 default:
6669 SAFE_FREE(queue);
6670 *returned=0;
6671 wret = WERR_UNKNOWN_LEVEL;
6674 free_a_printer( &ntprinter, 2 );
6675 return wret;
6678 /****************************************************************************
6679 ****************************************************************************/
6681 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6683 return WERR_OK;
6686 /****************************************************************************
6687 ****************************************************************************/
6689 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6691 POLICY_HND *handle = &q_u->handle;
6692 uint32 jobid = q_u->jobid;
6693 uint32 command = q_u->command;
6695 struct current_user user;
6696 int snum;
6697 WERROR errcode = WERR_BADFUNC;
6699 if (!get_printer_snum(p, handle, &snum)) {
6700 return WERR_BADFID;
6703 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6704 return WERR_INVALID_PRINTER_NAME;
6707 get_current_user(&user, p);
6709 switch (command) {
6710 case JOB_CONTROL_CANCEL:
6711 case JOB_CONTROL_DELETE:
6712 if (print_job_delete(&user, snum, jobid, &errcode)) {
6713 errcode = WERR_OK;
6715 break;
6716 case JOB_CONTROL_PAUSE:
6717 if (print_job_pause(&user, snum, jobid, &errcode)) {
6718 errcode = WERR_OK;
6720 break;
6721 case JOB_CONTROL_RESTART:
6722 case JOB_CONTROL_RESUME:
6723 if (print_job_resume(&user, snum, jobid, &errcode)) {
6724 errcode = WERR_OK;
6726 break;
6727 default:
6728 return WERR_UNKNOWN_LEVEL;
6731 return errcode;
6734 /****************************************************************************
6735 Enumerates all printer drivers at level 1.
6736 ****************************************************************************/
6738 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6740 int i;
6741 int ndrivers;
6742 uint32 version;
6743 fstring *list = NULL;
6744 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6745 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6746 WERROR result = WERR_OK;
6748 *returned=0;
6750 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6751 list=NULL;
6752 ndrivers=get_ntdrivers(&list, architecture, version);
6753 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6755 if(ndrivers == -1)
6756 return WERR_NOMEM;
6758 if(ndrivers != 0) {
6759 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6760 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6761 SAFE_FREE(driver_info_1);
6762 SAFE_FREE(list);
6763 return WERR_NOMEM;
6765 else driver_info_1 = tdi1;
6768 for (i=0; i<ndrivers; i++) {
6769 WERROR status;
6770 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6771 ZERO_STRUCT(driver);
6772 status = get_a_printer_driver(&driver, 3, list[i],
6773 architecture, version);
6774 if (!W_ERROR_IS_OK(status)) {
6775 SAFE_FREE(list);
6776 return status;
6778 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6779 free_a_printer_driver(driver, 3);
6782 *returned+=ndrivers;
6783 SAFE_FREE(list);
6786 /* check the required size. */
6787 for (i=0; i<*returned; i++) {
6788 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6789 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6792 if (*needed > offered) {
6793 result = WERR_INSUFFICIENT_BUFFER;
6794 goto out;
6797 if (!rpcbuf_alloc_size(buffer, *needed)) {
6798 result = WERR_NOMEM;
6799 goto out;
6802 /* fill the buffer with the driver structures */
6803 for (i=0; i<*returned; i++) {
6804 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6805 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6808 out:
6809 SAFE_FREE(driver_info_1);
6811 if ( !W_ERROR_IS_OK(result) )
6812 *returned = 0;
6814 return result;
6817 /****************************************************************************
6818 Enumerates all printer drivers at level 2.
6819 ****************************************************************************/
6821 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6823 int i;
6824 int ndrivers;
6825 uint32 version;
6826 fstring *list = NULL;
6827 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6828 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6829 WERROR result = WERR_OK;
6831 *returned=0;
6833 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6834 list=NULL;
6835 ndrivers=get_ntdrivers(&list, architecture, version);
6836 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6838 if(ndrivers == -1)
6839 return WERR_NOMEM;
6841 if(ndrivers != 0) {
6842 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6843 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6844 SAFE_FREE(driver_info_2);
6845 SAFE_FREE(list);
6846 return WERR_NOMEM;
6848 else driver_info_2 = tdi2;
6851 for (i=0; i<ndrivers; i++) {
6852 WERROR status;
6854 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6855 ZERO_STRUCT(driver);
6856 status = get_a_printer_driver(&driver, 3, list[i],
6857 architecture, version);
6858 if (!W_ERROR_IS_OK(status)) {
6859 SAFE_FREE(list);
6860 return status;
6862 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6863 free_a_printer_driver(driver, 3);
6866 *returned+=ndrivers;
6867 SAFE_FREE(list);
6870 /* check the required size. */
6871 for (i=0; i<*returned; i++) {
6872 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6873 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6876 if (*needed > offered) {
6877 result = WERR_INSUFFICIENT_BUFFER;
6878 goto out;
6881 if (!rpcbuf_alloc_size(buffer, *needed)) {
6882 result = WERR_NOMEM;
6883 goto out;
6886 /* fill the buffer with the form structures */
6887 for (i=0; i<*returned; i++) {
6888 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6889 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6892 out:
6893 SAFE_FREE(driver_info_2);
6895 if ( !W_ERROR_IS_OK(result) )
6896 *returned = 0;
6898 return result;
6901 /****************************************************************************
6902 Enumerates all printer drivers at level 3.
6903 ****************************************************************************/
6905 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6907 int i;
6908 int ndrivers;
6909 uint32 version;
6910 fstring *list = NULL;
6911 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6912 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6913 WERROR result = WERR_OK;
6915 *returned=0;
6917 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6918 list=NULL;
6919 ndrivers=get_ntdrivers(&list, architecture, version);
6920 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6922 if(ndrivers == -1)
6923 return WERR_NOMEM;
6925 if(ndrivers != 0) {
6926 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6927 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6928 SAFE_FREE(driver_info_3);
6929 SAFE_FREE(list);
6930 return WERR_NOMEM;
6932 else driver_info_3 = tdi3;
6935 for (i=0; i<ndrivers; i++) {
6936 WERROR status;
6938 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6939 ZERO_STRUCT(driver);
6940 status = get_a_printer_driver(&driver, 3, list[i],
6941 architecture, version);
6942 if (!W_ERROR_IS_OK(status)) {
6943 SAFE_FREE(list);
6944 return status;
6946 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6947 free_a_printer_driver(driver, 3);
6950 *returned+=ndrivers;
6951 SAFE_FREE(list);
6954 /* check the required size. */
6955 for (i=0; i<*returned; i++) {
6956 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6957 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6960 if (*needed > offered) {
6961 result = WERR_INSUFFICIENT_BUFFER;
6962 goto out;
6965 if (!rpcbuf_alloc_size(buffer, *needed)) {
6966 result = WERR_NOMEM;
6967 goto out;
6970 /* fill the buffer with the driver structures */
6971 for (i=0; i<*returned; i++) {
6972 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6973 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6976 out:
6977 for (i=0; i<*returned; i++)
6978 SAFE_FREE(driver_info_3[i].dependentfiles);
6980 SAFE_FREE(driver_info_3);
6982 if ( !W_ERROR_IS_OK(result) )
6983 *returned = 0;
6985 return result;
6988 /****************************************************************************
6989 Enumerates all printer drivers.
6990 ****************************************************************************/
6992 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6994 uint32 level = q_u->level;
6995 RPC_BUFFER *buffer = NULL;
6996 uint32 offered = q_u->offered;
6997 uint32 *needed = &r_u->needed;
6998 uint32 *returned = &r_u->returned;
7000 fstring servername;
7001 fstring architecture;
7003 /* that's an [in out] buffer */
7005 if ( q_u->buffer ) {
7006 rpcbuf_move(q_u->buffer, &r_u->buffer);
7007 buffer = r_u->buffer;
7010 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7012 *needed = 0;
7013 *returned = 0;
7015 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7016 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7018 if ( !is_myname_or_ipaddr( servername ) )
7019 return WERR_UNKNOWN_PRINTER_DRIVER;
7021 switch (level) {
7022 case 1:
7023 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7024 case 2:
7025 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7026 case 3:
7027 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7028 default:
7029 return WERR_UNKNOWN_LEVEL;
7033 /****************************************************************************
7034 ****************************************************************************/
7036 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7038 form->flag=list->flag;
7039 init_unistr(&form->name, list->name);
7040 form->width=list->width;
7041 form->length=list->length;
7042 form->left=list->left;
7043 form->top=list->top;
7044 form->right=list->right;
7045 form->bottom=list->bottom;
7048 /****************************************************************************
7049 ****************************************************************************/
7051 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7053 uint32 level = q_u->level;
7054 RPC_BUFFER *buffer = NULL;
7055 uint32 offered = q_u->offered;
7056 uint32 *needed = &r_u->needed;
7057 uint32 *numofforms = &r_u->numofforms;
7058 uint32 numbuiltinforms;
7060 nt_forms_struct *list=NULL;
7061 nt_forms_struct *builtinlist=NULL;
7062 FORM_1 *forms_1;
7063 int buffer_size=0;
7064 int i;
7066 /* that's an [in out] buffer */
7068 if ( q_u->buffer ) {
7069 rpcbuf_move(q_u->buffer, &r_u->buffer);
7070 buffer = r_u->buffer;
7073 DEBUG(4,("_spoolss_enumforms\n"));
7074 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7075 DEBUGADD(5,("Info level [%d]\n", level));
7077 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7078 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7079 *numofforms = get_ntforms(&list);
7080 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7081 *numofforms += numbuiltinforms;
7083 if (*numofforms == 0)
7084 return WERR_NO_MORE_ITEMS;
7086 switch (level) {
7087 case 1:
7088 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7089 *numofforms=0;
7090 return WERR_NOMEM;
7093 /* construct the list of form structures */
7094 for (i=0; i<numbuiltinforms; i++) {
7095 DEBUGADD(6,("Filling form number [%d]\n",i));
7096 fill_form_1(&forms_1[i], &builtinlist[i]);
7099 SAFE_FREE(builtinlist);
7101 for (; i<*numofforms; i++) {
7102 DEBUGADD(6,("Filling form number [%d]\n",i));
7103 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7106 SAFE_FREE(list);
7108 /* check the required size. */
7109 for (i=0; i<numbuiltinforms; i++) {
7110 DEBUGADD(6,("adding form [%d]'s size\n",i));
7111 buffer_size += spoolss_size_form_1(&forms_1[i]);
7113 for (; i<*numofforms; i++) {
7114 DEBUGADD(6,("adding form [%d]'s size\n",i));
7115 buffer_size += spoolss_size_form_1(&forms_1[i]);
7118 *needed=buffer_size;
7120 if (*needed > offered) {
7121 SAFE_FREE(forms_1);
7122 *numofforms=0;
7123 return WERR_INSUFFICIENT_BUFFER;
7126 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7127 SAFE_FREE(forms_1);
7128 *numofforms=0;
7129 return WERR_NOMEM;
7132 /* fill the buffer with the form structures */
7133 for (i=0; i<numbuiltinforms; i++) {
7134 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7135 smb_io_form_1("", buffer, &forms_1[i], 0);
7137 for (; i<*numofforms; i++) {
7138 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7139 smb_io_form_1("", buffer, &forms_1[i], 0);
7142 SAFE_FREE(forms_1);
7144 return WERR_OK;
7146 default:
7147 SAFE_FREE(list);
7148 SAFE_FREE(builtinlist);
7149 return WERR_UNKNOWN_LEVEL;
7154 /****************************************************************************
7155 ****************************************************************************/
7157 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7159 uint32 level = q_u->level;
7160 UNISTR2 *uni_formname = &q_u->formname;
7161 RPC_BUFFER *buffer = NULL;
7162 uint32 offered = q_u->offered;
7163 uint32 *needed = &r_u->needed;
7165 nt_forms_struct *list=NULL;
7166 nt_forms_struct builtin_form;
7167 BOOL foundBuiltin;
7168 FORM_1 form_1;
7169 fstring form_name;
7170 int buffer_size=0;
7171 int numofforms=0, i=0;
7173 /* that's an [in out] buffer */
7175 if ( q_u->buffer ) {
7176 rpcbuf_move(q_u->buffer, &r_u->buffer);
7177 buffer = r_u->buffer;
7180 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7182 DEBUG(4,("_spoolss_getform\n"));
7183 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7184 DEBUGADD(5,("Info level [%d]\n", level));
7186 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7187 if (!foundBuiltin) {
7188 numofforms = get_ntforms(&list);
7189 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7191 if (numofforms == 0)
7192 return WERR_BADFID;
7195 switch (level) {
7196 case 1:
7197 if (foundBuiltin) {
7198 fill_form_1(&form_1, &builtin_form);
7199 } else {
7201 /* Check if the requested name is in the list of form structures */
7202 for (i=0; i<numofforms; i++) {
7204 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7206 if (strequal(form_name, list[i].name)) {
7207 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7208 fill_form_1(&form_1, &list[i]);
7209 break;
7213 SAFE_FREE(list);
7214 if (i == numofforms) {
7215 return WERR_BADFID;
7218 /* check the required size. */
7220 *needed=spoolss_size_form_1(&form_1);
7222 if (*needed > offered)
7223 return WERR_INSUFFICIENT_BUFFER;
7225 if (!rpcbuf_alloc_size(buffer, buffer_size))
7226 return WERR_NOMEM;
7228 /* fill the buffer with the form structures */
7229 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7230 smb_io_form_1("", buffer, &form_1, 0);
7232 return WERR_OK;
7234 default:
7235 SAFE_FREE(list);
7236 return WERR_UNKNOWN_LEVEL;
7240 /****************************************************************************
7241 ****************************************************************************/
7243 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7245 init_unistr(&port->port_name, name);
7248 /****************************************************************************
7249 ****************************************************************************/
7251 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7253 init_unistr(&port->port_name, name);
7254 init_unistr(&port->monitor_name, "Local Monitor");
7255 init_unistr(&port->description, "Local Port");
7256 port->port_type=PORT_TYPE_WRITE;
7257 port->reserved=0x0;
7261 /****************************************************************************
7262 wrapper around the enumer ports command
7263 ****************************************************************************/
7265 WERROR enumports_hook( int *count, char ***lines )
7267 char *cmd = lp_enumports_cmd();
7268 char **qlines;
7269 pstring command;
7270 int numlines;
7271 int ret;
7272 int fd;
7275 /* if no hook then just fill in the default port */
7277 if ( !*cmd ) {
7278 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7279 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7280 qlines[1] = NULL;
7281 numlines = 1;
7283 else {
7284 /* we have a valid enumport command */
7286 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7288 DEBUG(10,("Running [%s]\n", command));
7289 ret = smbrun(command, &fd);
7290 DEBUG(10,("Returned [%d]\n", ret));
7291 if (ret != 0) {
7292 if (fd != -1)
7293 close(fd);
7295 return WERR_ACCESS_DENIED;
7298 numlines = 0;
7299 qlines = fd_lines_load(fd, &numlines);
7300 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7301 close(fd);
7304 *count = numlines;
7305 *lines = qlines;
7307 return WERR_OK;
7310 /****************************************************************************
7311 enumports level 1.
7312 ****************************************************************************/
7314 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7316 PORT_INFO_1 *ports=NULL;
7317 int i=0;
7318 WERROR result = WERR_OK;
7319 char **qlines;
7320 int numlines;
7322 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7323 return result;
7325 if(numlines) {
7326 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7327 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7328 dos_errstr(WERR_NOMEM)));
7329 file_lines_free(qlines);
7330 return WERR_NOMEM;
7333 for (i=0; i<numlines; i++) {
7334 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7335 fill_port_1(&ports[i], qlines[i]);
7338 file_lines_free(qlines);
7341 *returned = numlines;
7343 /* check the required size. */
7344 for (i=0; i<*returned; i++) {
7345 DEBUGADD(6,("adding port [%d]'s size\n", i));
7346 *needed += spoolss_size_port_info_1(&ports[i]);
7349 if (*needed > offered) {
7350 result = WERR_INSUFFICIENT_BUFFER;
7351 goto out;
7354 if (!rpcbuf_alloc_size(buffer, *needed)) {
7355 result = WERR_NOMEM;
7356 goto out;
7359 /* fill the buffer with the ports structures */
7360 for (i=0; i<*returned; i++) {
7361 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7362 smb_io_port_1("", buffer, &ports[i], 0);
7365 out:
7366 SAFE_FREE(ports);
7368 if ( !W_ERROR_IS_OK(result) )
7369 *returned = 0;
7371 return result;
7374 /****************************************************************************
7375 enumports level 2.
7376 ****************************************************************************/
7378 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7380 PORT_INFO_2 *ports=NULL;
7381 int i=0;
7382 WERROR result = WERR_OK;
7383 char **qlines;
7384 int numlines;
7386 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7387 return result;
7390 if(numlines) {
7391 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7392 file_lines_free(qlines);
7393 return WERR_NOMEM;
7396 for (i=0; i<numlines; i++) {
7397 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7398 fill_port_2(&(ports[i]), qlines[i]);
7401 file_lines_free(qlines);
7404 *returned = numlines;
7406 /* check the required size. */
7407 for (i=0; i<*returned; i++) {
7408 DEBUGADD(6,("adding port [%d]'s size\n", i));
7409 *needed += spoolss_size_port_info_2(&ports[i]);
7412 if (*needed > offered) {
7413 result = WERR_INSUFFICIENT_BUFFER;
7414 goto out;
7417 if (!rpcbuf_alloc_size(buffer, *needed)) {
7418 result = WERR_NOMEM;
7419 goto out;
7422 /* fill the buffer with the ports structures */
7423 for (i=0; i<*returned; i++) {
7424 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7425 smb_io_port_2("", buffer, &ports[i], 0);
7428 out:
7429 SAFE_FREE(ports);
7431 if ( !W_ERROR_IS_OK(result) )
7432 *returned = 0;
7434 return result;
7437 /****************************************************************************
7438 enumports.
7439 ****************************************************************************/
7441 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7443 uint32 level = q_u->level;
7444 RPC_BUFFER *buffer = NULL;
7445 uint32 offered = q_u->offered;
7446 uint32 *needed = &r_u->needed;
7447 uint32 *returned = &r_u->returned;
7449 /* that's an [in out] buffer */
7451 if ( q_u->buffer ) {
7452 rpcbuf_move(q_u->buffer, &r_u->buffer);
7453 buffer = r_u->buffer;
7456 DEBUG(4,("_spoolss_enumports\n"));
7458 *returned=0;
7459 *needed=0;
7461 switch (level) {
7462 case 1:
7463 return enumports_level_1(buffer, offered, needed, returned);
7464 case 2:
7465 return enumports_level_2(buffer, offered, needed, returned);
7466 default:
7467 return WERR_UNKNOWN_LEVEL;
7471 /****************************************************************************
7472 ****************************************************************************/
7474 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7475 const SPOOL_PRINTER_INFO_LEVEL *info,
7476 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7477 uint32 user_switch, const SPOOL_USER_CTR *user,
7478 POLICY_HND *handle)
7480 NT_PRINTER_INFO_LEVEL *printer = NULL;
7481 fstring name;
7482 int snum;
7483 WERROR err = WERR_OK;
7485 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7486 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7487 return WERR_NOMEM;
7490 ZERO_STRUCTP(printer);
7492 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7493 if (!convert_printer_info(info, printer, 2)) {
7494 free_a_printer(&printer, 2);
7495 return WERR_NOMEM;
7498 /* check to see if the printer already exists */
7500 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7501 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7502 printer->info_2->sharename));
7503 free_a_printer(&printer, 2);
7504 return WERR_PRINTER_ALREADY_EXISTS;
7507 /* FIXME!!! smbd should check to see if the driver is installed before
7508 trying to add a printer like this --jerry */
7510 if (*lp_addprinter_cmd() ) {
7511 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7512 free_a_printer(&printer,2);
7513 return WERR_ACCESS_DENIED;
7515 } else {
7516 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7517 "smb.conf parameter \"addprinter command\" is defined. This"
7518 "parameter must exist for this call to succeed\n",
7519 printer->info_2->sharename ));
7522 /* use our primary netbios name since get_a_printer() will convert
7523 it to what the client expects on a case by case basis */
7525 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7526 printer->info_2->sharename);
7529 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7530 free_a_printer(&printer,2);
7531 return WERR_ACCESS_DENIED;
7534 /* you must be a printer admin to add a new printer */
7535 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7536 free_a_printer(&printer,2);
7537 return WERR_ACCESS_DENIED;
7541 * Do sanity check on the requested changes for Samba.
7544 if (!check_printer_ok(printer->info_2, snum)) {
7545 free_a_printer(&printer,2);
7546 return WERR_INVALID_PARAM;
7550 * When a printer is created, the drivername bound to the printer is used
7551 * to lookup previously saved driver initialization info, which is then
7552 * bound to the new printer, simulating what happens in the Windows arch.
7555 if (!devmode)
7557 set_driver_init(printer, 2);
7559 else
7561 /* A valid devmode was included, convert and link it
7563 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7565 if (!convert_devicemode(printer->info_2->printername, devmode,
7566 &printer->info_2->devmode))
7567 return WERR_NOMEM;
7570 /* write the ASCII on disk */
7571 err = mod_a_printer(printer, 2);
7572 if (!W_ERROR_IS_OK(err)) {
7573 free_a_printer(&printer,2);
7574 return err;
7577 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7578 /* Handle open failed - remove addition. */
7579 del_a_printer(printer->info_2->sharename);
7580 free_a_printer(&printer,2);
7581 return WERR_ACCESS_DENIED;
7584 update_c_setprinter(False);
7585 free_a_printer(&printer,2);
7587 return WERR_OK;
7590 /****************************************************************************
7591 ****************************************************************************/
7593 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7595 UNISTR2 *uni_srv_name = q_u->server_name;
7596 uint32 level = q_u->level;
7597 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7598 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7599 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7600 uint32 user_switch = q_u->user_switch;
7601 SPOOL_USER_CTR *user = &q_u->user_ctr;
7602 POLICY_HND *handle = &r_u->handle;
7604 switch (level) {
7605 case 1:
7606 /* we don't handle yet */
7607 /* but I know what to do ... */
7608 return WERR_UNKNOWN_LEVEL;
7609 case 2:
7610 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7611 devmode, sdb,
7612 user_switch, user, handle);
7613 default:
7614 return WERR_UNKNOWN_LEVEL;
7618 /****************************************************************************
7619 ****************************************************************************/
7621 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7623 uint32 level = q_u->level;
7624 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7625 WERROR err = WERR_OK;
7626 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7627 struct current_user user;
7628 fstring driver_name;
7629 uint32 version;
7631 ZERO_STRUCT(driver);
7633 get_current_user(&user, p);
7635 if (!convert_printer_driver_info(info, &driver, level)) {
7636 err = WERR_NOMEM;
7637 goto done;
7640 DEBUG(5,("Cleaning driver's information\n"));
7641 err = clean_up_driver_struct(driver, level, &user);
7642 if (!W_ERROR_IS_OK(err))
7643 goto done;
7645 DEBUG(5,("Moving driver to final destination\n"));
7646 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7647 goto done;
7650 if (add_a_printer_driver(driver, level)!=0) {
7651 err = WERR_ACCESS_DENIED;
7652 goto done;
7655 /* BEGIN_ADMIN_LOG */
7656 switch(level) {
7657 case 3:
7658 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7659 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7660 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7661 break;
7662 case 6:
7663 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7664 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7665 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7666 break;
7668 /* END_ADMIN_LOG */
7671 * I think this is where he DrvUpgradePrinter() hook would be
7672 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7673 * server. Right now, we just need to send ourselves a message
7674 * to update each printer bound to this driver. --jerry
7677 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7678 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7679 driver_name));
7683 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7684 * decide if the driver init data should be deleted. The rules are:
7685 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7686 * 2) delete init data only if there is no 2k/Xp driver
7687 * 3) always delete init data
7688 * The generalized rule is always use init data from the highest order driver.
7689 * It is necessary to follow the driver install by an initialization step to
7690 * finish off this process.
7692 if (level == 3)
7693 version = driver.info_3->cversion;
7694 else if (level == 6)
7695 version = driver.info_6->version;
7696 else
7697 version = -1;
7698 switch (version) {
7700 * 9x printer driver - never delete init data
7702 case 0:
7703 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7704 driver_name));
7705 break;
7708 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7709 * there is no 2k/Xp driver init data for this driver name.
7711 case 2:
7713 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7715 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7717 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7719 if (!del_driver_init(driver_name))
7720 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7721 } else {
7723 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7725 free_a_printer_driver(driver1,3);
7726 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7727 driver_name));
7730 break;
7733 * 2k or Xp printer driver - always delete init data
7735 case 3:
7736 if (!del_driver_init(driver_name))
7737 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7738 break;
7740 default:
7741 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7742 break;
7746 done:
7747 free_a_printer_driver(driver, level);
7748 return err;
7751 /********************************************************************
7752 * spoolss_addprinterdriverex
7753 ********************************************************************/
7755 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7757 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7758 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7761 * we only support the semantics of AddPrinterDriver()
7762 * i.e. only copy files that are newer than existing ones
7765 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7766 return WERR_ACCESS_DENIED;
7768 ZERO_STRUCT(q_u_local);
7769 ZERO_STRUCT(r_u_local);
7771 /* just pass the information off to _spoolss_addprinterdriver() */
7772 q_u_local.server_name_ptr = q_u->server_name_ptr;
7773 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7774 q_u_local.level = q_u->level;
7775 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7777 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7780 /****************************************************************************
7781 ****************************************************************************/
7783 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7785 init_unistr(&info->name, name);
7788 /****************************************************************************
7789 ****************************************************************************/
7791 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7793 pstring path;
7794 pstring long_archi;
7795 fstring servername;
7796 char *pservername;
7797 const char *short_archi;
7798 DRIVER_DIRECTORY_1 *info=NULL;
7799 WERROR result = WERR_OK;
7801 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7802 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7804 /* check for beginning double '\'s and that the server
7805 long enough */
7807 pservername = servername;
7808 if ( *pservername == '\\' && strlen(servername)>2 ) {
7809 pservername += 2;
7812 if ( !is_myname_or_ipaddr( pservername ) )
7813 return WERR_INVALID_PARAM;
7815 if (!(short_archi = get_short_archi(long_archi)))
7816 return WERR_INVALID_ENVIRONMENT;
7818 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7819 return WERR_NOMEM;
7821 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7823 DEBUG(4,("printer driver directory: [%s]\n", path));
7825 fill_driverdir_1(info, path);
7827 *needed += spoolss_size_driverdir_info_1(info);
7829 if (*needed > offered) {
7830 result = WERR_INSUFFICIENT_BUFFER;
7831 goto out;
7834 if (!rpcbuf_alloc_size(buffer, *needed)) {
7835 result = WERR_NOMEM;
7836 goto out;
7839 smb_io_driverdir_1("", buffer, info, 0);
7841 out:
7842 SAFE_FREE(info);
7844 return result;
7847 /****************************************************************************
7848 ****************************************************************************/
7850 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7852 UNISTR2 *name = &q_u->name;
7853 UNISTR2 *uni_environment = &q_u->environment;
7854 uint32 level = q_u->level;
7855 RPC_BUFFER *buffer = NULL;
7856 uint32 offered = q_u->offered;
7857 uint32 *needed = &r_u->needed;
7859 /* that's an [in out] buffer */
7861 if ( q_u->buffer ) {
7862 rpcbuf_move(q_u->buffer, &r_u->buffer);
7863 buffer = r_u->buffer;
7866 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7868 *needed=0;
7870 switch(level) {
7871 case 1:
7872 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7873 default:
7874 return WERR_UNKNOWN_LEVEL;
7878 /****************************************************************************
7879 ****************************************************************************/
7881 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7883 POLICY_HND *handle = &q_u->handle;
7884 uint32 idx = q_u->index;
7885 uint32 in_value_len = q_u->valuesize;
7886 uint32 in_data_len = q_u->datasize;
7887 uint32 *out_max_value_len = &r_u->valuesize;
7888 uint16 **out_value = &r_u->value;
7889 uint32 *out_value_len = &r_u->realvaluesize;
7890 uint32 *out_type = &r_u->type;
7891 uint32 *out_max_data_len = &r_u->datasize;
7892 uint8 **data_out = &r_u->data;
7893 uint32 *out_data_len = &r_u->realdatasize;
7895 NT_PRINTER_INFO_LEVEL *printer = NULL;
7897 uint32 biggest_valuesize;
7898 uint32 biggest_datasize;
7899 uint32 data_len;
7900 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7901 int snum;
7902 WERROR result;
7903 REGISTRY_VALUE *val = NULL;
7904 NT_PRINTER_DATA *p_data;
7905 int i, key_index, num_values;
7906 int name_length;
7908 ZERO_STRUCT( printer );
7910 *out_type = 0;
7912 *out_max_data_len = 0;
7913 *data_out = NULL;
7914 *out_data_len = 0;
7916 DEBUG(5,("spoolss_enumprinterdata\n"));
7918 if (!Printer) {
7919 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7920 return WERR_BADFID;
7923 if (!get_printer_snum(p,handle, &snum))
7924 return WERR_BADFID;
7926 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7927 if (!W_ERROR_IS_OK(result))
7928 return result;
7930 p_data = &printer->info_2->data;
7931 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7933 result = WERR_OK;
7936 * The NT machine wants to know the biggest size of value and data
7938 * cf: MSDN EnumPrinterData remark section
7941 if ( !in_value_len && !in_data_len && (key_index != -1) )
7943 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7945 biggest_valuesize = 0;
7946 biggest_datasize = 0;
7948 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7950 for ( i=0; i<num_values; i++ )
7952 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7954 name_length = strlen(val->valuename);
7955 if ( strlen(val->valuename) > biggest_valuesize )
7956 biggest_valuesize = name_length;
7958 if ( val->size > biggest_datasize )
7959 biggest_datasize = val->size;
7961 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7962 biggest_datasize));
7965 /* the value is an UNICODE string but real_value_size is the length
7966 in bytes including the trailing 0 */
7968 *out_value_len = 2 * (1+biggest_valuesize);
7969 *out_data_len = biggest_datasize;
7971 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7973 goto done;
7977 * the value len is wrong in NT sp3
7978 * that's the number of bytes not the number of unicode chars
7981 if ( key_index != -1 )
7982 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7984 if ( !val )
7987 /* out_value should default to "" or else NT4 has
7988 problems unmarshalling the response */
7990 *out_max_value_len=(in_value_len/sizeof(uint16));
7992 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7994 result = WERR_NOMEM;
7995 goto done;
7998 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8000 /* the data is counted in bytes */
8002 *out_max_data_len = in_data_len;
8003 *out_data_len = in_data_len;
8005 /* only allocate when given a non-zero data_len */
8007 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8009 result = WERR_NOMEM;
8010 goto done;
8013 result = WERR_NO_MORE_ITEMS;
8015 else
8018 * the value is:
8019 * - counted in bytes in the request
8020 * - counted in UNICODE chars in the max reply
8021 * - counted in bytes in the real size
8023 * take a pause *before* coding not *during* coding
8026 /* name */
8027 *out_max_value_len=(in_value_len/sizeof(uint16));
8028 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8030 result = WERR_NOMEM;
8031 goto done;
8034 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
8036 /* type */
8038 *out_type = regval_type( val );
8040 /* data - counted in bytes */
8042 *out_max_data_len = in_data_len;
8043 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8045 result = WERR_NOMEM;
8046 goto done;
8048 data_len = regval_size(val);
8049 if ( *data_out )
8050 memcpy( *data_out, regval_data_p(val), data_len );
8051 *out_data_len = data_len;
8054 done:
8055 free_a_printer(&printer, 2);
8056 return result;
8059 /****************************************************************************
8060 ****************************************************************************/
8062 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8064 POLICY_HND *handle = &q_u->handle;
8065 UNISTR2 *value = &q_u->value;
8066 uint32 type = q_u->type;
8067 uint8 *data = q_u->data;
8068 uint32 real_len = q_u->real_len;
8070 NT_PRINTER_INFO_LEVEL *printer = NULL;
8071 int snum=0;
8072 WERROR status = WERR_OK;
8073 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8074 fstring valuename;
8076 DEBUG(5,("spoolss_setprinterdata\n"));
8078 if (!Printer) {
8079 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8080 return WERR_BADFID;
8083 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8084 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8085 return WERR_INVALID_PARAM;
8088 if (!get_printer_snum(p,handle, &snum))
8089 return WERR_BADFID;
8092 * Access check : NT returns "access denied" if you make a
8093 * SetPrinterData call without the necessary privildge.
8094 * we were originally returning OK if nothing changed
8095 * which made Win2k issue **a lot** of SetPrinterData
8096 * when connecting to a printer --jerry
8099 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8101 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8102 status = WERR_ACCESS_DENIED;
8103 goto done;
8106 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8107 if (!W_ERROR_IS_OK(status))
8108 return status;
8110 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8113 * When client side code sets a magic printer data key, detect it and save
8114 * the current printer data and the magic key's data (its the DEVMODE) for
8115 * future printer/driver initializations.
8117 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8119 /* Set devmode and printer initialization info */
8120 status = save_driver_init( printer, 2, data, real_len );
8122 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8124 else
8126 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8127 type, data, real_len );
8128 if ( W_ERROR_IS_OK(status) )
8129 status = mod_a_printer(printer, 2);
8132 done:
8133 free_a_printer(&printer, 2);
8135 return status;
8138 /****************************************************************************
8139 ****************************************************************************/
8141 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8143 POLICY_HND *handle = &q_u->handle;
8144 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8145 int snum;
8147 DEBUG(5,("_spoolss_resetprinter\n"));
8150 * All we do is to check to see if the handle and queue is valid.
8151 * This call really doesn't mean anything to us because we only
8152 * support RAW printing. --jerry
8155 if (!Printer) {
8156 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8157 return WERR_BADFID;
8160 if (!get_printer_snum(p,handle, &snum))
8161 return WERR_BADFID;
8164 /* blindly return success */
8165 return WERR_OK;
8169 /****************************************************************************
8170 ****************************************************************************/
8172 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8174 POLICY_HND *handle = &q_u->handle;
8175 UNISTR2 *value = &q_u->valuename;
8177 NT_PRINTER_INFO_LEVEL *printer = NULL;
8178 int snum=0;
8179 WERROR status = WERR_OK;
8180 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8181 pstring valuename;
8183 DEBUG(5,("spoolss_deleteprinterdata\n"));
8185 if (!Printer) {
8186 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8187 return WERR_BADFID;
8190 if (!get_printer_snum(p, handle, &snum))
8191 return WERR_BADFID;
8193 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8194 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8195 return WERR_ACCESS_DENIED;
8198 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8199 if (!W_ERROR_IS_OK(status))
8200 return status;
8202 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8204 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8206 if ( W_ERROR_IS_OK(status) )
8207 mod_a_printer( printer, 2 );
8209 free_a_printer(&printer, 2);
8211 return status;
8214 /****************************************************************************
8215 ****************************************************************************/
8217 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8219 POLICY_HND *handle = &q_u->handle;
8220 FORM *form = &q_u->form;
8221 nt_forms_struct tmpForm;
8222 int snum;
8223 WERROR status = WERR_OK;
8224 NT_PRINTER_INFO_LEVEL *printer = NULL;
8226 int count=0;
8227 nt_forms_struct *list=NULL;
8228 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8230 DEBUG(5,("spoolss_addform\n"));
8232 if (!Printer) {
8233 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8234 return WERR_BADFID;
8238 /* forms can be added on printer of on the print server handle */
8240 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8242 if (!get_printer_snum(p,handle, &snum))
8243 return WERR_BADFID;
8245 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8246 if (!W_ERROR_IS_OK(status))
8247 goto done;
8250 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8251 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8252 status = WERR_ACCESS_DENIED;
8253 goto done;
8256 /* can't add if builtin */
8258 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8259 status = WERR_ALREADY_EXISTS;
8260 goto done;
8263 count = get_ntforms(&list);
8265 if(!add_a_form(&list, form, &count)) {
8266 status = WERR_NOMEM;
8267 goto done;
8270 write_ntforms(&list, count);
8273 * ChangeID must always be set if this is a printer
8276 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8277 status = mod_a_printer(printer, 2);
8279 done:
8280 if ( printer )
8281 free_a_printer(&printer, 2);
8282 SAFE_FREE(list);
8284 return status;
8287 /****************************************************************************
8288 ****************************************************************************/
8290 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8292 POLICY_HND *handle = &q_u->handle;
8293 UNISTR2 *form_name = &q_u->name;
8294 nt_forms_struct tmpForm;
8295 int count=0;
8296 nt_forms_struct *list=NULL;
8297 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8298 int snum;
8299 WERROR status = WERR_OK;
8300 NT_PRINTER_INFO_LEVEL *printer = NULL;
8302 DEBUG(5,("spoolss_deleteform\n"));
8304 if (!Printer) {
8305 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8306 return WERR_BADFID;
8309 /* forms can be deleted on printer of on the print server handle */
8311 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8313 if (!get_printer_snum(p,handle, &snum))
8314 return WERR_BADFID;
8316 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8317 if (!W_ERROR_IS_OK(status))
8318 goto done;
8321 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8322 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8323 status = WERR_ACCESS_DENIED;
8324 goto done;
8327 /* can't delete if builtin */
8329 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8330 status = WERR_INVALID_PARAM;
8331 goto done;
8334 count = get_ntforms(&list);
8336 if ( !delete_a_form(&list, form_name, &count, &status ))
8337 goto done;
8340 * ChangeID must always be set if this is a printer
8343 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8344 status = mod_a_printer(printer, 2);
8346 done:
8347 if ( printer )
8348 free_a_printer(&printer, 2);
8349 SAFE_FREE(list);
8351 return status;
8354 /****************************************************************************
8355 ****************************************************************************/
8357 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8359 POLICY_HND *handle = &q_u->handle;
8360 FORM *form = &q_u->form;
8361 nt_forms_struct tmpForm;
8362 int snum;
8363 WERROR status = WERR_OK;
8364 NT_PRINTER_INFO_LEVEL *printer = NULL;
8366 int count=0;
8367 nt_forms_struct *list=NULL;
8368 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8370 DEBUG(5,("spoolss_setform\n"));
8372 if (!Printer) {
8373 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8374 return WERR_BADFID;
8377 /* forms can be modified on printer of on the print server handle */
8379 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8381 if (!get_printer_snum(p,handle, &snum))
8382 return WERR_BADFID;
8384 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8385 if (!W_ERROR_IS_OK(status))
8386 goto done;
8389 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8390 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8391 status = WERR_ACCESS_DENIED;
8392 goto done;
8395 /* can't set if builtin */
8396 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8397 status = WERR_INVALID_PARAM;
8398 goto done;
8401 count = get_ntforms(&list);
8402 update_a_form(&list, form, count);
8403 write_ntforms(&list, count);
8406 * ChangeID must always be set if this is a printer
8409 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8410 status = mod_a_printer(printer, 2);
8413 done:
8414 if ( printer )
8415 free_a_printer(&printer, 2);
8416 SAFE_FREE(list);
8418 return status;
8421 /****************************************************************************
8422 enumprintprocessors level 1.
8423 ****************************************************************************/
8425 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8427 PRINTPROCESSOR_1 *info_1=NULL;
8428 WERROR result = WERR_OK;
8430 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8431 return WERR_NOMEM;
8433 (*returned) = 0x1;
8435 init_unistr(&info_1->name, "winprint");
8437 *needed += spoolss_size_printprocessor_info_1(info_1);
8439 if (*needed > offered) {
8440 result = WERR_INSUFFICIENT_BUFFER;
8441 goto out;
8444 if (!rpcbuf_alloc_size(buffer, *needed)) {
8445 result = WERR_NOMEM;
8446 goto out;
8449 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8451 out:
8452 SAFE_FREE(info_1);
8454 if ( !W_ERROR_IS_OK(result) )
8455 *returned = 0;
8457 return result;
8460 /****************************************************************************
8461 ****************************************************************************/
8463 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8465 uint32 level = q_u->level;
8466 RPC_BUFFER *buffer = NULL;
8467 uint32 offered = q_u->offered;
8468 uint32 *needed = &r_u->needed;
8469 uint32 *returned = &r_u->returned;
8471 /* that's an [in out] buffer */
8473 if ( q_u->buffer ) {
8474 rpcbuf_move(q_u->buffer, &r_u->buffer);
8475 buffer = r_u->buffer;
8478 DEBUG(5,("spoolss_enumprintprocessors\n"));
8481 * Enumerate the print processors ...
8483 * Just reply with "winprint", to keep NT happy
8484 * and I can use my nice printer checker.
8487 *returned=0;
8488 *needed=0;
8490 switch (level) {
8491 case 1:
8492 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8493 default:
8494 return WERR_UNKNOWN_LEVEL;
8498 /****************************************************************************
8499 enumprintprocdatatypes level 1.
8500 ****************************************************************************/
8502 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8504 PRINTPROCDATATYPE_1 *info_1=NULL;
8505 WERROR result = WERR_NOMEM;
8507 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8508 return WERR_NOMEM;
8510 (*returned) = 0x1;
8512 init_unistr(&info_1->name, "RAW");
8514 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8516 if (*needed > offered) {
8517 result = WERR_INSUFFICIENT_BUFFER;
8518 goto out;
8521 if (!rpcbuf_alloc_size(buffer, *needed)) {
8522 result = WERR_NOMEM;
8523 goto out;
8526 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8528 out:
8529 SAFE_FREE(info_1);
8531 if ( !W_ERROR_IS_OK(result) )
8532 *returned = 0;
8534 return result;
8537 /****************************************************************************
8538 ****************************************************************************/
8540 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8542 uint32 level = q_u->level;
8543 RPC_BUFFER *buffer = NULL;
8544 uint32 offered = q_u->offered;
8545 uint32 *needed = &r_u->needed;
8546 uint32 *returned = &r_u->returned;
8548 /* that's an [in out] buffer */
8550 if ( q_u->buffer ) {
8551 rpcbuf_move(q_u->buffer, &r_u->buffer);
8552 buffer = r_u->buffer;
8555 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8557 *returned=0;
8558 *needed=0;
8560 switch (level) {
8561 case 1:
8562 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8563 default:
8564 return WERR_UNKNOWN_LEVEL;
8568 /****************************************************************************
8569 enumprintmonitors level 1.
8570 ****************************************************************************/
8572 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8574 PRINTMONITOR_1 *info_1=NULL;
8575 WERROR result = WERR_OK;
8577 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8578 return WERR_NOMEM;
8580 (*returned) = 0x1;
8582 init_unistr(&info_1->name, "Local Port");
8584 *needed += spoolss_size_printmonitor_info_1(info_1);
8586 if (*needed > offered) {
8587 result = WERR_INSUFFICIENT_BUFFER;
8588 goto out;
8591 if (!rpcbuf_alloc_size(buffer, *needed)) {
8592 result = WERR_NOMEM;
8593 goto out;
8596 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8598 out:
8599 SAFE_FREE(info_1);
8601 if ( !W_ERROR_IS_OK(result) )
8602 *returned = 0;
8604 return result;
8607 /****************************************************************************
8608 enumprintmonitors level 2.
8609 ****************************************************************************/
8611 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8613 PRINTMONITOR_2 *info_2=NULL;
8614 WERROR result = WERR_OK;
8616 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8617 return WERR_NOMEM;
8619 (*returned) = 0x1;
8621 init_unistr(&info_2->name, "Local Port");
8622 init_unistr(&info_2->environment, "Windows NT X86");
8623 init_unistr(&info_2->dll_name, "localmon.dll");
8625 *needed += spoolss_size_printmonitor_info_2(info_2);
8627 if (*needed > offered) {
8628 result = WERR_INSUFFICIENT_BUFFER;
8629 goto out;
8632 if (!rpcbuf_alloc_size(buffer, *needed)) {
8633 result = WERR_NOMEM;
8634 goto out;
8637 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8639 out:
8640 SAFE_FREE(info_2);
8642 if ( !W_ERROR_IS_OK(result) )
8643 *returned = 0;
8645 return result;
8648 /****************************************************************************
8649 ****************************************************************************/
8651 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8653 uint32 level = q_u->level;
8654 RPC_BUFFER *buffer = NULL;
8655 uint32 offered = q_u->offered;
8656 uint32 *needed = &r_u->needed;
8657 uint32 *returned = &r_u->returned;
8659 /* that's an [in out] buffer */
8661 if ( q_u->buffer ) {
8662 rpcbuf_move(q_u->buffer, &r_u->buffer);
8663 buffer = r_u->buffer;
8666 DEBUG(5,("spoolss_enumprintmonitors\n"));
8669 * Enumerate the print monitors ...
8671 * Just reply with "Local Port", to keep NT happy
8672 * and I can use my nice printer checker.
8675 *returned=0;
8676 *needed=0;
8678 switch (level) {
8679 case 1:
8680 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8681 case 2:
8682 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8683 default:
8684 return WERR_UNKNOWN_LEVEL;
8688 /****************************************************************************
8689 ****************************************************************************/
8691 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8692 NT_PRINTER_INFO_LEVEL *ntprinter,
8693 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8694 uint32 *needed)
8696 int i=0;
8697 BOOL found=False;
8698 JOB_INFO_1 *info_1=NULL;
8699 WERROR result = WERR_OK;
8701 info_1=SMB_MALLOC_P(JOB_INFO_1);
8703 if (info_1 == NULL) {
8704 return WERR_NOMEM;
8707 for (i=0; i<count && found==False; i++) {
8708 if ((*queue)[i].job==(int)jobid)
8709 found=True;
8712 if (found==False) {
8713 SAFE_FREE(info_1);
8714 /* NT treats not found as bad param... yet another bad choice */
8715 return WERR_INVALID_PARAM;
8718 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8720 *needed += spoolss_size_job_info_1(info_1);
8722 if (*needed > offered) {
8723 result = WERR_INSUFFICIENT_BUFFER;
8724 goto out;
8727 if (!rpcbuf_alloc_size(buffer, *needed)) {
8728 result = WERR_NOMEM;
8729 goto out;
8732 smb_io_job_info_1("", buffer, info_1, 0);
8734 out:
8735 SAFE_FREE(info_1);
8737 return result;
8740 /****************************************************************************
8741 ****************************************************************************/
8743 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8744 NT_PRINTER_INFO_LEVEL *ntprinter,
8745 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8746 uint32 *needed)
8748 int i = 0;
8749 BOOL found = False;
8750 JOB_INFO_2 *info_2;
8751 WERROR result;
8752 DEVICEMODE *devmode = NULL;
8753 NT_DEVICEMODE *nt_devmode = NULL;
8755 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8756 return WERR_NOMEM;
8758 ZERO_STRUCTP(info_2);
8760 for ( i=0; i<count && found==False; i++ )
8762 if ((*queue)[i].job == (int)jobid)
8763 found = True;
8766 if ( !found ) {
8767 /* NT treats not found as bad param... yet another bad
8768 choice */
8769 result = WERR_INVALID_PARAM;
8770 goto done;
8774 * if the print job does not have a DEVMODE associated with it,
8775 * just use the one for the printer. A NULL devicemode is not
8776 * a failure condition
8779 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8780 devmode = construct_dev_mode(snum);
8781 else {
8782 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8783 ZERO_STRUCTP( devmode );
8784 convert_nt_devicemode( devmode, nt_devmode );
8788 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8790 *needed += spoolss_size_job_info_2(info_2);
8792 if (*needed > offered) {
8793 result = WERR_INSUFFICIENT_BUFFER;
8794 goto done;
8797 if (!rpcbuf_alloc_size(buffer, *needed)) {
8798 result = WERR_NOMEM;
8799 goto done;
8802 smb_io_job_info_2("", buffer, info_2, 0);
8804 result = WERR_OK;
8806 done:
8807 /* Cleanup allocated memory */
8809 free_job_info_2(info_2); /* Also frees devmode */
8810 SAFE_FREE(info_2);
8812 return result;
8815 /****************************************************************************
8816 ****************************************************************************/
8818 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8820 POLICY_HND *handle = &q_u->handle;
8821 uint32 jobid = q_u->jobid;
8822 uint32 level = q_u->level;
8823 RPC_BUFFER *buffer = NULL;
8824 uint32 offered = q_u->offered;
8825 uint32 *needed = &r_u->needed;
8826 WERROR wstatus = WERR_OK;
8827 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8828 int snum;
8829 int count;
8830 print_queue_struct *queue = NULL;
8831 print_status_struct prt_status;
8833 /* that's an [in out] buffer */
8835 if ( q_u->buffer ) {
8836 rpcbuf_move(q_u->buffer, &r_u->buffer);
8837 buffer = r_u->buffer;
8840 DEBUG(5,("spoolss_getjob\n"));
8842 *needed = 0;
8844 if (!get_printer_snum(p, handle, &snum))
8845 return WERR_BADFID;
8847 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8848 if ( !W_ERROR_IS_OK(wstatus) )
8849 return wstatus;
8851 count = print_queue_status(snum, &queue, &prt_status);
8853 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8854 count, prt_status.status, prt_status.message));
8856 switch ( level ) {
8857 case 1:
8858 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8859 buffer, offered, needed);
8860 break;
8861 case 2:
8862 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8863 buffer, offered, needed);
8864 break;
8865 default:
8866 wstatus = WERR_UNKNOWN_LEVEL;
8867 break;
8870 SAFE_FREE(queue);
8871 free_a_printer( &ntprinter, 2 );
8873 return wstatus;
8876 /********************************************************************
8877 spoolss_getprinterdataex
8879 From MSDN documentation of GetPrinterDataEx: pass request
8880 to GetPrinterData if key is "PrinterDriverData".
8881 ********************************************************************/
8883 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8885 POLICY_HND *handle = &q_u->handle;
8886 uint32 in_size = q_u->size;
8887 uint32 *type = &r_u->type;
8888 uint32 *out_size = &r_u->size;
8889 uint8 **data = &r_u->data;
8890 uint32 *needed = &r_u->needed;
8891 fstring keyname, valuename;
8893 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8895 NT_PRINTER_INFO_LEVEL *printer = NULL;
8896 int snum = 0;
8897 WERROR status = WERR_OK;
8899 DEBUG(4,("_spoolss_getprinterdataex\n"));
8901 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8902 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8904 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8905 keyname, valuename));
8907 /* in case of problem, return some default values */
8909 *needed = 0;
8910 *type = 0;
8911 *out_size = in_size;
8913 if (!Printer) {
8914 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8915 status = WERR_BADFID;
8916 goto done;
8919 /* Is the handle to a printer or to the server? */
8921 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8922 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8923 status = WERR_INVALID_PARAM;
8924 goto done;
8927 if ( !get_printer_snum(p,handle, &snum) )
8928 return WERR_BADFID;
8930 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8931 if ( !W_ERROR_IS_OK(status) )
8932 goto done;
8934 /* check to see if the keyname is valid */
8935 if ( !strlen(keyname) ) {
8936 status = WERR_INVALID_PARAM;
8937 goto done;
8940 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8941 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8942 free_a_printer( &printer, 2 );
8943 status = WERR_BADFILE;
8944 goto done;
8947 /* When given a new keyname, we should just create it */
8949 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8951 if (*needed > *out_size)
8952 status = WERR_MORE_DATA;
8954 done:
8955 if ( !W_ERROR_IS_OK(status) )
8957 DEBUG(5, ("error: allocating %d\n", *out_size));
8959 /* reply this param doesn't exist */
8961 if ( *out_size )
8963 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8964 status = WERR_NOMEM;
8965 goto done;
8968 else {
8969 *data = NULL;
8973 if ( printer )
8974 free_a_printer( &printer, 2 );
8976 return status;
8979 /********************************************************************
8980 * spoolss_setprinterdataex
8981 ********************************************************************/
8983 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8985 POLICY_HND *handle = &q_u->handle;
8986 uint32 type = q_u->type;
8987 uint8 *data = q_u->data;
8988 uint32 real_len = q_u->real_len;
8990 NT_PRINTER_INFO_LEVEL *printer = NULL;
8991 int snum = 0;
8992 WERROR status = WERR_OK;
8993 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8994 fstring valuename;
8995 fstring keyname;
8996 char *oid_string;
8998 DEBUG(4,("_spoolss_setprinterdataex\n"));
9000 /* From MSDN documentation of SetPrinterDataEx: pass request to
9001 SetPrinterData if key is "PrinterDriverData" */
9003 if (!Printer) {
9004 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9005 return WERR_BADFID;
9008 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
9009 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9010 return WERR_INVALID_PARAM;
9013 if ( !get_printer_snum(p,handle, &snum) )
9014 return WERR_BADFID;
9017 * Access check : NT returns "access denied" if you make a
9018 * SetPrinterData call without the necessary privildge.
9019 * we were originally returning OK if nothing changed
9020 * which made Win2k issue **a lot** of SetPrinterData
9021 * when connecting to a printer --jerry
9024 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9026 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9027 return WERR_ACCESS_DENIED;
9030 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9031 if (!W_ERROR_IS_OK(status))
9032 return status;
9034 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9035 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9037 /* check for OID in valuename */
9039 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9041 *oid_string = '\0';
9042 oid_string++;
9045 /* save the registry data */
9047 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9049 if ( W_ERROR_IS_OK(status) )
9051 /* save the OID if one was specified */
9052 if ( oid_string ) {
9053 fstrcat( keyname, "\\" );
9054 fstrcat( keyname, SPOOL_OID_KEY );
9057 * I'm not checking the status here on purpose. Don't know
9058 * if this is right, but I'm returning the status from the
9059 * previous set_printer_dataex() call. I have no idea if
9060 * this is right. --jerry
9063 set_printer_dataex( printer, keyname, valuename,
9064 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9067 status = mod_a_printer(printer, 2);
9070 free_a_printer(&printer, 2);
9072 return status;
9076 /********************************************************************
9077 * spoolss_deleteprinterdataex
9078 ********************************************************************/
9080 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9082 POLICY_HND *handle = &q_u->handle;
9083 UNISTR2 *value = &q_u->valuename;
9084 UNISTR2 *key = &q_u->keyname;
9086 NT_PRINTER_INFO_LEVEL *printer = NULL;
9087 int snum=0;
9088 WERROR status = WERR_OK;
9089 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9090 pstring valuename, keyname;
9092 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9094 if (!Printer) {
9095 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9096 return WERR_BADFID;
9099 if (!get_printer_snum(p, handle, &snum))
9100 return WERR_BADFID;
9102 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9103 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9104 return WERR_ACCESS_DENIED;
9107 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9108 if (!W_ERROR_IS_OK(status))
9109 return status;
9111 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9112 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9114 status = delete_printer_dataex( printer, keyname, valuename );
9116 if ( W_ERROR_IS_OK(status) )
9117 mod_a_printer( printer, 2 );
9119 free_a_printer(&printer, 2);
9121 return status;
9124 /********************************************************************
9125 * spoolss_enumprinterkey
9126 ********************************************************************/
9129 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9131 fstring key;
9132 fstring *keynames = NULL;
9133 uint16 *enumkeys = NULL;
9134 int num_keys;
9135 int printerkey_len;
9136 POLICY_HND *handle = &q_u->handle;
9137 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9138 NT_PRINTER_DATA *data;
9139 NT_PRINTER_INFO_LEVEL *printer = NULL;
9140 int snum = 0;
9141 WERROR status = WERR_BADFILE;
9144 DEBUG(4,("_spoolss_enumprinterkey\n"));
9146 if (!Printer) {
9147 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9148 return WERR_BADFID;
9151 if ( !get_printer_snum(p,handle, &snum) )
9152 return WERR_BADFID;
9154 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9155 if (!W_ERROR_IS_OK(status))
9156 return status;
9158 /* get the list of subkey names */
9160 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9161 data = &printer->info_2->data;
9163 num_keys = get_printer_subkeys( data, key, &keynames );
9165 if ( num_keys == -1 ) {
9166 status = WERR_BADFILE;
9167 goto done;
9170 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9172 r_u->needed = printerkey_len*2;
9174 if ( q_u->size < r_u->needed ) {
9175 status = WERR_MORE_DATA;
9176 goto done;
9179 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9180 status = WERR_NOMEM;
9181 goto done;
9184 status = WERR_OK;
9186 if ( q_u->size < r_u->needed )
9187 status = WERR_MORE_DATA;
9189 done:
9190 free_a_printer( &printer, 2 );
9191 SAFE_FREE( keynames );
9193 return status;
9196 /********************************************************************
9197 * spoolss_deleteprinterkey
9198 ********************************************************************/
9200 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9202 POLICY_HND *handle = &q_u->handle;
9203 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9204 fstring key;
9205 NT_PRINTER_INFO_LEVEL *printer = NULL;
9206 int snum=0;
9207 WERROR status;
9209 DEBUG(5,("spoolss_deleteprinterkey\n"));
9211 if (!Printer) {
9212 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9213 return WERR_BADFID;
9216 /* if keyname == NULL, return error */
9218 if ( !q_u->keyname.buffer )
9219 return WERR_INVALID_PARAM;
9221 if (!get_printer_snum(p, handle, &snum))
9222 return WERR_BADFID;
9224 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9225 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9226 return WERR_ACCESS_DENIED;
9229 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9230 if (!W_ERROR_IS_OK(status))
9231 return status;
9233 /* delete the key and all subneys */
9235 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9237 status = delete_all_printer_data( printer->info_2, key );
9239 if ( W_ERROR_IS_OK(status) )
9240 status = mod_a_printer(printer, 2);
9242 free_a_printer( &printer, 2 );
9244 return status;
9248 /********************************************************************
9249 * spoolss_enumprinterdataex
9250 ********************************************************************/
9252 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9254 POLICY_HND *handle = &q_u->handle;
9255 uint32 in_size = q_u->size;
9256 uint32 num_entries,
9257 needed;
9258 NT_PRINTER_INFO_LEVEL *printer = NULL;
9259 PRINTER_ENUM_VALUES *enum_values = NULL;
9260 NT_PRINTER_DATA *p_data;
9261 fstring key;
9262 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9263 int snum;
9264 WERROR result;
9265 int key_index;
9266 int i;
9267 REGISTRY_VALUE *val;
9268 char *value_name;
9269 uint32 data_len;
9272 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9274 if (!Printer) {
9275 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9276 return WERR_BADFID;
9280 * first check for a keyname of NULL or "". Win2k seems to send
9281 * this a lot and we should send back WERR_INVALID_PARAM
9282 * no need to spend time looking up the printer in this case.
9283 * --jerry
9286 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9287 if ( !strlen(key) ) {
9288 result = WERR_INVALID_PARAM;
9289 goto done;
9292 /* get the printer off of disk */
9294 if (!get_printer_snum(p,handle, &snum))
9295 return WERR_BADFID;
9297 ZERO_STRUCT(printer);
9298 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9299 if (!W_ERROR_IS_OK(result))
9300 return result;
9302 /* now look for a match on the key name */
9304 p_data = &printer->info_2->data;
9306 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9307 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9309 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9310 result = WERR_INVALID_PARAM;
9311 goto done;
9314 result = WERR_OK;
9315 needed = 0;
9317 /* allocate the memory for the array of pointers -- if necessary */
9319 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9320 if ( num_entries )
9322 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9324 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9325 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9326 result = WERR_NOMEM;
9327 goto done;
9330 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9334 * loop through all params and build the array to pass
9335 * back to the client
9338 for ( i=0; i<num_entries; i++ )
9340 /* lookup the registry value */
9342 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9343 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9345 /* copy the data */
9347 value_name = regval_name( val );
9348 init_unistr( &enum_values[i].valuename, value_name );
9349 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9350 enum_values[i].type = regval_type( val );
9352 data_len = regval_size( val );
9353 if ( data_len ) {
9354 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9356 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9357 data_len ));
9358 result = WERR_NOMEM;
9359 goto done;
9362 enum_values[i].data_len = data_len;
9364 /* keep track of the size of the array in bytes */
9366 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9369 /* housekeeping information in the reply */
9371 r_u->needed = needed;
9372 r_u->returned = num_entries;
9374 if (needed > in_size) {
9375 result = WERR_MORE_DATA;
9376 goto done;
9379 /* copy data into the reply */
9381 r_u->ctr.size = r_u->needed;
9382 r_u->ctr.size_of_array = r_u->returned;
9383 r_u->ctr.values = enum_values;
9387 done:
9388 if ( printer )
9389 free_a_printer(&printer, 2);
9391 return result;
9394 /****************************************************************************
9395 ****************************************************************************/
9397 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9399 init_unistr(&info->name, name);
9402 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9403 UNISTR2 *environment,
9404 RPC_BUFFER *buffer,
9405 uint32 offered,
9406 uint32 *needed)
9408 pstring path;
9409 pstring long_archi;
9410 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9411 WERROR result = WERR_OK;
9413 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9415 if (!get_short_archi(long_archi))
9416 return WERR_INVALID_ENVIRONMENT;
9418 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9419 return WERR_NOMEM;
9421 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9423 fill_printprocessordirectory_1(info, path);
9425 *needed += spoolss_size_printprocessordirectory_info_1(info);
9427 if (*needed > offered) {
9428 result = WERR_INSUFFICIENT_BUFFER;
9429 goto out;
9432 if (!rpcbuf_alloc_size(buffer, *needed)) {
9433 result = WERR_INSUFFICIENT_BUFFER;
9434 goto out;
9437 smb_io_printprocessordirectory_1("", buffer, info, 0);
9439 out:
9440 SAFE_FREE(info);
9442 return result;
9445 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9447 uint32 level = q_u->level;
9448 RPC_BUFFER *buffer = NULL;
9449 uint32 offered = q_u->offered;
9450 uint32 *needed = &r_u->needed;
9451 WERROR result;
9453 /* that's an [in out] buffer */
9455 if ( q_u->buffer ) {
9456 rpcbuf_move(q_u->buffer, &r_u->buffer);
9457 buffer = r_u->buffer;
9460 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9462 *needed=0;
9464 switch(level) {
9465 case 1:
9466 result = getprintprocessordirectory_level_1
9467 (&q_u->name, &q_u->environment, buffer, offered, needed);
9468 break;
9469 default:
9470 result = WERR_UNKNOWN_LEVEL;
9473 return result;
9476 #if 0
9478 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9479 SPOOL_R_REPLYOPENPRINTER *r_u)
9481 DEBUG(5,("_spoolss_replyopenprinter\n"));
9483 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9485 return WERR_OK;
9488 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9489 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9491 DEBUG(5,("_spoolss_replycloseprinter\n"));
9492 return WERR_OK;
9495 #endif