r5806: * fix a couple more segvs in spoolss
[Samba/gbeck.git] / source / rpc_server / srv_spoolss_nt.c
blob3c611be9ace60860e916f7fe1cabcec7d6e7e94a
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 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_RPC_SRV
34 #ifndef MAX_OPEN_PRINTER_EXS
35 #define MAX_OPEN_PRINTER_EXS 50
36 #endif
38 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
39 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42 /* Table to map the driver version */
43 /* to OS */
44 static const char * drv_ver_to_os[] = {
45 "WIN9X", /* driver version/cversion 0 */
46 "", /* unused ? */
47 "WINNT", /* driver version/cversion 2 */
48 "WIN2K", /* driver version/cversion 3 */
51 static const char *get_drv_ver_to_os(int ver)
53 if (ver < 0 || ver > 3)
54 return "";
55 return drv_ver_to_os[ver];
58 struct table_node {
59 const char *long_archi;
60 const char *short_archi;
61 int version;
64 static Printer_entry *printers_list;
66 typedef struct _counter_printer_0 {
67 struct _counter_printer_0 *next;
68 struct _counter_printer_0 *prev;
70 int snum;
71 uint32 counter;
72 } counter_printer_0;
74 static counter_printer_0 *counter_list;
76 static struct cli_state notify_cli; /* print notify back-channel */
77 static uint32 smb_connections=0;
80 /* in printing/nt_printing.c */
82 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
84 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
85 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
87 /* translate between internal status numbers and NT status numbers */
88 static int nt_printj_status(int v)
90 switch (v) {
91 case LPQ_QUEUED:
92 return 0;
93 case LPQ_PAUSED:
94 return JOB_STATUS_PAUSED;
95 case LPQ_SPOOLING:
96 return JOB_STATUS_SPOOLING;
97 case LPQ_PRINTING:
98 return JOB_STATUS_PRINTING;
99 case LPQ_ERROR:
100 return JOB_STATUS_ERROR;
101 case LPQ_DELETING:
102 return JOB_STATUS_DELETING;
103 case LPQ_OFFLINE:
104 return JOB_STATUS_OFFLINE;
105 case LPQ_PAPEROUT:
106 return JOB_STATUS_PAPEROUT;
107 case LPQ_PRINTED:
108 return JOB_STATUS_PRINTED;
109 case LPQ_DELETED:
110 return JOB_STATUS_DELETED;
111 case LPQ_BLOCKED:
112 return JOB_STATUS_BLOCKED;
113 case LPQ_USER_INTERVENTION:
114 return JOB_STATUS_USER_INTERVENTION;
116 return 0;
119 static int nt_printq_status(int v)
121 switch (v) {
122 case LPQ_PAUSED:
123 return PRINTER_STATUS_PAUSED;
124 case LPQ_QUEUED:
125 case LPQ_SPOOLING:
126 case LPQ_PRINTING:
127 return 0;
129 return 0;
132 /****************************************************************************
133 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
134 ****************************************************************************/
136 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
138 if (*pp == NULL)
139 return;
141 SAFE_FREE((*pp)->ctr.type);
142 SAFE_FREE(*pp);
145 /***************************************************************************
146 Disconnect from the client
147 ****************************************************************************/
149 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
151 WERROR result;
154 * Tell the specific printing tdb we no longer want messages for this printer
155 * by deregistering our PID.
158 if (!print_notify_deregister_pid(snum))
159 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
161 /* weird if the test succeds !!! */
162 if (smb_connections==0) {
163 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
164 return;
167 result = cli_spoolss_reply_close_printer(&notify_cli, notify_cli.mem_ctx, handle);
169 if (!W_ERROR_IS_OK(result))
170 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171 dos_errstr(result)));
173 /* if it's the last connection, deconnect the IPC$ share */
174 if (smb_connections==1) {
175 cli_nt_session_close(&notify_cli);
176 cli_ulogoff(&notify_cli);
177 cli_shutdown(&notify_cli);
178 message_deregister(MSG_PRINTER_NOTIFY2);
180 /* Tell the connections db we're no longer interested in
181 * printer notify messages. */
183 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
186 smb_connections--;
189 /****************************************************************************
190 Functions to free a printer entry datastruct.
191 ****************************************************************************/
193 static void free_printer_entry(void *ptr)
195 Printer_entry *Printer = (Printer_entry *)ptr;
197 if (Printer->notify.client_connected==True) {
198 int snum = -1;
200 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
201 snum = -1;
202 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
204 snum = print_queue_snum(Printer->sharename);
205 if (snum != -1)
206 srv_spoolss_replycloseprinter(snum,
207 &Printer->notify.client_hnd);
211 Printer->notify.flags=0;
212 Printer->notify.options=0;
213 Printer->notify.localmachine[0]='\0';
214 Printer->notify.printerlocal=0;
215 free_spool_notify_option(&Printer->notify.option);
216 Printer->notify.option=NULL;
217 Printer->notify.client_connected=False;
219 free_nt_devicemode( &Printer->nt_devmode );
220 free_a_printer( &Printer->printer_info, 2 );
222 talloc_destroy( Printer->ctx );
224 /* Remove from the internal list. */
225 DLIST_REMOVE(printers_list, Printer);
227 SAFE_FREE(Printer);
230 /****************************************************************************
231 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
232 ****************************************************************************/
234 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
236 SPOOL_NOTIFY_OPTION *new_sp = NULL;
238 if (!sp)
239 return NULL;
241 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
242 if (!new_sp)
243 return NULL;
245 *new_sp = *sp;
247 if (sp->ctr.count) {
248 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
250 if (!new_sp->ctr.type) {
251 SAFE_FREE(new_sp);
252 return NULL;
256 return new_sp;
259 /****************************************************************************
260 find printer index by handle
261 ****************************************************************************/
263 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
265 Printer_entry *find_printer = NULL;
267 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
268 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
269 return NULL;
272 return find_printer;
275 /****************************************************************************
276 look for a printer object cached on an open printer handle
277 ****************************************************************************/
279 WERROR find_printer_in_print_hnd_cache( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 **info2,
280 const char *servername, const char *printername )
282 Printer_entry *p;
284 DEBUG(10,("find_printer_in_print_hnd_cache: printer [\\\\%s\\%s]\n",
285 servername, printername));
287 for ( p=printers_list; p; p=p->next )
289 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
290 && p->printer_info
291 && strequal( p->sharename, printername )
292 && strequal( p->servername, servername ) )
294 DEBUG(10,("Found printer\n"));
295 *info2 = dup_printer_2( ctx, p->printer_info->info_2 );
296 if ( *info2 )
297 return WERR_OK;
301 return WERR_INVALID_PRINTER_NAME;
304 /****************************************************************************
305 destroy any cached printer_info_2 structures on open handles
306 ****************************************************************************/
308 void invalidate_printer_hnd_cache( char *printername )
310 Printer_entry *p;
312 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
314 for ( p=printers_list; p; p=p->next )
316 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
317 && p->printer_info
318 && StrCaseCmp(p->sharename, printername)==0)
320 DEBUG(10,("invalidating printer_info cache for handl:\n"));
321 free_a_printer( &p->printer_info, 2 );
322 p->printer_info = NULL;
326 return;
328 /****************************************************************************
329 Close printer index by handle.
330 ****************************************************************************/
332 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
334 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
336 if (!Printer) {
337 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
338 return False;
341 close_policy_hnd(p, hnd);
343 return True;
346 /****************************************************************************
347 Delete a printer given a handle.
348 ****************************************************************************/
350 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
352 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
354 if (!Printer) {
355 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
356 return WERR_BADFID;
360 * It turns out that Windows allows delete printer on a handle
361 * opened by an admin user, then used on a pipe handle created
362 * by an anonymous user..... but they're working on security.... riiight !
363 * JRA.
366 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
367 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
368 return WERR_ACCESS_DENIED;
371 #if 0
372 /* Check calling user has permission to delete printer. Note that
373 since we set the snum parameter to -1 only administrators can
374 delete the printer. This stops people with the Full Control
375 permission from deleting the printer. */
377 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
378 DEBUG(3, ("printer delete denied by security descriptor\n"));
379 return WERR_ACCESS_DENIED;
381 #endif
383 /* this does not need a become root since the access check has been
384 done on the handle already */
386 if (del_a_printer( Printer->sharename ) != 0) {
387 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
388 return WERR_BADFID;
391 /* the delete printer script shoudl be run as root if the user has perms */
393 if (*lp_deleteprinter_cmd()) {
395 char *cmd = lp_deleteprinter_cmd();
396 pstring command;
397 int ret;
398 SE_PRIV se_printop = SE_PRINT_OPERATOR;
399 BOOL is_print_op;
401 pstr_sprintf(command, "%s \"%s\"", cmd, Printer->sharename);
403 is_print_op = user_has_privileges( p->pipe_user.nt_user_token, &se_printop );
405 DEBUG(10,("Running [%s]\n", command));
407 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
409 if ( is_print_op )
410 become_root();
412 if ( (ret = smbrun(command, NULL)) == 0 ) {
413 /* Tell everyone we updated smb.conf. */
414 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
417 if ( is_print_op )
418 unbecome_root();
420 /********** END SePrintOperatorPrivlege BLOCK **********/
422 DEBUGADD(10,("returned [%d]\n", ret));
424 if (ret != 0)
425 return WERR_BADFID; /* What to return here? */
427 /* go ahead and re-read the services immediately */
428 reload_services( False );
430 if ( lp_servicenumber( Printer->sharename ) < 0 )
431 return WERR_ACCESS_DENIED;
434 return WERR_OK;
437 /****************************************************************************
438 Return the snum of a printer corresponding to an handle.
439 ****************************************************************************/
441 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
443 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
445 if (!Printer) {
446 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
447 return False;
450 switch (Printer->printer_type) {
451 case PRINTER_HANDLE_IS_PRINTER:
452 DEBUG(4,("short name:%s\n", Printer->sharename));
453 *number = print_queue_snum(Printer->sharename);
454 return (*number != -1);
455 case PRINTER_HANDLE_IS_PRINTSERVER:
456 return False;
457 default:
458 return False;
462 /****************************************************************************
463 Set printer handle type.
464 Check if it's \\server or \\server\printer
465 ****************************************************************************/
467 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
469 DEBUG(3,("Setting printer type=%s\n", handlename));
471 if ( strlen(handlename) < 3 ) {
472 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
473 return False;
476 /* it's a print server */
477 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
478 DEBUGADD(4,("Printer is a print server\n"));
479 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
481 /* it's a printer */
482 else {
483 DEBUGADD(4,("Printer is a printer\n"));
484 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
487 return True;
490 /****************************************************************************
491 Set printer handle name.
492 ****************************************************************************/
494 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
496 int snum;
497 int n_services=lp_numservices();
498 char *aprinter, *printername;
499 const char *servername;
500 fstring sname;
501 BOOL found=False;
502 NT_PRINTER_INFO_LEVEL *printer;
503 WERROR result;
505 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
507 aprinter = handlename;
508 if ( *handlename == '\\' ) {
509 servername = handlename + 2;
510 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
511 *aprinter = '\0';
512 aprinter++;
515 else {
516 servername = "";
519 /* save the servername to fill in replies on this handle */
521 if ( !is_myname_or_ipaddr( servername ) )
522 return False;
524 fstrcpy( Printer->servername, servername );
526 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
527 return True;
529 if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
530 return False;
532 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
534 /* Search all sharenames first as this is easier than pulling
535 the printer_info_2 off of disk */
537 snum = find_service(aprinter);
539 if ( lp_snum_ok(snum) && lp_print_ok(snum) ) {
540 found = True;
541 fstrcpy( sname, aprinter );
544 /* do another loop to look for printernames */
546 for (snum=0; !found && snum<n_services; snum++) {
548 /* no point in checking if this is not a printer or
549 we aren't allowing printername != sharename */
551 if ( !(lp_snum_ok(snum)
552 && lp_print_ok(snum)
553 && !lp_force_printername(snum)) )
555 continue;
558 fstrcpy(sname, lp_servicename(snum));
560 printer = NULL;
561 result = get_a_printer( NULL, &printer, 2, sname );
562 if ( !W_ERROR_IS_OK(result) ) {
563 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
564 sname, dos_errstr(result)));
565 continue;
568 /* printername is always returned as \\server\printername */
569 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
570 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
571 printer->info_2->printername));
572 free_a_printer( &printer, 2);
573 continue;
576 printername++;
578 if ( strequal(printername, aprinter) ) {
579 found = True;
582 DEBUGADD(10, ("printername: %s\n", printername));
584 free_a_printer( &printer, 2);
587 if ( !found ) {
588 DEBUGADD(4,("Printer not found\n"));
589 return False;
592 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
594 fstrcpy(Printer->sharename, sname);
596 return True;
599 /****************************************************************************
600 Find first available printer slot. creates a printer handle for you.
601 ****************************************************************************/
603 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
605 Printer_entry *new_printer;
607 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
609 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
610 return False;
612 ZERO_STRUCTP(new_printer);
614 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
615 SAFE_FREE(new_printer);
616 return False;
619 /* Add to the internal list. */
620 DLIST_ADD(printers_list, new_printer);
622 new_printer->notify.option=NULL;
624 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
625 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
626 close_printer_handle(p, hnd);
627 return False;
630 if (!set_printer_hnd_printertype(new_printer, name)) {
631 close_printer_handle(p, hnd);
632 return False;
635 if (!set_printer_hnd_name(new_printer, name)) {
636 close_printer_handle(p, hnd);
637 return False;
640 new_printer->access_granted = access_granted;
642 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
644 return True;
647 /***************************************************************************
648 check to see if the client motify handle is monitoring the notification
649 given by (notify_type, notify_field).
650 **************************************************************************/
652 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
653 uint16 notify_field)
655 return True;
658 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
659 uint16 notify_field)
661 SPOOL_NOTIFY_OPTION *option = p->notify.option;
662 uint32 i, j;
665 * Flags should always be zero when the change notify
666 * is registered by the client's spooler. A user Win32 app
667 * might use the flags though instead of the NOTIFY_OPTION_INFO
668 * --jerry
671 if (!option) {
672 return False;
675 if (p->notify.flags)
676 return is_monitoring_event_flags(
677 p->notify.flags, notify_type, notify_field);
679 for (i = 0; i < option->count; i++) {
681 /* Check match for notify_type */
683 if (option->ctr.type[i].type != notify_type)
684 continue;
686 /* Check match for field */
688 for (j = 0; j < option->ctr.type[i].count; j++) {
689 if (option->ctr.type[i].fields[j] == notify_field) {
690 return True;
695 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
696 p->servername, p->sharename, notify_type, notify_field));
698 return False;
701 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
703 static void notify_one_value(struct spoolss_notify_msg *msg,
704 SPOOL_NOTIFY_INFO_DATA *data,
705 TALLOC_CTX *mem_ctx)
707 data->notify_data.value[0] = msg->notify.value[0];
708 data->notify_data.value[1] = 0;
711 static void notify_string(struct spoolss_notify_msg *msg,
712 SPOOL_NOTIFY_INFO_DATA *data,
713 TALLOC_CTX *mem_ctx)
715 UNISTR2 unistr;
717 /* The length of the message includes the trailing \0 */
719 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
721 data->notify_data.data.length = msg->len * 2;
722 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
724 if (!data->notify_data.data.string) {
725 data->notify_data.data.length = 0;
726 return;
729 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
732 static void notify_system_time(struct spoolss_notify_msg *msg,
733 SPOOL_NOTIFY_INFO_DATA *data,
734 TALLOC_CTX *mem_ctx)
736 SYSTEMTIME systime;
737 prs_struct ps;
739 if (msg->len != sizeof(time_t)) {
740 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
741 msg->len));
742 return;
745 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
746 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
747 return;
750 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
751 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
752 return;
755 if (!spoolss_io_system_time("", &ps, 0, &systime))
756 return;
758 data->notify_data.data.length = prs_offset(&ps);
759 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
761 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
763 prs_mem_free(&ps);
766 struct notify2_message_table {
767 const char *name;
768 void (*fn)(struct spoolss_notify_msg *msg,
769 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
772 static struct notify2_message_table printer_notify_table[] = {
773 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
774 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
775 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
776 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
777 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
778 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
779 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
780 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
781 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
782 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
783 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
784 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
785 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
786 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
787 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
788 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
789 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
790 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
791 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
794 static struct notify2_message_table job_notify_table[] = {
795 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
796 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
797 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
798 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
799 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
800 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
801 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
802 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
803 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
804 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
805 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
806 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
807 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
808 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
809 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
810 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
811 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
812 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
813 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
814 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
815 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
816 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
817 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
818 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
822 /***********************************************************************
823 Allocate talloc context for container object
824 **********************************************************************/
826 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
828 if ( !ctr )
829 return;
831 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
833 return;
836 /***********************************************************************
837 release all allocated memory and zero out structure
838 **********************************************************************/
840 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
842 if ( !ctr )
843 return;
845 if ( ctr->ctx )
846 talloc_destroy(ctr->ctx);
848 ZERO_STRUCTP(ctr);
850 return;
853 /***********************************************************************
854 **********************************************************************/
856 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
858 if ( !ctr )
859 return NULL;
861 return ctr->ctx;
864 /***********************************************************************
865 **********************************************************************/
867 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
869 if ( !ctr || !ctr->msg_groups )
870 return NULL;
872 if ( idx >= ctr->num_groups )
873 return NULL;
875 return &ctr->msg_groups[idx];
879 /***********************************************************************
880 How many groups of change messages do we have ?
881 **********************************************************************/
883 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
885 if ( !ctr )
886 return 0;
888 return ctr->num_groups;
891 /***********************************************************************
892 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
893 **********************************************************************/
895 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
897 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
898 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
899 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
900 int i, new_slot;
902 if ( !ctr || !msg )
903 return 0;
905 /* loop over all groups looking for a matching printer name */
907 for ( i=0; i<ctr->num_groups; i++ ) {
908 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
909 break;
912 /* add a new group? */
914 if ( i == ctr->num_groups ) {
915 ctr->num_groups++;
917 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
918 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
919 return 0;
921 ctr->msg_groups = groups;
923 /* clear the new entry and set the printer name */
925 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
926 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
929 /* add the change messages; 'i' is the correct index now regardless */
931 msg_grp = &ctr->msg_groups[i];
933 msg_grp->num_msgs++;
935 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
936 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
937 return 0;
939 msg_grp->msgs = msg_list;
941 new_slot = msg_grp->num_msgs-1;
942 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
944 /* need to allocate own copy of data */
946 if ( msg->len != 0 )
947 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
949 return ctr->num_groups;
952 /***********************************************************************
953 Send a change notication message on all handles which have a call
954 back registered
955 **********************************************************************/
957 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
959 Printer_entry *p;
960 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
961 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
962 SPOOLSS_NOTIFY_MSG *messages;
963 int sending_msg_count;
965 if ( !msg_group ) {
966 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
967 return;
970 messages = msg_group->msgs;
972 if ( !messages ) {
973 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
974 return;
977 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
979 /* loop over all printers */
981 for (p = printers_list; p; p = p->next) {
982 SPOOL_NOTIFY_INFO_DATA *data;
983 uint32 data_len = 0;
984 uint32 id;
985 int i;
987 /* Is there notification on this handle? */
989 if ( !p->notify.client_connected )
990 continue;
992 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
994 /* For this printer? Print servers always receive
995 notifications. */
997 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
998 ( !strequal(msg_group->printername, p->sharename) ) )
999 continue;
1001 DEBUG(10,("Our printer\n"));
1003 /* allocate the max entries possible */
1005 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
1006 ZERO_STRUCTP(data);
1008 /* build the array of change notifications */
1010 sending_msg_count = 0;
1012 for ( i=0; i<msg_group->num_msgs; i++ ) {
1013 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1015 /* Are we monitoring this event? */
1017 if (!is_monitoring_event(p, msg->type, msg->field))
1018 continue;
1020 sending_msg_count++;
1023 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1024 msg->type, msg->field, p->sharename));
1027 * if the is a printer notification handle and not a job notification
1028 * type, then set the id to 0. Other wise just use what was specified
1029 * in the message.
1031 * When registering change notification on a print server handle
1032 * we always need to send back the id (snum) matching the printer
1033 * for which the change took place. For change notify registered
1034 * on a printer handle, this does not matter and the id should be 0.
1036 * --jerry
1039 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1040 id = 0;
1041 else
1042 id = msg->id;
1045 /* Convert unix jobid to smb jobid */
1047 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1048 id = sysjob_to_jobid(msg->id);
1050 if (id == -1) {
1051 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1052 goto done;
1056 construct_info_data( &data[data_len], msg->type, msg->field, id );
1058 switch(msg->type) {
1059 case PRINTER_NOTIFY_TYPE:
1060 if ( printer_notify_table[msg->field].fn )
1061 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1062 break;
1064 case JOB_NOTIFY_TYPE:
1065 if ( job_notify_table[msg->field].fn )
1066 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1067 break;
1069 default:
1070 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1071 goto done;
1074 data_len++;
1077 if ( sending_msg_count ) {
1078 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
1079 data_len, data, p->notify.change, 0 );
1083 done:
1084 DEBUG(8,("send_notify2_changes: Exit...\n"));
1085 return;
1088 /***********************************************************************
1089 **********************************************************************/
1091 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1094 uint32 tv_sec, tv_usec;
1095 size_t offset = 0;
1097 /* Unpack message */
1099 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1100 msg->printer);
1102 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1103 &tv_sec, &tv_usec,
1104 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1106 if (msg->len == 0)
1107 tdb_unpack((char *)buf + offset, len - offset, "dd",
1108 &msg->notify.value[0], &msg->notify.value[1]);
1109 else
1110 tdb_unpack((char *)buf + offset, len - offset, "B",
1111 &msg->len, &msg->notify.data);
1113 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1114 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1116 tv->tv_sec = tv_sec;
1117 tv->tv_usec = tv_usec;
1119 if (msg->len == 0)
1120 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1121 msg->notify.value[1]));
1122 else
1123 dump_data(3, msg->notify.data, msg->len);
1125 return True;
1128 /********************************************************************
1129 Receive a notify2 message list
1130 ********************************************************************/
1132 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1134 size_t msg_count, i;
1135 char *buf = (char *)msg;
1136 char *msg_ptr;
1137 size_t msg_len;
1138 SPOOLSS_NOTIFY_MSG notify;
1139 SPOOLSS_NOTIFY_MSG_CTR messages;
1140 int num_groups;
1142 if (len < 4) {
1143 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1144 return;
1147 msg_count = IVAL(buf, 0);
1148 msg_ptr = buf + 4;
1150 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1152 if (msg_count == 0) {
1153 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1154 return;
1157 /* initialize the container */
1159 ZERO_STRUCT( messages );
1160 notify_msg_ctr_init( &messages );
1163 * build message groups for each printer identified
1164 * in a change_notify msg. Remember that a PCN message
1165 * includes the handle returned for the srv_spoolss_replyopenprinter()
1166 * call. Therefore messages are grouped according to printer handle.
1169 for ( i=0; i<msg_count; i++ ) {
1170 struct timeval msg_tv;
1172 if (msg_ptr + 4 - buf > len) {
1173 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1174 return;
1177 msg_len = IVAL(msg_ptr,0);
1178 msg_ptr += 4;
1180 if (msg_ptr + msg_len - buf > len) {
1181 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1182 return;
1185 /* unpack messages */
1187 ZERO_STRUCT( notify );
1188 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1189 msg_ptr += msg_len;
1191 /* add to correct list in container */
1193 notify_msg_ctr_addmsg( &messages, &notify );
1195 /* free memory that might have been allocated by notify2_unpack_msg() */
1197 if ( notify.len != 0 )
1198 SAFE_FREE( notify.notify.data );
1201 /* process each group of messages */
1203 num_groups = notify_msg_ctr_numgroups( &messages );
1204 for ( i=0; i<num_groups; i++ )
1205 send_notify2_changes( &messages, i );
1208 /* cleanup */
1210 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1212 notify_msg_ctr_destroy( &messages );
1214 return;
1217 /********************************************************************
1218 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1219 one smbd, all of processes must clear their printer cache immediately.
1220 ********************************************************************/
1222 void receive_printer_mod_msg(int msg_type, pid_t src, void *buf, size_t len)
1224 fstring printername;
1226 fstrcpy( printername, buf );
1228 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername ));
1230 invalidate_printer_hnd_cache( printername );
1233 /********************************************************************
1234 Send a message to ourself about new driver being installed
1235 so we can upgrade the information for each printer bound to this
1236 driver
1237 ********************************************************************/
1239 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1241 int len = strlen(drivername);
1243 if (!len)
1244 return False;
1246 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1247 drivername));
1249 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1251 return True;
1254 /**********************************************************************
1255 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1256 over all printers, upgrading ones as necessary
1257 **********************************************************************/
1259 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1261 fstring drivername;
1262 int snum;
1263 int n_services = lp_numservices();
1265 len = MIN(len,sizeof(drivername)-1);
1266 strncpy(drivername, buf, len);
1268 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1270 /* Iterate the printer list */
1272 for (snum=0; snum<n_services; snum++)
1274 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1276 WERROR result;
1277 NT_PRINTER_INFO_LEVEL *printer = NULL;
1279 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1280 if (!W_ERROR_IS_OK(result))
1281 continue;
1283 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1285 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1287 /* all we care about currently is the change_id */
1289 result = mod_a_printer(printer, 2);
1290 if (!W_ERROR_IS_OK(result)) {
1291 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1292 dos_errstr(result)));
1296 free_a_printer(&printer, 2);
1300 /* all done */
1303 /********************************************************************
1304 Update the cache for all printq's with a registered client
1305 connection
1306 ********************************************************************/
1308 void update_monitored_printq_cache( void )
1310 Printer_entry *printer = printers_list;
1311 int snum;
1313 /* loop through all printers and update the cache where
1314 client_connected == True */
1315 while ( printer )
1317 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1318 && printer->notify.client_connected )
1320 snum = print_queue_snum(printer->sharename);
1321 print_queue_status( snum, NULL, NULL );
1324 printer = printer->next;
1327 return;
1329 /********************************************************************
1330 Send a message to ourself about new driver being installed
1331 so we can upgrade the information for each printer bound to this
1332 driver
1333 ********************************************************************/
1335 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1337 int len = strlen(drivername);
1339 if (!len)
1340 return False;
1342 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1343 drivername));
1345 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1347 return True;
1350 /**********************************************************************
1351 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1352 over all printers, resetting printer data as neessary
1353 **********************************************************************/
1355 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1357 fstring drivername;
1358 int snum;
1359 int n_services = lp_numservices();
1361 len = MIN( len, sizeof(drivername)-1 );
1362 strncpy( drivername, buf, len );
1364 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1366 /* Iterate the printer list */
1368 for ( snum=0; snum<n_services; snum++ )
1370 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1372 WERROR result;
1373 NT_PRINTER_INFO_LEVEL *printer = NULL;
1375 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1376 if ( !W_ERROR_IS_OK(result) )
1377 continue;
1380 * if the printer is bound to the driver,
1381 * then reset to the new driver initdata
1384 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1386 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1388 if ( !set_driver_init(printer, 2) ) {
1389 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1390 printer->info_2->printername, printer->info_2->drivername));
1393 result = mod_a_printer( printer, 2 );
1394 if ( !W_ERROR_IS_OK(result) ) {
1395 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1396 get_dos_error_msg(result)));
1400 free_a_printer( &printer, 2 );
1404 /* all done */
1406 return;
1409 /********************************************************************
1410 Copy routines used by convert_to_openprinterex()
1411 *******************************************************************/
1413 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1415 DEVICEMODE *d;
1416 int len;
1418 if (!devmode)
1419 return NULL;
1421 DEBUG (8,("dup_devmode\n"));
1423 /* bulk copy first */
1425 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1426 if (!d)
1427 return NULL;
1429 /* dup the pointer members separately */
1431 len = unistrlen(devmode->devicename.buffer);
1432 if (len != -1) {
1433 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1434 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1435 return NULL;
1439 len = unistrlen(devmode->formname.buffer);
1440 if (len != -1) {
1441 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1442 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1443 return NULL;
1446 d->private = TALLOC_MEMDUP(ctx, devmode->private, devmode->driverextra);
1448 return d;
1451 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1453 if (!new_ctr || !ctr)
1454 return;
1456 DEBUG(8,("copy_devmode_ctr\n"));
1458 new_ctr->size = ctr->size;
1459 new_ctr->devmode_ptr = ctr->devmode_ptr;
1461 if(ctr->devmode_ptr)
1462 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1465 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1467 if (!new_def || !def)
1468 return;
1470 DEBUG(8,("copy_printer_defaults\n"));
1472 new_def->datatype_ptr = def->datatype_ptr;
1474 if (def->datatype_ptr)
1475 copy_unistr2(&new_def->datatype, &def->datatype);
1477 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1479 new_def->access_required = def->access_required;
1482 /********************************************************************
1483 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1484 * SPOOL_Q_OPEN_PRINTER_EX structure
1485 ********************************************************************/
1487 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1489 if (!q_u_ex || !q_u)
1490 return;
1492 DEBUG(8,("convert_to_openprinterex\n"));
1494 q_u_ex->printername_ptr = q_u->printername_ptr;
1496 if (q_u->printername_ptr)
1497 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1499 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1502 /********************************************************************
1503 * spoolss_open_printer
1505 * called from the spoolss dispatcher
1506 ********************************************************************/
1508 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1510 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1511 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1513 if (!q_u || !r_u)
1514 return WERR_NOMEM;
1516 ZERO_STRUCT(q_u_ex);
1517 ZERO_STRUCT(r_u_ex);
1519 /* convert the OpenPrinter() call to OpenPrinterEx() */
1521 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1523 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1525 /* convert back to OpenPrinter() */
1527 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1529 return r_u->status;
1532 /********************************************************************
1533 * spoolss_open_printer
1535 * If the openprinterex rpc call contains a devmode,
1536 * it's a per-user one. This per-user devmode is derivated
1537 * from the global devmode. Openprinterex() contains a per-user
1538 * devmode for when you do EMF printing and spooling.
1539 * In the EMF case, the NT workstation is only doing half the job
1540 * of rendering the page. The other half is done by running the printer
1541 * driver on the server.
1542 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1543 * The EMF file only contains what is to be printed on the page.
1544 * So in order for the server to know how to print, the NT client sends
1545 * a devicemode attached to the openprinterex call.
1546 * But this devicemode is short lived, it's only valid for the current print job.
1548 * If Samba would have supported EMF spooling, this devicemode would
1549 * have been attached to the handle, to sent it to the driver to correctly
1550 * rasterize the EMF file.
1552 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1553 * we just act as a pass-thru between windows and the printer.
1555 * In order to know that Samba supports only RAW spooling, NT has to call
1556 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1557 * and until NT sends a RAW job, we refuse it.
1559 * But to call getprinter() or startdoc(), you first need a valid handle,
1560 * and to get an handle you have to call openprintex(). Hence why you have
1561 * a devicemode in the openprinterex() call.
1564 * Differences between NT4 and NT 2000.
1565 * NT4:
1566 * ---
1567 * On NT4, you only have a global devicemode. This global devicemode can be changed
1568 * by the administrator (or by a user with enough privs). Everytime a user
1569 * wants to print, the devicemode is resetted to the default. In Word, everytime
1570 * you print, the printer's characteristics are always reset to the global devicemode.
1572 * NT 2000:
1573 * -------
1574 * In W2K, there is the notion of per-user devicemode. The first time you use
1575 * a printer, a per-user devicemode is build from the global devicemode.
1576 * If you change your per-user devicemode, it is saved in the registry, under the
1577 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1578 * printer preferences available.
1580 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1581 * on the General Tab of the printer properties windows.
1583 * To change the global devicemode: it's the "Printing Defaults..." button
1584 * on the Advanced Tab of the printer properties window.
1586 * JFM.
1587 ********************************************************************/
1589 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1591 UNISTR2 *printername = NULL;
1592 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1593 POLICY_HND *handle = &r_u->handle;
1595 fstring name;
1596 int snum;
1597 struct current_user user;
1598 Printer_entry *Printer=NULL;
1600 if (q_u->printername_ptr != 0)
1601 printername = &q_u->printername;
1603 if (printername == NULL)
1604 return WERR_INVALID_PRINTER_NAME;
1606 /* some sanity check because you can open a printer or a print server */
1607 /* aka: \\server\printer or \\server */
1608 unistr2_to_ascii(name, printername, sizeof(name)-1);
1610 DEBUGADD(3,("checking name: %s\n",name));
1612 if (!open_printer_hnd(p, handle, name, 0))
1613 return WERR_INVALID_PRINTER_NAME;
1615 Printer=find_printer_index_by_hnd(p, handle);
1616 if ( !Printer ) {
1617 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1618 "handle we created for printer %s\n", name ));
1619 close_printer_handle(p,handle);
1620 return WERR_INVALID_PRINTER_NAME;
1623 get_current_user(&user, p);
1626 * First case: the user is opening the print server:
1628 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1629 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1631 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1632 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1633 * or if the user is listed in the smb.conf printer admin parameter.
1635 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1636 * client view printer folder, but does not show the MSAPW.
1638 * Note: this test needs code to check access rights here too. Jeremy
1639 * could you look at this?
1641 * Second case: the user is opening a printer:
1642 * NT doesn't let us connect to a printer if the connecting user
1643 * doesn't have print permission.
1646 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1648 /* Printserver handles use global struct... */
1650 snum = -1;
1652 /* Map standard access rights to object specific access rights */
1654 se_map_standard(&printer_default->access_required,
1655 &printserver_std_mapping);
1657 /* Deny any object specific bits that don't apply to print
1658 servers (i.e printer and job specific bits) */
1660 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1662 if (printer_default->access_required &
1663 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1664 DEBUG(3, ("access DENIED for non-printserver bits"));
1665 close_printer_handle(p, handle);
1666 return WERR_ACCESS_DENIED;
1669 /* Allow admin access */
1671 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1673 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1675 if (!lp_ms_add_printer_wizard()) {
1676 close_printer_handle(p, handle);
1677 return WERR_ACCESS_DENIED;
1680 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1681 and not a printer admin, then fail */
1683 if ( user.uid != 0
1684 && !user_has_privileges( user.nt_user_token, &se_printop )
1685 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1687 close_printer_handle(p, handle);
1688 return WERR_ACCESS_DENIED;
1691 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1693 else
1695 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1698 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1699 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1701 /* We fall through to return WERR_OK */
1704 else
1706 /* NT doesn't let us connect to a printer if the connecting user
1707 doesn't have print permission. */
1709 if (!get_printer_snum(p, handle, &snum)) {
1710 close_printer_handle(p, handle);
1711 return WERR_BADFID;
1714 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1716 /* map an empty access mask to the minimum access mask */
1717 if (printer_default->access_required == 0x0)
1718 printer_default->access_required = PRINTER_ACCESS_USE;
1721 * If we are not serving the printer driver for this printer,
1722 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1723 * will keep NT clients happy --jerry
1726 if (lp_use_client_driver(snum)
1727 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1729 printer_default->access_required = PRINTER_ACCESS_USE;
1732 /* check smb.conf parameters and the the sec_desc */
1734 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1735 DEBUG(3, ("access DENIED for printer open\n"));
1736 close_printer_handle(p, handle);
1737 return WERR_ACCESS_DENIED;
1740 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1741 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1742 close_printer_handle(p, handle);
1743 return WERR_ACCESS_DENIED;
1746 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1747 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1748 else
1749 printer_default->access_required = PRINTER_ACCESS_USE;
1751 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1752 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1756 Printer->access_granted = printer_default->access_required;
1759 * If the client sent a devmode in the OpenPrinter() call, then
1760 * save it here in case we get a job submission on this handle
1763 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1764 && q_u->printer_default.devmode_cont.devmode_ptr )
1766 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1767 &Printer->nt_devmode );
1770 #if 0 /* JERRY -- I'm doubtful this is really effective */
1771 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1772 optimization in Windows 2000 clients --jerry */
1774 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1775 && (RA_WIN2K == get_remote_arch()) )
1777 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1778 sys_usleep( 500000 );
1780 #endif
1782 return WERR_OK;
1785 /****************************************************************************
1786 ****************************************************************************/
1788 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1789 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1791 BOOL ret = True;
1793 switch (level) {
1794 case 2:
1795 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1796 break;
1797 default:
1798 break;
1801 return ret;
1804 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1805 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1807 BOOL result = True;
1809 switch (level) {
1810 case 3:
1811 printer->info_3=NULL;
1812 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1813 result = False;
1814 break;
1815 case 6:
1816 printer->info_6=NULL;
1817 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1818 result = False;
1819 break;
1820 default:
1821 break;
1824 return result;
1827 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1828 NT_DEVICEMODE **pp_nt_devmode)
1830 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1833 * Ensure nt_devmode is a valid pointer
1834 * as we will be overwriting it.
1837 if (nt_devmode == NULL) {
1838 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1839 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1840 return False;
1843 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1844 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1846 nt_devmode->specversion=devmode->specversion;
1847 nt_devmode->driverversion=devmode->driverversion;
1848 nt_devmode->size=devmode->size;
1849 nt_devmode->fields=devmode->fields;
1850 nt_devmode->orientation=devmode->orientation;
1851 nt_devmode->papersize=devmode->papersize;
1852 nt_devmode->paperlength=devmode->paperlength;
1853 nt_devmode->paperwidth=devmode->paperwidth;
1854 nt_devmode->scale=devmode->scale;
1855 nt_devmode->copies=devmode->copies;
1856 nt_devmode->defaultsource=devmode->defaultsource;
1857 nt_devmode->printquality=devmode->printquality;
1858 nt_devmode->color=devmode->color;
1859 nt_devmode->duplex=devmode->duplex;
1860 nt_devmode->yresolution=devmode->yresolution;
1861 nt_devmode->ttoption=devmode->ttoption;
1862 nt_devmode->collate=devmode->collate;
1864 nt_devmode->logpixels=devmode->logpixels;
1865 nt_devmode->bitsperpel=devmode->bitsperpel;
1866 nt_devmode->pelswidth=devmode->pelswidth;
1867 nt_devmode->pelsheight=devmode->pelsheight;
1868 nt_devmode->displayflags=devmode->displayflags;
1869 nt_devmode->displayfrequency=devmode->displayfrequency;
1870 nt_devmode->icmmethod=devmode->icmmethod;
1871 nt_devmode->icmintent=devmode->icmintent;
1872 nt_devmode->mediatype=devmode->mediatype;
1873 nt_devmode->dithertype=devmode->dithertype;
1874 nt_devmode->reserved1=devmode->reserved1;
1875 nt_devmode->reserved2=devmode->reserved2;
1876 nt_devmode->panningwidth=devmode->panningwidth;
1877 nt_devmode->panningheight=devmode->panningheight;
1880 * Only change private and driverextra if the incoming devmode
1881 * has a new one. JRA.
1884 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1885 SAFE_FREE(nt_devmode->private);
1886 nt_devmode->driverextra=devmode->driverextra;
1887 if((nt_devmode->private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1888 return False;
1889 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1892 *pp_nt_devmode = nt_devmode;
1894 return True;
1897 /********************************************************************
1898 * _spoolss_enddocprinter_internal.
1899 ********************************************************************/
1901 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1903 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1904 int snum;
1906 if (!Printer) {
1907 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1908 return WERR_BADFID;
1911 if (!get_printer_snum(p, handle, &snum))
1912 return WERR_BADFID;
1914 Printer->document_started=False;
1915 print_job_end(snum, Printer->jobid,True);
1916 /* error codes unhandled so far ... */
1918 return WERR_OK;
1921 /********************************************************************
1922 * api_spoolss_closeprinter
1923 ********************************************************************/
1925 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1927 POLICY_HND *handle = &q_u->handle;
1929 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1931 if (Printer && Printer->document_started)
1932 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1934 if (!close_printer_handle(p, handle))
1935 return WERR_BADFID;
1937 /* clear the returned printer handle. Observed behavior
1938 from Win2k server. Don't think this really matters.
1939 Previous code just copied the value of the closed
1940 handle. --jerry */
1942 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1944 return WERR_OK;
1947 /********************************************************************
1948 * api_spoolss_deleteprinter
1950 ********************************************************************/
1952 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1954 POLICY_HND *handle = &q_u->handle;
1955 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1956 WERROR result;
1958 if (Printer && Printer->document_started)
1959 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1961 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1963 result = delete_printer_handle(p, handle);
1965 update_c_setprinter(False);
1967 return result;
1970 /*******************************************************************
1971 * static function to lookup the version id corresponding to an
1972 * long architecture string
1973 ******************************************************************/
1975 static int get_version_id (char * arch)
1977 int i;
1978 struct table_node archi_table[]= {
1980 {"Windows 4.0", "WIN40", 0 },
1981 {"Windows NT x86", "W32X86", 2 },
1982 {"Windows NT R4000", "W32MIPS", 2 },
1983 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1984 {"Windows NT PowerPC", "W32PPC", 2 },
1985 {"Windows IA64", "IA64", 3 },
1986 {"Windows x64", "x64", 3 },
1987 {NULL, "", -1 }
1990 for (i=0; archi_table[i].long_archi != NULL; i++)
1992 if (strcmp(arch, archi_table[i].long_archi) == 0)
1993 return (archi_table[i].version);
1996 return -1;
1999 /********************************************************************
2000 * _spoolss_deleteprinterdriver
2001 ********************************************************************/
2003 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2005 fstring driver;
2006 fstring arch;
2007 NT_PRINTER_DRIVER_INFO_LEVEL info;
2008 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2009 int version;
2010 struct current_user user;
2011 WERROR status;
2012 WERROR status_win2k = WERR_ACCESS_DENIED;
2014 get_current_user(&user, p);
2016 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2017 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2019 /* check that we have a valid driver name first */
2021 if ((version=get_version_id(arch)) == -1)
2022 return WERR_INVALID_ENVIRONMENT;
2024 ZERO_STRUCT(info);
2025 ZERO_STRUCT(info_win2k);
2027 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2029 /* try for Win2k driver if "Windows NT x86" */
2031 if ( version == 2 ) {
2032 version = 3;
2033 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2034 status = WERR_UNKNOWN_PRINTER_DRIVER;
2035 goto done;
2038 /* otherwise it was a failure */
2039 else {
2040 status = WERR_UNKNOWN_PRINTER_DRIVER;
2041 goto done;
2046 if (printer_driver_in_use(info.info_3)) {
2047 status = WERR_PRINTER_DRIVER_IN_USE;
2048 goto done;
2051 if ( version == 2 )
2053 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2055 /* if we get to here, we now have 2 driver info structures to remove */
2056 /* remove the Win2k driver first*/
2058 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2059 free_a_printer_driver( info_win2k, 3 );
2061 /* this should not have failed---if it did, report to client */
2062 if ( !W_ERROR_IS_OK(status_win2k) )
2063 goto done;
2067 status = delete_printer_driver(info.info_3, &user, version, False);
2069 /* if at least one of the deletes succeeded return OK */
2071 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2072 status = WERR_OK;
2074 done:
2075 free_a_printer_driver( info, 3 );
2077 return status;
2080 /********************************************************************
2081 * spoolss_deleteprinterdriverex
2082 ********************************************************************/
2084 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2086 fstring driver;
2087 fstring arch;
2088 NT_PRINTER_DRIVER_INFO_LEVEL info;
2089 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2090 int version;
2091 uint32 flags = q_u->delete_flags;
2092 BOOL delete_files;
2093 struct current_user user;
2094 WERROR status;
2095 WERROR status_win2k = WERR_ACCESS_DENIED;
2097 get_current_user(&user, p);
2099 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2100 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2102 /* check that we have a valid driver name first */
2103 if ((version=get_version_id(arch)) == -1) {
2104 /* this is what NT returns */
2105 return WERR_INVALID_ENVIRONMENT;
2108 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2109 version = q_u->version;
2111 ZERO_STRUCT(info);
2112 ZERO_STRUCT(info_win2k);
2114 status = get_a_printer_driver(&info, 3, driver, arch, version);
2116 if ( !W_ERROR_IS_OK(status) )
2119 * if the client asked for a specific version,
2120 * or this is something other than Windows NT x86,
2121 * then we've failed
2124 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2125 goto done;
2127 /* try for Win2k driver if "Windows NT x86" */
2129 version = 3;
2130 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2131 status = WERR_UNKNOWN_PRINTER_DRIVER;
2132 goto done;
2136 if ( printer_driver_in_use(info.info_3) ) {
2137 status = WERR_PRINTER_DRIVER_IN_USE;
2138 goto done;
2142 * we have a couple of cases to consider.
2143 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2144 * then the delete should fail if **any** files overlap with
2145 * other drivers
2146 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2147 * non-overlapping files
2148 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2149 * is set, the do not delete any files
2150 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2153 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2155 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2157 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2158 /* no idea of the correct error here */
2159 status = WERR_ACCESS_DENIED;
2160 goto done;
2164 /* also check for W32X86/3 if necessary; maybe we already have? */
2166 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2167 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2170 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2171 /* no idea of the correct error here */
2172 free_a_printer_driver( info_win2k, 3 );
2173 status = WERR_ACCESS_DENIED;
2174 goto done;
2177 /* if we get to here, we now have 2 driver info structures to remove */
2178 /* remove the Win2k driver first*/
2180 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2181 free_a_printer_driver( info_win2k, 3 );
2183 /* this should not have failed---if it did, report to client */
2185 if ( !W_ERROR_IS_OK(status_win2k) )
2186 goto done;
2190 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2192 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2193 status = WERR_OK;
2194 done:
2195 free_a_printer_driver( info, 3 );
2197 return status;
2201 /****************************************************************************
2202 Internal routine for retreiving printerdata
2203 ***************************************************************************/
2205 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2206 const char *key, const char *value, uint32 *type, uint8 **data,
2207 uint32 *needed, uint32 in_size )
2209 REGISTRY_VALUE *val;
2210 int size, data_len;
2212 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2213 return WERR_BADFILE;
2215 *type = regval_type( val );
2217 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2219 size = regval_size( val );
2221 /* copy the min(in_size, len) */
2223 if ( in_size ) {
2224 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2226 /* special case for 0 length values */
2227 if ( data_len ) {
2228 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2229 return WERR_NOMEM;
2231 else {
2232 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2233 return WERR_NOMEM;
2236 else
2237 *data = NULL;
2239 *needed = size;
2241 DEBUG(5,("get_printer_dataex: copy done\n"));
2243 return WERR_OK;
2246 /****************************************************************************
2247 Internal routine for removing printerdata
2248 ***************************************************************************/
2250 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2252 return delete_printer_data( printer->info_2, key, value );
2255 /****************************************************************************
2256 Internal routine for storing printerdata
2257 ***************************************************************************/
2259 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2260 uint32 type, uint8 *data, int real_len )
2262 delete_printer_data( printer->info_2, key, value );
2264 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2267 /********************************************************************
2268 GetPrinterData on a printer server Handle.
2269 ********************************************************************/
2271 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2273 int i;
2275 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2277 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2278 *type = REG_DWORD;
2279 if((*data = (uint8 *)TALLOC_ZERO(ctx, 4*sizeof(uint8) )) == NULL)
2280 return WERR_NOMEM;
2281 *needed = 0x4;
2282 return WERR_OK;
2285 if (!StrCaseCmp(value, "BeepEnabled")) {
2286 *type = REG_DWORD;
2287 if((*data = (uint8 *)TALLOC(ctx, 4*sizeof(uint8) )) == NULL)
2288 return WERR_NOMEM;
2289 SIVAL(*data, 0, 0x00);
2290 *needed = 0x4;
2291 return WERR_OK;
2294 if (!StrCaseCmp(value, "EventLog")) {
2295 *type = REG_DWORD;
2296 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2297 return WERR_NOMEM;
2298 /* formally was 0x1b */
2299 SIVAL(*data, 0, 0x0);
2300 *needed = 0x4;
2301 return WERR_OK;
2304 if (!StrCaseCmp(value, "NetPopup")) {
2305 *type = REG_DWORD;
2306 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2307 return WERR_NOMEM;
2308 SIVAL(*data, 0, 0x00);
2309 *needed = 0x4;
2310 return WERR_OK;
2313 if (!StrCaseCmp(value, "MajorVersion")) {
2314 *type = REG_DWORD;
2315 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2316 return WERR_NOMEM;
2318 /* Windows NT 4.0 seems to not allow uploading of drivers
2319 to a server that reports 0x3 as the MajorVersion.
2320 need to investigate more how Win2k gets around this .
2321 -- jerry */
2323 if ( RA_WINNT == get_remote_arch() )
2324 SIVAL(*data, 0, 2);
2325 else
2326 SIVAL(*data, 0, 3);
2328 *needed = 0x4;
2329 return WERR_OK;
2332 if (!StrCaseCmp(value, "MinorVersion")) {
2333 *type = REG_DWORD;
2334 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2335 return WERR_NOMEM;
2336 SIVAL(*data, 0, 0);
2337 *needed = 0x4;
2338 return WERR_OK;
2341 /* REG_BINARY
2342 * uint32 size = 0x114
2343 * uint32 major = 5
2344 * uint32 minor = [0|1]
2345 * uint32 build = [2195|2600]
2346 * extra unicode string = e.g. "Service Pack 3"
2348 if (!StrCaseCmp(value, "OSVersion")) {
2349 *type = REG_BINARY;
2350 *needed = 0x114;
2352 if((*data = (uint8 *)TALLOC(ctx, *needed)) == NULL)
2353 return WERR_NOMEM;
2354 ZERO_STRUCTP( *data );
2356 SIVAL(*data, 0, *needed); /* size */
2357 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2358 SIVAL(*data, 8, 0);
2359 SIVAL(*data, 12, 2195); /* build */
2361 /* leave extra string empty */
2363 return WERR_OK;
2367 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2368 const char *string="C:\\PRINTERS";
2369 *type = REG_SZ;
2370 *needed = 2*(strlen(string)+1);
2371 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2372 return WERR_NOMEM;
2373 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2375 /* it's done by hand ready to go on the wire */
2376 for (i=0; i<strlen(string); i++) {
2377 (*data)[2*i]=string[i];
2378 (*data)[2*i+1]='\0';
2380 return WERR_OK;
2383 if (!StrCaseCmp(value, "Architecture")) {
2384 const char *string="Windows NT x86";
2385 *type = REG_SZ;
2386 *needed = 2*(strlen(string)+1);
2387 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2388 return WERR_NOMEM;
2389 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2390 for (i=0; i<strlen(string); i++) {
2391 (*data)[2*i]=string[i];
2392 (*data)[2*i+1]='\0';
2394 return WERR_OK;
2397 if (!StrCaseCmp(value, "DsPresent")) {
2398 *type = REG_DWORD;
2399 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2400 return WERR_NOMEM;
2402 /* only show the publish check box if we are a
2403 memeber of a AD domain */
2405 if ( lp_security() == SEC_ADS )
2406 SIVAL(*data, 0, 0x01);
2407 else
2408 SIVAL(*data, 0, 0x00);
2410 *needed = 0x4;
2411 return WERR_OK;
2414 if (!StrCaseCmp(value, "DNSMachineName")) {
2415 pstring hostname;
2417 if (!get_mydnsfullname(hostname))
2418 return WERR_BADFILE;
2419 *type = REG_SZ;
2420 *needed = 2*(strlen(hostname)+1);
2421 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2422 return WERR_NOMEM;
2423 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2424 for (i=0; i<strlen(hostname); i++) {
2425 (*data)[2*i]=hostname[i];
2426 (*data)[2*i+1]='\0';
2428 return WERR_OK;
2432 return WERR_BADFILE;
2435 /********************************************************************
2436 * spoolss_getprinterdata
2437 ********************************************************************/
2439 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2441 POLICY_HND *handle = &q_u->handle;
2442 UNISTR2 *valuename = &q_u->valuename;
2443 uint32 in_size = q_u->size;
2444 uint32 *type = &r_u->type;
2445 uint32 *out_size = &r_u->size;
2446 uint8 **data = &r_u->data;
2447 uint32 *needed = &r_u->needed;
2448 WERROR status;
2449 fstring value;
2450 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2451 NT_PRINTER_INFO_LEVEL *printer = NULL;
2452 int snum = 0;
2455 * Reminder: when it's a string, the length is in BYTES
2456 * even if UNICODE is negociated.
2458 * JFM, 4/19/1999
2461 *out_size = in_size;
2463 /* in case of problem, return some default values */
2465 *needed = 0;
2466 *type = 0;
2468 DEBUG(4,("_spoolss_getprinterdata\n"));
2470 if ( !Printer ) {
2471 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2472 status = WERR_BADFID;
2473 goto done;
2476 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2478 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2479 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2480 else
2482 if ( !get_printer_snum(p,handle, &snum) ) {
2483 status = WERR_BADFID;
2484 goto done;
2487 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2488 if ( !W_ERROR_IS_OK(status) )
2489 goto done;
2491 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2493 if ( strequal(value, "ChangeId") ) {
2494 *type = REG_DWORD;
2495 *needed = sizeof(uint32);
2496 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2497 status = WERR_NOMEM;
2498 goto done;
2500 SIVAL( *data, 0, printer->info_2->changeid );
2501 status = WERR_OK;
2503 else
2504 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2507 if (*needed > *out_size)
2508 status = WERR_MORE_DATA;
2510 done:
2511 if ( !W_ERROR_IS_OK(status) )
2513 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2515 /* reply this param doesn't exist */
2517 if ( *out_size ) {
2518 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2519 if ( printer )
2520 free_a_printer( &printer, 2 );
2521 return WERR_NOMEM;
2524 else {
2525 *data = NULL;
2529 /* cleanup & exit */
2531 if ( printer )
2532 free_a_printer( &printer, 2 );
2534 return status;
2537 /*********************************************************
2538 Connect to the client machine.
2539 **********************************************************/
2541 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2542 struct in_addr *client_ip, const char *remote_machine)
2544 ZERO_STRUCTP(the_cli);
2546 if(cli_initialise(the_cli) == NULL) {
2547 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2548 return False;
2551 if ( is_zero_ip(*client_ip) ) {
2552 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2553 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2554 cli_shutdown(the_cli);
2555 return False;
2558 if (ismyip(the_cli->dest_ip)) {
2559 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2560 cli_shutdown(the_cli);
2561 return False;
2564 else {
2565 the_cli->dest_ip.s_addr = client_ip->s_addr;
2566 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2567 inet_ntoa(*client_ip) ));
2570 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2571 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) ));
2572 cli_shutdown(the_cli);
2573 return False;
2576 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2577 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2578 remote_machine));
2579 cli_shutdown(the_cli);
2580 return False;
2583 the_cli->protocol = PROTOCOL_NT1;
2584 cli_setup_signing_state(the_cli, lp_client_signing());
2586 if (!cli_negprot(the_cli)) {
2587 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2588 cli_shutdown(the_cli);
2589 return False;
2592 if (the_cli->protocol != PROTOCOL_NT1) {
2593 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2594 cli_shutdown(the_cli);
2595 return False;
2599 * Do an anonymous session setup.
2602 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2603 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2604 cli_shutdown(the_cli);
2605 return False;
2608 if (!(the_cli->sec_mode & 1)) {
2609 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2610 cli_shutdown(the_cli);
2611 return False;
2614 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2615 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) ));
2616 cli_shutdown(the_cli);
2617 return False;
2621 * Ok - we have an anonymous connection to the IPC$ share.
2622 * Now start the NT Domain stuff :-).
2625 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2626 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)));
2627 cli_nt_session_close(the_cli);
2628 cli_ulogoff(the_cli);
2629 cli_shutdown(the_cli);
2630 return False;
2633 return True;
2636 /***************************************************************************
2637 Connect to the client.
2638 ****************************************************************************/
2640 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2641 uint32 localprinter, uint32 type,
2642 POLICY_HND *handle, struct in_addr *client_ip)
2644 WERROR result;
2647 * If it's the first connection, contact the client
2648 * and connect to the IPC$ share anonymously
2650 if (smb_connections==0) {
2651 fstring unix_printer;
2653 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2655 ZERO_STRUCT(notify_cli);
2657 if(!spoolss_connect_to_client(&notify_cli, client_ip, unix_printer))
2658 return False;
2660 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2661 /* Tell the connections db we're now interested in printer
2662 * notify messages. */
2663 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2667 * Tell the specific printing tdb we want messages for this printer
2668 * by registering our PID.
2671 if (!print_notify_register_pid(snum))
2672 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2674 smb_connections++;
2676 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2677 type, handle);
2679 if (!W_ERROR_IS_OK(result))
2680 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2681 dos_errstr(result)));
2683 return (W_ERROR_IS_OK(result));
2686 /********************************************************************
2687 * _spoolss_rffpcnex
2688 * ReplyFindFirstPrinterChangeNotifyEx
2690 * before replying OK: status=0 a rpc call is made to the workstation
2691 * asking ReplyOpenPrinter
2693 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2694 * called from api_spoolss_rffpcnex
2695 ********************************************************************/
2697 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2699 POLICY_HND *handle = &q_u->handle;
2700 uint32 flags = q_u->flags;
2701 uint32 options = q_u->options;
2702 UNISTR2 *localmachine = &q_u->localmachine;
2703 uint32 printerlocal = q_u->printerlocal;
2704 int snum = -1;
2705 SPOOL_NOTIFY_OPTION *option = q_u->option;
2706 struct in_addr client_ip;
2708 /* store the notify value in the printer struct */
2710 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2712 if (!Printer) {
2713 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2714 return WERR_BADFID;
2717 Printer->notify.flags=flags;
2718 Printer->notify.options=options;
2719 Printer->notify.printerlocal=printerlocal;
2721 if (Printer->notify.option)
2722 free_spool_notify_option(&Printer->notify.option);
2724 Printer->notify.option=dup_spool_notify_option(option);
2726 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2727 sizeof(Printer->notify.localmachine)-1);
2729 /* Connect to the client machine and send a ReplyOpenPrinter */
2731 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2732 snum = -1;
2733 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2734 !get_printer_snum(p, handle, &snum) )
2735 return WERR_BADFID;
2737 client_ip.s_addr = inet_addr(p->conn->client_address);
2739 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2740 Printer->notify.printerlocal, 1,
2741 &Printer->notify.client_hnd, &client_ip))
2742 return WERR_SERVER_UNAVAILABLE;
2744 Printer->notify.client_connected=True;
2746 return WERR_OK;
2749 /*******************************************************************
2750 * fill a notify_info_data with the servername
2751 ********************************************************************/
2753 void spoolss_notify_server_name(int snum,
2754 SPOOL_NOTIFY_INFO_DATA *data,
2755 print_queue_struct *queue,
2756 NT_PRINTER_INFO_LEVEL *printer,
2757 TALLOC_CTX *mem_ctx)
2759 pstring temp;
2760 uint32 len;
2762 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2764 data->notify_data.data.length = len;
2765 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2767 if (!data->notify_data.data.string) {
2768 data->notify_data.data.length = 0;
2769 return;
2772 memcpy(data->notify_data.data.string, temp, len);
2775 /*******************************************************************
2776 * fill a notify_info_data with the printername (not including the servername).
2777 ********************************************************************/
2779 void spoolss_notify_printer_name(int snum,
2780 SPOOL_NOTIFY_INFO_DATA *data,
2781 print_queue_struct *queue,
2782 NT_PRINTER_INFO_LEVEL *printer,
2783 TALLOC_CTX *mem_ctx)
2785 pstring temp;
2786 uint32 len;
2788 /* the notify name should not contain the \\server\ part */
2789 char *p = strrchr(printer->info_2->printername, '\\');
2791 if (!p) {
2792 p = printer->info_2->printername;
2793 } else {
2794 p++;
2797 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2799 data->notify_data.data.length = len;
2800 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2802 if (!data->notify_data.data.string) {
2803 data->notify_data.data.length = 0;
2804 return;
2807 memcpy(data->notify_data.data.string, temp, len);
2810 /*******************************************************************
2811 * fill a notify_info_data with the servicename
2812 ********************************************************************/
2814 void spoolss_notify_share_name(int snum,
2815 SPOOL_NOTIFY_INFO_DATA *data,
2816 print_queue_struct *queue,
2817 NT_PRINTER_INFO_LEVEL *printer,
2818 TALLOC_CTX *mem_ctx)
2820 pstring temp;
2821 uint32 len;
2823 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2825 data->notify_data.data.length = len;
2826 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2828 if (!data->notify_data.data.string) {
2829 data->notify_data.data.length = 0;
2830 return;
2833 memcpy(data->notify_data.data.string, temp, len);
2836 /*******************************************************************
2837 * fill a notify_info_data with the port name
2838 ********************************************************************/
2840 void spoolss_notify_port_name(int snum,
2841 SPOOL_NOTIFY_INFO_DATA *data,
2842 print_queue_struct *queue,
2843 NT_PRINTER_INFO_LEVEL *printer,
2844 TALLOC_CTX *mem_ctx)
2846 pstring temp;
2847 uint32 len;
2849 /* even if it's strange, that's consistant in all the code */
2851 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2853 data->notify_data.data.length = len;
2854 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2856 if (!data->notify_data.data.string) {
2857 data->notify_data.data.length = 0;
2858 return;
2861 memcpy(data->notify_data.data.string, temp, len);
2864 /*******************************************************************
2865 * fill a notify_info_data with the printername
2866 * but it doesn't exist, have to see what to do
2867 ********************************************************************/
2869 void spoolss_notify_driver_name(int snum,
2870 SPOOL_NOTIFY_INFO_DATA *data,
2871 print_queue_struct *queue,
2872 NT_PRINTER_INFO_LEVEL *printer,
2873 TALLOC_CTX *mem_ctx)
2875 pstring temp;
2876 uint32 len;
2878 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2880 data->notify_data.data.length = len;
2881 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2883 if (!data->notify_data.data.string) {
2884 data->notify_data.data.length = 0;
2885 return;
2888 memcpy(data->notify_data.data.string, temp, len);
2891 /*******************************************************************
2892 * fill a notify_info_data with the comment
2893 ********************************************************************/
2895 void spoolss_notify_comment(int snum,
2896 SPOOL_NOTIFY_INFO_DATA *data,
2897 print_queue_struct *queue,
2898 NT_PRINTER_INFO_LEVEL *printer,
2899 TALLOC_CTX *mem_ctx)
2901 pstring temp;
2902 uint32 len;
2904 if (*printer->info_2->comment == '\0')
2905 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2906 else
2907 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2909 data->notify_data.data.length = len;
2910 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2912 if (!data->notify_data.data.string) {
2913 data->notify_data.data.length = 0;
2914 return;
2917 memcpy(data->notify_data.data.string, temp, len);
2920 /*******************************************************************
2921 * fill a notify_info_data with the comment
2922 * location = "Room 1, floor 2, building 3"
2923 ********************************************************************/
2925 void spoolss_notify_location(int snum,
2926 SPOOL_NOTIFY_INFO_DATA *data,
2927 print_queue_struct *queue,
2928 NT_PRINTER_INFO_LEVEL *printer,
2929 TALLOC_CTX *mem_ctx)
2931 pstring temp;
2932 uint32 len;
2934 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2936 data->notify_data.data.length = len;
2937 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2939 if (!data->notify_data.data.string) {
2940 data->notify_data.data.length = 0;
2941 return;
2944 memcpy(data->notify_data.data.string, temp, len);
2947 /*******************************************************************
2948 * fill a notify_info_data with the device mode
2949 * jfm:xxxx don't to it for know but that's a real problem !!!
2950 ********************************************************************/
2952 static void spoolss_notify_devmode(int snum,
2953 SPOOL_NOTIFY_INFO_DATA *data,
2954 print_queue_struct *queue,
2955 NT_PRINTER_INFO_LEVEL *printer,
2956 TALLOC_CTX *mem_ctx)
2960 /*******************************************************************
2961 * fill a notify_info_data with the separator file name
2962 ********************************************************************/
2964 void spoolss_notify_sepfile(int snum,
2965 SPOOL_NOTIFY_INFO_DATA *data,
2966 print_queue_struct *queue,
2967 NT_PRINTER_INFO_LEVEL *printer,
2968 TALLOC_CTX *mem_ctx)
2970 pstring temp;
2971 uint32 len;
2973 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2975 data->notify_data.data.length = len;
2976 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2978 if (!data->notify_data.data.string) {
2979 data->notify_data.data.length = 0;
2980 return;
2983 memcpy(data->notify_data.data.string, temp, len);
2986 /*******************************************************************
2987 * fill a notify_info_data with the print processor
2988 * jfm:xxxx return always winprint to indicate we don't do anything to it
2989 ********************************************************************/
2991 void spoolss_notify_print_processor(int snum,
2992 SPOOL_NOTIFY_INFO_DATA *data,
2993 print_queue_struct *queue,
2994 NT_PRINTER_INFO_LEVEL *printer,
2995 TALLOC_CTX *mem_ctx)
2997 pstring temp;
2998 uint32 len;
3000 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3002 data->notify_data.data.length = len;
3003 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3005 if (!data->notify_data.data.string) {
3006 data->notify_data.data.length = 0;
3007 return;
3010 memcpy(data->notify_data.data.string, temp, len);
3013 /*******************************************************************
3014 * fill a notify_info_data with the print processor options
3015 * jfm:xxxx send an empty string
3016 ********************************************************************/
3018 void spoolss_notify_parameters(int snum,
3019 SPOOL_NOTIFY_INFO_DATA *data,
3020 print_queue_struct *queue,
3021 NT_PRINTER_INFO_LEVEL *printer,
3022 TALLOC_CTX *mem_ctx)
3024 pstring temp;
3025 uint32 len;
3027 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3029 data->notify_data.data.length = len;
3030 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3032 if (!data->notify_data.data.string) {
3033 data->notify_data.data.length = 0;
3034 return;
3037 memcpy(data->notify_data.data.string, temp, len);
3040 /*******************************************************************
3041 * fill a notify_info_data with the data type
3042 * jfm:xxxx always send RAW as data type
3043 ********************************************************************/
3045 void spoolss_notify_datatype(int snum,
3046 SPOOL_NOTIFY_INFO_DATA *data,
3047 print_queue_struct *queue,
3048 NT_PRINTER_INFO_LEVEL *printer,
3049 TALLOC_CTX *mem_ctx)
3051 pstring temp;
3052 uint32 len;
3054 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3056 data->notify_data.data.length = len;
3057 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3059 if (!data->notify_data.data.string) {
3060 data->notify_data.data.length = 0;
3061 return;
3064 memcpy(data->notify_data.data.string, temp, len);
3067 /*******************************************************************
3068 * fill a notify_info_data with the security descriptor
3069 * jfm:xxxx send an null pointer to say no security desc
3070 * have to implement security before !
3071 ********************************************************************/
3073 static void spoolss_notify_security_desc(int snum,
3074 SPOOL_NOTIFY_INFO_DATA *data,
3075 print_queue_struct *queue,
3076 NT_PRINTER_INFO_LEVEL *printer,
3077 TALLOC_CTX *mem_ctx)
3079 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3080 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3083 /*******************************************************************
3084 * fill a notify_info_data with the attributes
3085 * jfm:xxxx a samba printer is always shared
3086 ********************************************************************/
3088 void spoolss_notify_attributes(int snum,
3089 SPOOL_NOTIFY_INFO_DATA *data,
3090 print_queue_struct *queue,
3091 NT_PRINTER_INFO_LEVEL *printer,
3092 TALLOC_CTX *mem_ctx)
3094 data->notify_data.value[0] = printer->info_2->attributes;
3095 data->notify_data.value[1] = 0;
3098 /*******************************************************************
3099 * fill a notify_info_data with the priority
3100 ********************************************************************/
3102 static void spoolss_notify_priority(int snum,
3103 SPOOL_NOTIFY_INFO_DATA *data,
3104 print_queue_struct *queue,
3105 NT_PRINTER_INFO_LEVEL *printer,
3106 TALLOC_CTX *mem_ctx)
3108 data->notify_data.value[0] = printer->info_2->priority;
3109 data->notify_data.value[1] = 0;
3112 /*******************************************************************
3113 * fill a notify_info_data with the default priority
3114 ********************************************************************/
3116 static void spoolss_notify_default_priority(int snum,
3117 SPOOL_NOTIFY_INFO_DATA *data,
3118 print_queue_struct *queue,
3119 NT_PRINTER_INFO_LEVEL *printer,
3120 TALLOC_CTX *mem_ctx)
3122 data->notify_data.value[0] = printer->info_2->default_priority;
3123 data->notify_data.value[1] = 0;
3126 /*******************************************************************
3127 * fill a notify_info_data with the start time
3128 ********************************************************************/
3130 static void spoolss_notify_start_time(int snum,
3131 SPOOL_NOTIFY_INFO_DATA *data,
3132 print_queue_struct *queue,
3133 NT_PRINTER_INFO_LEVEL *printer,
3134 TALLOC_CTX *mem_ctx)
3136 data->notify_data.value[0] = printer->info_2->starttime;
3137 data->notify_data.value[1] = 0;
3140 /*******************************************************************
3141 * fill a notify_info_data with the until time
3142 ********************************************************************/
3144 static void spoolss_notify_until_time(int snum,
3145 SPOOL_NOTIFY_INFO_DATA *data,
3146 print_queue_struct *queue,
3147 NT_PRINTER_INFO_LEVEL *printer,
3148 TALLOC_CTX *mem_ctx)
3150 data->notify_data.value[0] = printer->info_2->untiltime;
3151 data->notify_data.value[1] = 0;
3154 /*******************************************************************
3155 * fill a notify_info_data with the status
3156 ********************************************************************/
3158 static void spoolss_notify_status(int snum,
3159 SPOOL_NOTIFY_INFO_DATA *data,
3160 print_queue_struct *queue,
3161 NT_PRINTER_INFO_LEVEL *printer,
3162 TALLOC_CTX *mem_ctx)
3164 print_status_struct status;
3166 print_queue_length(snum, &status);
3167 data->notify_data.value[0]=(uint32) status.status;
3168 data->notify_data.value[1] = 0;
3171 /*******************************************************************
3172 * fill a notify_info_data with the number of jobs queued
3173 ********************************************************************/
3175 void spoolss_notify_cjobs(int snum,
3176 SPOOL_NOTIFY_INFO_DATA *data,
3177 print_queue_struct *queue,
3178 NT_PRINTER_INFO_LEVEL *printer,
3179 TALLOC_CTX *mem_ctx)
3181 data->notify_data.value[0] = print_queue_length(snum, NULL);
3182 data->notify_data.value[1] = 0;
3185 /*******************************************************************
3186 * fill a notify_info_data with the average ppm
3187 ********************************************************************/
3189 static void spoolss_notify_average_ppm(int snum,
3190 SPOOL_NOTIFY_INFO_DATA *data,
3191 print_queue_struct *queue,
3192 NT_PRINTER_INFO_LEVEL *printer,
3193 TALLOC_CTX *mem_ctx)
3195 /* always respond 8 pages per minutes */
3196 /* a little hard ! */
3197 data->notify_data.value[0] = printer->info_2->averageppm;
3198 data->notify_data.value[1] = 0;
3201 /*******************************************************************
3202 * fill a notify_info_data with username
3203 ********************************************************************/
3205 static void spoolss_notify_username(int snum,
3206 SPOOL_NOTIFY_INFO_DATA *data,
3207 print_queue_struct *queue,
3208 NT_PRINTER_INFO_LEVEL *printer,
3209 TALLOC_CTX *mem_ctx)
3211 pstring temp;
3212 uint32 len;
3214 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3216 data->notify_data.data.length = len;
3217 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3219 if (!data->notify_data.data.string) {
3220 data->notify_data.data.length = 0;
3221 return;
3224 memcpy(data->notify_data.data.string, temp, len);
3227 /*******************************************************************
3228 * fill a notify_info_data with job status
3229 ********************************************************************/
3231 static void spoolss_notify_job_status(int snum,
3232 SPOOL_NOTIFY_INFO_DATA *data,
3233 print_queue_struct *queue,
3234 NT_PRINTER_INFO_LEVEL *printer,
3235 TALLOC_CTX *mem_ctx)
3237 data->notify_data.value[0]=nt_printj_status(queue->status);
3238 data->notify_data.value[1] = 0;
3241 /*******************************************************************
3242 * fill a notify_info_data with job name
3243 ********************************************************************/
3245 static void spoolss_notify_job_name(int snum,
3246 SPOOL_NOTIFY_INFO_DATA *data,
3247 print_queue_struct *queue,
3248 NT_PRINTER_INFO_LEVEL *printer,
3249 TALLOC_CTX *mem_ctx)
3251 pstring temp;
3252 uint32 len;
3254 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3256 data->notify_data.data.length = len;
3257 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3259 if (!data->notify_data.data.string) {
3260 data->notify_data.data.length = 0;
3261 return;
3264 memcpy(data->notify_data.data.string, temp, len);
3267 /*******************************************************************
3268 * fill a notify_info_data with job status
3269 ********************************************************************/
3271 static void spoolss_notify_job_status_string(int snum,
3272 SPOOL_NOTIFY_INFO_DATA *data,
3273 print_queue_struct *queue,
3274 NT_PRINTER_INFO_LEVEL *printer,
3275 TALLOC_CTX *mem_ctx)
3278 * Now we're returning job status codes we just return a "" here. JRA.
3281 const char *p = "";
3282 pstring temp;
3283 uint32 len;
3285 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3286 p = "unknown";
3288 switch (queue->status) {
3289 case LPQ_QUEUED:
3290 p = "Queued";
3291 break;
3292 case LPQ_PAUSED:
3293 p = ""; /* NT provides the paused string */
3294 break;
3295 case LPQ_SPOOLING:
3296 p = "Spooling";
3297 break;
3298 case LPQ_PRINTING:
3299 p = "Printing";
3300 break;
3302 #endif /* NO LONGER NEEDED. */
3304 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3306 data->notify_data.data.length = len;
3307 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3309 if (!data->notify_data.data.string) {
3310 data->notify_data.data.length = 0;
3311 return;
3314 memcpy(data->notify_data.data.string, temp, len);
3317 /*******************************************************************
3318 * fill a notify_info_data with job time
3319 ********************************************************************/
3321 static void spoolss_notify_job_time(int snum,
3322 SPOOL_NOTIFY_INFO_DATA *data,
3323 print_queue_struct *queue,
3324 NT_PRINTER_INFO_LEVEL *printer,
3325 TALLOC_CTX *mem_ctx)
3327 data->notify_data.value[0]=0x0;
3328 data->notify_data.value[1]=0;
3331 /*******************************************************************
3332 * fill a notify_info_data with job size
3333 ********************************************************************/
3335 static void spoolss_notify_job_size(int snum,
3336 SPOOL_NOTIFY_INFO_DATA *data,
3337 print_queue_struct *queue,
3338 NT_PRINTER_INFO_LEVEL *printer,
3339 TALLOC_CTX *mem_ctx)
3341 data->notify_data.value[0]=queue->size;
3342 data->notify_data.value[1]=0;
3345 /*******************************************************************
3346 * fill a notify_info_data with page info
3347 ********************************************************************/
3348 static void spoolss_notify_total_pages(int snum,
3349 SPOOL_NOTIFY_INFO_DATA *data,
3350 print_queue_struct *queue,
3351 NT_PRINTER_INFO_LEVEL *printer,
3352 TALLOC_CTX *mem_ctx)
3354 data->notify_data.value[0]=queue->page_count;
3355 data->notify_data.value[1]=0;
3358 /*******************************************************************
3359 * fill a notify_info_data with pages printed info.
3360 ********************************************************************/
3361 static void spoolss_notify_pages_printed(int snum,
3362 SPOOL_NOTIFY_INFO_DATA *data,
3363 print_queue_struct *queue,
3364 NT_PRINTER_INFO_LEVEL *printer,
3365 TALLOC_CTX *mem_ctx)
3367 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3368 data->notify_data.value[1]=0;
3371 /*******************************************************************
3372 Fill a notify_info_data with job position.
3373 ********************************************************************/
3375 static void spoolss_notify_job_position(int snum,
3376 SPOOL_NOTIFY_INFO_DATA *data,
3377 print_queue_struct *queue,
3378 NT_PRINTER_INFO_LEVEL *printer,
3379 TALLOC_CTX *mem_ctx)
3381 data->notify_data.value[0]=queue->job;
3382 data->notify_data.value[1]=0;
3385 /*******************************************************************
3386 Fill a notify_info_data with submitted time.
3387 ********************************************************************/
3389 static void spoolss_notify_submitted_time(int snum,
3390 SPOOL_NOTIFY_INFO_DATA *data,
3391 print_queue_struct *queue,
3392 NT_PRINTER_INFO_LEVEL *printer,
3393 TALLOC_CTX *mem_ctx)
3395 struct tm *t;
3396 uint32 len;
3397 SYSTEMTIME st;
3398 char *p;
3400 t=gmtime(&queue->time);
3402 len = sizeof(SYSTEMTIME);
3404 data->notify_data.data.length = len;
3405 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3407 if (!data->notify_data.data.string) {
3408 data->notify_data.data.length = 0;
3409 return;
3412 make_systemtime(&st, t);
3415 * Systemtime must be linearized as a set of UINT16's.
3416 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3419 p = (char *)data->notify_data.data.string;
3420 SSVAL(p, 0, st.year);
3421 SSVAL(p, 2, st.month);
3422 SSVAL(p, 4, st.dayofweek);
3423 SSVAL(p, 6, st.day);
3424 SSVAL(p, 8, st.hour);
3425 SSVAL(p, 10, st.minute);
3426 SSVAL(p, 12, st.second);
3427 SSVAL(p, 14, st.milliseconds);
3430 struct s_notify_info_data_table
3432 uint16 type;
3433 uint16 field;
3434 const char *name;
3435 uint32 size;
3436 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3437 print_queue_struct *queue,
3438 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3441 /* A table describing the various print notification constants and
3442 whether the notification data is a pointer to a variable sized
3443 buffer, a one value uint32 or a two value uint32. */
3445 static const struct s_notify_info_data_table notify_info_data_table[] =
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3496 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3499 /*******************************************************************
3500 Return the size of info_data structure.
3501 ********************************************************************/
3503 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3505 int i=0;
3507 for (i = 0; i < sizeof(notify_info_data_table); i++)
3509 if ( (notify_info_data_table[i].type == type)
3510 && (notify_info_data_table[i].field == field) )
3512 switch(notify_info_data_table[i].size)
3514 case NOTIFY_ONE_VALUE:
3515 case NOTIFY_TWO_VALUE:
3516 return 1;
3517 case NOTIFY_STRING:
3518 return 2;
3520 /* The only pointer notify data I have seen on
3521 the wire is the submitted time and this has
3522 the notify size set to 4. -tpot */
3524 case NOTIFY_POINTER:
3525 return 4;
3527 case NOTIFY_SECDESC:
3528 return 5;
3533 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3535 return 0;
3538 /*******************************************************************
3539 Return the type of notify_info_data.
3540 ********************************************************************/
3542 static int type_of_notify_info_data(uint16 type, uint16 field)
3544 int i=0;
3546 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3547 if (notify_info_data_table[i].type == type &&
3548 notify_info_data_table[i].field == field)
3549 return notify_info_data_table[i].size;
3552 return False;
3555 /****************************************************************************
3556 ****************************************************************************/
3558 static int search_notify(uint16 type, uint16 field, int *value)
3560 int i;
3562 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3563 if (notify_info_data_table[i].type == type &&
3564 notify_info_data_table[i].field == field &&
3565 notify_info_data_table[i].fn != NULL) {
3566 *value = i;
3567 return True;
3571 return False;
3574 /****************************************************************************
3575 ****************************************************************************/
3577 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3579 info_data->type = type;
3580 info_data->field = field;
3581 info_data->reserved = 0;
3583 info_data->size = size_of_notify_info_data(type, field);
3584 info_data->enc_type = type_of_notify_info_data(type, field);
3586 info_data->id = id;
3591 /*******************************************************************
3593 * fill a notify_info struct with info asked
3595 ********************************************************************/
3597 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3598 snum, SPOOL_NOTIFY_OPTION_TYPE
3599 *option_type, uint32 id,
3600 TALLOC_CTX *mem_ctx)
3602 int field_num,j;
3603 uint16 type;
3604 uint16 field;
3606 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3607 NT_PRINTER_INFO_LEVEL *printer = NULL;
3608 print_queue_struct *queue=NULL;
3610 type=option_type->type;
3612 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3613 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3614 option_type->count, lp_servicename(snum)));
3616 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3617 return False;
3619 for(field_num=0; field_num<option_type->count; field_num++) {
3620 field = option_type->fields[field_num];
3622 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3624 if (!search_notify(type, field, &j) )
3625 continue;
3627 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3628 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3629 return False;
3630 } else
3631 info->data = tid;
3633 current_data = &info->data[info->count];
3635 construct_info_data(current_data, type, field, id);
3637 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3638 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3640 notify_info_data_table[j].fn(snum, current_data, queue,
3641 printer, mem_ctx);
3643 info->count++;
3646 free_a_printer(&printer, 2);
3647 return True;
3650 /*******************************************************************
3652 * fill a notify_info struct with info asked
3654 ********************************************************************/
3656 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3657 SPOOL_NOTIFY_INFO *info,
3658 NT_PRINTER_INFO_LEVEL *printer,
3659 int snum, SPOOL_NOTIFY_OPTION_TYPE
3660 *option_type, uint32 id,
3661 TALLOC_CTX *mem_ctx)
3663 int field_num,j;
3664 uint16 type;
3665 uint16 field;
3667 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3669 DEBUG(4,("construct_notify_jobs_info\n"));
3671 type = option_type->type;
3673 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3674 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3675 option_type->count));
3677 for(field_num=0; field_num<option_type->count; field_num++) {
3678 field = option_type->fields[field_num];
3680 if (!search_notify(type, field, &j) )
3681 continue;
3683 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3684 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3685 return False;
3687 else info->data = tid;
3689 current_data=&(info->data[info->count]);
3691 construct_info_data(current_data, type, field, id);
3692 notify_info_data_table[j].fn(snum, current_data, queue,
3693 printer, mem_ctx);
3694 info->count++;
3697 return True;
3701 * JFM: The enumeration is not that simple, it's even non obvious.
3703 * let's take an example: I want to monitor the PRINTER SERVER for
3704 * the printer's name and the number of jobs currently queued.
3705 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3706 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3708 * I have 3 printers on the back of my server.
3710 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3711 * structures.
3712 * Number Data Id
3713 * 1 printer 1 name 1
3714 * 2 printer 1 cjob 1
3715 * 3 printer 2 name 2
3716 * 4 printer 2 cjob 2
3717 * 5 printer 3 name 3
3718 * 6 printer 3 name 3
3720 * that's the print server case, the printer case is even worse.
3723 /*******************************************************************
3725 * enumerate all printers on the printserver
3726 * fill a notify_info struct with info asked
3728 ********************************************************************/
3730 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3731 SPOOL_NOTIFY_INFO *info,
3732 TALLOC_CTX *mem_ctx)
3734 int snum;
3735 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3736 int n_services=lp_numservices();
3737 int i;
3738 SPOOL_NOTIFY_OPTION *option;
3739 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3741 DEBUG(4,("printserver_notify_info\n"));
3743 if (!Printer)
3744 return WERR_BADFID;
3746 option=Printer->notify.option;
3747 info->version=2;
3748 info->data=NULL;
3749 info->count=0;
3751 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3752 sending a ffpcn() request first */
3754 if ( !option )
3755 return WERR_BADFID;
3757 for (i=0; i<option->count; i++) {
3758 option_type=&(option->ctr.type[i]);
3760 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3761 continue;
3763 for (snum=0; snum<n_services; snum++)
3765 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3766 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3770 #if 0
3772 * Debugging information, don't delete.
3775 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3776 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3777 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3779 for (i=0; i<info->count; i++) {
3780 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3781 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3782 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3784 #endif
3786 return WERR_OK;
3789 /*******************************************************************
3791 * fill a notify_info struct with info asked
3793 ********************************************************************/
3795 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3796 TALLOC_CTX *mem_ctx)
3798 int snum;
3799 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3800 int i;
3801 uint32 id;
3802 SPOOL_NOTIFY_OPTION *option;
3803 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3804 int count,j;
3805 print_queue_struct *queue=NULL;
3806 print_status_struct status;
3808 DEBUG(4,("printer_notify_info\n"));
3810 if (!Printer)
3811 return WERR_BADFID;
3813 option=Printer->notify.option;
3814 id = 0x0;
3815 info->version=2;
3816 info->data=NULL;
3817 info->count=0;
3819 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3820 sending a ffpcn() request first */
3822 if ( !option )
3823 return WERR_BADFID;
3825 get_printer_snum(p, hnd, &snum);
3827 for (i=0; i<option->count; i++) {
3828 option_type=&option->ctr.type[i];
3830 switch ( option_type->type ) {
3831 case PRINTER_NOTIFY_TYPE:
3832 if(construct_notify_printer_info(Printer, info, snum,
3833 option_type, id,
3834 mem_ctx))
3835 id--;
3836 break;
3838 case JOB_NOTIFY_TYPE: {
3839 NT_PRINTER_INFO_LEVEL *printer = NULL;
3841 count = print_queue_status(snum, &queue, &status);
3843 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3844 goto done;
3846 for (j=0; j<count; j++) {
3847 construct_notify_jobs_info(&queue[j], info,
3848 printer, snum,
3849 option_type,
3850 queue[j].job,
3851 mem_ctx);
3854 free_a_printer(&printer, 2);
3856 done:
3857 SAFE_FREE(queue);
3858 break;
3864 * Debugging information, don't delete.
3867 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3868 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3869 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3871 for (i=0; i<info->count; i++) {
3872 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3873 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3874 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3877 return WERR_OK;
3880 /********************************************************************
3881 * spoolss_rfnpcnex
3882 ********************************************************************/
3884 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3886 POLICY_HND *handle = &q_u->handle;
3887 SPOOL_NOTIFY_INFO *info = &r_u->info;
3889 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3890 WERROR result = WERR_BADFID;
3892 /* we always have a NOTIFY_INFO struct */
3893 r_u->info_ptr=0x1;
3895 if (!Printer) {
3896 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3897 OUR_HANDLE(handle)));
3898 goto done;
3901 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3904 * We are now using the change value, and
3905 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3906 * I don't have a global notification system, I'm sending back all the
3907 * informations even when _NOTHING_ has changed.
3910 /* We need to keep track of the change value to send back in
3911 RRPCN replies otherwise our updates are ignored. */
3913 Printer->notify.fnpcn = True;
3915 if (Printer->notify.client_connected) {
3916 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3917 Printer->notify.change = q_u->change;
3920 /* just ignore the SPOOL_NOTIFY_OPTION */
3922 switch (Printer->printer_type) {
3923 case PRINTER_HANDLE_IS_PRINTSERVER:
3924 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3925 break;
3927 case PRINTER_HANDLE_IS_PRINTER:
3928 result = printer_notify_info(p, handle, info, p->mem_ctx);
3929 break;
3932 Printer->notify.fnpcn = False;
3934 done:
3935 return result;
3938 /********************************************************************
3939 * construct_printer_info_0
3940 * fill a printer_info_0 struct
3941 ********************************************************************/
3943 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3945 pstring chaine;
3946 int count;
3947 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3948 counter_printer_0 *session_counter;
3949 uint32 global_counter;
3950 struct tm *t;
3951 time_t setuptime;
3952 print_status_struct status;
3954 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3955 return False;
3957 count = print_queue_length(snum, &status);
3959 /* check if we already have a counter for this printer */
3960 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3961 if (session_counter->snum == snum)
3962 break;
3965 /* it's the first time, add it to the list */
3966 if (session_counter==NULL) {
3967 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3968 free_a_printer(&ntprinter, 2);
3969 return False;
3971 ZERO_STRUCTP(session_counter);
3972 session_counter->snum=snum;
3973 session_counter->counter=0;
3974 DLIST_ADD(counter_list, session_counter);
3977 /* increment it */
3978 session_counter->counter++;
3980 /* JFM:
3981 * the global_counter should be stored in a TDB as it's common to all the clients
3982 * and should be zeroed on samba startup
3984 global_counter=session_counter->counter;
3986 pstrcpy(chaine,ntprinter->info_2->printername);
3988 init_unistr(&printer->printername, chaine);
3990 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3991 init_unistr(&printer->servername, chaine);
3993 printer->cjobs = count;
3994 printer->total_jobs = 0;
3995 printer->total_bytes = 0;
3997 setuptime = (time_t)ntprinter->info_2->setuptime;
3998 t=gmtime(&setuptime);
4000 printer->year = t->tm_year+1900;
4001 printer->month = t->tm_mon+1;
4002 printer->dayofweek = t->tm_wday;
4003 printer->day = t->tm_mday;
4004 printer->hour = t->tm_hour;
4005 printer->minute = t->tm_min;
4006 printer->second = t->tm_sec;
4007 printer->milliseconds = 0;
4009 printer->global_counter = global_counter;
4010 printer->total_pages = 0;
4012 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4013 printer->major_version = 0x0005; /* NT 5 */
4014 printer->build_version = 0x0893; /* build 2195 */
4016 printer->unknown7 = 0x1;
4017 printer->unknown8 = 0x0;
4018 printer->unknown9 = 0x0;
4019 printer->session_counter = session_counter->counter;
4020 printer->unknown11 = 0x0;
4021 printer->printer_errors = 0x0; /* number of print failure */
4022 printer->unknown13 = 0x0;
4023 printer->unknown14 = 0x1;
4024 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4025 printer->unknown16 = 0x0;
4026 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4027 printer->unknown18 = 0x0;
4028 printer->status = nt_printq_status(status.status);
4029 printer->unknown20 = 0x0;
4030 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4031 printer->unknown22 = 0x0;
4032 printer->unknown23 = 0x6; /* 6 ???*/
4033 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4034 printer->unknown25 = 0;
4035 printer->unknown26 = 0;
4036 printer->unknown27 = 0;
4037 printer->unknown28 = 0;
4038 printer->unknown29 = 0;
4040 free_a_printer(&ntprinter,2);
4041 return (True);
4044 /********************************************************************
4045 * construct_printer_info_1
4046 * fill a printer_info_1 struct
4047 ********************************************************************/
4048 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4050 pstring chaine;
4051 pstring chaine2;
4052 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4054 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4055 return False;
4057 printer->flags=flags;
4059 if (*ntprinter->info_2->comment == '\0') {
4060 init_unistr(&printer->comment, lp_comment(snum));
4061 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4062 ntprinter->info_2->drivername, lp_comment(snum));
4064 else {
4065 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4066 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4067 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4070 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4072 init_unistr(&printer->description, chaine);
4073 init_unistr(&printer->name, chaine2);
4075 free_a_printer(&ntprinter,2);
4077 return True;
4080 /****************************************************************************
4081 Free a DEVMODE struct.
4082 ****************************************************************************/
4084 static void free_dev_mode(DEVICEMODE *dev)
4086 if (dev == NULL)
4087 return;
4089 SAFE_FREE(dev->private);
4090 SAFE_FREE(dev);
4094 /****************************************************************************
4095 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4096 should be valid upon entry
4097 ****************************************************************************/
4099 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4101 if ( !devmode || !ntdevmode )
4102 return False;
4104 init_unistr(&devmode->devicename, ntdevmode->devicename);
4106 init_unistr(&devmode->formname, ntdevmode->formname);
4108 devmode->specversion = ntdevmode->specversion;
4109 devmode->driverversion = ntdevmode->driverversion;
4110 devmode->size = ntdevmode->size;
4111 devmode->driverextra = ntdevmode->driverextra;
4112 devmode->fields = ntdevmode->fields;
4114 devmode->orientation = ntdevmode->orientation;
4115 devmode->papersize = ntdevmode->papersize;
4116 devmode->paperlength = ntdevmode->paperlength;
4117 devmode->paperwidth = ntdevmode->paperwidth;
4118 devmode->scale = ntdevmode->scale;
4119 devmode->copies = ntdevmode->copies;
4120 devmode->defaultsource = ntdevmode->defaultsource;
4121 devmode->printquality = ntdevmode->printquality;
4122 devmode->color = ntdevmode->color;
4123 devmode->duplex = ntdevmode->duplex;
4124 devmode->yresolution = ntdevmode->yresolution;
4125 devmode->ttoption = ntdevmode->ttoption;
4126 devmode->collate = ntdevmode->collate;
4127 devmode->icmmethod = ntdevmode->icmmethod;
4128 devmode->icmintent = ntdevmode->icmintent;
4129 devmode->mediatype = ntdevmode->mediatype;
4130 devmode->dithertype = ntdevmode->dithertype;
4132 if (ntdevmode->private != NULL) {
4133 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4134 return False;
4137 return True;
4140 /****************************************************************************
4141 Create a DEVMODE struct. Returns malloced memory.
4142 ****************************************************************************/
4144 DEVICEMODE *construct_dev_mode(int snum)
4146 NT_PRINTER_INFO_LEVEL *printer = NULL;
4147 DEVICEMODE *devmode = NULL;
4149 DEBUG(7,("construct_dev_mode\n"));
4151 DEBUGADD(8,("getting printer characteristics\n"));
4153 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4154 return NULL;
4156 if ( !printer->info_2->devmode ) {
4157 DEBUG(5, ("BONG! There was no device mode!\n"));
4158 goto done;
4161 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4162 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4163 goto done;
4166 ZERO_STRUCTP(devmode);
4168 DEBUGADD(8,("loading DEVICEMODE\n"));
4170 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4171 free_dev_mode( devmode );
4172 devmode = NULL;
4175 done:
4176 free_a_printer(&printer,2);
4178 return devmode;
4181 /********************************************************************
4182 * construct_printer_info_2
4183 * fill a printer_info_2 struct
4184 ********************************************************************/
4186 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4188 int count;
4189 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4191 print_status_struct status;
4193 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4194 return False;
4196 count = print_queue_length(snum, &status);
4198 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4199 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4200 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4201 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4202 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4204 if (*ntprinter->info_2->comment == '\0')
4205 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4206 else
4207 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4209 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4210 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4211 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4212 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4213 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4215 printer->attributes = ntprinter->info_2->attributes;
4217 printer->priority = ntprinter->info_2->priority; /* priority */
4218 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4219 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4220 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4221 printer->status = nt_printq_status(status.status); /* status */
4222 printer->cjobs = count; /* jobs */
4223 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4225 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4226 DEBUG(8, ("Returning NULL Devicemode!\n"));
4229 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4230 /* steal the printer info sec_desc structure. [badly done]. */
4231 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4232 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4233 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4234 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4236 else {
4237 printer->secdesc = NULL;
4240 free_a_printer(&ntprinter, 2);
4241 return True;
4244 /********************************************************************
4245 * construct_printer_info_3
4246 * fill a printer_info_3 struct
4247 ********************************************************************/
4249 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4251 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4252 PRINTER_INFO_3 *printer = NULL;
4254 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4255 return False;
4257 *pp_printer = NULL;
4258 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4259 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4260 return False;
4263 ZERO_STRUCTP(printer);
4265 printer->flags = 4; /* These are the components of the SD we are returning. */
4266 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4267 /* steal the printer info sec_desc structure. [badly done]. */
4268 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4270 #if 0
4272 * Set the flags for the components we are returning.
4275 if (printer->secdesc->owner_sid)
4276 printer->flags |= OWNER_SECURITY_INFORMATION;
4278 if (printer->secdesc->grp_sid)
4279 printer->flags |= GROUP_SECURITY_INFORMATION;
4281 if (printer->secdesc->dacl)
4282 printer->flags |= DACL_SECURITY_INFORMATION;
4284 if (printer->secdesc->sacl)
4285 printer->flags |= SACL_SECURITY_INFORMATION;
4286 #endif
4288 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4289 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4290 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4293 free_a_printer(&ntprinter, 2);
4295 *pp_printer = printer;
4296 return True;
4299 /********************************************************************
4300 * construct_printer_info_4
4301 * fill a printer_info_4 struct
4302 ********************************************************************/
4304 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4306 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4308 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4309 return False;
4311 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4312 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4313 printer->attributes = ntprinter->info_2->attributes;
4315 free_a_printer(&ntprinter, 2);
4316 return True;
4319 /********************************************************************
4320 * construct_printer_info_5
4321 * fill a printer_info_5 struct
4322 ********************************************************************/
4324 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4326 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4328 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4329 return False;
4331 init_unistr(&printer->printername, ntprinter->info_2->printername);
4332 init_unistr(&printer->portname, ntprinter->info_2->portname);
4333 printer->attributes = ntprinter->info_2->attributes;
4335 /* these two are not used by NT+ according to MSDN */
4337 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4338 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4340 free_a_printer(&ntprinter, 2);
4342 return True;
4345 /********************************************************************
4346 * construct_printer_info_7
4347 * fill a printer_info_7 struct
4348 ********************************************************************/
4350 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4352 char *guid_str = NULL;
4353 struct uuid guid;
4355 if (is_printer_published(print_hnd, snum, &guid)) {
4356 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4357 strupper_m(guid_str);
4358 init_unistr(&printer->guid, guid_str);
4359 printer->action = SPOOL_DS_PUBLISH;
4360 } else {
4361 init_unistr(&printer->guid, "");
4362 printer->action = SPOOL_DS_UNPUBLISH;
4365 return True;
4368 /********************************************************************
4369 Spoolss_enumprinters.
4370 ********************************************************************/
4372 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4374 int snum;
4375 int i;
4376 int n_services=lp_numservices();
4377 PRINTER_INFO_1 *tp, *printers=NULL;
4378 PRINTER_INFO_1 current_prt;
4379 WERROR result = WERR_OK;
4381 DEBUG(4,("enum_all_printers_info_1\n"));
4383 for (snum=0; snum<n_services; snum++) {
4384 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4385 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4387 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4388 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4389 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4390 SAFE_FREE(printers);
4391 *returned=0;
4392 return WERR_NOMEM;
4394 else printers = tp;
4395 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4397 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4398 (*returned)++;
4403 /* check the required size. */
4404 for (i=0; i<*returned; i++)
4405 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4407 if (*needed > offered) {
4408 result = WERR_INSUFFICIENT_BUFFER;
4409 goto out;
4412 if (!rpcbuf_alloc_size(buffer, *needed)) {
4413 result = WERR_NOMEM;
4414 goto out;
4417 /* fill the buffer with the structures */
4418 for (i=0; i<*returned; i++)
4419 smb_io_printer_info_1("", buffer, &printers[i], 0);
4421 out:
4422 /* clear memory */
4424 SAFE_FREE(printers);
4426 if ( !W_ERROR_IS_OK(result) )
4427 *returned = 0;
4429 return result;
4432 /********************************************************************
4433 enum_all_printers_info_1_local.
4434 *********************************************************************/
4436 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4438 DEBUG(4,("enum_all_printers_info_1_local\n"));
4440 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4443 /********************************************************************
4444 enum_all_printers_info_1_name.
4445 *********************************************************************/
4447 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4449 char *s = name;
4451 DEBUG(4,("enum_all_printers_info_1_name\n"));
4453 if ((name[0] == '\\') && (name[1] == '\\'))
4454 s = name + 2;
4456 if (is_myname_or_ipaddr(s)) {
4457 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4459 else
4460 return WERR_INVALID_NAME;
4463 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4464 /********************************************************************
4465 enum_all_printers_info_1_remote.
4466 *********************************************************************/
4468 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4470 PRINTER_INFO_1 *printer;
4471 fstring printername;
4472 fstring desc;
4473 fstring comment;
4474 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4475 WERROR result = WERR_OK;
4477 /* JFM: currently it's more a place holder than anything else.
4478 * In the spooler world there is a notion of server registration.
4479 * the print servers are registered on the PDC (in the same domain)
4481 * We should have a TDB here. The registration is done thru an
4482 * undocumented RPC call.
4485 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4486 return WERR_NOMEM;
4488 *returned=1;
4490 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4491 slprintf(desc, sizeof(desc)-1,"%s", name);
4492 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4494 init_unistr(&printer->description, desc);
4495 init_unistr(&printer->name, printername);
4496 init_unistr(&printer->comment, comment);
4497 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4499 /* check the required size. */
4500 *needed += spoolss_size_printer_info_1(printer);
4502 if (*needed > offered) {
4503 result = WERR_INSUFFICIENT_BUFFER;
4504 goto out;
4507 if (!rpcbuf_alloc_size(buffer, *needed)) {
4508 result = WERR_NOMEM;
4509 goto out;
4512 /* fill the buffer with the structures */
4513 smb_io_printer_info_1("", buffer, printer, 0);
4515 out:
4516 /* clear memory */
4517 SAFE_FREE(printer);
4519 if ( !W_ERROR_IS_OK(result) )
4520 *returned = 0;
4522 return result;
4525 #endif
4527 /********************************************************************
4528 enum_all_printers_info_1_network.
4529 *********************************************************************/
4531 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4533 char *s = name;
4535 DEBUG(4,("enum_all_printers_info_1_network\n"));
4537 /* If we respond to a enum_printers level 1 on our name with flags
4538 set to PRINTER_ENUM_REMOTE with a list of printers then these
4539 printers incorrectly appear in the APW browse list.
4540 Specifically the printers for the server appear at the workgroup
4541 level where all the other servers in the domain are
4542 listed. Windows responds to this call with a
4543 WERR_CAN_NOT_COMPLETE so we should do the same. */
4545 if (name[0] == '\\' && name[1] == '\\')
4546 s = name + 2;
4548 if (is_myname_or_ipaddr(s))
4549 return WERR_CAN_NOT_COMPLETE;
4551 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4554 /********************************************************************
4555 * api_spoolss_enumprinters
4557 * called from api_spoolss_enumprinters (see this to understand)
4558 ********************************************************************/
4560 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4562 int snum;
4563 int i;
4564 int n_services=lp_numservices();
4565 PRINTER_INFO_2 *tp, *printers=NULL;
4566 PRINTER_INFO_2 current_prt;
4567 WERROR result = WERR_OK;
4569 for (snum=0; snum<n_services; snum++) {
4570 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4571 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4573 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4574 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) == NULL) {
4575 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4576 SAFE_FREE(printers);
4577 *returned = 0;
4578 return WERR_NOMEM;
4580 else printers = tp;
4581 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4582 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4583 (*returned)++;
4588 /* check the required size. */
4589 for (i=0; i<*returned; i++)
4590 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4592 if (*needed > offered) {
4593 result = WERR_INSUFFICIENT_BUFFER;
4594 goto out;
4597 if (!rpcbuf_alloc_size(buffer, *needed)) {
4598 result = WERR_NOMEM;
4599 goto out;
4602 /* fill the buffer with the structures */
4603 for (i=0; i<*returned; i++)
4604 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4606 out:
4607 /* clear memory */
4608 for (i=0; i<*returned; i++) {
4609 free_devmode(printers[i].devmode);
4611 SAFE_FREE(printers);
4613 if ( !W_ERROR_IS_OK(result) )
4614 *returned = 0;
4616 return result;
4619 /********************************************************************
4620 * handle enumeration of printers at level 1
4621 ********************************************************************/
4623 static WERROR enumprinters_level1( uint32 flags, fstring name,
4624 RPC_BUFFER *buffer, uint32 offered,
4625 uint32 *needed, uint32 *returned)
4627 /* Not all the flags are equals */
4629 if (flags & PRINTER_ENUM_LOCAL)
4630 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4632 if (flags & PRINTER_ENUM_NAME)
4633 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4635 #if 0 /* JERRY - disabled for now */
4636 if (flags & PRINTER_ENUM_REMOTE)
4637 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4638 #endif
4640 if (flags & PRINTER_ENUM_NETWORK)
4641 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4643 return WERR_OK; /* NT4sp5 does that */
4646 /********************************************************************
4647 * handle enumeration of printers at level 2
4648 ********************************************************************/
4650 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4651 RPC_BUFFER *buffer, uint32 offered,
4652 uint32 *needed, uint32 *returned)
4654 char *s = servername;
4656 if (flags & PRINTER_ENUM_LOCAL) {
4657 return enum_all_printers_info_2(buffer, offered, needed, returned);
4660 if (flags & PRINTER_ENUM_NAME) {
4661 if ((servername[0] == '\\') && (servername[1] == '\\'))
4662 s = servername + 2;
4663 if (is_myname_or_ipaddr(s))
4664 return enum_all_printers_info_2(buffer, offered, needed, returned);
4665 else
4666 return WERR_INVALID_NAME;
4669 if (flags & PRINTER_ENUM_REMOTE)
4670 return WERR_UNKNOWN_LEVEL;
4672 return WERR_OK;
4675 /********************************************************************
4676 * handle enumeration of printers at level 5
4677 ********************************************************************/
4679 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4680 RPC_BUFFER *buffer, uint32 offered,
4681 uint32 *needed, uint32 *returned)
4683 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4684 return WERR_OK;
4687 /********************************************************************
4688 * api_spoolss_enumprinters
4690 * called from api_spoolss_enumprinters (see this to understand)
4691 ********************************************************************/
4693 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4695 uint32 flags = q_u->flags;
4696 UNISTR2 *servername = &q_u->servername;
4697 uint32 level = q_u->level;
4698 RPC_BUFFER *buffer = NULL;
4699 uint32 offered = q_u->offered;
4700 uint32 *needed = &r_u->needed;
4701 uint32 *returned = &r_u->returned;
4703 fstring name;
4705 /* that's an [in out] buffer */
4707 if ( q_u->buffer ) {
4708 rpcbuf_move(q_u->buffer, &r_u->buffer);
4709 buffer = r_u->buffer;
4712 DEBUG(4,("_spoolss_enumprinters\n"));
4714 *needed=0;
4715 *returned=0;
4718 * Level 1:
4719 * flags==PRINTER_ENUM_NAME
4720 * if name=="" then enumerates all printers
4721 * if name!="" then enumerate the printer
4722 * flags==PRINTER_ENUM_REMOTE
4723 * name is NULL, enumerate printers
4724 * Level 2: name!="" enumerates printers, name can't be NULL
4725 * Level 3: doesn't exist
4726 * Level 4: does a local registry lookup
4727 * Level 5: same as Level 2
4730 unistr2_to_ascii(name, servername, sizeof(name)-1);
4731 strupper_m(name);
4733 switch (level) {
4734 case 1:
4735 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4736 case 2:
4737 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4738 case 5:
4739 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4740 case 3:
4741 case 4:
4742 break;
4744 return WERR_UNKNOWN_LEVEL;
4747 /****************************************************************************
4748 ****************************************************************************/
4750 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4752 PRINTER_INFO_0 *printer=NULL;
4753 WERROR result = WERR_OK;
4755 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4756 return WERR_NOMEM;
4758 construct_printer_info_0(print_hnd, printer, snum);
4760 /* check the required size. */
4761 *needed += spoolss_size_printer_info_0(printer);
4763 if (*needed > offered) {
4764 result = WERR_INSUFFICIENT_BUFFER;
4765 goto out;
4768 if (!rpcbuf_alloc_size(buffer, *needed)) {
4769 result = WERR_NOMEM;
4770 goto out;
4773 /* fill the buffer with the structures */
4774 smb_io_printer_info_0("", buffer, printer, 0);
4776 out:
4777 /* clear memory */
4779 SAFE_FREE(printer);
4781 return result;
4784 /****************************************************************************
4785 ****************************************************************************/
4787 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4789 PRINTER_INFO_1 *printer=NULL;
4790 WERROR result = WERR_OK;
4792 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4793 return WERR_NOMEM;
4795 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4797 /* check the required size. */
4798 *needed += spoolss_size_printer_info_1(printer);
4800 if (*needed > offered) {
4801 result = WERR_INSUFFICIENT_BUFFER;
4802 goto out;
4805 if (!rpcbuf_alloc_size(buffer, *needed)) {
4806 result = WERR_NOMEM;
4807 goto out;
4810 /* fill the buffer with the structures */
4811 smb_io_printer_info_1("", buffer, printer, 0);
4813 out:
4814 /* clear memory */
4815 SAFE_FREE(printer);
4817 return result;
4820 /****************************************************************************
4821 ****************************************************************************/
4823 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4825 PRINTER_INFO_2 *printer=NULL;
4826 WERROR result = WERR_OK;
4828 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4829 return WERR_NOMEM;
4831 construct_printer_info_2(print_hnd, printer, snum);
4833 /* check the required size. */
4834 *needed += spoolss_size_printer_info_2(printer);
4836 if (*needed > offered) {
4837 result = WERR_INSUFFICIENT_BUFFER;
4838 goto out;
4841 if (!rpcbuf_alloc_size(buffer, *needed)) {
4842 result = WERR_NOMEM;
4843 goto out;
4846 /* fill the buffer with the structures */
4847 if (!smb_io_printer_info_2("", buffer, printer, 0))
4848 result = WERR_NOMEM;
4850 out:
4851 /* clear memory */
4852 free_printer_info_2(printer);
4854 return result;
4857 /****************************************************************************
4858 ****************************************************************************/
4860 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4862 PRINTER_INFO_3 *printer=NULL;
4863 WERROR result = WERR_OK;
4865 if (!construct_printer_info_3(print_hnd, &printer, snum))
4866 return WERR_NOMEM;
4868 /* check the required size. */
4869 *needed += spoolss_size_printer_info_3(printer);
4871 if (*needed > offered) {
4872 result = WERR_INSUFFICIENT_BUFFER;
4873 goto out;
4876 if (!rpcbuf_alloc_size(buffer, *needed)) {
4877 result = WERR_NOMEM;
4878 goto out;
4881 /* fill the buffer with the structures */
4882 smb_io_printer_info_3("", buffer, printer, 0);
4884 out:
4885 /* clear memory */
4886 free_printer_info_3(printer);
4888 return result;
4891 /****************************************************************************
4892 ****************************************************************************/
4894 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4896 PRINTER_INFO_4 *printer=NULL;
4897 WERROR result = WERR_OK;
4899 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4900 return WERR_NOMEM;
4902 if (!construct_printer_info_4(print_hnd, printer, snum))
4903 return WERR_NOMEM;
4905 /* check the required size. */
4906 *needed += spoolss_size_printer_info_4(printer);
4908 if (*needed > offered) {
4909 result = WERR_INSUFFICIENT_BUFFER;
4910 goto out;
4913 if (!rpcbuf_alloc_size(buffer, *needed)) {
4914 result = WERR_NOMEM;
4915 goto out;
4918 /* fill the buffer with the structures */
4919 smb_io_printer_info_4("", buffer, printer, 0);
4921 out:
4922 /* clear memory */
4923 free_printer_info_4(printer);
4925 return result;
4928 /****************************************************************************
4929 ****************************************************************************/
4931 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4933 PRINTER_INFO_5 *printer=NULL;
4934 WERROR result = WERR_OK;
4936 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4937 return WERR_NOMEM;
4939 if (!construct_printer_info_5(print_hnd, printer, snum))
4940 return WERR_NOMEM;
4942 /* check the required size. */
4943 *needed += spoolss_size_printer_info_5(printer);
4945 if (*needed > offered) {
4946 result = WERR_INSUFFICIENT_BUFFER;
4947 goto out;
4950 if (!rpcbuf_alloc_size(buffer, *needed)) {
4951 result = WERR_NOMEM;
4952 goto out;
4955 /* fill the buffer with the structures */
4956 smb_io_printer_info_5("", buffer, printer, 0);
4958 out:
4959 /* clear memory */
4960 free_printer_info_5(printer);
4962 return result;
4965 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4967 PRINTER_INFO_7 *printer=NULL;
4968 WERROR result = WERR_OK;
4970 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4971 return WERR_NOMEM;
4973 if (!construct_printer_info_7(print_hnd, printer, snum))
4974 return WERR_NOMEM;
4976 /* check the required size. */
4977 *needed += spoolss_size_printer_info_7(printer);
4979 if (*needed > offered) {
4980 result = WERR_INSUFFICIENT_BUFFER;
4981 goto out;
4984 if (!rpcbuf_alloc_size(buffer, *needed)) {
4985 result = WERR_NOMEM;
4986 goto out;
4990 /* fill the buffer with the structures */
4991 smb_io_printer_info_7("", buffer, printer, 0);
4993 out:
4994 /* clear memory */
4995 free_printer_info_7(printer);
4997 return result;
5000 /****************************************************************************
5001 ****************************************************************************/
5003 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5005 POLICY_HND *handle = &q_u->handle;
5006 uint32 level = q_u->level;
5007 RPC_BUFFER *buffer = NULL;
5008 uint32 offered = q_u->offered;
5009 uint32 *needed = &r_u->needed;
5010 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5012 int snum;
5014 /* that's an [in out] buffer */
5016 if ( q_u->buffer ) {
5017 rpcbuf_move(q_u->buffer, &r_u->buffer);
5018 buffer = r_u->buffer;
5021 *needed=0;
5023 if (!get_printer_snum(p, handle, &snum))
5024 return WERR_BADFID;
5026 switch (level) {
5027 case 0:
5028 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5029 case 1:
5030 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5031 case 2:
5032 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5033 case 3:
5034 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5035 case 4:
5036 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5037 case 5:
5038 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5039 case 7:
5040 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5042 return WERR_UNKNOWN_LEVEL;
5045 /********************************************************************
5046 * fill a DRIVER_INFO_1 struct
5047 ********************************************************************/
5049 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5051 init_unistr( &info->name, driver.info_3->name);
5054 /********************************************************************
5055 * construct_printer_driver_info_1
5056 ********************************************************************/
5058 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5060 NT_PRINTER_INFO_LEVEL *printer = NULL;
5061 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5063 ZERO_STRUCT(driver);
5065 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5066 return WERR_INVALID_PRINTER_NAME;
5068 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5069 return WERR_UNKNOWN_PRINTER_DRIVER;
5071 fill_printer_driver_info_1(info, driver, servername, architecture);
5073 free_a_printer(&printer,2);
5075 return WERR_OK;
5078 /********************************************************************
5079 * construct_printer_driver_info_2
5080 * fill a printer_info_2 struct
5081 ********************************************************************/
5083 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5085 pstring temp;
5087 info->version=driver.info_3->cversion;
5089 init_unistr( &info->name, driver.info_3->name );
5090 init_unistr( &info->architecture, driver.info_3->environment );
5093 if (strlen(driver.info_3->driverpath)) {
5094 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5095 init_unistr( &info->driverpath, temp );
5096 } else
5097 init_unistr( &info->driverpath, "" );
5099 if (strlen(driver.info_3->datafile)) {
5100 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5101 init_unistr( &info->datafile, temp );
5102 } else
5103 init_unistr( &info->datafile, "" );
5105 if (strlen(driver.info_3->configfile)) {
5106 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5107 init_unistr( &info->configfile, temp );
5108 } else
5109 init_unistr( &info->configfile, "" );
5112 /********************************************************************
5113 * construct_printer_driver_info_2
5114 * fill a printer_info_2 struct
5115 ********************************************************************/
5117 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5119 NT_PRINTER_INFO_LEVEL *printer = NULL;
5120 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5122 ZERO_STRUCT(printer);
5123 ZERO_STRUCT(driver);
5125 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5126 return WERR_INVALID_PRINTER_NAME;
5128 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5129 return WERR_UNKNOWN_PRINTER_DRIVER;
5131 fill_printer_driver_info_2(info, driver, servername);
5133 free_a_printer(&printer,2);
5135 return WERR_OK;
5138 /********************************************************************
5139 * copy a strings array and convert to UNICODE
5141 * convert an array of ascii string to a UNICODE string
5142 ********************************************************************/
5144 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5146 int i=0;
5147 int j=0;
5148 const char *v;
5149 pstring line;
5150 uint16 *tuary;
5152 DEBUG(6,("init_unistr_array\n"));
5153 *uni_array=NULL;
5155 while (True)
5157 if ( !char_array )
5158 v = "";
5159 else
5161 v = char_array[i];
5162 if (!v)
5163 v = ""; /* hack to handle null lists */
5166 /* hack to allow this to be used in places other than when generating
5167 the list of dependent files */
5169 if ( servername )
5170 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5171 else
5172 pstrcpy( line, v );
5174 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5176 /* add one extra unit16 for the second terminating NULL */
5178 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5179 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5180 return 0;
5181 } else
5182 *uni_array = tuary;
5184 if ( !strlen(v) )
5185 break;
5187 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5188 i++;
5191 if (*uni_array) {
5192 /* special case for ""; we need to add both NULL's here */
5193 if (!j)
5194 (*uni_array)[j++]=0x0000;
5195 (*uni_array)[j]=0x0000;
5198 DEBUGADD(6,("last one:done\n"));
5200 /* return size of array in uint16's */
5202 return j+1;
5205 /********************************************************************
5206 * construct_printer_info_3
5207 * fill a printer_info_3 struct
5208 ********************************************************************/
5210 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5212 pstring temp;
5214 ZERO_STRUCTP(info);
5216 info->version=driver.info_3->cversion;
5218 init_unistr( &info->name, driver.info_3->name );
5219 init_unistr( &info->architecture, driver.info_3->environment );
5221 if (strlen(driver.info_3->driverpath)) {
5222 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5223 init_unistr( &info->driverpath, temp );
5224 } else
5225 init_unistr( &info->driverpath, "" );
5227 if (strlen(driver.info_3->datafile)) {
5228 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5229 init_unistr( &info->datafile, temp );
5230 } else
5231 init_unistr( &info->datafile, "" );
5233 if (strlen(driver.info_3->configfile)) {
5234 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5235 init_unistr( &info->configfile, temp );
5236 } else
5237 init_unistr( &info->configfile, "" );
5239 if (strlen(driver.info_3->helpfile)) {
5240 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5241 init_unistr( &info->helpfile, temp );
5242 } else
5243 init_unistr( &info->helpfile, "" );
5245 init_unistr( &info->monitorname, driver.info_3->monitorname );
5246 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5248 info->dependentfiles=NULL;
5249 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5252 /********************************************************************
5253 * construct_printer_info_3
5254 * fill a printer_info_3 struct
5255 ********************************************************************/
5257 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5259 NT_PRINTER_INFO_LEVEL *printer = NULL;
5260 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5261 WERROR status;
5262 ZERO_STRUCT(driver);
5264 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5265 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5266 if (!W_ERROR_IS_OK(status))
5267 return WERR_INVALID_PRINTER_NAME;
5269 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5270 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5272 #if 0 /* JERRY */
5275 * I put this code in during testing. Helpful when commenting out the
5276 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5277 * as win2k always queries the driver using an infor level of 6.
5278 * I've left it in (but ifdef'd out) because I'll probably
5279 * use it in experimentation again in the future. --jerry 22/01/2002
5282 if (!W_ERROR_IS_OK(status)) {
5284 * Is this a W2k client ?
5286 if (version == 3) {
5287 /* Yes - try again with a WinNT driver. */
5288 version = 2;
5289 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5290 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5292 #endif
5294 if (!W_ERROR_IS_OK(status)) {
5295 free_a_printer(&printer,2);
5296 return WERR_UNKNOWN_PRINTER_DRIVER;
5299 #if 0 /* JERRY */
5301 #endif
5304 fill_printer_driver_info_3(info, driver, servername);
5306 free_a_printer(&printer,2);
5308 return WERR_OK;
5311 /********************************************************************
5312 * construct_printer_info_6
5313 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5314 ********************************************************************/
5316 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5318 pstring temp;
5319 fstring nullstr;
5321 ZERO_STRUCTP(info);
5322 memset(&nullstr, '\0', sizeof(fstring));
5324 info->version=driver.info_3->cversion;
5326 init_unistr( &info->name, driver.info_3->name );
5327 init_unistr( &info->architecture, driver.info_3->environment );
5329 if (strlen(driver.info_3->driverpath)) {
5330 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5331 init_unistr( &info->driverpath, temp );
5332 } else
5333 init_unistr( &info->driverpath, "" );
5335 if (strlen(driver.info_3->datafile)) {
5336 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5337 init_unistr( &info->datafile, temp );
5338 } else
5339 init_unistr( &info->datafile, "" );
5341 if (strlen(driver.info_3->configfile)) {
5342 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5343 init_unistr( &info->configfile, temp );
5344 } else
5345 init_unistr( &info->configfile, "" );
5347 if (strlen(driver.info_3->helpfile)) {
5348 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5349 init_unistr( &info->helpfile, temp );
5350 } else
5351 init_unistr( &info->helpfile, "" );
5353 init_unistr( &info->monitorname, driver.info_3->monitorname );
5354 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5356 info->dependentfiles = NULL;
5357 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5359 info->previousdrivernames=NULL;
5360 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5362 info->driver_date.low=0;
5363 info->driver_date.high=0;
5365 info->padding=0;
5366 info->driver_version_low=0;
5367 info->driver_version_high=0;
5369 init_unistr( &info->mfgname, "");
5370 init_unistr( &info->oem_url, "");
5371 init_unistr( &info->hardware_id, "");
5372 init_unistr( &info->provider, "");
5375 /********************************************************************
5376 * construct_printer_info_6
5377 * fill a printer_info_6 struct
5378 ********************************************************************/
5380 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5381 fstring servername, fstring architecture, uint32 version)
5383 NT_PRINTER_INFO_LEVEL *printer = NULL;
5384 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5385 WERROR status;
5387 ZERO_STRUCT(driver);
5389 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5391 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5393 if (!W_ERROR_IS_OK(status))
5394 return WERR_INVALID_PRINTER_NAME;
5396 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5398 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5400 if (!W_ERROR_IS_OK(status))
5403 * Is this a W2k client ?
5406 if (version < 3) {
5407 free_a_printer(&printer,2);
5408 return WERR_UNKNOWN_PRINTER_DRIVER;
5411 /* Yes - try again with a WinNT driver. */
5412 version = 2;
5413 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5414 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5415 if (!W_ERROR_IS_OK(status)) {
5416 free_a_printer(&printer,2);
5417 return WERR_UNKNOWN_PRINTER_DRIVER;
5421 fill_printer_driver_info_6(info, driver, servername);
5423 free_a_printer(&printer,2);
5424 free_a_printer_driver(driver, 3);
5426 return WERR_OK;
5429 /****************************************************************************
5430 ****************************************************************************/
5432 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5434 SAFE_FREE(info->dependentfiles);
5437 /****************************************************************************
5438 ****************************************************************************/
5440 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5442 SAFE_FREE(info->dependentfiles);
5445 /****************************************************************************
5446 ****************************************************************************/
5448 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5450 DRIVER_INFO_1 *info=NULL;
5451 WERROR result;
5453 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5454 return WERR_NOMEM;
5456 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5457 if (!W_ERROR_IS_OK(result))
5458 goto out;
5460 /* check the required size. */
5461 *needed += spoolss_size_printer_driver_info_1(info);
5463 if (*needed > offered) {
5464 result = WERR_INSUFFICIENT_BUFFER;
5465 goto out;
5468 if (!rpcbuf_alloc_size(buffer, *needed)) {
5469 result = WERR_NOMEM;
5470 goto out;
5473 /* fill the buffer with the structures */
5474 smb_io_printer_driver_info_1("", buffer, info, 0);
5476 out:
5477 /* clear memory */
5478 SAFE_FREE(info);
5480 return result;
5483 /****************************************************************************
5484 ****************************************************************************/
5486 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5488 DRIVER_INFO_2 *info=NULL;
5489 WERROR result;
5491 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5492 return WERR_NOMEM;
5494 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5495 if (!W_ERROR_IS_OK(result))
5496 goto out;
5498 /* check the required size. */
5499 *needed += spoolss_size_printer_driver_info_2(info);
5501 if (*needed > offered) {
5502 result = WERR_INSUFFICIENT_BUFFER;
5503 goto out;
5506 if (!rpcbuf_alloc_size(buffer, *needed)) {
5507 result = WERR_NOMEM;
5508 goto out;
5511 /* fill the buffer with the structures */
5512 smb_io_printer_driver_info_2("", buffer, info, 0);
5514 out:
5515 /* clear memory */
5516 SAFE_FREE(info);
5518 return result;
5521 /****************************************************************************
5522 ****************************************************************************/
5524 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5526 DRIVER_INFO_3 info;
5527 WERROR result;
5529 ZERO_STRUCT(info);
5531 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5532 if (!W_ERROR_IS_OK(result))
5533 goto out;
5535 /* check the required size. */
5536 *needed += spoolss_size_printer_driver_info_3(&info);
5538 if (*needed > offered) {
5539 result = WERR_INSUFFICIENT_BUFFER;
5540 goto out;
5543 if (!rpcbuf_alloc_size(buffer, *needed)) {
5544 result = WERR_NOMEM;
5545 goto out;
5548 /* fill the buffer with the structures */
5549 smb_io_printer_driver_info_3("", buffer, &info, 0);
5551 out:
5552 free_printer_driver_info_3(&info);
5554 return result;
5557 /****************************************************************************
5558 ****************************************************************************/
5560 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5562 DRIVER_INFO_6 info;
5563 WERROR result;
5565 ZERO_STRUCT(info);
5567 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5568 if (!W_ERROR_IS_OK(result))
5569 goto out;
5571 /* check the required size. */
5572 *needed += spoolss_size_printer_driver_info_6(&info);
5574 if (*needed > offered) {
5575 result = WERR_INSUFFICIENT_BUFFER;
5576 goto out;
5579 if (!rpcbuf_alloc_size(buffer, *needed)) {
5580 result = WERR_NOMEM;
5581 goto out;
5584 /* fill the buffer with the structures */
5585 smb_io_printer_driver_info_6("", buffer, &info, 0);
5587 out:
5588 free_printer_driver_info_6(&info);
5590 return result;
5593 /****************************************************************************
5594 ****************************************************************************/
5596 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5598 POLICY_HND *handle = &q_u->handle;
5599 UNISTR2 *uni_arch = &q_u->architecture;
5600 uint32 level = q_u->level;
5601 uint32 clientmajorversion = q_u->clientmajorversion;
5602 RPC_BUFFER *buffer = NULL;
5603 uint32 offered = q_u->offered;
5604 uint32 *needed = &r_u->needed;
5605 uint32 *servermajorversion = &r_u->servermajorversion;
5606 uint32 *serverminorversion = &r_u->serverminorversion;
5607 Printer_entry *printer;
5609 fstring servername;
5610 fstring architecture;
5611 int snum;
5613 /* that's an [in out] buffer */
5615 if ( q_u->buffer ) {
5616 rpcbuf_move(q_u->buffer, &r_u->buffer);
5617 buffer = r_u->buffer;
5620 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5622 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5623 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5624 return WERR_INVALID_PRINTER_NAME;
5627 *needed = 0;
5628 *servermajorversion = 0;
5629 *serverminorversion = 0;
5631 fstrcpy(servername, get_server_name( printer ));
5632 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5634 if (!get_printer_snum(p, handle, &snum))
5635 return WERR_BADFID;
5637 switch (level) {
5638 case 1:
5639 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5640 case 2:
5641 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5642 case 3:
5643 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5644 case 6:
5645 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5646 #if 0 /* JERRY */
5647 case 101:
5648 /* apparently this call is the equivalent of
5649 EnumPrinterDataEx() for the DsDriver key */
5650 break;
5651 #endif
5654 return WERR_UNKNOWN_LEVEL;
5657 /****************************************************************************
5658 ****************************************************************************/
5660 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5662 POLICY_HND *handle = &q_u->handle;
5664 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5666 if (!Printer) {
5667 DEBUG(3,("Error in startpageprinter printer handle\n"));
5668 return WERR_BADFID;
5671 Printer->page_started=True;
5672 return WERR_OK;
5675 /****************************************************************************
5676 ****************************************************************************/
5678 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5680 POLICY_HND *handle = &q_u->handle;
5681 int snum;
5683 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5685 if (!Printer) {
5686 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5687 return WERR_BADFID;
5690 if (!get_printer_snum(p, handle, &snum))
5691 return WERR_BADFID;
5693 Printer->page_started=False;
5694 print_job_endpage(snum, Printer->jobid);
5696 return WERR_OK;
5699 /********************************************************************
5700 * api_spoolss_getprinter
5701 * called from the spoolss dispatcher
5703 ********************************************************************/
5705 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5707 POLICY_HND *handle = &q_u->handle;
5708 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5709 uint32 *jobid = &r_u->jobid;
5711 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5712 int snum;
5713 pstring jobname;
5714 fstring datatype;
5715 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5716 struct current_user user;
5718 if (!Printer) {
5719 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5720 return WERR_BADFID;
5723 get_current_user(&user, p);
5726 * a nice thing with NT is it doesn't listen to what you tell it.
5727 * when asked to send _only_ RAW datas, it tries to send datas
5728 * in EMF format.
5730 * So I add checks like in NT Server ...
5733 if (info_1->p_datatype != 0) {
5734 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5735 if (strcmp(datatype, "RAW") != 0) {
5736 (*jobid)=0;
5737 return WERR_INVALID_DATATYPE;
5741 /* get the share number of the printer */
5742 if (!get_printer_snum(p, handle, &snum)) {
5743 return WERR_BADFID;
5746 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5748 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5750 /* An error occured in print_job_start() so return an appropriate
5751 NT error code. */
5753 if (Printer->jobid == -1) {
5754 return map_werror_from_unix(errno);
5757 Printer->document_started=True;
5758 (*jobid) = Printer->jobid;
5760 return WERR_OK;
5763 /********************************************************************
5764 * api_spoolss_getprinter
5765 * called from the spoolss dispatcher
5767 ********************************************************************/
5769 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5771 POLICY_HND *handle = &q_u->handle;
5773 return _spoolss_enddocprinter_internal(p, handle);
5776 /****************************************************************************
5777 ****************************************************************************/
5779 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5781 POLICY_HND *handle = &q_u->handle;
5782 uint32 buffer_size = q_u->buffer_size;
5783 uint8 *buffer = q_u->buffer;
5784 uint32 *buffer_written = &q_u->buffer_size2;
5785 int snum;
5786 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5788 if (!Printer) {
5789 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5790 r_u->buffer_written = q_u->buffer_size2;
5791 return WERR_BADFID;
5794 if (!get_printer_snum(p, handle, &snum))
5795 return WERR_BADFID;
5797 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5798 if (*buffer_written == -1) {
5799 r_u->buffer_written = 0;
5800 if (errno == ENOSPC)
5801 return WERR_NO_SPOOL_SPACE;
5802 else
5803 return WERR_ACCESS_DENIED;
5806 r_u->buffer_written = q_u->buffer_size2;
5808 return WERR_OK;
5811 /********************************************************************
5812 * api_spoolss_getprinter
5813 * called from the spoolss dispatcher
5815 ********************************************************************/
5817 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5818 pipes_struct *p)
5820 struct current_user user;
5821 int snum;
5822 WERROR errcode = WERR_BADFUNC;
5823 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5825 get_current_user(&user, p);
5827 if (!Printer) {
5828 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5829 return WERR_BADFID;
5832 if (!get_printer_snum(p, handle, &snum))
5833 return WERR_BADFID;
5835 switch (command) {
5836 case PRINTER_CONTROL_PAUSE:
5837 if (print_queue_pause(&user, snum, &errcode)) {
5838 errcode = WERR_OK;
5840 break;
5841 case PRINTER_CONTROL_RESUME:
5842 case PRINTER_CONTROL_UNPAUSE:
5843 if (print_queue_resume(&user, snum, &errcode)) {
5844 errcode = WERR_OK;
5846 break;
5847 case PRINTER_CONTROL_PURGE:
5848 if (print_queue_purge(&user, snum, &errcode)) {
5849 errcode = WERR_OK;
5851 break;
5852 default:
5853 return WERR_UNKNOWN_LEVEL;
5856 return errcode;
5859 /********************************************************************
5860 * api_spoolss_abortprinter
5861 * From MSDN: "Deletes printer's spool file if printer is configured
5862 * for spooling"
5863 ********************************************************************/
5865 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5867 POLICY_HND *handle = &q_u->handle;
5868 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5869 int snum;
5870 struct current_user user;
5871 WERROR errcode = WERR_OK;
5873 if (!Printer) {
5874 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5875 return WERR_BADFID;
5878 if (!get_printer_snum(p, handle, &snum))
5879 return WERR_BADFID;
5881 get_current_user( &user, p );
5883 print_job_delete( &user, snum, Printer->jobid, &errcode );
5885 return errcode;
5888 /********************************************************************
5889 * called by spoolss_api_setprinter
5890 * when updating a printer description
5891 ********************************************************************/
5893 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5894 const SPOOL_PRINTER_INFO_LEVEL *info,
5895 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5897 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5898 WERROR result;
5899 int snum;
5901 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5903 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5904 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5905 OUR_HANDLE(handle)));
5907 result = WERR_BADFID;
5908 goto done;
5911 /* Check the user has permissions to change the security
5912 descriptor. By experimentation with two NT machines, the user
5913 requires Full Access to the printer to change security
5914 information. */
5916 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5917 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5918 result = WERR_ACCESS_DENIED;
5919 goto done;
5922 /* NT seems to like setting the security descriptor even though
5923 nothing may have actually changed. */
5925 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5927 if (DEBUGLEVEL >= 10) {
5928 SEC_ACL *the_acl;
5929 int i;
5931 the_acl = old_secdesc_ctr->sec->dacl;
5932 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5933 PRINTERNAME(snum), the_acl->num_aces));
5935 for (i = 0; i < the_acl->num_aces; i++) {
5936 fstring sid_str;
5938 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5940 DEBUG(10, ("%s 0x%08x\n", sid_str,
5941 the_acl->ace[i].info.mask));
5944 the_acl = secdesc_ctr->sec->dacl;
5946 if (the_acl) {
5947 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5948 PRINTERNAME(snum), the_acl->num_aces));
5950 for (i = 0; i < the_acl->num_aces; i++) {
5951 fstring sid_str;
5953 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5955 DEBUG(10, ("%s 0x%08x\n", sid_str,
5956 the_acl->ace[i].info.mask));
5958 } else {
5959 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5963 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5965 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5966 result = WERR_OK;
5967 goto done;
5970 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5972 done:
5974 return result;
5977 /********************************************************************
5978 Canonicalize printer info from a client
5980 ATTN: It does not matter what we set the servername to hear
5981 since we do the necessary work in get_a_printer() to set it to
5982 the correct value based on what the client sent in the
5983 _spoolss_open_printer_ex().
5984 ********************************************************************/
5986 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5988 fstring printername;
5989 const char *p;
5991 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5992 "portname=%s drivername=%s comment=%s location=%s\n",
5993 info->servername, info->printername, info->sharename,
5994 info->portname, info->drivername, info->comment, info->location));
5996 /* we force some elements to "correct" values */
5997 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5998 fstrcpy(info->sharename, lp_servicename(snum));
6000 /* check to see if we allow printername != sharename */
6002 if ( lp_force_printername(snum) ) {
6003 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6004 global_myname(), info->sharename );
6005 } else {
6007 /* make sure printername is in \\server\printername format */
6009 fstrcpy( printername, info->printername );
6010 p = printername;
6011 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6012 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6013 p++;
6016 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6017 global_myname(), p );
6020 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6021 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6025 return True;
6028 /****************************************************************************
6029 ****************************************************************************/
6031 static BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6033 extern userdom_struct current_user_info;
6034 char *cmd = lp_addprinter_cmd();
6035 char **qlines;
6036 pstring command;
6037 int numlines;
6038 int ret;
6039 int fd;
6040 fstring remote_machine = "%m";
6041 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6042 BOOL is_print_op;
6044 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6046 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6047 cmd, printer->info_2->printername, printer->info_2->sharename,
6048 printer->info_2->portname, printer->info_2->drivername,
6049 printer->info_2->location, printer->info_2->comment, remote_machine);
6051 is_print_op = user_has_privileges( token, &se_printop );
6053 DEBUG(10,("Running [%s]\n", command));
6055 /********* BEGIN SePrintOperatorPrivilege **********/
6057 if ( is_print_op )
6058 become_root();
6060 if ( (ret = smbrun(command, &fd)) == 0 ) {
6061 /* Tell everyone we updated smb.conf. */
6062 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6065 if ( is_print_op )
6066 unbecome_root();
6068 /********* END SePrintOperatorPrivilege **********/
6070 DEBUGADD(10,("returned [%d]\n", ret));
6072 if ( ret != 0 ) {
6073 if (fd != -1)
6074 close(fd);
6075 return False;
6078 /* reload our services immediately */
6079 reload_services( False );
6081 numlines = 0;
6082 /* Get lines and convert them back to dos-codepage */
6083 qlines = fd_lines_load(fd, &numlines);
6084 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6085 close(fd);
6087 /* Set the portname to what the script says the portname should be. */
6088 /* but don't require anything to be return from the script exit a good error code */
6090 if (numlines) {
6091 /* Set the portname to what the script says the portname should be. */
6092 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6093 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6096 file_lines_free(qlines);
6097 return True;
6100 /********************************************************************
6101 * Called by spoolss_api_setprinter
6102 * when updating a printer description.
6103 ********************************************************************/
6105 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6106 const SPOOL_PRINTER_INFO_LEVEL *info,
6107 DEVICEMODE *devmode)
6109 int snum;
6110 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6111 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6112 WERROR result;
6113 UNISTR2 buffer;
6114 fstring asc_buffer;
6116 DEBUG(8,("update_printer\n"));
6118 result = WERR_OK;
6120 if (!Printer) {
6121 result = WERR_BADFID;
6122 goto done;
6125 if (!get_printer_snum(p, handle, &snum)) {
6126 result = WERR_BADFID;
6127 goto done;
6130 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6131 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6132 result = WERR_BADFID;
6133 goto done;
6136 DEBUGADD(8,("Converting info_2 struct\n"));
6139 * convert_printer_info converts the incoming
6140 * info from the client and overwrites the info
6141 * just read from the tdb in the pointer 'printer'.
6144 if (!convert_printer_info(info, printer, level)) {
6145 result = WERR_NOMEM;
6146 goto done;
6149 if (devmode) {
6150 /* we have a valid devmode
6151 convert it and link it*/
6153 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6154 if (!convert_devicemode(printer->info_2->printername, devmode,
6155 &printer->info_2->devmode)) {
6156 result = WERR_NOMEM;
6157 goto done;
6161 /* Do sanity check on the requested changes for Samba */
6163 if (!check_printer_ok(printer->info_2, snum)) {
6164 result = WERR_INVALID_PARAM;
6165 goto done;
6168 /* FIXME!!! If the driver has changed we really should verify that
6169 it is installed before doing much else --jerry */
6171 /* Check calling user has permission to update printer description */
6173 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6174 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6175 result = WERR_ACCESS_DENIED;
6176 goto done;
6179 /* Call addprinter hook */
6180 /* Check changes to see if this is really needed */
6182 if ( *lp_addprinter_cmd()
6183 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6184 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6185 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6186 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6188 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6189 result = WERR_ACCESS_DENIED;
6190 goto done;
6194 * make sure we actually reload the services after
6195 * this as smb.conf could have a new section in it
6196 * .... shouldn't .... but could
6198 reload_services(False);
6202 * When a *new* driver is bound to a printer, the drivername is used to
6203 * lookup previously saved driver initialization info, which is then
6204 * bound to the printer, simulating what happens in the Windows arch.
6206 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6208 if (!set_driver_init(printer, 2))
6210 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6211 printer->info_2->drivername));
6214 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6215 printer->info_2->drivername));
6217 notify_printer_driver(snum, printer->info_2->drivername);
6221 * flag which changes actually occured. This is a small subset of
6222 * all the possible changes. We also have to update things in the
6223 * DsSpooler key.
6226 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6227 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6228 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6229 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6231 notify_printer_comment(snum, printer->info_2->comment);
6234 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6235 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6236 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6237 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6239 notify_printer_sharename(snum, printer->info_2->sharename);
6242 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6243 char *pname;
6245 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6246 pname++;
6247 else
6248 pname = printer->info_2->printername;
6251 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6252 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6253 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6255 notify_printer_printername( snum, pname );
6258 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6259 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6260 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6261 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6263 notify_printer_port(snum, printer->info_2->portname);
6266 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6267 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6268 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6269 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6271 notify_printer_location(snum, printer->info_2->location);
6274 /* here we need to update some more DsSpooler keys */
6275 /* uNCName, serverName, shortServerName */
6277 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6278 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6279 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6280 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6281 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6283 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6284 global_myname(), printer->info_2->sharename );
6285 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6286 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6287 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6289 /* Update printer info */
6290 result = mod_a_printer(printer, 2);
6292 done:
6293 free_a_printer(&printer, 2);
6294 free_a_printer(&old_printer, 2);
6297 return result;
6300 /****************************************************************************
6301 ****************************************************************************/
6302 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6303 const SPOOL_PRINTER_INFO_LEVEL *info)
6305 #ifdef HAVE_ADS
6306 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6307 int snum;
6308 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6310 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6312 if (!Printer)
6313 return WERR_BADFID;
6315 if (!get_printer_snum(p, handle, &snum))
6316 return WERR_BADFID;
6318 nt_printer_publish(Printer, snum, info7->action);
6320 return WERR_OK;
6321 #else
6322 return WERR_UNKNOWN_LEVEL;
6323 #endif
6325 /****************************************************************************
6326 ****************************************************************************/
6328 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6330 POLICY_HND *handle = &q_u->handle;
6331 uint32 level = q_u->level;
6332 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6333 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6334 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6335 uint32 command = q_u->command;
6336 WERROR result;
6338 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6340 if (!Printer) {
6341 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6342 return WERR_BADFID;
6345 /* check the level */
6346 switch (level) {
6347 case 0:
6348 return control_printer(handle, command, p);
6349 case 2:
6350 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6351 if (!W_ERROR_IS_OK(result))
6352 return result;
6353 if (secdesc_ctr)
6354 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6355 return result;
6356 case 3:
6357 return update_printer_sec(handle, level, info, p,
6358 secdesc_ctr);
6359 case 7:
6360 return publish_or_unpublish_printer(p, handle, info);
6361 default:
6362 return WERR_UNKNOWN_LEVEL;
6366 /****************************************************************************
6367 ****************************************************************************/
6369 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6371 POLICY_HND *handle = &q_u->handle;
6372 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6374 if (!Printer) {
6375 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6376 return WERR_BADFID;
6379 if (Printer->notify.client_connected==True) {
6380 int snum = -1;
6382 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6383 snum = -1;
6384 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6385 !get_printer_snum(p, handle, &snum) )
6386 return WERR_BADFID;
6388 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6391 Printer->notify.flags=0;
6392 Printer->notify.options=0;
6393 Printer->notify.localmachine[0]='\0';
6394 Printer->notify.printerlocal=0;
6395 if (Printer->notify.option)
6396 free_spool_notify_option(&Printer->notify.option);
6397 Printer->notify.client_connected=False;
6399 return WERR_OK;
6402 /****************************************************************************
6403 ****************************************************************************/
6405 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6407 /* that's an [in out] buffer */
6409 if ( q_u->buffer )
6410 rpcbuf_move(q_u->buffer, &r_u->buffer);
6412 r_u->needed = 0;
6413 return WERR_INVALID_PARAM; /* this is what a NT server
6414 returns for AddJob. AddJob
6415 must fail on non-local
6416 printers */
6419 /****************************************************************************
6420 ****************************************************************************/
6422 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6423 int position, int snum,
6424 NT_PRINTER_INFO_LEVEL *ntprinter)
6426 struct tm *t;
6428 t=gmtime(&queue->time);
6430 job_info->jobid=queue->job;
6431 init_unistr(&job_info->printername, lp_servicename(snum));
6432 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6433 init_unistr(&job_info->username, queue->fs_user);
6434 init_unistr(&job_info->document, queue->fs_file);
6435 init_unistr(&job_info->datatype, "RAW");
6436 init_unistr(&job_info->text_status, "");
6437 job_info->status=nt_printj_status(queue->status);
6438 job_info->priority=queue->priority;
6439 job_info->position=position;
6440 job_info->totalpages=queue->page_count;
6441 job_info->pagesprinted=0;
6443 make_systemtime(&job_info->submitted, t);
6446 /****************************************************************************
6447 ****************************************************************************/
6449 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6450 int position, int snum,
6451 NT_PRINTER_INFO_LEVEL *ntprinter,
6452 DEVICEMODE *devmode)
6454 struct tm *t;
6456 t=gmtime(&queue->time);
6458 job_info->jobid=queue->job;
6460 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6462 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6463 init_unistr(&job_info->username, queue->fs_user);
6464 init_unistr(&job_info->document, queue->fs_file);
6465 init_unistr(&job_info->notifyname, queue->fs_user);
6466 init_unistr(&job_info->datatype, "RAW");
6467 init_unistr(&job_info->printprocessor, "winprint");
6468 init_unistr(&job_info->parameters, "");
6469 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6470 init_unistr(&job_info->text_status, "");
6472 /* and here the security descriptor */
6474 job_info->status=nt_printj_status(queue->status);
6475 job_info->priority=queue->priority;
6476 job_info->position=position;
6477 job_info->starttime=0;
6478 job_info->untiltime=0;
6479 job_info->totalpages=queue->page_count;
6480 job_info->size=queue->size;
6481 make_systemtime(&(job_info->submitted), t);
6482 job_info->timeelapsed=0;
6483 job_info->pagesprinted=0;
6485 job_info->devmode = devmode;
6487 return (True);
6490 /****************************************************************************
6491 Enumjobs at level 1.
6492 ****************************************************************************/
6494 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6495 NT_PRINTER_INFO_LEVEL *ntprinter,
6496 RPC_BUFFER *buffer, uint32 offered,
6497 uint32 *needed, uint32 *returned)
6499 JOB_INFO_1 *info;
6500 int i;
6501 WERROR result = WERR_OK;
6503 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6504 if (info==NULL) {
6505 SAFE_FREE(queue);
6506 *returned=0;
6507 return WERR_NOMEM;
6510 for (i=0; i<*returned; i++)
6511 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6513 SAFE_FREE(queue);
6515 /* check the required size. */
6516 for (i=0; i<*returned; i++)
6517 (*needed) += spoolss_size_job_info_1(&info[i]);
6519 if (*needed > offered) {
6520 result = WERR_INSUFFICIENT_BUFFER;
6521 goto out;
6524 if (!rpcbuf_alloc_size(buffer, *needed)) {
6525 result = WERR_NOMEM;
6526 goto out;
6529 /* fill the buffer with the structures */
6530 for (i=0; i<*returned; i++)
6531 smb_io_job_info_1("", buffer, &info[i], 0);
6533 out:
6534 /* clear memory */
6535 SAFE_FREE(info);
6537 if ( !W_ERROR_IS_OK(result) )
6538 *returned = 0;
6540 return result;
6543 /****************************************************************************
6544 Enumjobs at level 2.
6545 ****************************************************************************/
6547 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6548 NT_PRINTER_INFO_LEVEL *ntprinter,
6549 RPC_BUFFER *buffer, uint32 offered,
6550 uint32 *needed, uint32 *returned)
6552 JOB_INFO_2 *info = NULL;
6553 int i;
6554 WERROR result = WERR_OK;
6555 DEVICEMODE *devmode = NULL;
6557 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6558 *returned=0;
6559 return WERR_NOMEM;
6562 /* this should not be a failure condition if the devmode is NULL */
6564 devmode = construct_dev_mode(snum);
6566 for (i=0; i<*returned; i++)
6567 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6569 free_a_printer(&ntprinter, 2);
6570 SAFE_FREE(queue);
6572 /* check the required size. */
6573 for (i=0; i<*returned; i++)
6574 (*needed) += spoolss_size_job_info_2(&info[i]);
6576 if (*needed > offered) {
6577 result = WERR_INSUFFICIENT_BUFFER;
6578 goto out;
6581 if (!rpcbuf_alloc_size(buffer, *needed)) {
6582 result = WERR_NOMEM;
6583 goto out;
6586 /* fill the buffer with the structures */
6587 for (i=0; i<*returned; i++)
6588 smb_io_job_info_2("", buffer, &info[i], 0);
6590 out:
6591 free_devmode(devmode);
6592 SAFE_FREE(info);
6594 if ( !W_ERROR_IS_OK(result) )
6595 *returned = 0;
6597 return result;
6601 /****************************************************************************
6602 Enumjobs.
6603 ****************************************************************************/
6605 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6607 POLICY_HND *handle = &q_u->handle;
6608 uint32 level = q_u->level;
6609 RPC_BUFFER *buffer = NULL;
6610 uint32 offered = q_u->offered;
6611 uint32 *needed = &r_u->needed;
6612 uint32 *returned = &r_u->returned;
6613 WERROR wret;
6614 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6615 int snum;
6616 print_status_struct prt_status;
6617 print_queue_struct *queue=NULL;
6619 /* that's an [in out] buffer */
6621 if ( q_u->buffer ) {
6622 rpcbuf_move(q_u->buffer, &r_u->buffer);
6623 buffer = r_u->buffer;
6626 DEBUG(4,("_spoolss_enumjobs\n"));
6628 *needed=0;
6629 *returned=0;
6631 /* lookup the printer snum and tdb entry */
6633 if (!get_printer_snum(p, handle, &snum))
6634 return WERR_BADFID;
6636 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6637 if ( !W_ERROR_IS_OK(wret) )
6638 return wret;
6640 *returned = print_queue_status(snum, &queue, &prt_status);
6641 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6643 if (*returned == 0) {
6644 SAFE_FREE(queue);
6645 return WERR_OK;
6648 switch (level) {
6649 case 1:
6650 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6651 return wret;
6652 case 2:
6653 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6654 return wret;
6655 default:
6656 SAFE_FREE(queue);
6657 *returned=0;
6658 wret = WERR_UNKNOWN_LEVEL;
6661 free_a_printer( &ntprinter, 2 );
6662 return wret;
6665 /****************************************************************************
6666 ****************************************************************************/
6668 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6670 return WERR_OK;
6673 /****************************************************************************
6674 ****************************************************************************/
6676 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6678 POLICY_HND *handle = &q_u->handle;
6679 uint32 jobid = q_u->jobid;
6680 uint32 command = q_u->command;
6682 struct current_user user;
6683 int snum;
6684 WERROR errcode = WERR_BADFUNC;
6686 if (!get_printer_snum(p, handle, &snum)) {
6687 return WERR_BADFID;
6690 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6691 return WERR_INVALID_PRINTER_NAME;
6694 get_current_user(&user, p);
6696 switch (command) {
6697 case JOB_CONTROL_CANCEL:
6698 case JOB_CONTROL_DELETE:
6699 if (print_job_delete(&user, snum, jobid, &errcode)) {
6700 errcode = WERR_OK;
6702 break;
6703 case JOB_CONTROL_PAUSE:
6704 if (print_job_pause(&user, snum, jobid, &errcode)) {
6705 errcode = WERR_OK;
6707 break;
6708 case JOB_CONTROL_RESTART:
6709 case JOB_CONTROL_RESUME:
6710 if (print_job_resume(&user, snum, jobid, &errcode)) {
6711 errcode = WERR_OK;
6713 break;
6714 default:
6715 return WERR_UNKNOWN_LEVEL;
6718 return errcode;
6721 /****************************************************************************
6722 Enumerates all printer drivers at level 1.
6723 ****************************************************************************/
6725 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6727 int i;
6728 int ndrivers;
6729 uint32 version;
6730 fstring *list = NULL;
6731 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6732 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6733 WERROR result = WERR_OK;
6735 *returned=0;
6737 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6738 list=NULL;
6739 ndrivers=get_ntdrivers(&list, architecture, version);
6740 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6742 if(ndrivers == -1)
6743 return WERR_NOMEM;
6745 if(ndrivers != 0) {
6746 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6747 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6748 SAFE_FREE(driver_info_1);
6749 SAFE_FREE(list);
6750 return WERR_NOMEM;
6752 else driver_info_1 = tdi1;
6755 for (i=0; i<ndrivers; i++) {
6756 WERROR status;
6757 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6758 ZERO_STRUCT(driver);
6759 status = get_a_printer_driver(&driver, 3, list[i],
6760 architecture, version);
6761 if (!W_ERROR_IS_OK(status)) {
6762 SAFE_FREE(list);
6763 return status;
6765 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6766 free_a_printer_driver(driver, 3);
6769 *returned+=ndrivers;
6770 SAFE_FREE(list);
6773 /* check the required size. */
6774 for (i=0; i<*returned; i++) {
6775 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6776 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6779 if (*needed > offered) {
6780 result = WERR_INSUFFICIENT_BUFFER;
6781 goto out;
6784 if (!rpcbuf_alloc_size(buffer, *needed)) {
6785 result = WERR_NOMEM;
6786 goto out;
6789 /* fill the buffer with the driver structures */
6790 for (i=0; i<*returned; i++) {
6791 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6792 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6795 out:
6796 SAFE_FREE(driver_info_1);
6798 if ( !W_ERROR_IS_OK(result) )
6799 *returned = 0;
6801 return result;
6804 /****************************************************************************
6805 Enumerates all printer drivers at level 2.
6806 ****************************************************************************/
6808 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6810 int i;
6811 int ndrivers;
6812 uint32 version;
6813 fstring *list = NULL;
6814 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6815 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6816 WERROR result = WERR_OK;
6818 *returned=0;
6820 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6821 list=NULL;
6822 ndrivers=get_ntdrivers(&list, architecture, version);
6823 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6825 if(ndrivers == -1)
6826 return WERR_NOMEM;
6828 if(ndrivers != 0) {
6829 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6830 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6831 SAFE_FREE(driver_info_2);
6832 SAFE_FREE(list);
6833 return WERR_NOMEM;
6835 else driver_info_2 = tdi2;
6838 for (i=0; i<ndrivers; i++) {
6839 WERROR status;
6841 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6842 ZERO_STRUCT(driver);
6843 status = get_a_printer_driver(&driver, 3, list[i],
6844 architecture, version);
6845 if (!W_ERROR_IS_OK(status)) {
6846 SAFE_FREE(list);
6847 return status;
6849 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6850 free_a_printer_driver(driver, 3);
6853 *returned+=ndrivers;
6854 SAFE_FREE(list);
6857 /* check the required size. */
6858 for (i=0; i<*returned; i++) {
6859 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6860 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6863 if (*needed > offered) {
6864 result = WERR_INSUFFICIENT_BUFFER;
6865 goto out;
6868 if (!rpcbuf_alloc_size(buffer, *needed)) {
6869 result = WERR_NOMEM;
6870 goto out;
6873 /* fill the buffer with the form structures */
6874 for (i=0; i<*returned; i++) {
6875 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6876 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6879 out:
6880 SAFE_FREE(driver_info_2);
6882 if ( !W_ERROR_IS_OK(result) )
6883 *returned = 0;
6885 return result;
6888 /****************************************************************************
6889 Enumerates all printer drivers at level 3.
6890 ****************************************************************************/
6892 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6894 int i;
6895 int ndrivers;
6896 uint32 version;
6897 fstring *list = NULL;
6898 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6899 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6900 WERROR result = WERR_OK;
6902 *returned=0;
6904 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6905 list=NULL;
6906 ndrivers=get_ntdrivers(&list, architecture, version);
6907 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6909 if(ndrivers == -1)
6910 return WERR_NOMEM;
6912 if(ndrivers != 0) {
6913 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6914 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6915 SAFE_FREE(driver_info_3);
6916 SAFE_FREE(list);
6917 return WERR_NOMEM;
6919 else driver_info_3 = tdi3;
6922 for (i=0; i<ndrivers; i++) {
6923 WERROR status;
6925 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6926 ZERO_STRUCT(driver);
6927 status = get_a_printer_driver(&driver, 3, list[i],
6928 architecture, version);
6929 if (!W_ERROR_IS_OK(status)) {
6930 SAFE_FREE(list);
6931 return status;
6933 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6934 free_a_printer_driver(driver, 3);
6937 *returned+=ndrivers;
6938 SAFE_FREE(list);
6941 /* check the required size. */
6942 for (i=0; i<*returned; i++) {
6943 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6944 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6947 if (*needed > offered) {
6948 result = WERR_INSUFFICIENT_BUFFER;
6949 goto out;
6952 if (!rpcbuf_alloc_size(buffer, *needed)) {
6953 result = WERR_NOMEM;
6954 goto out;
6957 /* fill the buffer with the driver structures */
6958 for (i=0; i<*returned; i++) {
6959 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6960 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6963 out:
6964 for (i=0; i<*returned; i++)
6965 SAFE_FREE(driver_info_3[i].dependentfiles);
6967 SAFE_FREE(driver_info_3);
6969 if ( !W_ERROR_IS_OK(result) )
6970 *returned = 0;
6972 return result;
6975 /****************************************************************************
6976 Enumerates all printer drivers.
6977 ****************************************************************************/
6979 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6981 uint32 level = q_u->level;
6982 RPC_BUFFER *buffer = NULL;
6983 uint32 offered = q_u->offered;
6984 uint32 *needed = &r_u->needed;
6985 uint32 *returned = &r_u->returned;
6987 fstring servername;
6988 fstring architecture;
6990 /* that's an [in out] buffer */
6992 if ( q_u->buffer ) {
6993 rpcbuf_move(q_u->buffer, &r_u->buffer);
6994 buffer = r_u->buffer;
6997 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6999 *needed = 0;
7000 *returned = 0;
7002 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7003 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7005 if ( !is_myname_or_ipaddr( servername ) )
7006 return WERR_UNKNOWN_PRINTER_DRIVER;
7008 switch (level) {
7009 case 1:
7010 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7011 case 2:
7012 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7013 case 3:
7014 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7015 default:
7016 return WERR_UNKNOWN_LEVEL;
7020 /****************************************************************************
7021 ****************************************************************************/
7023 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7025 form->flag=list->flag;
7026 init_unistr(&form->name, list->name);
7027 form->width=list->width;
7028 form->length=list->length;
7029 form->left=list->left;
7030 form->top=list->top;
7031 form->right=list->right;
7032 form->bottom=list->bottom;
7035 /****************************************************************************
7036 ****************************************************************************/
7038 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7040 uint32 level = q_u->level;
7041 RPC_BUFFER *buffer = NULL;
7042 uint32 offered = q_u->offered;
7043 uint32 *needed = &r_u->needed;
7044 uint32 *numofforms = &r_u->numofforms;
7045 uint32 numbuiltinforms;
7047 nt_forms_struct *list=NULL;
7048 nt_forms_struct *builtinlist=NULL;
7049 FORM_1 *forms_1;
7050 int buffer_size=0;
7051 int i;
7053 /* that's an [in out] buffer */
7055 if ( q_u->buffer ) {
7056 rpcbuf_move(q_u->buffer, &r_u->buffer);
7057 buffer = r_u->buffer;
7060 DEBUG(4,("_spoolss_enumforms\n"));
7061 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7062 DEBUGADD(5,("Info level [%d]\n", level));
7064 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7065 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7066 *numofforms = get_ntforms(&list);
7067 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7068 *numofforms += numbuiltinforms;
7070 if (*numofforms == 0)
7071 return WERR_NO_MORE_ITEMS;
7073 switch (level) {
7074 case 1:
7075 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7076 *numofforms=0;
7077 return WERR_NOMEM;
7080 /* construct the list of form structures */
7081 for (i=0; i<numbuiltinforms; i++) {
7082 DEBUGADD(6,("Filling form number [%d]\n",i));
7083 fill_form_1(&forms_1[i], &builtinlist[i]);
7086 SAFE_FREE(builtinlist);
7088 for (; i<*numofforms; i++) {
7089 DEBUGADD(6,("Filling form number [%d]\n",i));
7090 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7093 SAFE_FREE(list);
7095 /* check the required size. */
7096 for (i=0; i<numbuiltinforms; i++) {
7097 DEBUGADD(6,("adding form [%d]'s size\n",i));
7098 buffer_size += spoolss_size_form_1(&forms_1[i]);
7100 for (; i<*numofforms; i++) {
7101 DEBUGADD(6,("adding form [%d]'s size\n",i));
7102 buffer_size += spoolss_size_form_1(&forms_1[i]);
7105 *needed=buffer_size;
7107 if (*needed > offered) {
7108 SAFE_FREE(forms_1);
7109 *numofforms=0;
7110 return WERR_INSUFFICIENT_BUFFER;
7113 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7114 SAFE_FREE(forms_1);
7115 *numofforms=0;
7116 return WERR_NOMEM;
7119 /* fill the buffer with the form structures */
7120 for (i=0; i<numbuiltinforms; i++) {
7121 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7122 smb_io_form_1("", buffer, &forms_1[i], 0);
7124 for (; i<*numofforms; i++) {
7125 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7126 smb_io_form_1("", buffer, &forms_1[i], 0);
7129 SAFE_FREE(forms_1);
7131 return WERR_OK;
7133 default:
7134 SAFE_FREE(list);
7135 SAFE_FREE(builtinlist);
7136 return WERR_UNKNOWN_LEVEL;
7141 /****************************************************************************
7142 ****************************************************************************/
7144 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7146 uint32 level = q_u->level;
7147 UNISTR2 *uni_formname = &q_u->formname;
7148 RPC_BUFFER *buffer = NULL;
7149 uint32 offered = q_u->offered;
7150 uint32 *needed = &r_u->needed;
7152 nt_forms_struct *list=NULL;
7153 nt_forms_struct builtin_form;
7154 BOOL foundBuiltin;
7155 FORM_1 form_1;
7156 fstring form_name;
7157 int buffer_size=0;
7158 int numofforms=0, i=0;
7160 /* that's an [in out] buffer */
7162 if ( q_u->buffer ) {
7163 rpcbuf_move(q_u->buffer, &r_u->buffer);
7164 buffer = r_u->buffer;
7167 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7169 DEBUG(4,("_spoolss_getform\n"));
7170 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7171 DEBUGADD(5,("Info level [%d]\n", level));
7173 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7174 if (!foundBuiltin) {
7175 numofforms = get_ntforms(&list);
7176 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7178 if (numofforms == 0)
7179 return WERR_BADFID;
7182 switch (level) {
7183 case 1:
7184 if (foundBuiltin) {
7185 fill_form_1(&form_1, &builtin_form);
7186 } else {
7188 /* Check if the requested name is in the list of form structures */
7189 for (i=0; i<numofforms; i++) {
7191 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7193 if (strequal(form_name, list[i].name)) {
7194 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7195 fill_form_1(&form_1, &list[i]);
7196 break;
7200 SAFE_FREE(list);
7201 if (i == numofforms) {
7202 return WERR_BADFID;
7205 /* check the required size. */
7207 *needed=spoolss_size_form_1(&form_1);
7209 if (*needed > offered)
7210 return WERR_INSUFFICIENT_BUFFER;
7212 if (!rpcbuf_alloc_size(buffer, buffer_size))
7213 return WERR_NOMEM;
7215 /* fill the buffer with the form structures */
7216 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7217 smb_io_form_1("", buffer, &form_1, 0);
7219 return WERR_OK;
7221 default:
7222 SAFE_FREE(list);
7223 return WERR_UNKNOWN_LEVEL;
7227 /****************************************************************************
7228 ****************************************************************************/
7230 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7232 init_unistr(&port->port_name, name);
7235 /****************************************************************************
7236 ****************************************************************************/
7238 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7240 init_unistr(&port->port_name, name);
7241 init_unistr(&port->monitor_name, "Local Monitor");
7242 init_unistr(&port->description, "Local Port");
7243 port->port_type=PORT_TYPE_WRITE;
7244 port->reserved=0x0;
7247 /****************************************************************************
7248 enumports level 1.
7249 ****************************************************************************/
7251 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7253 PORT_INFO_1 *ports=NULL;
7254 int i=0;
7255 WERROR result = WERR_OK;
7257 if (*lp_enumports_cmd()) {
7258 char *cmd = lp_enumports_cmd();
7259 char **qlines;
7260 pstring command;
7261 int numlines;
7262 int ret;
7263 int fd;
7265 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7267 DEBUG(10,("Running [%s]\n", command));
7268 ret = smbrun(command, &fd);
7269 DEBUG(10,("Returned [%d]\n", ret));
7270 if (ret != 0) {
7271 if (fd != -1)
7272 close(fd);
7273 /* Is this the best error to return here? */
7274 return WERR_ACCESS_DENIED;
7277 numlines = 0;
7278 qlines = fd_lines_load(fd, &numlines);
7279 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7280 close(fd);
7282 if(numlines) {
7283 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7284 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7285 dos_errstr(WERR_NOMEM)));
7286 file_lines_free(qlines);
7287 return WERR_NOMEM;
7290 for (i=0; i<numlines; i++) {
7291 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7292 fill_port_1(&ports[i], qlines[i]);
7295 file_lines_free(qlines);
7298 *returned = numlines;
7300 } else {
7301 *returned = 1; /* Sole Samba port returned. */
7303 if((ports=SMB_MALLOC_P(PORT_INFO_1)) == NULL)
7304 return WERR_NOMEM;
7306 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7308 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7311 /* check the required size. */
7312 for (i=0; i<*returned; i++) {
7313 DEBUGADD(6,("adding port [%d]'s size\n", i));
7314 *needed += spoolss_size_port_info_1(&ports[i]);
7317 if (*needed > offered) {
7318 result = WERR_INSUFFICIENT_BUFFER;
7319 goto out;
7322 if (!rpcbuf_alloc_size(buffer, *needed)) {
7323 result = WERR_NOMEM;
7324 goto out;
7327 /* fill the buffer with the ports structures */
7328 for (i=0; i<*returned; i++) {
7329 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7330 smb_io_port_1("", buffer, &ports[i], 0);
7333 out:
7334 SAFE_FREE(ports);
7336 if ( !W_ERROR_IS_OK(result) )
7337 *returned = 0;
7339 return result;
7342 /****************************************************************************
7343 enumports level 2.
7344 ****************************************************************************/
7346 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7348 PORT_INFO_2 *ports=NULL;
7349 int i=0;
7350 WERROR result = WERR_OK;
7352 if (*lp_enumports_cmd()) {
7353 char *cmd = lp_enumports_cmd();
7354 char *path;
7355 char **qlines;
7356 pstring tmp_file;
7357 pstring command;
7358 int numlines;
7359 int ret;
7360 int fd;
7362 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7363 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7364 else
7365 path = lp_lockdir();
7367 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7368 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7370 unlink(tmp_file);
7371 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7372 ret = smbrun(command, &fd);
7373 DEBUGADD(10,("returned [%d]\n", ret));
7374 if (ret != 0) {
7375 if (fd != -1)
7376 close(fd);
7377 /* Is this the best error to return here? */
7378 return WERR_ACCESS_DENIED;
7381 numlines = 0;
7382 qlines = fd_lines_load(fd, &numlines);
7383 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7384 close(fd);
7386 if(numlines) {
7387 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7388 file_lines_free(qlines);
7389 return WERR_NOMEM;
7392 for (i=0; i<numlines; i++) {
7393 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7394 fill_port_2(&(ports[i]), qlines[i]);
7397 file_lines_free(qlines);
7400 *returned = numlines;
7402 } else {
7404 *returned = 1;
7406 if((ports=SMB_MALLOC_P(PORT_INFO_2)) == NULL)
7407 return WERR_NOMEM;
7409 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7411 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7414 /* check the required size. */
7415 for (i=0; i<*returned; i++) {
7416 DEBUGADD(6,("adding port [%d]'s size\n", i));
7417 *needed += spoolss_size_port_info_2(&ports[i]);
7420 if (*needed > offered) {
7421 result = WERR_INSUFFICIENT_BUFFER;
7422 goto out;
7425 if (!rpcbuf_alloc_size(buffer, *needed)) {
7426 result = WERR_NOMEM;
7427 goto out;
7430 /* fill the buffer with the ports structures */
7431 for (i=0; i<*returned; i++) {
7432 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7433 smb_io_port_2("", buffer, &ports[i], 0);
7436 out:
7437 SAFE_FREE(ports);
7439 if ( !W_ERROR_IS_OK(result) )
7440 *returned = 0;
7442 return result;
7445 /****************************************************************************
7446 enumports.
7447 ****************************************************************************/
7449 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7451 uint32 level = q_u->level;
7452 RPC_BUFFER *buffer = NULL;
7453 uint32 offered = q_u->offered;
7454 uint32 *needed = &r_u->needed;
7455 uint32 *returned = &r_u->returned;
7457 /* that's an [in out] buffer */
7459 if ( q_u->buffer ) {
7460 rpcbuf_move(q_u->buffer, &r_u->buffer);
7461 buffer = r_u->buffer;
7464 DEBUG(4,("_spoolss_enumports\n"));
7466 *returned=0;
7467 *needed=0;
7469 switch (level) {
7470 case 1:
7471 return enumports_level_1(buffer, offered, needed, returned);
7472 case 2:
7473 return enumports_level_2(buffer, offered, needed, returned);
7474 default:
7475 return WERR_UNKNOWN_LEVEL;
7479 /****************************************************************************
7480 ****************************************************************************/
7482 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7483 const SPOOL_PRINTER_INFO_LEVEL *info,
7484 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7485 uint32 user_switch, const SPOOL_USER_CTR *user,
7486 POLICY_HND *handle)
7488 NT_PRINTER_INFO_LEVEL *printer = NULL;
7489 fstring name;
7490 int snum;
7491 WERROR err = WERR_OK;
7493 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7494 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7495 return WERR_NOMEM;
7498 ZERO_STRUCTP(printer);
7500 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7501 if (!convert_printer_info(info, printer, 2)) {
7502 free_a_printer(&printer, 2);
7503 return WERR_NOMEM;
7506 /* check to see if the printer already exists */
7508 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7509 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7510 printer->info_2->sharename));
7511 free_a_printer(&printer, 2);
7512 return WERR_PRINTER_ALREADY_EXISTS;
7515 /* FIXME!!! smbd should check to see if the driver is installed before
7516 trying to add a printer like this --jerry */
7518 if (*lp_addprinter_cmd() ) {
7519 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7520 free_a_printer(&printer,2);
7521 return WERR_ACCESS_DENIED;
7525 /* use our primary netbios name since get_a_printer() will convert
7526 it to what the client expects on a case by case basis */
7528 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7529 printer->info_2->sharename);
7532 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7533 free_a_printer(&printer,2);
7534 return WERR_ACCESS_DENIED;
7537 /* you must be a printer admin to add a new printer */
7538 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7539 free_a_printer(&printer,2);
7540 return WERR_ACCESS_DENIED;
7544 * Do sanity check on the requested changes for Samba.
7547 if (!check_printer_ok(printer->info_2, snum)) {
7548 free_a_printer(&printer,2);
7549 return WERR_INVALID_PARAM;
7553 * When a printer is created, the drivername bound to the printer is used
7554 * to lookup previously saved driver initialization info, which is then
7555 * bound to the new printer, simulating what happens in the Windows arch.
7558 if (!devmode)
7560 set_driver_init(printer, 2);
7562 else
7564 /* A valid devmode was included, convert and link it
7566 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7568 if (!convert_devicemode(printer->info_2->printername, devmode,
7569 &printer->info_2->devmode))
7570 return WERR_NOMEM;
7573 /* write the ASCII on disk */
7574 err = mod_a_printer(printer, 2);
7575 if (!W_ERROR_IS_OK(err)) {
7576 free_a_printer(&printer,2);
7577 return err;
7580 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7581 /* Handle open failed - remove addition. */
7582 del_a_printer(printer->info_2->sharename);
7583 free_a_printer(&printer,2);
7584 return WERR_ACCESS_DENIED;
7587 update_c_setprinter(False);
7588 free_a_printer(&printer,2);
7590 return WERR_OK;
7593 /****************************************************************************
7594 ****************************************************************************/
7596 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7598 UNISTR2 *uni_srv_name = &q_u->server_name;
7599 uint32 level = q_u->level;
7600 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7601 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7602 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7603 uint32 user_switch = q_u->user_switch;
7604 SPOOL_USER_CTR *user = &q_u->user_ctr;
7605 POLICY_HND *handle = &r_u->handle;
7607 switch (level) {
7608 case 1:
7609 /* we don't handle yet */
7610 /* but I know what to do ... */
7611 return WERR_UNKNOWN_LEVEL;
7612 case 2:
7613 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7614 devmode, sdb,
7615 user_switch, user, handle);
7616 default:
7617 return WERR_UNKNOWN_LEVEL;
7621 /****************************************************************************
7622 ****************************************************************************/
7624 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7626 uint32 level = q_u->level;
7627 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7628 WERROR err = WERR_OK;
7629 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7630 struct current_user user;
7631 fstring driver_name;
7632 uint32 version;
7634 ZERO_STRUCT(driver);
7636 get_current_user(&user, p);
7638 if (!convert_printer_driver_info(info, &driver, level)) {
7639 err = WERR_NOMEM;
7640 goto done;
7643 DEBUG(5,("Cleaning driver's information\n"));
7644 err = clean_up_driver_struct(driver, level, &user);
7645 if (!W_ERROR_IS_OK(err))
7646 goto done;
7648 DEBUG(5,("Moving driver to final destination\n"));
7649 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7650 if (W_ERROR_IS_OK(err))
7651 err = WERR_ACCESS_DENIED;
7652 goto done;
7655 if (add_a_printer_driver(driver, level)!=0) {
7656 err = WERR_ACCESS_DENIED;
7657 goto done;
7660 /* BEGIN_ADMIN_LOG */
7661 switch(level) {
7662 case 3:
7663 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->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_3->cversion),uidtoname(user.uid));
7666 break;
7667 case 6:
7668 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7669 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7670 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7671 break;
7673 /* END_ADMIN_LOG */
7676 * I think this is where he DrvUpgradePrinter() hook would be
7677 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7678 * server. Right now, we just need to send ourselves a message
7679 * to update each printer bound to this driver. --jerry
7682 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7683 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7684 driver_name));
7688 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7689 * decide if the driver init data should be deleted. The rules are:
7690 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7691 * 2) delete init data only if there is no 2k/Xp driver
7692 * 3) always delete init data
7693 * The generalized rule is always use init data from the highest order driver.
7694 * It is necessary to follow the driver install by an initialization step to
7695 * finish off this process.
7697 if (level == 3)
7698 version = driver.info_3->cversion;
7699 else if (level == 6)
7700 version = driver.info_6->version;
7701 else
7702 version = -1;
7703 switch (version) {
7705 * 9x printer driver - never delete init data
7707 case 0:
7708 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7709 driver_name));
7710 break;
7713 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7714 * there is no 2k/Xp driver init data for this driver name.
7716 case 2:
7718 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7720 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7722 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7724 if (!del_driver_init(driver_name))
7725 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7726 } else {
7728 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7730 free_a_printer_driver(driver1,3);
7731 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7732 driver_name));
7735 break;
7738 * 2k or Xp printer driver - always delete init data
7740 case 3:
7741 if (!del_driver_init(driver_name))
7742 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7743 break;
7745 default:
7746 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7747 break;
7751 done:
7752 free_a_printer_driver(driver, level);
7753 return err;
7756 /********************************************************************
7757 * spoolss_addprinterdriverex
7758 ********************************************************************/
7760 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7762 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7763 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7766 * we only support the semantics of AddPrinterDriver()
7767 * i.e. only copy files that are newer than existing ones
7770 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7771 return WERR_ACCESS_DENIED;
7773 ZERO_STRUCT(q_u_local);
7774 ZERO_STRUCT(r_u_local);
7776 /* just pass the information off to _spoolss_addprinterdriver() */
7777 q_u_local.server_name_ptr = q_u->server_name_ptr;
7778 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7779 q_u_local.level = q_u->level;
7780 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7782 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7785 /****************************************************************************
7786 ****************************************************************************/
7788 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7790 init_unistr(&info->name, name);
7793 /****************************************************************************
7794 ****************************************************************************/
7796 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7798 pstring path;
7799 pstring long_archi;
7800 fstring servername;
7801 char *pservername;
7802 const char *short_archi;
7803 DRIVER_DIRECTORY_1 *info=NULL;
7804 WERROR result = WERR_OK;
7806 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7807 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7809 /* check for beginning double '\'s and that the server
7810 long enough */
7812 pservername = servername;
7813 if ( *pservername == '\\' && strlen(servername)>2 ) {
7814 pservername += 2;
7817 if ( !is_myname_or_ipaddr( pservername ) )
7818 return WERR_INVALID_PARAM;
7820 if (!(short_archi = get_short_archi(long_archi)))
7821 return WERR_INVALID_ENVIRONMENT;
7823 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7824 return WERR_NOMEM;
7826 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7828 DEBUG(4,("printer driver directory: [%s]\n", path));
7830 fill_driverdir_1(info, path);
7832 *needed += spoolss_size_driverdir_info_1(info);
7834 if (*needed > offered) {
7835 result = WERR_INSUFFICIENT_BUFFER;
7836 goto out;
7839 if (!rpcbuf_alloc_size(buffer, *needed)) {
7840 result = WERR_NOMEM;
7841 goto out;
7844 smb_io_driverdir_1("", buffer, info, 0);
7846 out:
7847 SAFE_FREE(info);
7849 return result;
7852 /****************************************************************************
7853 ****************************************************************************/
7855 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7857 UNISTR2 *name = &q_u->name;
7858 UNISTR2 *uni_environment = &q_u->environment;
7859 uint32 level = q_u->level;
7860 RPC_BUFFER *buffer = NULL;
7861 uint32 offered = q_u->offered;
7862 uint32 *needed = &r_u->needed;
7864 /* that's an [in out] buffer */
7866 if ( q_u->buffer ) {
7867 rpcbuf_move(q_u->buffer, &r_u->buffer);
7868 buffer = r_u->buffer;
7871 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7873 *needed=0;
7875 switch(level) {
7876 case 1:
7877 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7878 default:
7879 return WERR_UNKNOWN_LEVEL;
7883 /****************************************************************************
7884 ****************************************************************************/
7886 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7888 POLICY_HND *handle = &q_u->handle;
7889 uint32 idx = q_u->index;
7890 uint32 in_value_len = q_u->valuesize;
7891 uint32 in_data_len = q_u->datasize;
7892 uint32 *out_max_value_len = &r_u->valuesize;
7893 uint16 **out_value = &r_u->value;
7894 uint32 *out_value_len = &r_u->realvaluesize;
7895 uint32 *out_type = &r_u->type;
7896 uint32 *out_max_data_len = &r_u->datasize;
7897 uint8 **data_out = &r_u->data;
7898 uint32 *out_data_len = &r_u->realdatasize;
7900 NT_PRINTER_INFO_LEVEL *printer = NULL;
7902 uint32 biggest_valuesize;
7903 uint32 biggest_datasize;
7904 uint32 data_len;
7905 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7906 int snum;
7907 WERROR result;
7908 REGISTRY_VALUE *val = NULL;
7909 NT_PRINTER_DATA *p_data;
7910 int i, key_index, num_values;
7911 int name_length;
7913 ZERO_STRUCT( printer );
7915 *out_type = 0;
7917 *out_max_data_len = 0;
7918 *data_out = NULL;
7919 *out_data_len = 0;
7921 DEBUG(5,("spoolss_enumprinterdata\n"));
7923 if (!Printer) {
7924 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7925 return WERR_BADFID;
7928 if (!get_printer_snum(p,handle, &snum))
7929 return WERR_BADFID;
7931 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7932 if (!W_ERROR_IS_OK(result))
7933 return result;
7935 p_data = &printer->info_2->data;
7936 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7938 result = WERR_OK;
7941 * The NT machine wants to know the biggest size of value and data
7943 * cf: MSDN EnumPrinterData remark section
7946 if ( !in_value_len && !in_data_len && (key_index != -1) )
7948 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7950 biggest_valuesize = 0;
7951 biggest_datasize = 0;
7953 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7955 for ( i=0; i<num_values; i++ )
7957 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7959 name_length = strlen(val->valuename);
7960 if ( strlen(val->valuename) > biggest_valuesize )
7961 biggest_valuesize = name_length;
7963 if ( val->size > biggest_datasize )
7964 biggest_datasize = val->size;
7966 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7967 biggest_datasize));
7970 /* the value is an UNICODE string but real_value_size is the length
7971 in bytes including the trailing 0 */
7973 *out_value_len = 2 * (1+biggest_valuesize);
7974 *out_data_len = biggest_datasize;
7976 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7978 goto done;
7982 * the value len is wrong in NT sp3
7983 * that's the number of bytes not the number of unicode chars
7986 if ( key_index != -1 )
7987 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7989 if ( !val )
7992 /* out_value should default to "" or else NT4 has
7993 problems unmarshalling the response */
7995 *out_max_value_len=(in_value_len/sizeof(uint16));
7997 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7999 result = WERR_NOMEM;
8000 goto done;
8003 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8005 /* the data is counted in bytes */
8007 *out_max_data_len = in_data_len;
8008 *out_data_len = in_data_len;
8010 /* only allocate when given a non-zero data_len */
8012 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8014 result = WERR_NOMEM;
8015 goto done;
8018 result = WERR_NO_MORE_ITEMS;
8020 else
8023 * the value is:
8024 * - counted in bytes in the request
8025 * - counted in UNICODE chars in the max reply
8026 * - counted in bytes in the real size
8028 * take a pause *before* coding not *during* coding
8031 /* name */
8032 *out_max_value_len=(in_value_len/sizeof(uint16));
8033 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8035 result = WERR_NOMEM;
8036 goto done;
8039 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
8041 /* type */
8043 *out_type = regval_type( val );
8045 /* data - counted in bytes */
8047 *out_max_data_len = in_data_len;
8048 if ( (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8050 result = WERR_NOMEM;
8051 goto done;
8053 data_len = (size_t)regval_size(val);
8054 memcpy( *data_out, regval_data_p(val), data_len );
8055 *out_data_len = data_len;
8058 done:
8059 free_a_printer(&printer, 2);
8060 return result;
8063 /****************************************************************************
8064 ****************************************************************************/
8066 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8068 POLICY_HND *handle = &q_u->handle;
8069 UNISTR2 *value = &q_u->value;
8070 uint32 type = q_u->type;
8071 uint8 *data = q_u->data;
8072 uint32 real_len = q_u->real_len;
8074 NT_PRINTER_INFO_LEVEL *printer = NULL;
8075 int snum=0;
8076 WERROR status = WERR_OK;
8077 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8078 fstring valuename;
8080 DEBUG(5,("spoolss_setprinterdata\n"));
8082 if (!Printer) {
8083 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8084 return WERR_BADFID;
8087 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8088 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8089 return WERR_INVALID_PARAM;
8092 if (!get_printer_snum(p,handle, &snum))
8093 return WERR_BADFID;
8096 * Access check : NT returns "access denied" if you make a
8097 * SetPrinterData call without the necessary privildge.
8098 * we were originally returning OK if nothing changed
8099 * which made Win2k issue **a lot** of SetPrinterData
8100 * when connecting to a printer --jerry
8103 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8105 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8106 status = WERR_ACCESS_DENIED;
8107 goto done;
8110 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8111 if (!W_ERROR_IS_OK(status))
8112 return status;
8114 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8117 * When client side code sets a magic printer data key, detect it and save
8118 * the current printer data and the magic key's data (its the DEVMODE) for
8119 * future printer/driver initializations.
8121 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8123 /* Set devmode and printer initialization info */
8124 status = save_driver_init( printer, 2, data, real_len );
8126 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8128 else
8130 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8131 type, data, real_len );
8132 if ( W_ERROR_IS_OK(status) )
8133 status = mod_a_printer(printer, 2);
8136 done:
8137 free_a_printer(&printer, 2);
8139 return status;
8142 /****************************************************************************
8143 ****************************************************************************/
8145 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8147 POLICY_HND *handle = &q_u->handle;
8148 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8149 int snum;
8151 DEBUG(5,("_spoolss_resetprinter\n"));
8154 * All we do is to check to see if the handle and queue is valid.
8155 * This call really doesn't mean anything to us because we only
8156 * support RAW printing. --jerry
8159 if (!Printer) {
8160 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8161 return WERR_BADFID;
8164 if (!get_printer_snum(p,handle, &snum))
8165 return WERR_BADFID;
8168 /* blindly return success */
8169 return WERR_OK;
8173 /****************************************************************************
8174 ****************************************************************************/
8176 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8178 POLICY_HND *handle = &q_u->handle;
8179 UNISTR2 *value = &q_u->valuename;
8181 NT_PRINTER_INFO_LEVEL *printer = NULL;
8182 int snum=0;
8183 WERROR status = WERR_OK;
8184 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8185 pstring valuename;
8187 DEBUG(5,("spoolss_deleteprinterdata\n"));
8189 if (!Printer) {
8190 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8191 return WERR_BADFID;
8194 if (!get_printer_snum(p, handle, &snum))
8195 return WERR_BADFID;
8197 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8198 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8199 return WERR_ACCESS_DENIED;
8202 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8203 if (!W_ERROR_IS_OK(status))
8204 return status;
8206 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8208 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8210 if ( W_ERROR_IS_OK(status) )
8211 mod_a_printer( printer, 2 );
8213 free_a_printer(&printer, 2);
8215 return status;
8218 /****************************************************************************
8219 ****************************************************************************/
8221 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8223 POLICY_HND *handle = &q_u->handle;
8224 FORM *form = &q_u->form;
8225 nt_forms_struct tmpForm;
8226 int snum;
8227 WERROR status = WERR_OK;
8228 NT_PRINTER_INFO_LEVEL *printer = NULL;
8230 int count=0;
8231 nt_forms_struct *list=NULL;
8232 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8234 DEBUG(5,("spoolss_addform\n"));
8236 if (!Printer) {
8237 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8238 return WERR_BADFID;
8242 /* forms can be added on printer of on the print server handle */
8244 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8246 if (!get_printer_snum(p,handle, &snum))
8247 return WERR_BADFID;
8249 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8250 if (!W_ERROR_IS_OK(status))
8251 goto done;
8254 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8255 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8256 status = WERR_ACCESS_DENIED;
8257 goto done;
8260 /* can't add if builtin */
8262 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8263 status = WERR_ALREADY_EXISTS;
8264 goto done;
8267 count = get_ntforms(&list);
8269 if(!add_a_form(&list, form, &count)) {
8270 status = WERR_NOMEM;
8271 goto done;
8274 write_ntforms(&list, count);
8277 * ChangeID must always be set if this is a printer
8280 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8281 status = mod_a_printer(printer, 2);
8283 done:
8284 if ( printer )
8285 free_a_printer(&printer, 2);
8286 SAFE_FREE(list);
8288 return status;
8291 /****************************************************************************
8292 ****************************************************************************/
8294 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8296 POLICY_HND *handle = &q_u->handle;
8297 UNISTR2 *form_name = &q_u->name;
8298 nt_forms_struct tmpForm;
8299 int count=0;
8300 nt_forms_struct *list=NULL;
8301 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8302 int snum;
8303 WERROR status = WERR_OK;
8304 NT_PRINTER_INFO_LEVEL *printer = NULL;
8306 DEBUG(5,("spoolss_deleteform\n"));
8308 if (!Printer) {
8309 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8310 return WERR_BADFID;
8313 /* forms can be deleted on printer of on the print server handle */
8315 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8317 if (!get_printer_snum(p,handle, &snum))
8318 return WERR_BADFID;
8320 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8321 if (!W_ERROR_IS_OK(status))
8322 goto done;
8325 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8326 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8327 status = WERR_ACCESS_DENIED;
8328 goto done;
8331 /* can't delete if builtin */
8333 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8334 status = WERR_INVALID_PARAM;
8335 goto done;
8338 count = get_ntforms(&list);
8340 if ( !delete_a_form(&list, form_name, &count, &status ))
8341 goto done;
8344 * ChangeID must always be set if this is a printer
8347 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8348 status = mod_a_printer(printer, 2);
8350 done:
8351 if ( printer )
8352 free_a_printer(&printer, 2);
8353 SAFE_FREE(list);
8355 return status;
8358 /****************************************************************************
8359 ****************************************************************************/
8361 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8363 POLICY_HND *handle = &q_u->handle;
8364 FORM *form = &q_u->form;
8365 nt_forms_struct tmpForm;
8366 int snum;
8367 WERROR status = WERR_OK;
8368 NT_PRINTER_INFO_LEVEL *printer = NULL;
8370 int count=0;
8371 nt_forms_struct *list=NULL;
8372 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8374 DEBUG(5,("spoolss_setform\n"));
8376 if (!Printer) {
8377 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8378 return WERR_BADFID;
8381 /* forms can be modified on printer of on the print server handle */
8383 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8385 if (!get_printer_snum(p,handle, &snum))
8386 return WERR_BADFID;
8388 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8389 if (!W_ERROR_IS_OK(status))
8390 goto done;
8393 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8394 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8395 status = WERR_ACCESS_DENIED;
8396 goto done;
8399 /* can't set if builtin */
8400 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8401 status = WERR_INVALID_PARAM;
8402 goto done;
8405 count = get_ntforms(&list);
8406 update_a_form(&list, form, count);
8407 write_ntforms(&list, count);
8410 * ChangeID must always be set if this is a printer
8413 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8414 status = mod_a_printer(printer, 2);
8417 done:
8418 if ( printer )
8419 free_a_printer(&printer, 2);
8420 SAFE_FREE(list);
8422 return status;
8425 /****************************************************************************
8426 enumprintprocessors level 1.
8427 ****************************************************************************/
8429 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8431 PRINTPROCESSOR_1 *info_1=NULL;
8432 WERROR result = WERR_OK;
8434 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8435 return WERR_NOMEM;
8437 (*returned) = 0x1;
8439 init_unistr(&info_1->name, "winprint");
8441 *needed += spoolss_size_printprocessor_info_1(info_1);
8443 if (*needed > offered) {
8444 result = WERR_INSUFFICIENT_BUFFER;
8445 goto out;
8448 if (!rpcbuf_alloc_size(buffer, *needed)) {
8449 result = WERR_NOMEM;
8450 goto out;
8453 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8455 out:
8456 SAFE_FREE(info_1);
8458 if ( !W_ERROR_IS_OK(result) )
8459 *returned = 0;
8461 return result;
8464 /****************************************************************************
8465 ****************************************************************************/
8467 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8469 uint32 level = q_u->level;
8470 RPC_BUFFER *buffer = NULL;
8471 uint32 offered = q_u->offered;
8472 uint32 *needed = &r_u->needed;
8473 uint32 *returned = &r_u->returned;
8475 /* that's an [in out] buffer */
8477 if ( q_u->buffer ) {
8478 rpcbuf_move(q_u->buffer, &r_u->buffer);
8479 buffer = r_u->buffer;
8482 DEBUG(5,("spoolss_enumprintprocessors\n"));
8485 * Enumerate the print processors ...
8487 * Just reply with "winprint", to keep NT happy
8488 * and I can use my nice printer checker.
8491 *returned=0;
8492 *needed=0;
8494 switch (level) {
8495 case 1:
8496 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8497 default:
8498 return WERR_UNKNOWN_LEVEL;
8502 /****************************************************************************
8503 enumprintprocdatatypes level 1.
8504 ****************************************************************************/
8506 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8508 PRINTPROCDATATYPE_1 *info_1=NULL;
8509 WERROR result = WERR_NOMEM;
8511 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8512 return WERR_NOMEM;
8514 (*returned) = 0x1;
8516 init_unistr(&info_1->name, "RAW");
8518 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8520 if (*needed > offered) {
8521 result = WERR_INSUFFICIENT_BUFFER;
8522 goto out;
8525 if (!rpcbuf_alloc_size(buffer, *needed)) {
8526 result = WERR_NOMEM;
8527 goto out;
8530 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8532 out:
8533 SAFE_FREE(info_1);
8535 if ( !W_ERROR_IS_OK(result) )
8536 *returned = 0;
8538 return result;
8541 /****************************************************************************
8542 ****************************************************************************/
8544 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8546 uint32 level = q_u->level;
8547 RPC_BUFFER *buffer = NULL;
8548 uint32 offered = q_u->offered;
8549 uint32 *needed = &r_u->needed;
8550 uint32 *returned = &r_u->returned;
8552 /* that's an [in out] buffer */
8554 if ( q_u->buffer ) {
8555 rpcbuf_move(q_u->buffer, &r_u->buffer);
8556 buffer = r_u->buffer;
8559 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8561 *returned=0;
8562 *needed=0;
8564 switch (level) {
8565 case 1:
8566 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8567 default:
8568 return WERR_UNKNOWN_LEVEL;
8572 /****************************************************************************
8573 enumprintmonitors level 1.
8574 ****************************************************************************/
8576 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8578 PRINTMONITOR_1 *info_1=NULL;
8579 WERROR result = WERR_OK;
8581 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8582 return WERR_NOMEM;
8584 (*returned) = 0x1;
8586 init_unistr(&info_1->name, "Local Port");
8588 *needed += spoolss_size_printmonitor_info_1(info_1);
8590 if (*needed > offered) {
8591 result = WERR_INSUFFICIENT_BUFFER;
8592 goto out;
8595 if (!rpcbuf_alloc_size(buffer, *needed)) {
8596 result = WERR_NOMEM;
8597 goto out;
8600 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8602 out:
8603 SAFE_FREE(info_1);
8605 if ( !W_ERROR_IS_OK(result) )
8606 *returned = 0;
8608 return result;
8611 /****************************************************************************
8612 enumprintmonitors level 2.
8613 ****************************************************************************/
8615 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8617 PRINTMONITOR_2 *info_2=NULL;
8618 WERROR result = WERR_OK;
8620 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8621 return WERR_NOMEM;
8623 (*returned) = 0x1;
8625 init_unistr(&info_2->name, "Local Port");
8626 init_unistr(&info_2->environment, "Windows NT X86");
8627 init_unistr(&info_2->dll_name, "localmon.dll");
8629 *needed += spoolss_size_printmonitor_info_2(info_2);
8631 if (*needed > offered) {
8632 result = WERR_INSUFFICIENT_BUFFER;
8633 goto out;
8636 if (!rpcbuf_alloc_size(buffer, *needed)) {
8637 result = WERR_NOMEM;
8638 goto out;
8641 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8643 out:
8644 SAFE_FREE(info_2);
8646 if ( !W_ERROR_IS_OK(result) )
8647 *returned = 0;
8649 return result;
8652 /****************************************************************************
8653 ****************************************************************************/
8655 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8657 uint32 level = q_u->level;
8658 RPC_BUFFER *buffer = NULL;
8659 uint32 offered = q_u->offered;
8660 uint32 *needed = &r_u->needed;
8661 uint32 *returned = &r_u->returned;
8663 /* that's an [in out] buffer */
8665 if ( q_u->buffer ) {
8666 rpcbuf_move(q_u->buffer, &r_u->buffer);
8667 buffer = r_u->buffer;
8670 DEBUG(5,("spoolss_enumprintmonitors\n"));
8673 * Enumerate the print monitors ...
8675 * Just reply with "Local Port", to keep NT happy
8676 * and I can use my nice printer checker.
8679 *returned=0;
8680 *needed=0;
8682 switch (level) {
8683 case 1:
8684 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8685 case 2:
8686 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8687 default:
8688 return WERR_UNKNOWN_LEVEL;
8692 /****************************************************************************
8693 ****************************************************************************/
8695 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8696 NT_PRINTER_INFO_LEVEL *ntprinter,
8697 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8698 uint32 *needed)
8700 int i=0;
8701 BOOL found=False;
8702 JOB_INFO_1 *info_1=NULL;
8703 WERROR result = WERR_OK;
8705 info_1=SMB_MALLOC_P(JOB_INFO_1);
8707 if (info_1 == NULL) {
8708 return WERR_NOMEM;
8711 for (i=0; i<count && found==False; i++) {
8712 if ((*queue)[i].job==(int)jobid)
8713 found=True;
8716 if (found==False) {
8717 SAFE_FREE(info_1);
8718 /* NT treats not found as bad param... yet another bad choice */
8719 return WERR_INVALID_PARAM;
8722 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8724 *needed += spoolss_size_job_info_1(info_1);
8726 if (*needed > offered) {
8727 result = WERR_INSUFFICIENT_BUFFER;
8728 goto out;
8731 if (!rpcbuf_alloc_size(buffer, *needed)) {
8732 result = WERR_NOMEM;
8733 goto out;
8736 smb_io_job_info_1("", buffer, info_1, 0);
8738 out:
8739 SAFE_FREE(info_1);
8741 return result;
8744 /****************************************************************************
8745 ****************************************************************************/
8747 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8748 NT_PRINTER_INFO_LEVEL *ntprinter,
8749 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8750 uint32 *needed)
8752 int i = 0;
8753 BOOL found = False;
8754 JOB_INFO_2 *info_2;
8755 WERROR result;
8756 DEVICEMODE *devmode = NULL;
8757 NT_DEVICEMODE *nt_devmode = NULL;
8759 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8760 return WERR_NOMEM;
8762 ZERO_STRUCTP(info_2);
8764 for ( i=0; i<count && found==False; i++ )
8766 if ((*queue)[i].job == (int)jobid)
8767 found = True;
8770 if ( !found ) {
8771 /* NT treats not found as bad param... yet another bad
8772 choice */
8773 result = WERR_INVALID_PARAM;
8774 goto done;
8778 * if the print job does not have a DEVMODE associated with it,
8779 * just use the one for the printer. A NULL devicemode is not
8780 * a failure condition
8783 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8784 devmode = construct_dev_mode(snum);
8785 else {
8786 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8787 ZERO_STRUCTP( devmode );
8788 convert_nt_devicemode( devmode, nt_devmode );
8792 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8794 *needed += spoolss_size_job_info_2(info_2);
8796 if (*needed > offered) {
8797 result = WERR_INSUFFICIENT_BUFFER;
8798 goto done;
8801 if (!rpcbuf_alloc_size(buffer, *needed)) {
8802 result = WERR_NOMEM;
8803 goto done;
8806 smb_io_job_info_2("", buffer, info_2, 0);
8808 result = WERR_OK;
8810 done:
8811 /* Cleanup allocated memory */
8813 free_job_info_2(info_2); /* Also frees devmode */
8814 SAFE_FREE(info_2);
8816 return result;
8819 /****************************************************************************
8820 ****************************************************************************/
8822 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8824 POLICY_HND *handle = &q_u->handle;
8825 uint32 jobid = q_u->jobid;
8826 uint32 level = q_u->level;
8827 RPC_BUFFER *buffer = NULL;
8828 uint32 offered = q_u->offered;
8829 uint32 *needed = &r_u->needed;
8830 WERROR wstatus = WERR_OK;
8831 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8832 int snum;
8833 int count;
8834 print_queue_struct *queue = NULL;
8835 print_status_struct prt_status;
8837 /* that's an [in out] buffer */
8839 if ( q_u->buffer ) {
8840 rpcbuf_move(q_u->buffer, &r_u->buffer);
8841 buffer = r_u->buffer;
8844 DEBUG(5,("spoolss_getjob\n"));
8846 *needed = 0;
8848 if (!get_printer_snum(p, handle, &snum))
8849 return WERR_BADFID;
8851 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8852 if ( !W_ERROR_IS_OK(wstatus) )
8853 return wstatus;
8855 count = print_queue_status(snum, &queue, &prt_status);
8857 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8858 count, prt_status.status, prt_status.message));
8860 switch ( level ) {
8861 case 1:
8862 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8863 buffer, offered, needed);
8864 break;
8865 case 2:
8866 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8867 buffer, offered, needed);
8868 break;
8869 default:
8870 wstatus = WERR_UNKNOWN_LEVEL;
8871 break;
8874 SAFE_FREE(queue);
8875 free_a_printer( &ntprinter, 2 );
8877 return wstatus;
8880 /********************************************************************
8881 spoolss_getprinterdataex
8883 From MSDN documentation of GetPrinterDataEx: pass request
8884 to GetPrinterData if key is "PrinterDriverData".
8885 ********************************************************************/
8887 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8889 POLICY_HND *handle = &q_u->handle;
8890 uint32 in_size = q_u->size;
8891 uint32 *type = &r_u->type;
8892 uint32 *out_size = &r_u->size;
8893 uint8 **data = &r_u->data;
8894 uint32 *needed = &r_u->needed;
8895 fstring keyname, valuename;
8897 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8899 NT_PRINTER_INFO_LEVEL *printer = NULL;
8900 int snum = 0;
8901 WERROR status = WERR_OK;
8903 DEBUG(4,("_spoolss_getprinterdataex\n"));
8905 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8906 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8908 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8909 keyname, valuename));
8911 /* in case of problem, return some default values */
8913 *needed = 0;
8914 *type = 0;
8915 *out_size = in_size;
8917 if (!Printer) {
8918 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8919 status = WERR_BADFID;
8920 goto done;
8923 /* Is the handle to a printer or to the server? */
8925 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8926 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8927 status = WERR_INVALID_PARAM;
8928 goto done;
8931 if ( !get_printer_snum(p,handle, &snum) )
8932 return WERR_BADFID;
8934 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8935 if ( !W_ERROR_IS_OK(status) )
8936 goto done;
8938 /* check to see if the keyname is valid */
8939 if ( !strlen(keyname) ) {
8940 status = WERR_INVALID_PARAM;
8941 goto done;
8944 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8945 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8946 free_a_printer( &printer, 2 );
8947 status = WERR_BADFILE;
8948 goto done;
8951 /* When given a new keyname, we should just create it */
8953 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8955 if (*needed > *out_size)
8956 status = WERR_MORE_DATA;
8958 done:
8959 if ( !W_ERROR_IS_OK(status) )
8961 DEBUG(5, ("error: allocating %d\n", *out_size));
8963 /* reply this param doesn't exist */
8965 if ( *out_size )
8967 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8968 status = WERR_NOMEM;
8969 goto done;
8972 else {
8973 *data = NULL;
8977 if ( printer )
8978 free_a_printer( &printer, 2 );
8980 return status;
8983 /********************************************************************
8984 * spoolss_setprinterdataex
8985 ********************************************************************/
8987 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8989 POLICY_HND *handle = &q_u->handle;
8990 uint32 type = q_u->type;
8991 uint8 *data = q_u->data;
8992 uint32 real_len = q_u->real_len;
8994 NT_PRINTER_INFO_LEVEL *printer = NULL;
8995 int snum = 0;
8996 WERROR status = WERR_OK;
8997 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8998 fstring valuename;
8999 fstring keyname;
9000 char *oid_string;
9002 DEBUG(4,("_spoolss_setprinterdataex\n"));
9004 /* From MSDN documentation of SetPrinterDataEx: pass request to
9005 SetPrinterData if key is "PrinterDriverData" */
9007 if (!Printer) {
9008 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9009 return WERR_BADFID;
9012 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
9013 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9014 return WERR_INVALID_PARAM;
9017 if ( !get_printer_snum(p,handle, &snum) )
9018 return WERR_BADFID;
9021 * Access check : NT returns "access denied" if you make a
9022 * SetPrinterData call without the necessary privildge.
9023 * we were originally returning OK if nothing changed
9024 * which made Win2k issue **a lot** of SetPrinterData
9025 * when connecting to a printer --jerry
9028 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9030 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9031 return WERR_ACCESS_DENIED;
9034 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9035 if (!W_ERROR_IS_OK(status))
9036 return status;
9038 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9039 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9041 /* check for OID in valuename */
9043 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9045 *oid_string = '\0';
9046 oid_string++;
9049 /* save the registry data */
9051 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9053 if ( W_ERROR_IS_OK(status) )
9055 /* save the OID if one was specified */
9056 if ( oid_string ) {
9057 fstrcat( keyname, "\\" );
9058 fstrcat( keyname, SPOOL_OID_KEY );
9061 * I'm not checking the status here on purpose. Don't know
9062 * if this is right, but I'm returning the status from the
9063 * previous set_printer_dataex() call. I have no idea if
9064 * this is right. --jerry
9067 set_printer_dataex( printer, keyname, valuename,
9068 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9071 status = mod_a_printer(printer, 2);
9074 free_a_printer(&printer, 2);
9076 return status;
9080 /********************************************************************
9081 * spoolss_deleteprinterdataex
9082 ********************************************************************/
9084 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9086 POLICY_HND *handle = &q_u->handle;
9087 UNISTR2 *value = &q_u->valuename;
9088 UNISTR2 *key = &q_u->keyname;
9090 NT_PRINTER_INFO_LEVEL *printer = NULL;
9091 int snum=0;
9092 WERROR status = WERR_OK;
9093 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9094 pstring valuename, keyname;
9096 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9098 if (!Printer) {
9099 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9100 return WERR_BADFID;
9103 if (!get_printer_snum(p, handle, &snum))
9104 return WERR_BADFID;
9106 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9107 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9108 return WERR_ACCESS_DENIED;
9111 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9112 if (!W_ERROR_IS_OK(status))
9113 return status;
9115 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9116 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9118 status = delete_printer_dataex( printer, keyname, valuename );
9120 if ( W_ERROR_IS_OK(status) )
9121 mod_a_printer( printer, 2 );
9123 free_a_printer(&printer, 2);
9125 return status;
9128 /********************************************************************
9129 * spoolss_enumprinterkey
9130 ********************************************************************/
9133 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9135 fstring key;
9136 fstring *keynames = NULL;
9137 uint16 *enumkeys = NULL;
9138 int num_keys;
9139 int printerkey_len;
9140 POLICY_HND *handle = &q_u->handle;
9141 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9142 NT_PRINTER_DATA *data;
9143 NT_PRINTER_INFO_LEVEL *printer = NULL;
9144 int snum = 0;
9145 WERROR status = WERR_BADFILE;
9148 DEBUG(4,("_spoolss_enumprinterkey\n"));
9150 if (!Printer) {
9151 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9152 return WERR_BADFID;
9155 if ( !get_printer_snum(p,handle, &snum) )
9156 return WERR_BADFID;
9158 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9159 if (!W_ERROR_IS_OK(status))
9160 return status;
9162 /* get the list of subkey names */
9164 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9165 data = &printer->info_2->data;
9167 num_keys = get_printer_subkeys( data, key, &keynames );
9169 if ( num_keys == -1 ) {
9170 status = WERR_BADFILE;
9171 goto done;
9174 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9176 r_u->needed = printerkey_len*2;
9178 if ( q_u->size < r_u->needed ) {
9179 status = WERR_MORE_DATA;
9180 goto done;
9183 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9184 status = WERR_NOMEM;
9185 goto done;
9188 status = WERR_OK;
9190 if ( q_u->size < r_u->needed )
9191 status = WERR_MORE_DATA;
9193 done:
9194 free_a_printer( &printer, 2 );
9195 SAFE_FREE( keynames );
9197 return status;
9200 /********************************************************************
9201 * spoolss_deleteprinterkey
9202 ********************************************************************/
9204 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9206 POLICY_HND *handle = &q_u->handle;
9207 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9208 fstring key;
9209 NT_PRINTER_INFO_LEVEL *printer = NULL;
9210 int snum=0;
9211 WERROR status;
9213 DEBUG(5,("spoolss_deleteprinterkey\n"));
9215 if (!Printer) {
9216 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9217 return WERR_BADFID;
9220 /* if keyname == NULL, return error */
9222 if ( !q_u->keyname.buffer )
9223 return WERR_INVALID_PARAM;
9225 if (!get_printer_snum(p, handle, &snum))
9226 return WERR_BADFID;
9228 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9229 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9230 return WERR_ACCESS_DENIED;
9233 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9234 if (!W_ERROR_IS_OK(status))
9235 return status;
9237 /* delete the key and all subneys */
9239 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9241 status = delete_all_printer_data( printer->info_2, key );
9243 if ( W_ERROR_IS_OK(status) )
9244 status = mod_a_printer(printer, 2);
9246 free_a_printer( &printer, 2 );
9248 return status;
9252 /********************************************************************
9253 * spoolss_enumprinterdataex
9254 ********************************************************************/
9256 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9258 POLICY_HND *handle = &q_u->handle;
9259 uint32 in_size = q_u->size;
9260 uint32 num_entries,
9261 needed;
9262 NT_PRINTER_INFO_LEVEL *printer = NULL;
9263 PRINTER_ENUM_VALUES *enum_values = NULL;
9264 NT_PRINTER_DATA *p_data;
9265 fstring key;
9266 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9267 int snum;
9268 WERROR result;
9269 int key_index;
9270 int i;
9271 REGISTRY_VALUE *val;
9272 char *value_name;
9273 int data_len;
9276 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9278 if (!Printer) {
9279 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9280 return WERR_BADFID;
9284 * first check for a keyname of NULL or "". Win2k seems to send
9285 * this a lot and we should send back WERR_INVALID_PARAM
9286 * no need to spend time looking up the printer in this case.
9287 * --jerry
9290 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9291 if ( !strlen(key) ) {
9292 result = WERR_INVALID_PARAM;
9293 goto done;
9296 /* get the printer off of disk */
9298 if (!get_printer_snum(p,handle, &snum))
9299 return WERR_BADFID;
9301 ZERO_STRUCT(printer);
9302 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9303 if (!W_ERROR_IS_OK(result))
9304 return result;
9306 /* now look for a match on the key name */
9308 p_data = &printer->info_2->data;
9310 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9311 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9313 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9314 result = WERR_INVALID_PARAM;
9315 goto done;
9318 result = WERR_OK;
9319 needed = 0;
9321 /* allocate the memory for the array of pointers -- if necessary */
9323 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9324 if ( num_entries )
9326 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9328 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9329 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9330 result = WERR_NOMEM;
9331 goto done;
9334 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9338 * loop through all params and build the array to pass
9339 * back to the client
9342 for ( i=0; i<num_entries; i++ )
9344 /* lookup the registry value */
9346 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9347 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9349 /* copy the data */
9351 value_name = regval_name( val );
9352 init_unistr( &enum_values[i].valuename, value_name );
9353 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9354 enum_values[i].type = regval_type( val );
9356 data_len = regval_size( val );
9357 if ( data_len ) {
9358 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9360 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9361 data_len ));
9362 result = WERR_NOMEM;
9363 goto done;
9366 enum_values[i].data_len = data_len;
9368 /* keep track of the size of the array in bytes */
9370 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9373 /* housekeeping information in the reply */
9375 r_u->needed = needed;
9376 r_u->returned = num_entries;
9378 if (needed > in_size) {
9379 result = WERR_MORE_DATA;
9380 goto done;
9383 /* copy data into the reply */
9385 r_u->ctr.size = r_u->needed;
9386 r_u->ctr.size_of_array = r_u->returned;
9387 r_u->ctr.values = enum_values;
9391 done:
9392 if ( printer )
9393 free_a_printer(&printer, 2);
9395 return result;
9398 /****************************************************************************
9399 ****************************************************************************/
9401 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9403 init_unistr(&info->name, name);
9406 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9407 UNISTR2 *environment,
9408 RPC_BUFFER *buffer,
9409 uint32 offered,
9410 uint32 *needed)
9412 pstring path;
9413 pstring long_archi;
9414 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9415 WERROR result = WERR_OK;
9417 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9419 if (!get_short_archi(long_archi))
9420 return WERR_INVALID_ENVIRONMENT;
9422 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9423 return WERR_NOMEM;
9425 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9427 fill_printprocessordirectory_1(info, path);
9429 *needed += spoolss_size_printprocessordirectory_info_1(info);
9431 if (*needed > offered) {
9432 result = WERR_INSUFFICIENT_BUFFER;
9433 goto out;
9436 if (!rpcbuf_alloc_size(buffer, *needed)) {
9437 result = WERR_INSUFFICIENT_BUFFER;
9438 goto out;
9441 smb_io_printprocessordirectory_1("", buffer, info, 0);
9443 out:
9444 SAFE_FREE(info);
9446 return result;
9449 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9451 uint32 level = q_u->level;
9452 RPC_BUFFER *buffer = NULL;
9453 uint32 offered = q_u->offered;
9454 uint32 *needed = &r_u->needed;
9455 WERROR result;
9457 /* that's an [in out] buffer */
9459 if ( q_u->buffer ) {
9460 rpcbuf_move(q_u->buffer, &r_u->buffer);
9461 buffer = r_u->buffer;
9464 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9466 *needed=0;
9468 switch(level) {
9469 case 1:
9470 result = getprintprocessordirectory_level_1
9471 (&q_u->name, &q_u->environment, buffer, offered, needed);
9472 break;
9473 default:
9474 result = WERR_UNKNOWN_LEVEL;
9477 return result;
9480 #if 0
9482 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9483 SPOOL_R_REPLYOPENPRINTER *r_u)
9485 DEBUG(5,("_spoolss_replyopenprinter\n"));
9487 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9489 return WERR_OK;
9492 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9493 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9495 DEBUG(5,("_spoolss_replycloseprinter\n"));
9496 return WERR_OK;
9499 #endif