r4904: sync up with 3.0 for 3.0.11pre2
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blobed7a544d72de9b7b918334aa471a195c03f4c6a0
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 Allocate more memory for a BUFFER.
649 ****************************************************************************/
651 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
653 prs_struct *ps;
654 uint32 extra_space;
655 uint32 old_offset;
657 ps= &buffer->prs;
659 /* damn, I'm doing the reverse operation of prs_grow() :) */
660 if (buffer_size < prs_data_size(ps))
661 extra_space=0;
662 else
663 extra_space = buffer_size - prs_data_size(ps);
666 * save the offset and move to the end of the buffer
667 * prs_grow() checks the extra_space against the offset
669 old_offset=prs_offset(ps);
670 prs_set_offset(ps, prs_data_size(ps));
672 if (!prs_grow(ps, extra_space))
673 return False;
675 prs_set_offset(ps, old_offset);
677 buffer->string_at_end=prs_data_size(ps);
679 return True;
682 /***************************************************************************
683 check to see if the client motify handle is monitoring the notification
684 given by (notify_type, notify_field).
685 **************************************************************************/
687 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
688 uint16 notify_field)
690 return True;
693 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
694 uint16 notify_field)
696 SPOOL_NOTIFY_OPTION *option = p->notify.option;
697 uint32 i, j;
700 * Flags should always be zero when the change notify
701 * is registered by the client's spooler. A user Win32 app
702 * might use the flags though instead of the NOTIFY_OPTION_INFO
703 * --jerry
706 if (!option) {
707 return False;
710 if (p->notify.flags)
711 return is_monitoring_event_flags(
712 p->notify.flags, notify_type, notify_field);
714 for (i = 0; i < option->count; i++) {
716 /* Check match for notify_type */
718 if (option->ctr.type[i].type != notify_type)
719 continue;
721 /* Check match for field */
723 for (j = 0; j < option->ctr.type[i].count; j++) {
724 if (option->ctr.type[i].fields[j] == notify_field) {
725 return True;
730 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
731 p->servername, p->sharename, notify_type, notify_field));
733 return False;
736 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
738 static void notify_one_value(struct spoolss_notify_msg *msg,
739 SPOOL_NOTIFY_INFO_DATA *data,
740 TALLOC_CTX *mem_ctx)
742 data->notify_data.value[0] = msg->notify.value[0];
743 data->notify_data.value[1] = 0;
746 static void notify_string(struct spoolss_notify_msg *msg,
747 SPOOL_NOTIFY_INFO_DATA *data,
748 TALLOC_CTX *mem_ctx)
750 UNISTR2 unistr;
752 /* The length of the message includes the trailing \0 */
754 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
756 data->notify_data.data.length = msg->len * 2;
757 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
759 if (!data->notify_data.data.string) {
760 data->notify_data.data.length = 0;
761 return;
764 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
767 static void notify_system_time(struct spoolss_notify_msg *msg,
768 SPOOL_NOTIFY_INFO_DATA *data,
769 TALLOC_CTX *mem_ctx)
771 SYSTEMTIME systime;
772 prs_struct ps;
774 if (msg->len != sizeof(time_t)) {
775 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
776 msg->len));
777 return;
780 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
781 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
782 return;
785 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
786 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
787 return;
790 if (!spoolss_io_system_time("", &ps, 0, &systime))
791 return;
793 data->notify_data.data.length = prs_offset(&ps);
794 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
796 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
798 prs_mem_free(&ps);
801 struct notify2_message_table {
802 const char *name;
803 void (*fn)(struct spoolss_notify_msg *msg,
804 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
807 static struct notify2_message_table printer_notify_table[] = {
808 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
809 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
810 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
811 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
812 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
813 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
814 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
815 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
816 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
817 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
818 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
819 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
820 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
821 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
822 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
823 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
824 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
825 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
826 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
829 static struct notify2_message_table job_notify_table[] = {
830 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
831 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
832 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
833 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
834 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
835 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
836 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
837 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
838 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
839 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
840 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
841 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
842 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
843 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
844 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
845 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
846 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
847 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
848 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
849 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
850 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
851 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
852 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
853 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
857 /***********************************************************************
858 Allocate talloc context for container object
859 **********************************************************************/
861 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
863 if ( !ctr )
864 return;
866 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
868 return;
871 /***********************************************************************
872 release all allocated memory and zero out structure
873 **********************************************************************/
875 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
877 if ( !ctr )
878 return;
880 if ( ctr->ctx )
881 talloc_destroy(ctr->ctx);
883 ZERO_STRUCTP(ctr);
885 return;
888 /***********************************************************************
889 **********************************************************************/
891 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
893 if ( !ctr )
894 return NULL;
896 return ctr->ctx;
899 /***********************************************************************
900 **********************************************************************/
902 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
904 if ( !ctr || !ctr->msg_groups )
905 return NULL;
907 if ( idx >= ctr->num_groups )
908 return NULL;
910 return &ctr->msg_groups[idx];
914 /***********************************************************************
915 How many groups of change messages do we have ?
916 **********************************************************************/
918 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
920 if ( !ctr )
921 return 0;
923 return ctr->num_groups;
926 /***********************************************************************
927 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
928 **********************************************************************/
930 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
932 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
933 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
934 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
935 int i, new_slot;
937 if ( !ctr || !msg )
938 return 0;
940 /* loop over all groups looking for a matching printer name */
942 for ( i=0; i<ctr->num_groups; i++ ) {
943 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
944 break;
947 /* add a new group? */
949 if ( i == ctr->num_groups ) {
950 ctr->num_groups++;
952 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
953 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
954 return 0;
956 ctr->msg_groups = groups;
958 /* clear the new entry and set the printer name */
960 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
961 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
964 /* add the change messages; 'i' is the correct index now regardless */
966 msg_grp = &ctr->msg_groups[i];
968 msg_grp->num_msgs++;
970 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
971 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
972 return 0;
974 msg_grp->msgs = msg_list;
976 new_slot = msg_grp->num_msgs-1;
977 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
979 /* need to allocate own copy of data */
981 if ( msg->len != 0 )
982 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
984 return ctr->num_groups;
987 /***********************************************************************
988 Send a change notication message on all handles which have a call
989 back registered
990 **********************************************************************/
992 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
994 Printer_entry *p;
995 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
996 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
997 SPOOLSS_NOTIFY_MSG *messages;
998 int sending_msg_count;
1000 if ( !msg_group ) {
1001 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1002 return;
1005 messages = msg_group->msgs;
1007 if ( !messages ) {
1008 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
1009 return;
1012 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1014 /* loop over all printers */
1016 for (p = printers_list; p; p = p->next) {
1017 SPOOL_NOTIFY_INFO_DATA *data;
1018 uint32 data_len = 0;
1019 uint32 id;
1020 int i;
1022 /* Is there notification on this handle? */
1024 if ( !p->notify.client_connected )
1025 continue;
1027 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
1029 /* For this printer? Print servers always receive
1030 notifications. */
1032 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
1033 ( !strequal(msg_group->printername, p->sharename) ) )
1034 continue;
1036 DEBUG(10,("Our printer\n"));
1038 /* allocate the max entries possible */
1040 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
1041 ZERO_STRUCTP(data);
1043 /* build the array of change notifications */
1045 sending_msg_count = 0;
1047 for ( i=0; i<msg_group->num_msgs; i++ ) {
1048 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1050 /* Are we monitoring this event? */
1052 if (!is_monitoring_event(p, msg->type, msg->field))
1053 continue;
1055 sending_msg_count++;
1058 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1059 msg->type, msg->field, p->sharename));
1062 * if the is a printer notification handle and not a job notification
1063 * type, then set the id to 0. Other wise just use what was specified
1064 * in the message.
1066 * When registering change notification on a print server handle
1067 * we always need to send back the id (snum) matching the printer
1068 * for which the change took place. For change notify registered
1069 * on a printer handle, this does not matter and the id should be 0.
1071 * --jerry
1074 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1075 id = 0;
1076 else
1077 id = msg->id;
1080 /* Convert unix jobid to smb jobid */
1082 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1083 id = sysjob_to_jobid(msg->id);
1085 if (id == -1) {
1086 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1087 goto done;
1091 construct_info_data( &data[data_len], msg->type, msg->field, id );
1093 switch(msg->type) {
1094 case PRINTER_NOTIFY_TYPE:
1095 if ( printer_notify_table[msg->field].fn )
1096 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1097 break;
1099 case JOB_NOTIFY_TYPE:
1100 if ( job_notify_table[msg->field].fn )
1101 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1102 break;
1104 default:
1105 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1106 goto done;
1109 data_len++;
1112 if ( sending_msg_count ) {
1113 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
1114 data_len, data, p->notify.change, 0 );
1118 done:
1119 DEBUG(8,("send_notify2_changes: Exit...\n"));
1120 return;
1123 /***********************************************************************
1124 **********************************************************************/
1126 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1129 uint32 tv_sec, tv_usec;
1130 size_t offset = 0;
1132 /* Unpack message */
1134 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1135 msg->printer);
1137 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1138 &tv_sec, &tv_usec,
1139 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1141 if (msg->len == 0)
1142 tdb_unpack((char *)buf + offset, len - offset, "dd",
1143 &msg->notify.value[0], &msg->notify.value[1]);
1144 else
1145 tdb_unpack((char *)buf + offset, len - offset, "B",
1146 &msg->len, &msg->notify.data);
1148 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1149 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1151 tv->tv_sec = tv_sec;
1152 tv->tv_usec = tv_usec;
1154 if (msg->len == 0)
1155 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1156 msg->notify.value[1]));
1157 else
1158 dump_data(3, msg->notify.data, msg->len);
1160 return True;
1163 /********************************************************************
1164 Receive a notify2 message list
1165 ********************************************************************/
1167 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1169 size_t msg_count, i;
1170 char *buf = (char *)msg;
1171 char *msg_ptr;
1172 size_t msg_len;
1173 SPOOLSS_NOTIFY_MSG notify;
1174 SPOOLSS_NOTIFY_MSG_CTR messages;
1175 int num_groups;
1177 if (len < 4) {
1178 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1179 return;
1182 msg_count = IVAL(buf, 0);
1183 msg_ptr = buf + 4;
1185 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1187 if (msg_count == 0) {
1188 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1189 return;
1192 /* initialize the container */
1194 ZERO_STRUCT( messages );
1195 notify_msg_ctr_init( &messages );
1198 * build message groups for each printer identified
1199 * in a change_notify msg. Remember that a PCN message
1200 * includes the handle returned for the srv_spoolss_replyopenprinter()
1201 * call. Therefore messages are grouped according to printer handle.
1204 for ( i=0; i<msg_count; i++ ) {
1205 struct timeval msg_tv;
1207 if (msg_ptr + 4 - buf > len) {
1208 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1209 return;
1212 msg_len = IVAL(msg_ptr,0);
1213 msg_ptr += 4;
1215 if (msg_ptr + msg_len - buf > len) {
1216 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1217 return;
1220 /* unpack messages */
1222 ZERO_STRUCT( notify );
1223 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1224 msg_ptr += msg_len;
1226 /* add to correct list in container */
1228 notify_msg_ctr_addmsg( &messages, &notify );
1230 /* free memory that might have been allocated by notify2_unpack_msg() */
1232 if ( notify.len != 0 )
1233 SAFE_FREE( notify.notify.data );
1236 /* process each group of messages */
1238 num_groups = notify_msg_ctr_numgroups( &messages );
1239 for ( i=0; i<num_groups; i++ )
1240 send_notify2_changes( &messages, i );
1243 /* cleanup */
1245 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1247 notify_msg_ctr_destroy( &messages );
1249 return;
1252 /********************************************************************
1253 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1254 one smbd, all of processes must clear their printer cache immediately.
1255 ********************************************************************/
1257 void receive_printer_mod_msg(int msg_type, pid_t src, void *buf, size_t len)
1259 fstring printername;
1261 fstrcpy( printername, buf );
1263 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername ));
1265 invalidate_printer_hnd_cache( printername );
1268 /********************************************************************
1269 Send a message to ourself about new driver being installed
1270 so we can upgrade the information for each printer bound to this
1271 driver
1272 ********************************************************************/
1274 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1276 int len = strlen(drivername);
1278 if (!len)
1279 return False;
1281 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1282 drivername));
1284 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1286 return True;
1289 /**********************************************************************
1290 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1291 over all printers, upgrading ones as necessary
1292 **********************************************************************/
1294 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1296 fstring drivername;
1297 int snum;
1298 int n_services = lp_numservices();
1300 len = MIN(len,sizeof(drivername)-1);
1301 strncpy(drivername, buf, len);
1303 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1305 /* Iterate the printer list */
1307 for (snum=0; snum<n_services; snum++)
1309 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1311 WERROR result;
1312 NT_PRINTER_INFO_LEVEL *printer = NULL;
1314 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1315 if (!W_ERROR_IS_OK(result))
1316 continue;
1318 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1320 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1322 /* all we care about currently is the change_id */
1324 result = mod_a_printer(printer, 2);
1325 if (!W_ERROR_IS_OK(result)) {
1326 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1327 dos_errstr(result)));
1331 free_a_printer(&printer, 2);
1335 /* all done */
1338 /********************************************************************
1339 Update the cache for all printq's with a registered client
1340 connection
1341 ********************************************************************/
1343 void update_monitored_printq_cache( void )
1345 Printer_entry *printer = printers_list;
1346 int snum;
1348 /* loop through all printers and update the cache where
1349 client_connected == True */
1350 while ( printer )
1352 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1353 && printer->notify.client_connected )
1355 snum = print_queue_snum(printer->sharename);
1356 print_queue_status( snum, NULL, NULL );
1359 printer = printer->next;
1362 return;
1364 /********************************************************************
1365 Send a message to ourself about new driver being installed
1366 so we can upgrade the information for each printer bound to this
1367 driver
1368 ********************************************************************/
1370 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1372 int len = strlen(drivername);
1374 if (!len)
1375 return False;
1377 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1378 drivername));
1380 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1382 return True;
1385 /**********************************************************************
1386 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1387 over all printers, resetting printer data as neessary
1388 **********************************************************************/
1390 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1392 fstring drivername;
1393 int snum;
1394 int n_services = lp_numservices();
1396 len = MIN( len, sizeof(drivername)-1 );
1397 strncpy( drivername, buf, len );
1399 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1401 /* Iterate the printer list */
1403 for ( snum=0; snum<n_services; snum++ )
1405 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1407 WERROR result;
1408 NT_PRINTER_INFO_LEVEL *printer = NULL;
1410 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1411 if ( !W_ERROR_IS_OK(result) )
1412 continue;
1415 * if the printer is bound to the driver,
1416 * then reset to the new driver initdata
1419 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1421 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1423 if ( !set_driver_init(printer, 2) ) {
1424 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1425 printer->info_2->printername, printer->info_2->drivername));
1428 result = mod_a_printer( printer, 2 );
1429 if ( !W_ERROR_IS_OK(result) ) {
1430 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1431 get_dos_error_msg(result)));
1435 free_a_printer( &printer, 2 );
1439 /* all done */
1441 return;
1444 /********************************************************************
1445 Copy routines used by convert_to_openprinterex()
1446 *******************************************************************/
1448 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1450 DEVICEMODE *d;
1451 int len;
1453 if (!devmode)
1454 return NULL;
1456 DEBUG (8,("dup_devmode\n"));
1458 /* bulk copy first */
1460 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1461 if (!d)
1462 return NULL;
1464 /* dup the pointer members separately */
1466 len = unistrlen(devmode->devicename.buffer);
1467 if (len != -1) {
1468 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1469 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1470 return NULL;
1474 len = unistrlen(devmode->formname.buffer);
1475 if (len != -1) {
1476 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1477 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1478 return NULL;
1481 d->private = TALLOC_MEMDUP(ctx, devmode->private, devmode->driverextra);
1483 return d;
1486 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1488 if (!new_ctr || !ctr)
1489 return;
1491 DEBUG(8,("copy_devmode_ctr\n"));
1493 new_ctr->size = ctr->size;
1494 new_ctr->devmode_ptr = ctr->devmode_ptr;
1496 if(ctr->devmode_ptr)
1497 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1500 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1502 if (!new_def || !def)
1503 return;
1505 DEBUG(8,("copy_printer_defaults\n"));
1507 new_def->datatype_ptr = def->datatype_ptr;
1509 if (def->datatype_ptr)
1510 copy_unistr2(&new_def->datatype, &def->datatype);
1512 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1514 new_def->access_required = def->access_required;
1517 /********************************************************************
1518 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1519 * SPOOL_Q_OPEN_PRINTER_EX structure
1520 ********************************************************************/
1522 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1524 if (!q_u_ex || !q_u)
1525 return;
1527 DEBUG(8,("convert_to_openprinterex\n"));
1529 q_u_ex->printername_ptr = q_u->printername_ptr;
1531 if (q_u->printername_ptr)
1532 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1534 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1537 /********************************************************************
1538 * spoolss_open_printer
1540 * called from the spoolss dispatcher
1541 ********************************************************************/
1543 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1545 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1546 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1548 if (!q_u || !r_u)
1549 return WERR_NOMEM;
1551 ZERO_STRUCT(q_u_ex);
1552 ZERO_STRUCT(r_u_ex);
1554 /* convert the OpenPrinter() call to OpenPrinterEx() */
1556 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1558 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1560 /* convert back to OpenPrinter() */
1562 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1564 return r_u->status;
1567 /********************************************************************
1568 * spoolss_open_printer
1570 * If the openprinterex rpc call contains a devmode,
1571 * it's a per-user one. This per-user devmode is derivated
1572 * from the global devmode. Openprinterex() contains a per-user
1573 * devmode for when you do EMF printing and spooling.
1574 * In the EMF case, the NT workstation is only doing half the job
1575 * of rendering the page. The other half is done by running the printer
1576 * driver on the server.
1577 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1578 * The EMF file only contains what is to be printed on the page.
1579 * So in order for the server to know how to print, the NT client sends
1580 * a devicemode attached to the openprinterex call.
1581 * But this devicemode is short lived, it's only valid for the current print job.
1583 * If Samba would have supported EMF spooling, this devicemode would
1584 * have been attached to the handle, to sent it to the driver to correctly
1585 * rasterize the EMF file.
1587 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1588 * we just act as a pass-thru between windows and the printer.
1590 * In order to know that Samba supports only RAW spooling, NT has to call
1591 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1592 * and until NT sends a RAW job, we refuse it.
1594 * But to call getprinter() or startdoc(), you first need a valid handle,
1595 * and to get an handle you have to call openprintex(). Hence why you have
1596 * a devicemode in the openprinterex() call.
1599 * Differences between NT4 and NT 2000.
1600 * NT4:
1601 * ---
1602 * On NT4, you only have a global devicemode. This global devicemode can be changed
1603 * by the administrator (or by a user with enough privs). Everytime a user
1604 * wants to print, the devicemode is resetted to the default. In Word, everytime
1605 * you print, the printer's characteristics are always reset to the global devicemode.
1607 * NT 2000:
1608 * -------
1609 * In W2K, there is the notion of per-user devicemode. The first time you use
1610 * a printer, a per-user devicemode is build from the global devicemode.
1611 * If you change your per-user devicemode, it is saved in the registry, under the
1612 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1613 * printer preferences available.
1615 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1616 * on the General Tab of the printer properties windows.
1618 * To change the global devicemode: it's the "Printing Defaults..." button
1619 * on the Advanced Tab of the printer properties window.
1621 * JFM.
1622 ********************************************************************/
1624 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1626 UNISTR2 *printername = NULL;
1627 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1628 POLICY_HND *handle = &r_u->handle;
1630 fstring name;
1631 int snum;
1632 struct current_user user;
1633 Printer_entry *Printer=NULL;
1635 if (q_u->printername_ptr != 0)
1636 printername = &q_u->printername;
1638 if (printername == NULL)
1639 return WERR_INVALID_PRINTER_NAME;
1641 /* some sanity check because you can open a printer or a print server */
1642 /* aka: \\server\printer or \\server */
1643 unistr2_to_ascii(name, printername, sizeof(name)-1);
1645 DEBUGADD(3,("checking name: %s\n",name));
1647 if (!open_printer_hnd(p, handle, name, 0))
1648 return WERR_INVALID_PRINTER_NAME;
1650 Printer=find_printer_index_by_hnd(p, handle);
1651 if ( !Printer ) {
1652 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1653 "handle we created for printer %s\n", name ));
1654 close_printer_handle(p,handle);
1655 return WERR_INVALID_PRINTER_NAME;
1658 get_current_user(&user, p);
1661 * First case: the user is opening the print server:
1663 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1664 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1666 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1667 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1668 * or if the user is listed in the smb.conf printer admin parameter.
1670 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1671 * client view printer folder, but does not show the MSAPW.
1673 * Note: this test needs code to check access rights here too. Jeremy
1674 * could you look at this?
1676 * Second case: the user is opening a printer:
1677 * NT doesn't let us connect to a printer if the connecting user
1678 * doesn't have print permission.
1681 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1683 /* Printserver handles use global struct... */
1685 snum = -1;
1687 /* Map standard access rights to object specific access rights */
1689 se_map_standard(&printer_default->access_required,
1690 &printserver_std_mapping);
1692 /* Deny any object specific bits that don't apply to print
1693 servers (i.e printer and job specific bits) */
1695 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1697 if (printer_default->access_required &
1698 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1699 DEBUG(3, ("access DENIED for non-printserver bits"));
1700 close_printer_handle(p, handle);
1701 return WERR_ACCESS_DENIED;
1704 /* Allow admin access */
1706 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1708 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1710 if (!lp_ms_add_printer_wizard()) {
1711 close_printer_handle(p, handle);
1712 return WERR_ACCESS_DENIED;
1715 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1716 and not a printer admin, then fail */
1718 if ( user.uid != 0
1719 && !user_has_privileges( user.nt_user_token, &se_printop )
1720 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1722 close_printer_handle(p, handle);
1723 return WERR_ACCESS_DENIED;
1726 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1728 else
1730 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1733 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1734 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1736 /* We fall through to return WERR_OK */
1739 else
1741 /* NT doesn't let us connect to a printer if the connecting user
1742 doesn't have print permission. */
1744 if (!get_printer_snum(p, handle, &snum)) {
1745 close_printer_handle(p, handle);
1746 return WERR_BADFID;
1749 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1751 /* map an empty access mask to the minimum access mask */
1752 if (printer_default->access_required == 0x0)
1753 printer_default->access_required = PRINTER_ACCESS_USE;
1756 * If we are not serving the printer driver for this printer,
1757 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1758 * will keep NT clients happy --jerry
1761 if (lp_use_client_driver(snum)
1762 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1764 printer_default->access_required = PRINTER_ACCESS_USE;
1767 /* check smb.conf parameters and the the sec_desc */
1769 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1770 DEBUG(3, ("access DENIED for printer open\n"));
1771 close_printer_handle(p, handle);
1772 return WERR_ACCESS_DENIED;
1775 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1776 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1777 close_printer_handle(p, handle);
1778 return WERR_ACCESS_DENIED;
1781 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1782 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1783 else
1784 printer_default->access_required = PRINTER_ACCESS_USE;
1786 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1787 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1791 Printer->access_granted = printer_default->access_required;
1794 * If the client sent a devmode in the OpenPrinter() call, then
1795 * save it here in case we get a job submission on this handle
1798 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1799 && q_u->printer_default.devmode_cont.devmode_ptr )
1801 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1802 &Printer->nt_devmode );
1805 #if 0 /* JERRY -- I'm doubtful this is really effective */
1806 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1807 optimization in Windows 2000 clients --jerry */
1809 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1810 && (RA_WIN2K == get_remote_arch()) )
1812 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1813 sys_usleep( 500000 );
1815 #endif
1817 return WERR_OK;
1820 /****************************************************************************
1821 ****************************************************************************/
1823 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1824 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1826 BOOL ret = True;
1828 switch (level) {
1829 case 2:
1830 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1831 break;
1832 default:
1833 break;
1836 return ret;
1839 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1840 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1842 BOOL result = True;
1844 switch (level) {
1845 case 3:
1846 printer->info_3=NULL;
1847 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1848 result = False;
1849 break;
1850 case 6:
1851 printer->info_6=NULL;
1852 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1853 result = False;
1854 break;
1855 default:
1856 break;
1859 return result;
1862 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1863 NT_DEVICEMODE **pp_nt_devmode)
1865 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1868 * Ensure nt_devmode is a valid pointer
1869 * as we will be overwriting it.
1872 if (nt_devmode == NULL) {
1873 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1874 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1875 return False;
1878 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1879 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1881 nt_devmode->specversion=devmode->specversion;
1882 nt_devmode->driverversion=devmode->driverversion;
1883 nt_devmode->size=devmode->size;
1884 nt_devmode->fields=devmode->fields;
1885 nt_devmode->orientation=devmode->orientation;
1886 nt_devmode->papersize=devmode->papersize;
1887 nt_devmode->paperlength=devmode->paperlength;
1888 nt_devmode->paperwidth=devmode->paperwidth;
1889 nt_devmode->scale=devmode->scale;
1890 nt_devmode->copies=devmode->copies;
1891 nt_devmode->defaultsource=devmode->defaultsource;
1892 nt_devmode->printquality=devmode->printquality;
1893 nt_devmode->color=devmode->color;
1894 nt_devmode->duplex=devmode->duplex;
1895 nt_devmode->yresolution=devmode->yresolution;
1896 nt_devmode->ttoption=devmode->ttoption;
1897 nt_devmode->collate=devmode->collate;
1899 nt_devmode->logpixels=devmode->logpixels;
1900 nt_devmode->bitsperpel=devmode->bitsperpel;
1901 nt_devmode->pelswidth=devmode->pelswidth;
1902 nt_devmode->pelsheight=devmode->pelsheight;
1903 nt_devmode->displayflags=devmode->displayflags;
1904 nt_devmode->displayfrequency=devmode->displayfrequency;
1905 nt_devmode->icmmethod=devmode->icmmethod;
1906 nt_devmode->icmintent=devmode->icmintent;
1907 nt_devmode->mediatype=devmode->mediatype;
1908 nt_devmode->dithertype=devmode->dithertype;
1909 nt_devmode->reserved1=devmode->reserved1;
1910 nt_devmode->reserved2=devmode->reserved2;
1911 nt_devmode->panningwidth=devmode->panningwidth;
1912 nt_devmode->panningheight=devmode->panningheight;
1915 * Only change private and driverextra if the incoming devmode
1916 * has a new one. JRA.
1919 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1920 SAFE_FREE(nt_devmode->private);
1921 nt_devmode->driverextra=devmode->driverextra;
1922 if((nt_devmode->private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1923 return False;
1924 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1927 *pp_nt_devmode = nt_devmode;
1929 return True;
1932 /********************************************************************
1933 * _spoolss_enddocprinter_internal.
1934 ********************************************************************/
1936 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1938 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1939 int snum;
1941 if (!Printer) {
1942 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1943 return WERR_BADFID;
1946 if (!get_printer_snum(p, handle, &snum))
1947 return WERR_BADFID;
1949 Printer->document_started=False;
1950 print_job_end(snum, Printer->jobid,True);
1951 /* error codes unhandled so far ... */
1953 return WERR_OK;
1956 /********************************************************************
1957 * api_spoolss_closeprinter
1958 ********************************************************************/
1960 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1962 POLICY_HND *handle = &q_u->handle;
1964 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1966 if (Printer && Printer->document_started)
1967 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1969 if (!close_printer_handle(p, handle))
1970 return WERR_BADFID;
1972 /* clear the returned printer handle. Observed behavior
1973 from Win2k server. Don't think this really matters.
1974 Previous code just copied the value of the closed
1975 handle. --jerry */
1977 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1979 return WERR_OK;
1982 /********************************************************************
1983 * api_spoolss_deleteprinter
1985 ********************************************************************/
1987 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1989 POLICY_HND *handle = &q_u->handle;
1990 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1991 WERROR result;
1993 if (Printer && Printer->document_started)
1994 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1996 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1998 result = delete_printer_handle(p, handle);
2000 update_c_setprinter(False);
2002 return result;
2005 /*******************************************************************
2006 * static function to lookup the version id corresponding to an
2007 * long architecture string
2008 ******************************************************************/
2010 static int get_version_id (char * arch)
2012 int i;
2013 struct table_node archi_table[]= {
2015 {"Windows 4.0", "WIN40", 0 },
2016 {"Windows NT x86", "W32X86", 2 },
2017 {"Windows NT R4000", "W32MIPS", 2 },
2018 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2019 {"Windows NT PowerPC", "W32PPC", 2 },
2020 {"Windows IA64", "IA64", 3 },
2021 {"Windows x64", "x64", 3 },
2022 {NULL, "", -1 }
2025 for (i=0; archi_table[i].long_archi != NULL; i++)
2027 if (strcmp(arch, archi_table[i].long_archi) == 0)
2028 return (archi_table[i].version);
2031 return -1;
2034 /********************************************************************
2035 * _spoolss_deleteprinterdriver
2036 ********************************************************************/
2038 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2040 fstring driver;
2041 fstring arch;
2042 NT_PRINTER_DRIVER_INFO_LEVEL info;
2043 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2044 int version;
2045 struct current_user user;
2046 WERROR status;
2047 WERROR status_win2k = WERR_ACCESS_DENIED;
2049 get_current_user(&user, p);
2051 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2052 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2054 /* check that we have a valid driver name first */
2056 if ((version=get_version_id(arch)) == -1)
2057 return WERR_INVALID_ENVIRONMENT;
2059 ZERO_STRUCT(info);
2060 ZERO_STRUCT(info_win2k);
2062 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2064 /* try for Win2k driver if "Windows NT x86" */
2066 if ( version == 2 ) {
2067 version = 3;
2068 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2069 status = WERR_UNKNOWN_PRINTER_DRIVER;
2070 goto done;
2073 /* otherwise it was a failure */
2074 else {
2075 status = WERR_UNKNOWN_PRINTER_DRIVER;
2076 goto done;
2081 if (printer_driver_in_use(info.info_3)) {
2082 status = WERR_PRINTER_DRIVER_IN_USE;
2083 goto done;
2086 if ( version == 2 )
2088 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2090 /* if we get to here, we now have 2 driver info structures to remove */
2091 /* remove the Win2k driver first*/
2093 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2094 free_a_printer_driver( info_win2k, 3 );
2096 /* this should not have failed---if it did, report to client */
2097 if ( !W_ERROR_IS_OK(status_win2k) )
2098 goto done;
2102 status = delete_printer_driver(info.info_3, &user, version, False);
2104 /* if at least one of the deletes succeeded return OK */
2106 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2107 status = WERR_OK;
2109 done:
2110 free_a_printer_driver( info, 3 );
2112 return status;
2115 /********************************************************************
2116 * spoolss_deleteprinterdriverex
2117 ********************************************************************/
2119 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2121 fstring driver;
2122 fstring arch;
2123 NT_PRINTER_DRIVER_INFO_LEVEL info;
2124 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2125 int version;
2126 uint32 flags = q_u->delete_flags;
2127 BOOL delete_files;
2128 struct current_user user;
2129 WERROR status;
2130 WERROR status_win2k = WERR_ACCESS_DENIED;
2132 get_current_user(&user, p);
2134 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2135 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2137 /* check that we have a valid driver name first */
2138 if ((version=get_version_id(arch)) == -1) {
2139 /* this is what NT returns */
2140 return WERR_INVALID_ENVIRONMENT;
2143 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2144 version = q_u->version;
2146 ZERO_STRUCT(info);
2147 ZERO_STRUCT(info_win2k);
2149 status = get_a_printer_driver(&info, 3, driver, arch, version);
2151 if ( !W_ERROR_IS_OK(status) )
2154 * if the client asked for a specific version,
2155 * or this is something other than Windows NT x86,
2156 * then we've failed
2159 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2160 goto done;
2162 /* try for Win2k driver if "Windows NT x86" */
2164 version = 3;
2165 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2166 status = WERR_UNKNOWN_PRINTER_DRIVER;
2167 goto done;
2171 if ( printer_driver_in_use(info.info_3) ) {
2172 status = WERR_PRINTER_DRIVER_IN_USE;
2173 goto done;
2177 * we have a couple of cases to consider.
2178 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2179 * then the delete should fail if **any** files overlap with
2180 * other drivers
2181 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2182 * non-overlapping files
2183 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2184 * is set, the do not delete any files
2185 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2188 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2190 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2192 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2193 /* no idea of the correct error here */
2194 status = WERR_ACCESS_DENIED;
2195 goto done;
2199 /* also check for W32X86/3 if necessary; maybe we already have? */
2201 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2202 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2205 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2206 /* no idea of the correct error here */
2207 free_a_printer_driver( info_win2k, 3 );
2208 status = WERR_ACCESS_DENIED;
2209 goto done;
2212 /* if we get to here, we now have 2 driver info structures to remove */
2213 /* remove the Win2k driver first*/
2215 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2216 free_a_printer_driver( info_win2k, 3 );
2218 /* this should not have failed---if it did, report to client */
2220 if ( !W_ERROR_IS_OK(status_win2k) )
2221 goto done;
2225 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2227 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2228 status = WERR_OK;
2229 done:
2230 free_a_printer_driver( info, 3 );
2232 return status;
2236 /****************************************************************************
2237 Internal routine for retreiving printerdata
2238 ***************************************************************************/
2240 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2241 const char *key, const char *value, uint32 *type, uint8 **data,
2242 uint32 *needed, uint32 in_size )
2244 REGISTRY_VALUE *val;
2245 int size, data_len;
2247 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2248 return WERR_BADFILE;
2250 *type = regval_type( val );
2252 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2254 size = regval_size( val );
2256 /* copy the min(in_size, len) */
2258 if ( in_size ) {
2259 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2261 /* special case for 0 length values */
2262 if ( data_len ) {
2263 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2264 return WERR_NOMEM;
2266 else {
2267 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2268 return WERR_NOMEM;
2271 else
2272 *data = NULL;
2274 *needed = size;
2276 DEBUG(5,("get_printer_dataex: copy done\n"));
2278 return WERR_OK;
2281 /****************************************************************************
2282 Internal routine for removing printerdata
2283 ***************************************************************************/
2285 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2287 return delete_printer_data( printer->info_2, key, value );
2290 /****************************************************************************
2291 Internal routine for storing printerdata
2292 ***************************************************************************/
2294 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2295 uint32 type, uint8 *data, int real_len )
2297 delete_printer_data( printer->info_2, key, value );
2299 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2302 /********************************************************************
2303 GetPrinterData on a printer server Handle.
2304 ********************************************************************/
2306 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2308 int i;
2310 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2312 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2313 *type = 0x4;
2314 if((*data = (uint8 *)TALLOC_ZERO(ctx, 4*sizeof(uint8) )) == NULL)
2315 return WERR_NOMEM;
2316 *needed = 0x4;
2317 return WERR_OK;
2320 if (!StrCaseCmp(value, "BeepEnabled")) {
2321 *type = 0x4;
2322 if((*data = (uint8 *)TALLOC(ctx, 4*sizeof(uint8) )) == NULL)
2323 return WERR_NOMEM;
2324 SIVAL(*data, 0, 0x00);
2325 *needed = 0x4;
2326 return WERR_OK;
2329 if (!StrCaseCmp(value, "EventLog")) {
2330 *type = 0x4;
2331 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2332 return WERR_NOMEM;
2333 /* formally was 0x1b */
2334 SIVAL(*data, 0, 0x0);
2335 *needed = 0x4;
2336 return WERR_OK;
2339 if (!StrCaseCmp(value, "NetPopup")) {
2340 *type = 0x4;
2341 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2342 return WERR_NOMEM;
2343 SIVAL(*data, 0, 0x00);
2344 *needed = 0x4;
2345 return WERR_OK;
2348 if (!StrCaseCmp(value, "MajorVersion")) {
2349 *type = 0x4;
2350 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2351 return WERR_NOMEM;
2353 /* Windows NT 4.0 seems to not allow uploading of drivers
2354 to a server that reports 0x3 as the MajorVersion.
2355 need to investigate more how Win2k gets around this .
2356 -- jerry */
2358 if ( RA_WINNT == get_remote_arch() )
2359 SIVAL(*data, 0, 2);
2360 else
2361 SIVAL(*data, 0, 3);
2363 *needed = 0x4;
2364 return WERR_OK;
2367 if (!StrCaseCmp(value, "MinorVersion")) {
2368 *type = 0x4;
2369 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2370 return WERR_NOMEM;
2371 SIVAL(*data, 0, 0);
2372 *needed = 0x4;
2373 return WERR_OK;
2376 /* REG_BINARY
2377 * uint32 size = 0x114
2378 * uint32 major = 5
2379 * uint32 minor = [0|1]
2380 * uint32 build = [2195|2600]
2381 * extra unicode string = e.g. "Service Pack 3"
2383 if (!StrCaseCmp(value, "OSVersion")) {
2384 *type = 0x3;
2385 *needed = 0x114;
2387 if((*data = (uint8 *)TALLOC(ctx, *needed)) == NULL)
2388 return WERR_NOMEM;
2389 ZERO_STRUCTP( *data );
2391 SIVAL(*data, 0, *needed); /* size */
2392 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2393 SIVAL(*data, 8, 0);
2394 SIVAL(*data, 12, 2195); /* build */
2396 /* leave extra string empty */
2398 return WERR_OK;
2402 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2403 const char *string="C:\\PRINTERS";
2404 *type = 0x1;
2405 *needed = 2*(strlen(string)+1);
2406 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2407 return WERR_NOMEM;
2408 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2410 /* it's done by hand ready to go on the wire */
2411 for (i=0; i<strlen(string); i++) {
2412 (*data)[2*i]=string[i];
2413 (*data)[2*i+1]='\0';
2415 return WERR_OK;
2418 if (!StrCaseCmp(value, "Architecture")) {
2419 const char *string="Windows NT x86";
2420 *type = 0x1;
2421 *needed = 2*(strlen(string)+1);
2422 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2423 return WERR_NOMEM;
2424 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2425 for (i=0; i<strlen(string); i++) {
2426 (*data)[2*i]=string[i];
2427 (*data)[2*i+1]='\0';
2429 return WERR_OK;
2432 if (!StrCaseCmp(value, "DsPresent")) {
2433 *type = 0x4;
2434 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2435 return WERR_NOMEM;
2436 SIVAL(*data, 0, 0x01);
2437 *needed = 0x4;
2438 return WERR_OK;
2441 if (!StrCaseCmp(value, "DNSMachineName")) {
2442 pstring hostname;
2444 if (!get_mydnsfullname(hostname))
2445 return WERR_BADFILE;
2446 *type = 0x1;
2447 *needed = 2*(strlen(hostname)+1);
2448 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2449 return WERR_NOMEM;
2450 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2451 for (i=0; i<strlen(hostname); i++) {
2452 (*data)[2*i]=hostname[i];
2453 (*data)[2*i+1]='\0';
2455 return WERR_OK;
2459 return WERR_BADFILE;
2462 /********************************************************************
2463 * spoolss_getprinterdata
2464 ********************************************************************/
2466 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2468 POLICY_HND *handle = &q_u->handle;
2469 UNISTR2 *valuename = &q_u->valuename;
2470 uint32 in_size = q_u->size;
2471 uint32 *type = &r_u->type;
2472 uint32 *out_size = &r_u->size;
2473 uint8 **data = &r_u->data;
2474 uint32 *needed = &r_u->needed;
2475 WERROR status;
2476 fstring value;
2477 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2478 NT_PRINTER_INFO_LEVEL *printer = NULL;
2479 int snum = 0;
2482 * Reminder: when it's a string, the length is in BYTES
2483 * even if UNICODE is negociated.
2485 * JFM, 4/19/1999
2488 *out_size = in_size;
2490 /* in case of problem, return some default values */
2492 *needed = 0;
2493 *type = 0;
2495 DEBUG(4,("_spoolss_getprinterdata\n"));
2497 if ( !Printer ) {
2498 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2499 status = WERR_BADFID;
2500 goto done;
2503 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2505 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2506 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2507 else
2509 if ( !get_printer_snum(p,handle, &snum) ) {
2510 status = WERR_BADFID;
2511 goto done;
2514 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2515 if ( !W_ERROR_IS_OK(status) )
2516 goto done;
2518 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2520 if ( strequal(value, "ChangeId") ) {
2521 *type = REG_DWORD;
2522 *needed = sizeof(uint32);
2523 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2524 status = WERR_NOMEM;
2525 goto done;
2527 SIVAL( *data, 0, printer->info_2->changeid );
2528 status = WERR_OK;
2530 else
2531 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2534 if (*needed > *out_size)
2535 status = WERR_MORE_DATA;
2537 done:
2538 if ( !W_ERROR_IS_OK(status) )
2540 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2542 /* reply this param doesn't exist */
2544 if ( *out_size ) {
2545 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2546 if ( printer )
2547 free_a_printer( &printer, 2 );
2548 return WERR_NOMEM;
2551 else {
2552 *data = NULL;
2556 /* cleanup & exit */
2558 if ( printer )
2559 free_a_printer( &printer, 2 );
2561 return status;
2564 /*********************************************************
2565 Connect to the client machine.
2566 **********************************************************/
2568 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2569 struct in_addr *client_ip, const char *remote_machine)
2571 ZERO_STRUCTP(the_cli);
2573 if(cli_initialise(the_cli) == NULL) {
2574 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2575 return False;
2578 if ( is_zero_ip(*client_ip) ) {
2579 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2580 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2581 cli_shutdown(the_cli);
2582 return False;
2585 if (ismyip(the_cli->dest_ip)) {
2586 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2587 cli_shutdown(the_cli);
2588 return False;
2591 else {
2592 the_cli->dest_ip.s_addr = client_ip->s_addr;
2593 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2594 inet_ntoa(*client_ip) ));
2597 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2598 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) ));
2599 cli_shutdown(the_cli);
2600 return False;
2603 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2604 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2605 remote_machine));
2606 cli_shutdown(the_cli);
2607 return False;
2610 the_cli->protocol = PROTOCOL_NT1;
2611 cli_setup_signing_state(the_cli, lp_client_signing());
2613 if (!cli_negprot(the_cli)) {
2614 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2615 cli_shutdown(the_cli);
2616 return False;
2619 if (the_cli->protocol != PROTOCOL_NT1) {
2620 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2621 cli_shutdown(the_cli);
2622 return False;
2626 * Do an anonymous session setup.
2629 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2630 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2631 cli_shutdown(the_cli);
2632 return False;
2635 if (!(the_cli->sec_mode & 1)) {
2636 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2637 cli_shutdown(the_cli);
2638 return False;
2641 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2642 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) ));
2643 cli_shutdown(the_cli);
2644 return False;
2648 * Ok - we have an anonymous connection to the IPC$ share.
2649 * Now start the NT Domain stuff :-).
2652 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2653 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)));
2654 cli_nt_session_close(the_cli);
2655 cli_ulogoff(the_cli);
2656 cli_shutdown(the_cli);
2657 return False;
2660 return True;
2663 /***************************************************************************
2664 Connect to the client.
2665 ****************************************************************************/
2667 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2668 uint32 localprinter, uint32 type,
2669 POLICY_HND *handle, struct in_addr *client_ip)
2671 WERROR result;
2674 * If it's the first connection, contact the client
2675 * and connect to the IPC$ share anonymously
2677 if (smb_connections==0) {
2678 fstring unix_printer;
2680 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2682 ZERO_STRUCT(notify_cli);
2684 if(!spoolss_connect_to_client(&notify_cli, client_ip, unix_printer))
2685 return False;
2687 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2688 /* Tell the connections db we're now interested in printer
2689 * notify messages. */
2690 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2694 * Tell the specific printing tdb we want messages for this printer
2695 * by registering our PID.
2698 if (!print_notify_register_pid(snum))
2699 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2701 smb_connections++;
2703 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2704 type, handle);
2706 if (!W_ERROR_IS_OK(result))
2707 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2708 dos_errstr(result)));
2710 return (W_ERROR_IS_OK(result));
2713 /********************************************************************
2714 * _spoolss_rffpcnex
2715 * ReplyFindFirstPrinterChangeNotifyEx
2717 * before replying OK: status=0 a rpc call is made to the workstation
2718 * asking ReplyOpenPrinter
2720 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2721 * called from api_spoolss_rffpcnex
2722 ********************************************************************/
2724 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2726 POLICY_HND *handle = &q_u->handle;
2727 uint32 flags = q_u->flags;
2728 uint32 options = q_u->options;
2729 UNISTR2 *localmachine = &q_u->localmachine;
2730 uint32 printerlocal = q_u->printerlocal;
2731 int snum = -1;
2732 SPOOL_NOTIFY_OPTION *option = q_u->option;
2733 struct in_addr client_ip;
2735 /* store the notify value in the printer struct */
2737 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2739 if (!Printer) {
2740 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2741 return WERR_BADFID;
2744 Printer->notify.flags=flags;
2745 Printer->notify.options=options;
2746 Printer->notify.printerlocal=printerlocal;
2748 if (Printer->notify.option)
2749 free_spool_notify_option(&Printer->notify.option);
2751 Printer->notify.option=dup_spool_notify_option(option);
2753 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2754 sizeof(Printer->notify.localmachine)-1);
2756 /* Connect to the client machine and send a ReplyOpenPrinter */
2758 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2759 snum = -1;
2760 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2761 !get_printer_snum(p, handle, &snum) )
2762 return WERR_BADFID;
2764 client_ip.s_addr = inet_addr(p->conn->client_address);
2766 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2767 Printer->notify.printerlocal, 1,
2768 &Printer->notify.client_hnd, &client_ip))
2769 return WERR_SERVER_UNAVAILABLE;
2771 Printer->notify.client_connected=True;
2773 return WERR_OK;
2776 /*******************************************************************
2777 * fill a notify_info_data with the servername
2778 ********************************************************************/
2780 void spoolss_notify_server_name(int snum,
2781 SPOOL_NOTIFY_INFO_DATA *data,
2782 print_queue_struct *queue,
2783 NT_PRINTER_INFO_LEVEL *printer,
2784 TALLOC_CTX *mem_ctx)
2786 pstring temp;
2787 uint32 len;
2789 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2791 data->notify_data.data.length = len;
2792 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2794 if (!data->notify_data.data.string) {
2795 data->notify_data.data.length = 0;
2796 return;
2799 memcpy(data->notify_data.data.string, temp, len);
2802 /*******************************************************************
2803 * fill a notify_info_data with the printername (not including the servername).
2804 ********************************************************************/
2806 void spoolss_notify_printer_name(int snum,
2807 SPOOL_NOTIFY_INFO_DATA *data,
2808 print_queue_struct *queue,
2809 NT_PRINTER_INFO_LEVEL *printer,
2810 TALLOC_CTX *mem_ctx)
2812 pstring temp;
2813 uint32 len;
2815 /* the notify name should not contain the \\server\ part */
2816 char *p = strrchr(printer->info_2->printername, '\\');
2818 if (!p) {
2819 p = printer->info_2->printername;
2820 } else {
2821 p++;
2824 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2826 data->notify_data.data.length = len;
2827 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2829 if (!data->notify_data.data.string) {
2830 data->notify_data.data.length = 0;
2831 return;
2834 memcpy(data->notify_data.data.string, temp, len);
2837 /*******************************************************************
2838 * fill a notify_info_data with the servicename
2839 ********************************************************************/
2841 void spoolss_notify_share_name(int snum,
2842 SPOOL_NOTIFY_INFO_DATA *data,
2843 print_queue_struct *queue,
2844 NT_PRINTER_INFO_LEVEL *printer,
2845 TALLOC_CTX *mem_ctx)
2847 pstring temp;
2848 uint32 len;
2850 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2852 data->notify_data.data.length = len;
2853 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2855 if (!data->notify_data.data.string) {
2856 data->notify_data.data.length = 0;
2857 return;
2860 memcpy(data->notify_data.data.string, temp, len);
2863 /*******************************************************************
2864 * fill a notify_info_data with the port name
2865 ********************************************************************/
2867 void spoolss_notify_port_name(int snum,
2868 SPOOL_NOTIFY_INFO_DATA *data,
2869 print_queue_struct *queue,
2870 NT_PRINTER_INFO_LEVEL *printer,
2871 TALLOC_CTX *mem_ctx)
2873 pstring temp;
2874 uint32 len;
2876 /* even if it's strange, that's consistant in all the code */
2878 len = rpcstr_push(temp, printer->info_2->portname, 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 printername
2893 * but it doesn't exist, have to see what to do
2894 ********************************************************************/
2896 void spoolss_notify_driver_name(int snum,
2897 SPOOL_NOTIFY_INFO_DATA *data,
2898 print_queue_struct *queue,
2899 NT_PRINTER_INFO_LEVEL *printer,
2900 TALLOC_CTX *mem_ctx)
2902 pstring temp;
2903 uint32 len;
2905 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2907 data->notify_data.data.length = len;
2908 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2910 if (!data->notify_data.data.string) {
2911 data->notify_data.data.length = 0;
2912 return;
2915 memcpy(data->notify_data.data.string, temp, len);
2918 /*******************************************************************
2919 * fill a notify_info_data with the comment
2920 ********************************************************************/
2922 void spoolss_notify_comment(int snum,
2923 SPOOL_NOTIFY_INFO_DATA *data,
2924 print_queue_struct *queue,
2925 NT_PRINTER_INFO_LEVEL *printer,
2926 TALLOC_CTX *mem_ctx)
2928 pstring temp;
2929 uint32 len;
2931 if (*printer->info_2->comment == '\0')
2932 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2933 else
2934 len = rpcstr_push(temp, printer->info_2->comment, 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 comment
2949 * location = "Room 1, floor 2, building 3"
2950 ********************************************************************/
2952 void spoolss_notify_location(int snum,
2953 SPOOL_NOTIFY_INFO_DATA *data,
2954 print_queue_struct *queue,
2955 NT_PRINTER_INFO_LEVEL *printer,
2956 TALLOC_CTX *mem_ctx)
2958 pstring temp;
2959 uint32 len;
2961 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2963 data->notify_data.data.length = len;
2964 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2966 if (!data->notify_data.data.string) {
2967 data->notify_data.data.length = 0;
2968 return;
2971 memcpy(data->notify_data.data.string, temp, len);
2974 /*******************************************************************
2975 * fill a notify_info_data with the device mode
2976 * jfm:xxxx don't to it for know but that's a real problem !!!
2977 ********************************************************************/
2979 static void spoolss_notify_devmode(int snum,
2980 SPOOL_NOTIFY_INFO_DATA *data,
2981 print_queue_struct *queue,
2982 NT_PRINTER_INFO_LEVEL *printer,
2983 TALLOC_CTX *mem_ctx)
2987 /*******************************************************************
2988 * fill a notify_info_data with the separator file name
2989 ********************************************************************/
2991 void spoolss_notify_sepfile(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->sepfile, 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
3015 * jfm:xxxx return always winprint to indicate we don't do anything to it
3016 ********************************************************************/
3018 void spoolss_notify_print_processor(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->printprocessor, 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 print processor options
3042 * jfm:xxxx send an empty string
3043 ********************************************************************/
3045 void spoolss_notify_parameters(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->parameters, sizeof(temp)-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 data type
3069 * jfm:xxxx always send RAW as data type
3070 ********************************************************************/
3072 void spoolss_notify_datatype(int snum,
3073 SPOOL_NOTIFY_INFO_DATA *data,
3074 print_queue_struct *queue,
3075 NT_PRINTER_INFO_LEVEL *printer,
3076 TALLOC_CTX *mem_ctx)
3078 pstring temp;
3079 uint32 len;
3081 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3083 data->notify_data.data.length = len;
3084 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3086 if (!data->notify_data.data.string) {
3087 data->notify_data.data.length = 0;
3088 return;
3091 memcpy(data->notify_data.data.string, temp, len);
3094 /*******************************************************************
3095 * fill a notify_info_data with the security descriptor
3096 * jfm:xxxx send an null pointer to say no security desc
3097 * have to implement security before !
3098 ********************************************************************/
3100 static void spoolss_notify_security_desc(int snum,
3101 SPOOL_NOTIFY_INFO_DATA *data,
3102 print_queue_struct *queue,
3103 NT_PRINTER_INFO_LEVEL *printer,
3104 TALLOC_CTX *mem_ctx)
3106 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3107 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3110 /*******************************************************************
3111 * fill a notify_info_data with the attributes
3112 * jfm:xxxx a samba printer is always shared
3113 ********************************************************************/
3115 void spoolss_notify_attributes(int snum,
3116 SPOOL_NOTIFY_INFO_DATA *data,
3117 print_queue_struct *queue,
3118 NT_PRINTER_INFO_LEVEL *printer,
3119 TALLOC_CTX *mem_ctx)
3121 data->notify_data.value[0] = printer->info_2->attributes;
3122 data->notify_data.value[1] = 0;
3125 /*******************************************************************
3126 * fill a notify_info_data with the priority
3127 ********************************************************************/
3129 static void spoolss_notify_priority(int snum,
3130 SPOOL_NOTIFY_INFO_DATA *data,
3131 print_queue_struct *queue,
3132 NT_PRINTER_INFO_LEVEL *printer,
3133 TALLOC_CTX *mem_ctx)
3135 data->notify_data.value[0] = printer->info_2->priority;
3136 data->notify_data.value[1] = 0;
3139 /*******************************************************************
3140 * fill a notify_info_data with the default priority
3141 ********************************************************************/
3143 static void spoolss_notify_default_priority(int snum,
3144 SPOOL_NOTIFY_INFO_DATA *data,
3145 print_queue_struct *queue,
3146 NT_PRINTER_INFO_LEVEL *printer,
3147 TALLOC_CTX *mem_ctx)
3149 data->notify_data.value[0] = printer->info_2->default_priority;
3150 data->notify_data.value[1] = 0;
3153 /*******************************************************************
3154 * fill a notify_info_data with the start time
3155 ********************************************************************/
3157 static void spoolss_notify_start_time(int snum,
3158 SPOOL_NOTIFY_INFO_DATA *data,
3159 print_queue_struct *queue,
3160 NT_PRINTER_INFO_LEVEL *printer,
3161 TALLOC_CTX *mem_ctx)
3163 data->notify_data.value[0] = printer->info_2->starttime;
3164 data->notify_data.value[1] = 0;
3167 /*******************************************************************
3168 * fill a notify_info_data with the until time
3169 ********************************************************************/
3171 static void spoolss_notify_until_time(int snum,
3172 SPOOL_NOTIFY_INFO_DATA *data,
3173 print_queue_struct *queue,
3174 NT_PRINTER_INFO_LEVEL *printer,
3175 TALLOC_CTX *mem_ctx)
3177 data->notify_data.value[0] = printer->info_2->untiltime;
3178 data->notify_data.value[1] = 0;
3181 /*******************************************************************
3182 * fill a notify_info_data with the status
3183 ********************************************************************/
3185 static void spoolss_notify_status(int snum,
3186 SPOOL_NOTIFY_INFO_DATA *data,
3187 print_queue_struct *queue,
3188 NT_PRINTER_INFO_LEVEL *printer,
3189 TALLOC_CTX *mem_ctx)
3191 print_status_struct status;
3193 print_queue_length(snum, &status);
3194 data->notify_data.value[0]=(uint32) status.status;
3195 data->notify_data.value[1] = 0;
3198 /*******************************************************************
3199 * fill a notify_info_data with the number of jobs queued
3200 ********************************************************************/
3202 void spoolss_notify_cjobs(int snum,
3203 SPOOL_NOTIFY_INFO_DATA *data,
3204 print_queue_struct *queue,
3205 NT_PRINTER_INFO_LEVEL *printer,
3206 TALLOC_CTX *mem_ctx)
3208 data->notify_data.value[0] = print_queue_length(snum, NULL);
3209 data->notify_data.value[1] = 0;
3212 /*******************************************************************
3213 * fill a notify_info_data with the average ppm
3214 ********************************************************************/
3216 static void spoolss_notify_average_ppm(int snum,
3217 SPOOL_NOTIFY_INFO_DATA *data,
3218 print_queue_struct *queue,
3219 NT_PRINTER_INFO_LEVEL *printer,
3220 TALLOC_CTX *mem_ctx)
3222 /* always respond 8 pages per minutes */
3223 /* a little hard ! */
3224 data->notify_data.value[0] = printer->info_2->averageppm;
3225 data->notify_data.value[1] = 0;
3228 /*******************************************************************
3229 * fill a notify_info_data with username
3230 ********************************************************************/
3232 static void spoolss_notify_username(int snum,
3233 SPOOL_NOTIFY_INFO_DATA *data,
3234 print_queue_struct *queue,
3235 NT_PRINTER_INFO_LEVEL *printer,
3236 TALLOC_CTX *mem_ctx)
3238 pstring temp;
3239 uint32 len;
3241 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3243 data->notify_data.data.length = len;
3244 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3246 if (!data->notify_data.data.string) {
3247 data->notify_data.data.length = 0;
3248 return;
3251 memcpy(data->notify_data.data.string, temp, len);
3254 /*******************************************************************
3255 * fill a notify_info_data with job status
3256 ********************************************************************/
3258 static void spoolss_notify_job_status(int snum,
3259 SPOOL_NOTIFY_INFO_DATA *data,
3260 print_queue_struct *queue,
3261 NT_PRINTER_INFO_LEVEL *printer,
3262 TALLOC_CTX *mem_ctx)
3264 data->notify_data.value[0]=nt_printj_status(queue->status);
3265 data->notify_data.value[1] = 0;
3268 /*******************************************************************
3269 * fill a notify_info_data with job name
3270 ********************************************************************/
3272 static void spoolss_notify_job_name(int snum,
3273 SPOOL_NOTIFY_INFO_DATA *data,
3274 print_queue_struct *queue,
3275 NT_PRINTER_INFO_LEVEL *printer,
3276 TALLOC_CTX *mem_ctx)
3278 pstring temp;
3279 uint32 len;
3281 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3283 data->notify_data.data.length = len;
3284 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3286 if (!data->notify_data.data.string) {
3287 data->notify_data.data.length = 0;
3288 return;
3291 memcpy(data->notify_data.data.string, temp, len);
3294 /*******************************************************************
3295 * fill a notify_info_data with job status
3296 ********************************************************************/
3298 static void spoolss_notify_job_status_string(int snum,
3299 SPOOL_NOTIFY_INFO_DATA *data,
3300 print_queue_struct *queue,
3301 NT_PRINTER_INFO_LEVEL *printer,
3302 TALLOC_CTX *mem_ctx)
3305 * Now we're returning job status codes we just return a "" here. JRA.
3308 const char *p = "";
3309 pstring temp;
3310 uint32 len;
3312 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3313 p = "unknown";
3315 switch (queue->status) {
3316 case LPQ_QUEUED:
3317 p = "Queued";
3318 break;
3319 case LPQ_PAUSED:
3320 p = ""; /* NT provides the paused string */
3321 break;
3322 case LPQ_SPOOLING:
3323 p = "Spooling";
3324 break;
3325 case LPQ_PRINTING:
3326 p = "Printing";
3327 break;
3329 #endif /* NO LONGER NEEDED. */
3331 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3333 data->notify_data.data.length = len;
3334 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3336 if (!data->notify_data.data.string) {
3337 data->notify_data.data.length = 0;
3338 return;
3341 memcpy(data->notify_data.data.string, temp, len);
3344 /*******************************************************************
3345 * fill a notify_info_data with job time
3346 ********************************************************************/
3348 static void spoolss_notify_job_time(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]=0x0;
3355 data->notify_data.value[1]=0;
3358 /*******************************************************************
3359 * fill a notify_info_data with job size
3360 ********************************************************************/
3362 static void spoolss_notify_job_size(int snum,
3363 SPOOL_NOTIFY_INFO_DATA *data,
3364 print_queue_struct *queue,
3365 NT_PRINTER_INFO_LEVEL *printer,
3366 TALLOC_CTX *mem_ctx)
3368 data->notify_data.value[0]=queue->size;
3369 data->notify_data.value[1]=0;
3372 /*******************************************************************
3373 * fill a notify_info_data with page info
3374 ********************************************************************/
3375 static void spoolss_notify_total_pages(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->page_count;
3382 data->notify_data.value[1]=0;
3385 /*******************************************************************
3386 * fill a notify_info_data with pages printed info.
3387 ********************************************************************/
3388 static void spoolss_notify_pages_printed(int snum,
3389 SPOOL_NOTIFY_INFO_DATA *data,
3390 print_queue_struct *queue,
3391 NT_PRINTER_INFO_LEVEL *printer,
3392 TALLOC_CTX *mem_ctx)
3394 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3395 data->notify_data.value[1]=0;
3398 /*******************************************************************
3399 Fill a notify_info_data with job position.
3400 ********************************************************************/
3402 static void spoolss_notify_job_position(int snum,
3403 SPOOL_NOTIFY_INFO_DATA *data,
3404 print_queue_struct *queue,
3405 NT_PRINTER_INFO_LEVEL *printer,
3406 TALLOC_CTX *mem_ctx)
3408 data->notify_data.value[0]=queue->job;
3409 data->notify_data.value[1]=0;
3412 /*******************************************************************
3413 Fill a notify_info_data with submitted time.
3414 ********************************************************************/
3416 static void spoolss_notify_submitted_time(int snum,
3417 SPOOL_NOTIFY_INFO_DATA *data,
3418 print_queue_struct *queue,
3419 NT_PRINTER_INFO_LEVEL *printer,
3420 TALLOC_CTX *mem_ctx)
3422 struct tm *t;
3423 uint32 len;
3424 SYSTEMTIME st;
3425 char *p;
3427 t=gmtime(&queue->time);
3429 len = sizeof(SYSTEMTIME);
3431 data->notify_data.data.length = len;
3432 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3434 if (!data->notify_data.data.string) {
3435 data->notify_data.data.length = 0;
3436 return;
3439 make_systemtime(&st, t);
3442 * Systemtime must be linearized as a set of UINT16's.
3443 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3446 p = (char *)data->notify_data.data.string;
3447 SSVAL(p, 0, st.year);
3448 SSVAL(p, 2, st.month);
3449 SSVAL(p, 4, st.dayofweek);
3450 SSVAL(p, 6, st.day);
3451 SSVAL(p, 8, st.hour);
3452 SSVAL(p, 10, st.minute);
3453 SSVAL(p, 12, st.second);
3454 SSVAL(p, 14, st.milliseconds);
3457 struct s_notify_info_data_table
3459 uint16 type;
3460 uint16 field;
3461 const char *name;
3462 uint32 size;
3463 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3464 print_queue_struct *queue,
3465 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3468 /* A table describing the various print notification constants and
3469 whether the notification data is a pointer to a variable sized
3470 buffer, a one value uint32 or a two value uint32. */
3472 static const struct s_notify_info_data_table notify_info_data_table[] =
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3485 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3486 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3487 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3488 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3489 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3490 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3491 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3492 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3493 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3494 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3495 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3496 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3497 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3498 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3499 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3508 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3509 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3510 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3511 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3512 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3513 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3514 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3515 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3516 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3517 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3518 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3519 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3520 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3521 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3522 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3523 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3526 /*******************************************************************
3527 Return the size of info_data structure.
3528 ********************************************************************/
3530 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3532 int i=0;
3534 for (i = 0; i < sizeof(notify_info_data_table); i++)
3536 if ( (notify_info_data_table[i].type == type)
3537 && (notify_info_data_table[i].field == field) )
3539 switch(notify_info_data_table[i].size)
3541 case NOTIFY_ONE_VALUE:
3542 case NOTIFY_TWO_VALUE:
3543 return 1;
3544 case NOTIFY_STRING:
3545 return 2;
3547 /* The only pointer notify data I have seen on
3548 the wire is the submitted time and this has
3549 the notify size set to 4. -tpot */
3551 case NOTIFY_POINTER:
3552 return 4;
3554 case NOTIFY_SECDESC:
3555 return 5;
3560 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3562 return 0;
3565 /*******************************************************************
3566 Return the type of notify_info_data.
3567 ********************************************************************/
3569 static int type_of_notify_info_data(uint16 type, uint16 field)
3571 int i=0;
3573 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3574 if (notify_info_data_table[i].type == type &&
3575 notify_info_data_table[i].field == field)
3576 return notify_info_data_table[i].size;
3579 return False;
3582 /****************************************************************************
3583 ****************************************************************************/
3585 static int search_notify(uint16 type, uint16 field, int *value)
3587 int i;
3589 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3590 if (notify_info_data_table[i].type == type &&
3591 notify_info_data_table[i].field == field &&
3592 notify_info_data_table[i].fn != NULL) {
3593 *value = i;
3594 return True;
3598 return False;
3601 /****************************************************************************
3602 ****************************************************************************/
3604 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3606 info_data->type = type;
3607 info_data->field = field;
3608 info_data->reserved = 0;
3610 info_data->size = size_of_notify_info_data(type, field);
3611 info_data->enc_type = type_of_notify_info_data(type, field);
3613 info_data->id = id;
3618 /*******************************************************************
3620 * fill a notify_info struct with info asked
3622 ********************************************************************/
3624 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3625 snum, SPOOL_NOTIFY_OPTION_TYPE
3626 *option_type, uint32 id,
3627 TALLOC_CTX *mem_ctx)
3629 int field_num,j;
3630 uint16 type;
3631 uint16 field;
3633 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3634 NT_PRINTER_INFO_LEVEL *printer = NULL;
3635 print_queue_struct *queue=NULL;
3637 type=option_type->type;
3639 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3640 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3641 option_type->count, lp_servicename(snum)));
3643 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3644 return False;
3646 for(field_num=0; field_num<option_type->count; field_num++) {
3647 field = option_type->fields[field_num];
3649 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3651 if (!search_notify(type, field, &j) )
3652 continue;
3654 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3655 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3656 return False;
3657 } else
3658 info->data = tid;
3660 current_data = &info->data[info->count];
3662 construct_info_data(current_data, type, field, id);
3664 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3665 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3667 notify_info_data_table[j].fn(snum, current_data, queue,
3668 printer, mem_ctx);
3670 info->count++;
3673 free_a_printer(&printer, 2);
3674 return True;
3677 /*******************************************************************
3679 * fill a notify_info struct with info asked
3681 ********************************************************************/
3683 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3684 SPOOL_NOTIFY_INFO *info,
3685 NT_PRINTER_INFO_LEVEL *printer,
3686 int snum, SPOOL_NOTIFY_OPTION_TYPE
3687 *option_type, uint32 id,
3688 TALLOC_CTX *mem_ctx)
3690 int field_num,j;
3691 uint16 type;
3692 uint16 field;
3694 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3696 DEBUG(4,("construct_notify_jobs_info\n"));
3698 type = option_type->type;
3700 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3701 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3702 option_type->count));
3704 for(field_num=0; field_num<option_type->count; field_num++) {
3705 field = option_type->fields[field_num];
3707 if (!search_notify(type, field, &j) )
3708 continue;
3710 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3711 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3712 return False;
3714 else info->data = tid;
3716 current_data=&(info->data[info->count]);
3718 construct_info_data(current_data, type, field, id);
3719 notify_info_data_table[j].fn(snum, current_data, queue,
3720 printer, mem_ctx);
3721 info->count++;
3724 return True;
3728 * JFM: The enumeration is not that simple, it's even non obvious.
3730 * let's take an example: I want to monitor the PRINTER SERVER for
3731 * the printer's name and the number of jobs currently queued.
3732 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3733 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3735 * I have 3 printers on the back of my server.
3737 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3738 * structures.
3739 * Number Data Id
3740 * 1 printer 1 name 1
3741 * 2 printer 1 cjob 1
3742 * 3 printer 2 name 2
3743 * 4 printer 2 cjob 2
3744 * 5 printer 3 name 3
3745 * 6 printer 3 name 3
3747 * that's the print server case, the printer case is even worse.
3750 /*******************************************************************
3752 * enumerate all printers on the printserver
3753 * fill a notify_info struct with info asked
3755 ********************************************************************/
3757 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3758 SPOOL_NOTIFY_INFO *info,
3759 TALLOC_CTX *mem_ctx)
3761 int snum;
3762 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3763 int n_services=lp_numservices();
3764 int i;
3765 SPOOL_NOTIFY_OPTION *option;
3766 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3768 DEBUG(4,("printserver_notify_info\n"));
3770 if (!Printer)
3771 return WERR_BADFID;
3773 option=Printer->notify.option;
3774 info->version=2;
3775 info->data=NULL;
3776 info->count=0;
3778 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3779 sending a ffpcn() request first */
3781 if ( !option )
3782 return WERR_BADFID;
3784 for (i=0; i<option->count; i++) {
3785 option_type=&(option->ctr.type[i]);
3787 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3788 continue;
3790 for (snum=0; snum<n_services; snum++)
3792 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3793 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3797 #if 0
3799 * Debugging information, don't delete.
3802 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3803 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3804 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3806 for (i=0; i<info->count; i++) {
3807 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3808 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3809 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3811 #endif
3813 return WERR_OK;
3816 /*******************************************************************
3818 * fill a notify_info struct with info asked
3820 ********************************************************************/
3822 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3823 TALLOC_CTX *mem_ctx)
3825 int snum;
3826 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3827 int i;
3828 uint32 id;
3829 SPOOL_NOTIFY_OPTION *option;
3830 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3831 int count,j;
3832 print_queue_struct *queue=NULL;
3833 print_status_struct status;
3835 DEBUG(4,("printer_notify_info\n"));
3837 if (!Printer)
3838 return WERR_BADFID;
3840 option=Printer->notify.option;
3841 id = 0x0;
3842 info->version=2;
3843 info->data=NULL;
3844 info->count=0;
3846 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3847 sending a ffpcn() request first */
3849 if ( !option )
3850 return WERR_BADFID;
3852 get_printer_snum(p, hnd, &snum);
3854 for (i=0; i<option->count; i++) {
3855 option_type=&option->ctr.type[i];
3857 switch ( option_type->type ) {
3858 case PRINTER_NOTIFY_TYPE:
3859 if(construct_notify_printer_info(Printer, info, snum,
3860 option_type, id,
3861 mem_ctx))
3862 id--;
3863 break;
3865 case JOB_NOTIFY_TYPE: {
3866 NT_PRINTER_INFO_LEVEL *printer = NULL;
3868 count = print_queue_status(snum, &queue, &status);
3870 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3871 goto done;
3873 for (j=0; j<count; j++) {
3874 construct_notify_jobs_info(&queue[j], info,
3875 printer, snum,
3876 option_type,
3877 queue[j].job,
3878 mem_ctx);
3881 free_a_printer(&printer, 2);
3883 done:
3884 SAFE_FREE(queue);
3885 break;
3891 * Debugging information, don't delete.
3894 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3895 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3896 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3898 for (i=0; i<info->count; i++) {
3899 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3900 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3901 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3904 return WERR_OK;
3907 /********************************************************************
3908 * spoolss_rfnpcnex
3909 ********************************************************************/
3911 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3913 POLICY_HND *handle = &q_u->handle;
3914 SPOOL_NOTIFY_INFO *info = &r_u->info;
3916 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3917 WERROR result = WERR_BADFID;
3919 /* we always have a NOTIFY_INFO struct */
3920 r_u->info_ptr=0x1;
3922 if (!Printer) {
3923 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3924 OUR_HANDLE(handle)));
3925 goto done;
3928 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3931 * We are now using the change value, and
3932 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3933 * I don't have a global notification system, I'm sending back all the
3934 * informations even when _NOTHING_ has changed.
3937 /* We need to keep track of the change value to send back in
3938 RRPCN replies otherwise our updates are ignored. */
3940 Printer->notify.fnpcn = True;
3942 if (Printer->notify.client_connected) {
3943 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3944 Printer->notify.change = q_u->change;
3947 /* just ignore the SPOOL_NOTIFY_OPTION */
3949 switch (Printer->printer_type) {
3950 case PRINTER_HANDLE_IS_PRINTSERVER:
3951 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3952 break;
3954 case PRINTER_HANDLE_IS_PRINTER:
3955 result = printer_notify_info(p, handle, info, p->mem_ctx);
3956 break;
3959 Printer->notify.fnpcn = False;
3961 done:
3962 return result;
3965 /********************************************************************
3966 * construct_printer_info_0
3967 * fill a printer_info_0 struct
3968 ********************************************************************/
3970 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3972 pstring chaine;
3973 int count;
3974 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3975 counter_printer_0 *session_counter;
3976 uint32 global_counter;
3977 struct tm *t;
3978 time_t setuptime;
3979 print_status_struct status;
3981 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3982 return False;
3984 count = print_queue_length(snum, &status);
3986 /* check if we already have a counter for this printer */
3987 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3988 if (session_counter->snum == snum)
3989 break;
3992 /* it's the first time, add it to the list */
3993 if (session_counter==NULL) {
3994 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3995 free_a_printer(&ntprinter, 2);
3996 return False;
3998 ZERO_STRUCTP(session_counter);
3999 session_counter->snum=snum;
4000 session_counter->counter=0;
4001 DLIST_ADD(counter_list, session_counter);
4004 /* increment it */
4005 session_counter->counter++;
4007 /* JFM:
4008 * the global_counter should be stored in a TDB as it's common to all the clients
4009 * and should be zeroed on samba startup
4011 global_counter=session_counter->counter;
4013 pstrcpy(chaine,ntprinter->info_2->printername);
4015 init_unistr(&printer->printername, chaine);
4017 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
4018 init_unistr(&printer->servername, chaine);
4020 printer->cjobs = count;
4021 printer->total_jobs = 0;
4022 printer->total_bytes = 0;
4024 setuptime = (time_t)ntprinter->info_2->setuptime;
4025 t=gmtime(&setuptime);
4027 printer->year = t->tm_year+1900;
4028 printer->month = t->tm_mon+1;
4029 printer->dayofweek = t->tm_wday;
4030 printer->day = t->tm_mday;
4031 printer->hour = t->tm_hour;
4032 printer->minute = t->tm_min;
4033 printer->second = t->tm_sec;
4034 printer->milliseconds = 0;
4036 printer->global_counter = global_counter;
4037 printer->total_pages = 0;
4039 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4040 printer->major_version = 0x0005; /* NT 5 */
4041 printer->build_version = 0x0893; /* build 2195 */
4043 printer->unknown7 = 0x1;
4044 printer->unknown8 = 0x0;
4045 printer->unknown9 = 0x0;
4046 printer->session_counter = session_counter->counter;
4047 printer->unknown11 = 0x0;
4048 printer->printer_errors = 0x0; /* number of print failure */
4049 printer->unknown13 = 0x0;
4050 printer->unknown14 = 0x1;
4051 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4052 printer->unknown16 = 0x0;
4053 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4054 printer->unknown18 = 0x0;
4055 printer->status = nt_printq_status(status.status);
4056 printer->unknown20 = 0x0;
4057 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4058 printer->unknown22 = 0x0;
4059 printer->unknown23 = 0x6; /* 6 ???*/
4060 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4061 printer->unknown25 = 0;
4062 printer->unknown26 = 0;
4063 printer->unknown27 = 0;
4064 printer->unknown28 = 0;
4065 printer->unknown29 = 0;
4067 free_a_printer(&ntprinter,2);
4068 return (True);
4071 /********************************************************************
4072 * construct_printer_info_1
4073 * fill a printer_info_1 struct
4074 ********************************************************************/
4075 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4077 pstring chaine;
4078 pstring chaine2;
4079 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4081 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4082 return False;
4084 printer->flags=flags;
4086 if (*ntprinter->info_2->comment == '\0') {
4087 init_unistr(&printer->comment, lp_comment(snum));
4088 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4089 ntprinter->info_2->drivername, lp_comment(snum));
4091 else {
4092 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4093 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4094 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4097 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4099 init_unistr(&printer->description, chaine);
4100 init_unistr(&printer->name, chaine2);
4102 free_a_printer(&ntprinter,2);
4104 return True;
4107 /****************************************************************************
4108 Free a DEVMODE struct.
4109 ****************************************************************************/
4111 static void free_dev_mode(DEVICEMODE *dev)
4113 if (dev == NULL)
4114 return;
4116 SAFE_FREE(dev->private);
4117 SAFE_FREE(dev);
4121 /****************************************************************************
4122 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4123 should be valid upon entry
4124 ****************************************************************************/
4126 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4128 if ( !devmode || !ntdevmode )
4129 return False;
4131 init_unistr(&devmode->devicename, ntdevmode->devicename);
4133 init_unistr(&devmode->formname, ntdevmode->formname);
4135 devmode->specversion = ntdevmode->specversion;
4136 devmode->driverversion = ntdevmode->driverversion;
4137 devmode->size = ntdevmode->size;
4138 devmode->driverextra = ntdevmode->driverextra;
4139 devmode->fields = ntdevmode->fields;
4141 devmode->orientation = ntdevmode->orientation;
4142 devmode->papersize = ntdevmode->papersize;
4143 devmode->paperlength = ntdevmode->paperlength;
4144 devmode->paperwidth = ntdevmode->paperwidth;
4145 devmode->scale = ntdevmode->scale;
4146 devmode->copies = ntdevmode->copies;
4147 devmode->defaultsource = ntdevmode->defaultsource;
4148 devmode->printquality = ntdevmode->printquality;
4149 devmode->color = ntdevmode->color;
4150 devmode->duplex = ntdevmode->duplex;
4151 devmode->yresolution = ntdevmode->yresolution;
4152 devmode->ttoption = ntdevmode->ttoption;
4153 devmode->collate = ntdevmode->collate;
4154 devmode->icmmethod = ntdevmode->icmmethod;
4155 devmode->icmintent = ntdevmode->icmintent;
4156 devmode->mediatype = ntdevmode->mediatype;
4157 devmode->dithertype = ntdevmode->dithertype;
4159 if (ntdevmode->private != NULL) {
4160 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4161 return False;
4164 return True;
4167 /****************************************************************************
4168 Create a DEVMODE struct. Returns malloced memory.
4169 ****************************************************************************/
4171 DEVICEMODE *construct_dev_mode(int snum)
4173 NT_PRINTER_INFO_LEVEL *printer = NULL;
4174 DEVICEMODE *devmode = NULL;
4176 DEBUG(7,("construct_dev_mode\n"));
4178 DEBUGADD(8,("getting printer characteristics\n"));
4180 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4181 return NULL;
4183 if ( !printer->info_2->devmode ) {
4184 DEBUG(5, ("BONG! There was no device mode!\n"));
4185 goto done;
4188 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4189 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4190 goto done;
4193 ZERO_STRUCTP(devmode);
4195 DEBUGADD(8,("loading DEVICEMODE\n"));
4197 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4198 free_dev_mode( devmode );
4199 devmode = NULL;
4202 done:
4203 free_a_printer(&printer,2);
4205 return devmode;
4208 /********************************************************************
4209 * construct_printer_info_2
4210 * fill a printer_info_2 struct
4211 ********************************************************************/
4213 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4215 int count;
4216 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4218 print_status_struct status;
4220 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4221 return False;
4223 count = print_queue_length(snum, &status);
4225 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4226 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4227 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4228 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4229 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4231 if (*ntprinter->info_2->comment == '\0')
4232 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4233 else
4234 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4236 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4237 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4238 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4239 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4240 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4242 printer->attributes = ntprinter->info_2->attributes;
4244 printer->priority = ntprinter->info_2->priority; /* priority */
4245 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4246 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4247 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4248 printer->status = nt_printq_status(status.status); /* status */
4249 printer->cjobs = count; /* jobs */
4250 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4252 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4253 DEBUG(8, ("Returning NULL Devicemode!\n"));
4256 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4257 /* steal the printer info sec_desc structure. [badly done]. */
4258 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4259 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4260 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4261 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4263 else {
4264 printer->secdesc = NULL;
4267 free_a_printer(&ntprinter, 2);
4268 return True;
4271 /********************************************************************
4272 * construct_printer_info_3
4273 * fill a printer_info_3 struct
4274 ********************************************************************/
4276 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4278 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4279 PRINTER_INFO_3 *printer = NULL;
4281 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4282 return False;
4284 *pp_printer = NULL;
4285 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4286 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4287 return False;
4290 ZERO_STRUCTP(printer);
4292 printer->flags = 4; /* These are the components of the SD we are returning. */
4293 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4294 /* steal the printer info sec_desc structure. [badly done]. */
4295 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4297 #if 0
4299 * Set the flags for the components we are returning.
4302 if (printer->secdesc->owner_sid)
4303 printer->flags |= OWNER_SECURITY_INFORMATION;
4305 if (printer->secdesc->grp_sid)
4306 printer->flags |= GROUP_SECURITY_INFORMATION;
4308 if (printer->secdesc->dacl)
4309 printer->flags |= DACL_SECURITY_INFORMATION;
4311 if (printer->secdesc->sacl)
4312 printer->flags |= SACL_SECURITY_INFORMATION;
4313 #endif
4315 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4316 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4317 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4320 free_a_printer(&ntprinter, 2);
4322 *pp_printer = printer;
4323 return True;
4326 /********************************************************************
4327 * construct_printer_info_4
4328 * fill a printer_info_4 struct
4329 ********************************************************************/
4331 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4333 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4335 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4336 return False;
4338 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4339 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4340 printer->attributes = ntprinter->info_2->attributes;
4342 free_a_printer(&ntprinter, 2);
4343 return True;
4346 /********************************************************************
4347 * construct_printer_info_5
4348 * fill a printer_info_5 struct
4349 ********************************************************************/
4351 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4353 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4355 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4356 return False;
4358 init_unistr(&printer->printername, ntprinter->info_2->printername);
4359 init_unistr(&printer->portname, ntprinter->info_2->portname);
4360 printer->attributes = ntprinter->info_2->attributes;
4362 /* these two are not used by NT+ according to MSDN */
4364 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4365 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4367 free_a_printer(&ntprinter, 2);
4369 return True;
4372 /********************************************************************
4373 * construct_printer_info_7
4374 * fill a printer_info_7 struct
4375 ********************************************************************/
4377 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4379 char *guid_str = NULL;
4380 struct uuid guid;
4382 if (is_printer_published(print_hnd, snum, &guid)) {
4383 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4384 strupper_m(guid_str);
4385 init_unistr(&printer->guid, guid_str);
4386 printer->action = SPOOL_DS_PUBLISH;
4387 } else {
4388 init_unistr(&printer->guid, "");
4389 printer->action = SPOOL_DS_UNPUBLISH;
4392 return True;
4395 /********************************************************************
4396 Spoolss_enumprinters.
4397 ********************************************************************/
4399 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4401 int snum;
4402 int i;
4403 int n_services=lp_numservices();
4404 PRINTER_INFO_1 *tp, *printers=NULL;
4405 PRINTER_INFO_1 current_prt;
4407 DEBUG(4,("enum_all_printers_info_1\n"));
4409 for (snum=0; snum<n_services; snum++) {
4410 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4411 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4413 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4414 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4415 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4416 SAFE_FREE(printers);
4417 *returned=0;
4418 return WERR_NOMEM;
4420 else printers = tp;
4421 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4423 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4424 (*returned)++;
4429 /* check the required size. */
4430 for (i=0; i<*returned; i++)
4431 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4433 if (!alloc_buffer_size(buffer, *needed))
4434 return WERR_INSUFFICIENT_BUFFER;
4436 /* fill the buffer with the structures */
4437 for (i=0; i<*returned; i++)
4438 smb_io_printer_info_1("", buffer, &printers[i], 0);
4440 /* clear memory */
4441 SAFE_FREE(printers);
4443 if (*needed > offered) {
4444 *returned=0;
4445 return WERR_INSUFFICIENT_BUFFER;
4447 else
4448 return WERR_OK;
4451 /********************************************************************
4452 enum_all_printers_info_1_local.
4453 *********************************************************************/
4455 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4457 DEBUG(4,("enum_all_printers_info_1_local\n"));
4459 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4462 /********************************************************************
4463 enum_all_printers_info_1_name.
4464 *********************************************************************/
4466 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4468 char *s = name;
4470 DEBUG(4,("enum_all_printers_info_1_name\n"));
4472 if ((name[0] == '\\') && (name[1] == '\\'))
4473 s = name + 2;
4475 if (is_myname_or_ipaddr(s)) {
4476 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4478 else
4479 return WERR_INVALID_NAME;
4482 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4483 /********************************************************************
4484 enum_all_printers_info_1_remote.
4485 *********************************************************************/
4487 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4489 PRINTER_INFO_1 *printer;
4490 fstring printername;
4491 fstring desc;
4492 fstring comment;
4493 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4495 /* JFM: currently it's more a place holder than anything else.
4496 * In the spooler world there is a notion of server registration.
4497 * the print servers are registered on the PDC (in the same domain)
4499 * We should have a TDB here. The registration is done thru an
4500 * undocumented RPC call.
4503 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4504 return WERR_NOMEM;
4506 *returned=1;
4508 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4509 slprintf(desc, sizeof(desc)-1,"%s", name);
4510 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4512 init_unistr(&printer->description, desc);
4513 init_unistr(&printer->name, printername);
4514 init_unistr(&printer->comment, comment);
4515 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4517 /* check the required size. */
4518 *needed += spoolss_size_printer_info_1(printer);
4520 if (!alloc_buffer_size(buffer, *needed)) {
4521 SAFE_FREE(printer);
4522 return WERR_INSUFFICIENT_BUFFER;
4525 /* fill the buffer with the structures */
4526 smb_io_printer_info_1("", buffer, printer, 0);
4528 /* clear memory */
4529 SAFE_FREE(printer);
4531 if (*needed > offered) {
4532 *returned=0;
4533 return WERR_INSUFFICIENT_BUFFER;
4535 else
4536 return WERR_OK;
4539 #endif
4541 /********************************************************************
4542 enum_all_printers_info_1_network.
4543 *********************************************************************/
4545 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4547 char *s = name;
4549 DEBUG(4,("enum_all_printers_info_1_network\n"));
4551 /* If we respond to a enum_printers level 1 on our name with flags
4552 set to PRINTER_ENUM_REMOTE with a list of printers then these
4553 printers incorrectly appear in the APW browse list.
4554 Specifically the printers for the server appear at the workgroup
4555 level where all the other servers in the domain are
4556 listed. Windows responds to this call with a
4557 WERR_CAN_NOT_COMPLETE so we should do the same. */
4559 if (name[0] == '\\' && name[1] == '\\')
4560 s = name + 2;
4562 if (is_myname_or_ipaddr(s))
4563 return WERR_CAN_NOT_COMPLETE;
4565 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4568 /********************************************************************
4569 * api_spoolss_enumprinters
4571 * called from api_spoolss_enumprinters (see this to understand)
4572 ********************************************************************/
4574 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4576 int snum;
4577 int i;
4578 int n_services=lp_numservices();
4579 PRINTER_INFO_2 *tp, *printers=NULL;
4580 PRINTER_INFO_2 current_prt;
4582 for (snum=0; snum<n_services; snum++) {
4583 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4584 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4586 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4587 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) == NULL) {
4588 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4589 SAFE_FREE(printers);
4590 *returned = 0;
4591 return WERR_NOMEM;
4593 else printers = tp;
4594 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4595 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4596 (*returned)++;
4601 /* check the required size. */
4602 for (i=0; i<*returned; i++)
4603 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4605 if (!alloc_buffer_size(buffer, *needed)) {
4606 for (i=0; i<*returned; i++) {
4607 free_devmode(printers[i].devmode);
4609 SAFE_FREE(printers);
4610 return WERR_INSUFFICIENT_BUFFER;
4613 /* fill the buffer with the structures */
4614 for (i=0; i<*returned; i++)
4615 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4617 /* clear memory */
4618 for (i=0; i<*returned; i++) {
4619 free_devmode(printers[i].devmode);
4621 SAFE_FREE(printers);
4623 if (*needed > offered) {
4624 *returned=0;
4625 return WERR_INSUFFICIENT_BUFFER;
4627 else
4628 return WERR_OK;
4631 /********************************************************************
4632 * handle enumeration of printers at level 1
4633 ********************************************************************/
4635 static WERROR enumprinters_level1( uint32 flags, fstring name,
4636 NEW_BUFFER *buffer, uint32 offered,
4637 uint32 *needed, uint32 *returned)
4639 /* Not all the flags are equals */
4641 if (flags & PRINTER_ENUM_LOCAL)
4642 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4644 if (flags & PRINTER_ENUM_NAME)
4645 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4647 #if 0 /* JERRY - disabled for now */
4648 if (flags & PRINTER_ENUM_REMOTE)
4649 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4650 #endif
4652 if (flags & PRINTER_ENUM_NETWORK)
4653 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4655 return WERR_OK; /* NT4sp5 does that */
4658 /********************************************************************
4659 * handle enumeration of printers at level 2
4660 ********************************************************************/
4662 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4663 NEW_BUFFER *buffer, uint32 offered,
4664 uint32 *needed, uint32 *returned)
4666 char *s = servername;
4668 if (flags & PRINTER_ENUM_LOCAL) {
4669 return enum_all_printers_info_2(buffer, offered, needed, returned);
4672 if (flags & PRINTER_ENUM_NAME) {
4673 if ((servername[0] == '\\') && (servername[1] == '\\'))
4674 s = servername + 2;
4675 if (is_myname_or_ipaddr(s))
4676 return enum_all_printers_info_2(buffer, offered, needed, returned);
4677 else
4678 return WERR_INVALID_NAME;
4681 if (flags & PRINTER_ENUM_REMOTE)
4682 return WERR_UNKNOWN_LEVEL;
4684 return WERR_OK;
4687 /********************************************************************
4688 * handle enumeration of printers at level 5
4689 ********************************************************************/
4691 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4692 NEW_BUFFER *buffer, uint32 offered,
4693 uint32 *needed, uint32 *returned)
4695 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4696 return WERR_OK;
4699 /********************************************************************
4700 * api_spoolss_enumprinters
4702 * called from api_spoolss_enumprinters (see this to understand)
4703 ********************************************************************/
4705 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4707 uint32 flags = q_u->flags;
4708 UNISTR2 *servername = &q_u->servername;
4709 uint32 level = q_u->level;
4710 NEW_BUFFER *buffer = NULL;
4711 uint32 offered = q_u->offered;
4712 uint32 *needed = &r_u->needed;
4713 uint32 *returned = &r_u->returned;
4715 fstring name;
4717 /* that's an [in out] buffer */
4718 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4719 buffer = r_u->buffer;
4721 DEBUG(4,("_spoolss_enumprinters\n"));
4723 *needed=0;
4724 *returned=0;
4727 * Level 1:
4728 * flags==PRINTER_ENUM_NAME
4729 * if name=="" then enumerates all printers
4730 * if name!="" then enumerate the printer
4731 * flags==PRINTER_ENUM_REMOTE
4732 * name is NULL, enumerate printers
4733 * Level 2: name!="" enumerates printers, name can't be NULL
4734 * Level 3: doesn't exist
4735 * Level 4: does a local registry lookup
4736 * Level 5: same as Level 2
4739 unistr2_to_ascii(name, servername, sizeof(name)-1);
4740 strupper_m(name);
4742 switch (level) {
4743 case 1:
4744 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4745 case 2:
4746 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4747 case 5:
4748 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4749 case 3:
4750 case 4:
4751 break;
4753 return WERR_UNKNOWN_LEVEL;
4756 /****************************************************************************
4757 ****************************************************************************/
4759 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4761 PRINTER_INFO_0 *printer=NULL;
4763 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4764 return WERR_NOMEM;
4766 construct_printer_info_0(print_hnd, printer, snum);
4768 /* check the required size. */
4769 *needed += spoolss_size_printer_info_0(printer);
4771 if (!alloc_buffer_size(buffer, *needed)) {
4772 SAFE_FREE(printer);
4773 return WERR_INSUFFICIENT_BUFFER;
4776 /* fill the buffer with the structures */
4777 smb_io_printer_info_0("", buffer, printer, 0);
4779 /* clear memory */
4780 SAFE_FREE(printer);
4782 if (*needed > offered) {
4783 return WERR_INSUFFICIENT_BUFFER;
4786 return WERR_OK;
4789 /****************************************************************************
4790 ****************************************************************************/
4792 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4794 PRINTER_INFO_1 *printer=NULL;
4796 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4797 return WERR_NOMEM;
4799 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4801 /* check the required size. */
4802 *needed += spoolss_size_printer_info_1(printer);
4804 if (!alloc_buffer_size(buffer, *needed)) {
4805 SAFE_FREE(printer);
4806 return WERR_INSUFFICIENT_BUFFER;
4809 /* fill the buffer with the structures */
4810 smb_io_printer_info_1("", buffer, printer, 0);
4812 /* clear memory */
4813 SAFE_FREE(printer);
4815 if (*needed > offered) {
4816 return WERR_INSUFFICIENT_BUFFER;
4819 return WERR_OK;
4822 /****************************************************************************
4823 ****************************************************************************/
4825 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4827 PRINTER_INFO_2 *printer=NULL;
4829 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4830 return WERR_NOMEM;
4832 construct_printer_info_2(print_hnd, printer, snum);
4834 /* check the required size. */
4835 *needed += spoolss_size_printer_info_2(printer);
4837 if (!alloc_buffer_size(buffer, *needed)) {
4838 free_printer_info_2(printer);
4839 return WERR_INSUFFICIENT_BUFFER;
4842 /* fill the buffer with the structures */
4843 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4844 free_printer_info_2(printer);
4845 return WERR_NOMEM;
4848 /* clear memory */
4849 free_printer_info_2(printer);
4851 if (*needed > offered) {
4852 return WERR_INSUFFICIENT_BUFFER;
4855 return WERR_OK;
4858 /****************************************************************************
4859 ****************************************************************************/
4861 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4863 PRINTER_INFO_3 *printer=NULL;
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 (!alloc_buffer_size(buffer, *needed)) {
4872 free_printer_info_3(printer);
4873 return WERR_INSUFFICIENT_BUFFER;
4876 /* fill the buffer with the structures */
4877 smb_io_printer_info_3("", buffer, printer, 0);
4879 /* clear memory */
4880 free_printer_info_3(printer);
4882 if (*needed > offered) {
4883 return WERR_INSUFFICIENT_BUFFER;
4886 return WERR_OK;
4889 /****************************************************************************
4890 ****************************************************************************/
4892 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4894 PRINTER_INFO_4 *printer=NULL;
4896 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4897 return WERR_NOMEM;
4899 if (!construct_printer_info_4(print_hnd, printer, snum))
4900 return WERR_NOMEM;
4902 /* check the required size. */
4903 *needed += spoolss_size_printer_info_4(printer);
4905 if (!alloc_buffer_size(buffer, *needed)) {
4906 free_printer_info_4(printer);
4907 return WERR_INSUFFICIENT_BUFFER;
4910 /* fill the buffer with the structures */
4911 smb_io_printer_info_4("", buffer, printer, 0);
4913 /* clear memory */
4914 free_printer_info_4(printer);
4916 if (*needed > offered) {
4917 return WERR_INSUFFICIENT_BUFFER;
4920 return WERR_OK;
4923 /****************************************************************************
4924 ****************************************************************************/
4926 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4928 PRINTER_INFO_5 *printer=NULL;
4930 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4931 return WERR_NOMEM;
4933 if (!construct_printer_info_5(print_hnd, printer, snum))
4934 return WERR_NOMEM;
4936 /* check the required size. */
4937 *needed += spoolss_size_printer_info_5(printer);
4939 if (!alloc_buffer_size(buffer, *needed)) {
4940 free_printer_info_5(printer);
4941 return WERR_INSUFFICIENT_BUFFER;
4944 /* fill the buffer with the structures */
4945 smb_io_printer_info_5("", buffer, printer, 0);
4947 /* clear memory */
4948 free_printer_info_5(printer);
4950 if (*needed > offered) {
4951 return WERR_INSUFFICIENT_BUFFER;
4954 return WERR_OK;
4957 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4959 PRINTER_INFO_7 *printer=NULL;
4961 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4962 return WERR_NOMEM;
4964 if (!construct_printer_info_7(print_hnd, printer, snum))
4965 return WERR_NOMEM;
4967 /* check the required size. */
4968 *needed += spoolss_size_printer_info_7(printer);
4970 if (!alloc_buffer_size(buffer, *needed)) {
4971 free_printer_info_7(printer);
4972 return WERR_INSUFFICIENT_BUFFER;
4975 /* fill the buffer with the structures */
4976 smb_io_printer_info_7("", buffer, printer, 0);
4978 /* clear memory */
4979 free_printer_info_7(printer);
4981 if (*needed > offered) {
4982 return WERR_INSUFFICIENT_BUFFER;
4985 return WERR_OK;
4988 /****************************************************************************
4989 ****************************************************************************/
4991 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4993 POLICY_HND *handle = &q_u->handle;
4994 uint32 level = q_u->level;
4995 NEW_BUFFER *buffer = NULL;
4996 uint32 offered = q_u->offered;
4997 uint32 *needed = &r_u->needed;
4998 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5000 int snum;
5002 /* that's an [in out] buffer */
5003 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5004 buffer = r_u->buffer;
5006 *needed=0;
5008 if (!get_printer_snum(p, handle, &snum))
5009 return WERR_BADFID;
5011 switch (level) {
5012 case 0:
5013 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5014 case 1:
5015 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5016 case 2:
5017 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5018 case 3:
5019 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5020 case 4:
5021 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5022 case 5:
5023 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5024 case 7:
5025 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5027 return WERR_UNKNOWN_LEVEL;
5030 /********************************************************************
5031 * fill a DRIVER_INFO_1 struct
5032 ********************************************************************/
5034 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5036 init_unistr( &info->name, driver.info_3->name);
5039 /********************************************************************
5040 * construct_printer_driver_info_1
5041 ********************************************************************/
5043 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5045 NT_PRINTER_INFO_LEVEL *printer = NULL;
5046 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5048 ZERO_STRUCT(driver);
5050 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5051 return WERR_INVALID_PRINTER_NAME;
5053 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5054 return WERR_UNKNOWN_PRINTER_DRIVER;
5056 fill_printer_driver_info_1(info, driver, servername, architecture);
5058 free_a_printer(&printer,2);
5060 return WERR_OK;
5063 /********************************************************************
5064 * construct_printer_driver_info_2
5065 * fill a printer_info_2 struct
5066 ********************************************************************/
5068 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5070 pstring temp;
5072 info->version=driver.info_3->cversion;
5074 init_unistr( &info->name, driver.info_3->name );
5075 init_unistr( &info->architecture, driver.info_3->environment );
5078 if (strlen(driver.info_3->driverpath)) {
5079 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5080 init_unistr( &info->driverpath, temp );
5081 } else
5082 init_unistr( &info->driverpath, "" );
5084 if (strlen(driver.info_3->datafile)) {
5085 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5086 init_unistr( &info->datafile, temp );
5087 } else
5088 init_unistr( &info->datafile, "" );
5090 if (strlen(driver.info_3->configfile)) {
5091 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5092 init_unistr( &info->configfile, temp );
5093 } else
5094 init_unistr( &info->configfile, "" );
5097 /********************************************************************
5098 * construct_printer_driver_info_2
5099 * fill a printer_info_2 struct
5100 ********************************************************************/
5102 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5104 NT_PRINTER_INFO_LEVEL *printer = NULL;
5105 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5107 ZERO_STRUCT(printer);
5108 ZERO_STRUCT(driver);
5110 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5111 return WERR_INVALID_PRINTER_NAME;
5113 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5114 return WERR_UNKNOWN_PRINTER_DRIVER;
5116 fill_printer_driver_info_2(info, driver, servername);
5118 free_a_printer(&printer,2);
5120 return WERR_OK;
5123 /********************************************************************
5124 * copy a strings array and convert to UNICODE
5126 * convert an array of ascii string to a UNICODE string
5127 ********************************************************************/
5129 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5131 int i=0;
5132 int j=0;
5133 const char *v;
5134 pstring line;
5135 uint16 *tuary;
5137 DEBUG(6,("init_unistr_array\n"));
5138 *uni_array=NULL;
5140 while (True)
5142 if ( !char_array )
5143 v = "";
5144 else
5146 v = char_array[i];
5147 if (!v)
5148 v = ""; /* hack to handle null lists */
5151 /* hack to allow this to be used in places other than when generating
5152 the list of dependent files */
5154 if ( servername )
5155 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5156 else
5157 pstrcpy( line, v );
5159 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5161 /* add one extra unit16 for the second terminating NULL */
5163 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5164 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5165 return 0;
5166 } else
5167 *uni_array = tuary;
5169 if ( !strlen(v) )
5170 break;
5172 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5173 i++;
5176 if (*uni_array) {
5177 /* special case for ""; we need to add both NULL's here */
5178 if (!j)
5179 (*uni_array)[j++]=0x0000;
5180 (*uni_array)[j]=0x0000;
5183 DEBUGADD(6,("last one:done\n"));
5185 /* return size of array in uint16's */
5187 return j+1;
5190 /********************************************************************
5191 * construct_printer_info_3
5192 * fill a printer_info_3 struct
5193 ********************************************************************/
5195 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5197 pstring temp;
5199 ZERO_STRUCTP(info);
5201 info->version=driver.info_3->cversion;
5203 init_unistr( &info->name, driver.info_3->name );
5204 init_unistr( &info->architecture, driver.info_3->environment );
5206 if (strlen(driver.info_3->driverpath)) {
5207 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5208 init_unistr( &info->driverpath, temp );
5209 } else
5210 init_unistr( &info->driverpath, "" );
5212 if (strlen(driver.info_3->datafile)) {
5213 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5214 init_unistr( &info->datafile, temp );
5215 } else
5216 init_unistr( &info->datafile, "" );
5218 if (strlen(driver.info_3->configfile)) {
5219 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5220 init_unistr( &info->configfile, temp );
5221 } else
5222 init_unistr( &info->configfile, "" );
5224 if (strlen(driver.info_3->helpfile)) {
5225 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5226 init_unistr( &info->helpfile, temp );
5227 } else
5228 init_unistr( &info->helpfile, "" );
5230 init_unistr( &info->monitorname, driver.info_3->monitorname );
5231 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5233 info->dependentfiles=NULL;
5234 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5237 /********************************************************************
5238 * construct_printer_info_3
5239 * fill a printer_info_3 struct
5240 ********************************************************************/
5242 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5244 NT_PRINTER_INFO_LEVEL *printer = NULL;
5245 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5246 WERROR status;
5247 ZERO_STRUCT(driver);
5249 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5250 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5251 if (!W_ERROR_IS_OK(status))
5252 return WERR_INVALID_PRINTER_NAME;
5254 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5255 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5257 #if 0 /* JERRY */
5260 * I put this code in during testing. Helpful when commenting out the
5261 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5262 * as win2k always queries the driver using an infor level of 6.
5263 * I've left it in (but ifdef'd out) because I'll probably
5264 * use it in experimentation again in the future. --jerry 22/01/2002
5267 if (!W_ERROR_IS_OK(status)) {
5269 * Is this a W2k client ?
5271 if (version == 3) {
5272 /* Yes - try again with a WinNT driver. */
5273 version = 2;
5274 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5275 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5277 #endif
5279 if (!W_ERROR_IS_OK(status)) {
5280 free_a_printer(&printer,2);
5281 return WERR_UNKNOWN_PRINTER_DRIVER;
5284 #if 0 /* JERRY */
5286 #endif
5289 fill_printer_driver_info_3(info, driver, servername);
5291 free_a_printer(&printer,2);
5293 return WERR_OK;
5296 /********************************************************************
5297 * construct_printer_info_6
5298 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5299 ********************************************************************/
5301 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5303 pstring temp;
5304 fstring nullstr;
5306 ZERO_STRUCTP(info);
5307 memset(&nullstr, '\0', sizeof(fstring));
5309 info->version=driver.info_3->cversion;
5311 init_unistr( &info->name, driver.info_3->name );
5312 init_unistr( &info->architecture, driver.info_3->environment );
5314 if (strlen(driver.info_3->driverpath)) {
5315 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5316 init_unistr( &info->driverpath, temp );
5317 } else
5318 init_unistr( &info->driverpath, "" );
5320 if (strlen(driver.info_3->datafile)) {
5321 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5322 init_unistr( &info->datafile, temp );
5323 } else
5324 init_unistr( &info->datafile, "" );
5326 if (strlen(driver.info_3->configfile)) {
5327 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5328 init_unistr( &info->configfile, temp );
5329 } else
5330 init_unistr( &info->configfile, "" );
5332 if (strlen(driver.info_3->helpfile)) {
5333 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5334 init_unistr( &info->helpfile, temp );
5335 } else
5336 init_unistr( &info->helpfile, "" );
5338 init_unistr( &info->monitorname, driver.info_3->monitorname );
5339 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5341 info->dependentfiles = NULL;
5342 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5344 info->previousdrivernames=NULL;
5345 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5347 info->driver_date.low=0;
5348 info->driver_date.high=0;
5350 info->padding=0;
5351 info->driver_version_low=0;
5352 info->driver_version_high=0;
5354 init_unistr( &info->mfgname, "");
5355 init_unistr( &info->oem_url, "");
5356 init_unistr( &info->hardware_id, "");
5357 init_unistr( &info->provider, "");
5360 /********************************************************************
5361 * construct_printer_info_6
5362 * fill a printer_info_6 struct
5363 ********************************************************************/
5365 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5366 fstring servername, fstring architecture, uint32 version)
5368 NT_PRINTER_INFO_LEVEL *printer = NULL;
5369 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5370 WERROR status;
5372 ZERO_STRUCT(driver);
5374 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5376 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5378 if (!W_ERROR_IS_OK(status))
5379 return WERR_INVALID_PRINTER_NAME;
5381 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5383 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5385 if (!W_ERROR_IS_OK(status))
5388 * Is this a W2k client ?
5391 if (version < 3) {
5392 free_a_printer(&printer,2);
5393 return WERR_UNKNOWN_PRINTER_DRIVER;
5396 /* Yes - try again with a WinNT driver. */
5397 version = 2;
5398 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5399 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5400 if (!W_ERROR_IS_OK(status)) {
5401 free_a_printer(&printer,2);
5402 return WERR_UNKNOWN_PRINTER_DRIVER;
5406 fill_printer_driver_info_6(info, driver, servername);
5408 free_a_printer(&printer,2);
5409 free_a_printer_driver(driver, 3);
5411 return WERR_OK;
5414 /****************************************************************************
5415 ****************************************************************************/
5417 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5419 SAFE_FREE(info->dependentfiles);
5422 /****************************************************************************
5423 ****************************************************************************/
5425 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5427 SAFE_FREE(info->dependentfiles);
5431 /****************************************************************************
5432 ****************************************************************************/
5434 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5436 DRIVER_INFO_1 *info=NULL;
5437 WERROR status;
5439 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5440 return WERR_NOMEM;
5442 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5443 if (!W_ERROR_IS_OK(status)) {
5444 SAFE_FREE(info);
5445 return status;
5448 /* check the required size. */
5449 *needed += spoolss_size_printer_driver_info_1(info);
5451 if (!alloc_buffer_size(buffer, *needed)) {
5452 SAFE_FREE(info);
5453 return WERR_INSUFFICIENT_BUFFER;
5456 /* fill the buffer with the structures */
5457 smb_io_printer_driver_info_1("", buffer, info, 0);
5459 /* clear memory */
5460 SAFE_FREE(info);
5462 if (*needed > offered)
5463 return WERR_INSUFFICIENT_BUFFER;
5465 return WERR_OK;
5468 /****************************************************************************
5469 ****************************************************************************/
5471 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5473 DRIVER_INFO_2 *info=NULL;
5474 WERROR status;
5476 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5477 return WERR_NOMEM;
5479 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5480 if (!W_ERROR_IS_OK(status)) {
5481 SAFE_FREE(info);
5482 return status;
5485 /* check the required size. */
5486 *needed += spoolss_size_printer_driver_info_2(info);
5488 if (!alloc_buffer_size(buffer, *needed)) {
5489 SAFE_FREE(info);
5490 return WERR_INSUFFICIENT_BUFFER;
5493 /* fill the buffer with the structures */
5494 smb_io_printer_driver_info_2("", buffer, info, 0);
5496 /* clear memory */
5497 SAFE_FREE(info);
5499 if (*needed > offered)
5500 return WERR_INSUFFICIENT_BUFFER;
5502 return WERR_OK;
5505 /****************************************************************************
5506 ****************************************************************************/
5508 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5510 DRIVER_INFO_3 info;
5511 WERROR status;
5513 ZERO_STRUCT(info);
5515 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5516 if (!W_ERROR_IS_OK(status)) {
5517 return status;
5520 /* check the required size. */
5521 *needed += spoolss_size_printer_driver_info_3(&info);
5523 if (!alloc_buffer_size(buffer, *needed)) {
5524 free_printer_driver_info_3(&info);
5525 return WERR_INSUFFICIENT_BUFFER;
5528 /* fill the buffer with the structures */
5529 smb_io_printer_driver_info_3("", buffer, &info, 0);
5531 free_printer_driver_info_3(&info);
5533 if (*needed > offered)
5534 return WERR_INSUFFICIENT_BUFFER;
5536 return WERR_OK;
5539 /****************************************************************************
5540 ****************************************************************************/
5542 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5544 DRIVER_INFO_6 info;
5545 WERROR status;
5547 ZERO_STRUCT(info);
5549 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5550 if (!W_ERROR_IS_OK(status)) {
5551 return status;
5554 /* check the required size. */
5555 *needed += spoolss_size_printer_driver_info_6(&info);
5557 if (!alloc_buffer_size(buffer, *needed)) {
5558 free_printer_driver_info_6(&info);
5559 return WERR_INSUFFICIENT_BUFFER;
5562 /* fill the buffer with the structures */
5563 smb_io_printer_driver_info_6("", buffer, &info, 0);
5565 free_printer_driver_info_6(&info);
5567 if (*needed > offered)
5568 return WERR_INSUFFICIENT_BUFFER;
5570 return WERR_OK;
5573 /****************************************************************************
5574 ****************************************************************************/
5576 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5578 POLICY_HND *handle = &q_u->handle;
5579 UNISTR2 *uni_arch = &q_u->architecture;
5580 uint32 level = q_u->level;
5581 uint32 clientmajorversion = q_u->clientmajorversion;
5582 NEW_BUFFER *buffer = NULL;
5583 uint32 offered = q_u->offered;
5584 uint32 *needed = &r_u->needed;
5585 uint32 *servermajorversion = &r_u->servermajorversion;
5586 uint32 *serverminorversion = &r_u->serverminorversion;
5587 Printer_entry *printer;
5589 fstring servername;
5590 fstring architecture;
5591 int snum;
5593 /* that's an [in out] buffer */
5594 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5595 buffer = r_u->buffer;
5597 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5599 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5600 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5601 return WERR_INVALID_PRINTER_NAME;
5604 *needed = 0;
5605 *servermajorversion = 0;
5606 *serverminorversion = 0;
5608 fstrcpy(servername, get_server_name( printer ));
5609 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5611 if (!get_printer_snum(p, handle, &snum))
5612 return WERR_BADFID;
5614 switch (level) {
5615 case 1:
5616 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5617 case 2:
5618 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5619 case 3:
5620 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5621 case 6:
5622 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5623 #if 0 /* JERRY */
5624 case 101:
5625 /* apparently this call is the equivalent of
5626 EnumPrinterDataEx() for the DsDriver key */
5627 break;
5628 #endif
5631 return WERR_UNKNOWN_LEVEL;
5634 /****************************************************************************
5635 ****************************************************************************/
5637 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5639 POLICY_HND *handle = &q_u->handle;
5641 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5643 if (!Printer) {
5644 DEBUG(3,("Error in startpageprinter printer handle\n"));
5645 return WERR_BADFID;
5648 Printer->page_started=True;
5649 return WERR_OK;
5652 /****************************************************************************
5653 ****************************************************************************/
5655 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5657 POLICY_HND *handle = &q_u->handle;
5658 int snum;
5660 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5662 if (!Printer) {
5663 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5664 return WERR_BADFID;
5667 if (!get_printer_snum(p, handle, &snum))
5668 return WERR_BADFID;
5670 Printer->page_started=False;
5671 print_job_endpage(snum, Printer->jobid);
5673 return WERR_OK;
5676 /********************************************************************
5677 * api_spoolss_getprinter
5678 * called from the spoolss dispatcher
5680 ********************************************************************/
5682 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5684 POLICY_HND *handle = &q_u->handle;
5685 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5686 uint32 *jobid = &r_u->jobid;
5688 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5689 int snum;
5690 pstring jobname;
5691 fstring datatype;
5692 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5693 struct current_user user;
5695 if (!Printer) {
5696 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5697 return WERR_BADFID;
5700 get_current_user(&user, p);
5703 * a nice thing with NT is it doesn't listen to what you tell it.
5704 * when asked to send _only_ RAW datas, it tries to send datas
5705 * in EMF format.
5707 * So I add checks like in NT Server ...
5710 if (info_1->p_datatype != 0) {
5711 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5712 if (strcmp(datatype, "RAW") != 0) {
5713 (*jobid)=0;
5714 return WERR_INVALID_DATATYPE;
5718 /* get the share number of the printer */
5719 if (!get_printer_snum(p, handle, &snum)) {
5720 return WERR_BADFID;
5723 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5725 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5727 /* An error occured in print_job_start() so return an appropriate
5728 NT error code. */
5730 if (Printer->jobid == -1) {
5731 return map_werror_from_unix(errno);
5734 Printer->document_started=True;
5735 (*jobid) = Printer->jobid;
5737 return WERR_OK;
5740 /********************************************************************
5741 * api_spoolss_getprinter
5742 * called from the spoolss dispatcher
5744 ********************************************************************/
5746 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5748 POLICY_HND *handle = &q_u->handle;
5750 return _spoolss_enddocprinter_internal(p, handle);
5753 /****************************************************************************
5754 ****************************************************************************/
5756 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5758 POLICY_HND *handle = &q_u->handle;
5759 uint32 buffer_size = q_u->buffer_size;
5760 uint8 *buffer = q_u->buffer;
5761 uint32 *buffer_written = &q_u->buffer_size2;
5762 int snum;
5763 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5765 if (!Printer) {
5766 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5767 r_u->buffer_written = q_u->buffer_size2;
5768 return WERR_BADFID;
5771 if (!get_printer_snum(p, handle, &snum))
5772 return WERR_BADFID;
5774 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5775 if (*buffer_written == -1) {
5776 r_u->buffer_written = 0;
5777 if (errno == ENOSPC)
5778 return WERR_NO_SPOOL_SPACE;
5779 else
5780 return WERR_ACCESS_DENIED;
5783 r_u->buffer_written = q_u->buffer_size2;
5785 return WERR_OK;
5788 /********************************************************************
5789 * api_spoolss_getprinter
5790 * called from the spoolss dispatcher
5792 ********************************************************************/
5794 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5795 pipes_struct *p)
5797 struct current_user user;
5798 int snum;
5799 WERROR errcode = WERR_BADFUNC;
5800 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5802 get_current_user(&user, p);
5804 if (!Printer) {
5805 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5806 return WERR_BADFID;
5809 if (!get_printer_snum(p, handle, &snum))
5810 return WERR_BADFID;
5812 switch (command) {
5813 case PRINTER_CONTROL_PAUSE:
5814 if (print_queue_pause(&user, snum, &errcode)) {
5815 errcode = WERR_OK;
5817 break;
5818 case PRINTER_CONTROL_RESUME:
5819 case PRINTER_CONTROL_UNPAUSE:
5820 if (print_queue_resume(&user, snum, &errcode)) {
5821 errcode = WERR_OK;
5823 break;
5824 case PRINTER_CONTROL_PURGE:
5825 if (print_queue_purge(&user, snum, &errcode)) {
5826 errcode = WERR_OK;
5828 break;
5829 default:
5830 return WERR_UNKNOWN_LEVEL;
5833 return errcode;
5836 /********************************************************************
5837 * api_spoolss_abortprinter
5838 * From MSDN: "Deletes printer's spool file if printer is configured
5839 * for spooling"
5840 ********************************************************************/
5842 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5844 POLICY_HND *handle = &q_u->handle;
5845 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5846 int snum;
5847 struct current_user user;
5848 WERROR errcode = WERR_OK;
5850 if (!Printer) {
5851 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5852 return WERR_BADFID;
5855 if (!get_printer_snum(p, handle, &snum))
5856 return WERR_BADFID;
5858 get_current_user( &user, p );
5860 print_job_delete( &user, snum, Printer->jobid, &errcode );
5862 return errcode;
5865 /********************************************************************
5866 * called by spoolss_api_setprinter
5867 * when updating a printer description
5868 ********************************************************************/
5870 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5871 const SPOOL_PRINTER_INFO_LEVEL *info,
5872 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5874 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5875 WERROR result;
5876 int snum;
5878 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5880 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5881 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5882 OUR_HANDLE(handle)));
5884 result = WERR_BADFID;
5885 goto done;
5888 /* Check the user has permissions to change the security
5889 descriptor. By experimentation with two NT machines, the user
5890 requires Full Access to the printer to change security
5891 information. */
5893 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5894 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5895 result = WERR_ACCESS_DENIED;
5896 goto done;
5899 /* NT seems to like setting the security descriptor even though
5900 nothing may have actually changed. */
5902 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5904 if (DEBUGLEVEL >= 10) {
5905 SEC_ACL *the_acl;
5906 int i;
5908 the_acl = old_secdesc_ctr->sec->dacl;
5909 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5910 PRINTERNAME(snum), the_acl->num_aces));
5912 for (i = 0; i < the_acl->num_aces; i++) {
5913 fstring sid_str;
5915 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5917 DEBUG(10, ("%s 0x%08x\n", sid_str,
5918 the_acl->ace[i].info.mask));
5921 the_acl = secdesc_ctr->sec->dacl;
5923 if (the_acl) {
5924 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5925 PRINTERNAME(snum), the_acl->num_aces));
5927 for (i = 0; i < the_acl->num_aces; i++) {
5928 fstring sid_str;
5930 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5932 DEBUG(10, ("%s 0x%08x\n", sid_str,
5933 the_acl->ace[i].info.mask));
5935 } else {
5936 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5940 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5942 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5943 result = WERR_OK;
5944 goto done;
5947 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5949 done:
5951 return result;
5954 /********************************************************************
5955 Canonicalize printer info from a client
5957 ATTN: It does not matter what we set the servername to hear
5958 since we do the necessary work in get_a_printer() to set it to
5959 the correct value based on what the client sent in the
5960 _spoolss_open_printer_ex().
5961 ********************************************************************/
5963 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5965 fstring printername;
5966 const char *p;
5968 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5969 "portname=%s drivername=%s comment=%s location=%s\n",
5970 info->servername, info->printername, info->sharename,
5971 info->portname, info->drivername, info->comment, info->location));
5973 /* we force some elements to "correct" values */
5974 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5975 fstrcpy(info->sharename, lp_servicename(snum));
5977 /* check to see if we allow printername != sharename */
5979 if ( lp_force_printername(snum) ) {
5980 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5981 global_myname(), info->sharename );
5982 } else {
5984 /* make sure printername is in \\server\printername format */
5986 fstrcpy( printername, info->printername );
5987 p = printername;
5988 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5989 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5990 p++;
5993 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5994 global_myname(), p );
5997 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5998 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6002 return True;
6005 /****************************************************************************
6006 ****************************************************************************/
6008 static BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6010 extern userdom_struct current_user_info;
6011 char *cmd = lp_addprinter_cmd();
6012 char **qlines;
6013 pstring command;
6014 int numlines;
6015 int ret;
6016 int fd;
6017 fstring remote_machine = "%m";
6018 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6019 BOOL is_print_op;
6021 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6023 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6024 cmd, printer->info_2->printername, printer->info_2->sharename,
6025 printer->info_2->portname, printer->info_2->drivername,
6026 printer->info_2->location, printer->info_2->comment, remote_machine);
6028 is_print_op = user_has_privileges( token, &se_printop );
6030 DEBUG(10,("Running [%s]\n", command));
6032 /********* BEGIN SePrintOperatorPrivilege **********/
6034 if ( is_print_op )
6035 become_root();
6037 if ( (ret = smbrun(command, &fd)) == 0 ) {
6038 /* Tell everyone we updated smb.conf. */
6039 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6042 if ( is_print_op )
6043 unbecome_root();
6045 /********* END SePrintOperatorPrivilege **********/
6047 DEBUGADD(10,("returned [%d]\n", ret));
6049 if ( ret != 0 ) {
6050 if (fd != -1)
6051 close(fd);
6052 return False;
6055 /* reload our services immediately */
6056 reload_services( False );
6058 numlines = 0;
6059 /* Get lines and convert them back to dos-codepage */
6060 qlines = fd_lines_load(fd, &numlines);
6061 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6062 close(fd);
6064 /* Set the portname to what the script says the portname should be. */
6065 /* but don't require anything to be return from the script exit a good error code */
6067 if (numlines) {
6068 /* Set the portname to what the script says the portname should be. */
6069 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6070 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6073 file_lines_free(qlines);
6074 return True;
6077 /********************************************************************
6078 * Called by spoolss_api_setprinter
6079 * when updating a printer description.
6080 ********************************************************************/
6082 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6083 const SPOOL_PRINTER_INFO_LEVEL *info,
6084 DEVICEMODE *devmode)
6086 int snum;
6087 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6088 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6089 WERROR result;
6090 UNISTR2 buffer;
6091 fstring asc_buffer;
6093 DEBUG(8,("update_printer\n"));
6095 result = WERR_OK;
6097 if (!Printer) {
6098 result = WERR_BADFID;
6099 goto done;
6102 if (!get_printer_snum(p, handle, &snum)) {
6103 result = WERR_BADFID;
6104 goto done;
6107 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6108 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6109 result = WERR_BADFID;
6110 goto done;
6113 DEBUGADD(8,("Converting info_2 struct\n"));
6116 * convert_printer_info converts the incoming
6117 * info from the client and overwrites the info
6118 * just read from the tdb in the pointer 'printer'.
6121 if (!convert_printer_info(info, printer, level)) {
6122 result = WERR_NOMEM;
6123 goto done;
6126 if (devmode) {
6127 /* we have a valid devmode
6128 convert it and link it*/
6130 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6131 if (!convert_devicemode(printer->info_2->printername, devmode,
6132 &printer->info_2->devmode)) {
6133 result = WERR_NOMEM;
6134 goto done;
6138 /* Do sanity check on the requested changes for Samba */
6140 if (!check_printer_ok(printer->info_2, snum)) {
6141 result = WERR_INVALID_PARAM;
6142 goto done;
6145 /* FIXME!!! If the driver has changed we really should verify that
6146 it is installed before doing much else --jerry */
6148 /* Check calling user has permission to update printer description */
6150 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6151 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6152 result = WERR_ACCESS_DENIED;
6153 goto done;
6156 /* Call addprinter hook */
6157 /* Check changes to see if this is really needed */
6159 if ( *lp_addprinter_cmd()
6160 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6161 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6162 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6163 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6165 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6166 result = WERR_ACCESS_DENIED;
6167 goto done;
6171 * make sure we actually reload the services after
6172 * this as smb.conf could have a new section in it
6173 * .... shouldn't .... but could
6175 reload_services(False);
6179 * When a *new* driver is bound to a printer, the drivername is used to
6180 * lookup previously saved driver initialization info, which is then
6181 * bound to the printer, simulating what happens in the Windows arch.
6183 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6185 if (!set_driver_init(printer, 2))
6187 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6188 printer->info_2->drivername));
6191 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6192 printer->info_2->drivername));
6194 notify_printer_driver(snum, printer->info_2->drivername);
6198 * flag which changes actually occured. This is a small subset of
6199 * all the possible changes. We also have to update things in the
6200 * DsSpooler key.
6203 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6204 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6205 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6206 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6208 notify_printer_comment(snum, printer->info_2->comment);
6211 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6212 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6213 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6214 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6216 notify_printer_sharename(snum, printer->info_2->sharename);
6219 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6220 char *pname;
6222 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6223 pname++;
6224 else
6225 pname = printer->info_2->printername;
6228 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6229 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6230 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6232 notify_printer_printername( snum, pname );
6235 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6236 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6237 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6238 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6240 notify_printer_port(snum, printer->info_2->portname);
6243 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6244 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6245 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6246 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6248 notify_printer_location(snum, printer->info_2->location);
6251 /* here we need to update some more DsSpooler keys */
6252 /* uNCName, serverName, shortServerName */
6254 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6255 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6256 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6257 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6258 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6260 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6261 global_myname(), printer->info_2->sharename );
6262 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6263 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6264 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6266 /* Update printer info */
6267 result = mod_a_printer(printer, 2);
6269 done:
6270 free_a_printer(&printer, 2);
6271 free_a_printer(&old_printer, 2);
6274 return result;
6277 /****************************************************************************
6278 ****************************************************************************/
6279 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6280 const SPOOL_PRINTER_INFO_LEVEL *info)
6282 #ifdef HAVE_ADS
6283 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6284 int snum;
6285 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6287 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6289 if (!Printer)
6290 return WERR_BADFID;
6292 if (!get_printer_snum(p, handle, &snum))
6293 return WERR_BADFID;
6295 nt_printer_publish(Printer, snum, info7->action);
6297 return WERR_OK;
6298 #else
6299 return WERR_UNKNOWN_LEVEL;
6300 #endif
6302 /****************************************************************************
6303 ****************************************************************************/
6305 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6307 POLICY_HND *handle = &q_u->handle;
6308 uint32 level = q_u->level;
6309 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6310 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6311 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6312 uint32 command = q_u->command;
6313 WERROR result;
6315 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6317 if (!Printer) {
6318 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6319 return WERR_BADFID;
6322 /* check the level */
6323 switch (level) {
6324 case 0:
6325 return control_printer(handle, command, p);
6326 case 2:
6327 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6328 if (!W_ERROR_IS_OK(result))
6329 return result;
6330 if (secdesc_ctr)
6331 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6332 return result;
6333 case 3:
6334 return update_printer_sec(handle, level, info, p,
6335 secdesc_ctr);
6336 case 7:
6337 return publish_or_unpublish_printer(p, handle, info);
6338 default:
6339 return WERR_UNKNOWN_LEVEL;
6343 /****************************************************************************
6344 ****************************************************************************/
6346 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6348 POLICY_HND *handle = &q_u->handle;
6349 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6351 if (!Printer) {
6352 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6353 return WERR_BADFID;
6356 if (Printer->notify.client_connected==True) {
6357 int snum = -1;
6359 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6360 snum = -1;
6361 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6362 !get_printer_snum(p, handle, &snum) )
6363 return WERR_BADFID;
6365 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6368 Printer->notify.flags=0;
6369 Printer->notify.options=0;
6370 Printer->notify.localmachine[0]='\0';
6371 Printer->notify.printerlocal=0;
6372 if (Printer->notify.option)
6373 free_spool_notify_option(&Printer->notify.option);
6374 Printer->notify.client_connected=False;
6376 return WERR_OK;
6379 /****************************************************************************
6380 ****************************************************************************/
6382 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6384 /* that's an [in out] buffer (despite appearences to the contrary) */
6385 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6387 r_u->needed = 0;
6388 return WERR_INVALID_PARAM; /* this is what a NT server
6389 returns for AddJob. AddJob
6390 must fail on non-local
6391 printers */
6394 /****************************************************************************
6395 ****************************************************************************/
6397 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6398 int position, int snum,
6399 NT_PRINTER_INFO_LEVEL *ntprinter)
6401 struct tm *t;
6403 t=gmtime(&queue->time);
6405 job_info->jobid=queue->job;
6406 init_unistr(&job_info->printername, lp_servicename(snum));
6407 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6408 init_unistr(&job_info->username, queue->fs_user);
6409 init_unistr(&job_info->document, queue->fs_file);
6410 init_unistr(&job_info->datatype, "RAW");
6411 init_unistr(&job_info->text_status, "");
6412 job_info->status=nt_printj_status(queue->status);
6413 job_info->priority=queue->priority;
6414 job_info->position=position;
6415 job_info->totalpages=queue->page_count;
6416 job_info->pagesprinted=0;
6418 make_systemtime(&job_info->submitted, t);
6421 /****************************************************************************
6422 ****************************************************************************/
6424 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6425 int position, int snum,
6426 NT_PRINTER_INFO_LEVEL *ntprinter,
6427 DEVICEMODE *devmode)
6429 struct tm *t;
6431 t=gmtime(&queue->time);
6433 job_info->jobid=queue->job;
6435 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6437 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6438 init_unistr(&job_info->username, queue->fs_user);
6439 init_unistr(&job_info->document, queue->fs_file);
6440 init_unistr(&job_info->notifyname, queue->fs_user);
6441 init_unistr(&job_info->datatype, "RAW");
6442 init_unistr(&job_info->printprocessor, "winprint");
6443 init_unistr(&job_info->parameters, "");
6444 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6445 init_unistr(&job_info->text_status, "");
6447 /* and here the security descriptor */
6449 job_info->status=nt_printj_status(queue->status);
6450 job_info->priority=queue->priority;
6451 job_info->position=position;
6452 job_info->starttime=0;
6453 job_info->untiltime=0;
6454 job_info->totalpages=queue->page_count;
6455 job_info->size=queue->size;
6456 make_systemtime(&(job_info->submitted), t);
6457 job_info->timeelapsed=0;
6458 job_info->pagesprinted=0;
6460 job_info->devmode = devmode;
6462 return (True);
6465 /****************************************************************************
6466 Enumjobs at level 1.
6467 ****************************************************************************/
6469 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6470 NT_PRINTER_INFO_LEVEL *ntprinter,
6471 NEW_BUFFER *buffer, uint32 offered,
6472 uint32 *needed, uint32 *returned)
6474 JOB_INFO_1 *info;
6475 int i;
6477 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6478 if (info==NULL) {
6479 SAFE_FREE(queue);
6480 *returned=0;
6481 return WERR_NOMEM;
6484 for (i=0; i<*returned; i++)
6485 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6487 SAFE_FREE(queue);
6489 /* check the required size. */
6490 for (i=0; i<*returned; i++)
6491 (*needed) += spoolss_size_job_info_1(&info[i]);
6493 if (!alloc_buffer_size(buffer, *needed)) {
6494 SAFE_FREE(info);
6495 return WERR_INSUFFICIENT_BUFFER;
6498 /* fill the buffer with the structures */
6499 for (i=0; i<*returned; i++)
6500 smb_io_job_info_1("", buffer, &info[i], 0);
6502 /* clear memory */
6503 SAFE_FREE(info);
6505 if (*needed > offered) {
6506 *returned=0;
6507 return WERR_INSUFFICIENT_BUFFER;
6510 return WERR_OK;
6513 /****************************************************************************
6514 Enumjobs at level 2.
6515 ****************************************************************************/
6517 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6518 NT_PRINTER_INFO_LEVEL *ntprinter,
6519 NEW_BUFFER *buffer, uint32 offered,
6520 uint32 *needed, uint32 *returned)
6522 JOB_INFO_2 *info = NULL;
6523 int i;
6524 WERROR result;
6525 DEVICEMODE *devmode = NULL;
6527 info=SMB_MALLOC_ARRAY(JOB_INFO_2,*returned);
6528 if (info==NULL) {
6529 *returned=0;
6530 result = WERR_NOMEM;
6531 goto done;
6534 /* this should not be a failure condition if the devmode is NULL */
6536 devmode = construct_dev_mode(snum);
6538 for (i=0; i<*returned; i++)
6539 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6540 devmode);
6542 free_a_printer(&ntprinter, 2);
6543 SAFE_FREE(queue);
6545 /* check the required size. */
6546 for (i=0; i<*returned; i++)
6547 (*needed) += spoolss_size_job_info_2(&info[i]);
6549 if (*needed > offered) {
6550 *returned=0;
6551 result = WERR_INSUFFICIENT_BUFFER;
6552 goto done;
6555 if (!alloc_buffer_size(buffer, *needed)) {
6556 SAFE_FREE(info);
6557 result = WERR_INSUFFICIENT_BUFFER;
6558 goto done;
6561 /* fill the buffer with the structures */
6562 for (i=0; i<*returned; i++)
6563 smb_io_job_info_2("", buffer, &info[i], 0);
6565 result = WERR_OK;
6567 done:
6568 free_a_printer(&ntprinter, 2);
6569 free_devmode(devmode);
6570 SAFE_FREE(queue);
6571 SAFE_FREE(info);
6573 return result;
6577 /****************************************************************************
6578 Enumjobs.
6579 ****************************************************************************/
6581 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6583 POLICY_HND *handle = &q_u->handle;
6584 uint32 level = q_u->level;
6585 NEW_BUFFER *buffer = NULL;
6586 uint32 offered = q_u->offered;
6587 uint32 *needed = &r_u->needed;
6588 uint32 *returned = &r_u->returned;
6589 WERROR wret;
6590 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6591 int snum;
6592 print_status_struct prt_status;
6593 print_queue_struct *queue=NULL;
6595 /* that's an [in out] buffer */
6596 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6597 buffer = r_u->buffer;
6599 DEBUG(4,("_spoolss_enumjobs\n"));
6601 *needed=0;
6602 *returned=0;
6604 /* lookup the printer snum and tdb entry */
6606 if (!get_printer_snum(p, handle, &snum))
6607 return WERR_BADFID;
6609 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6610 if ( !W_ERROR_IS_OK(wret) )
6611 return wret;
6613 *returned = print_queue_status(snum, &queue, &prt_status);
6614 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6616 if (*returned == 0) {
6617 SAFE_FREE(queue);
6618 return WERR_OK;
6621 switch (level) {
6622 case 1:
6623 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6624 return wret;
6625 case 2:
6626 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6627 return wret;
6628 default:
6629 SAFE_FREE(queue);
6630 *returned=0;
6631 wret = WERR_UNKNOWN_LEVEL;
6634 free_a_printer( &ntprinter, 2 );
6635 return wret;
6638 /****************************************************************************
6639 ****************************************************************************/
6641 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6643 return WERR_OK;
6646 /****************************************************************************
6647 ****************************************************************************/
6649 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6651 POLICY_HND *handle = &q_u->handle;
6652 uint32 jobid = q_u->jobid;
6653 uint32 command = q_u->command;
6655 struct current_user user;
6656 int snum;
6657 WERROR errcode = WERR_BADFUNC;
6659 if (!get_printer_snum(p, handle, &snum)) {
6660 return WERR_BADFID;
6663 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6664 return WERR_INVALID_PRINTER_NAME;
6667 get_current_user(&user, p);
6669 switch (command) {
6670 case JOB_CONTROL_CANCEL:
6671 case JOB_CONTROL_DELETE:
6672 if (print_job_delete(&user, snum, jobid, &errcode)) {
6673 errcode = WERR_OK;
6675 break;
6676 case JOB_CONTROL_PAUSE:
6677 if (print_job_pause(&user, snum, jobid, &errcode)) {
6678 errcode = WERR_OK;
6680 break;
6681 case JOB_CONTROL_RESTART:
6682 case JOB_CONTROL_RESUME:
6683 if (print_job_resume(&user, snum, jobid, &errcode)) {
6684 errcode = WERR_OK;
6686 break;
6687 default:
6688 return WERR_UNKNOWN_LEVEL;
6691 return errcode;
6694 /****************************************************************************
6695 Enumerates all printer drivers at level 1.
6696 ****************************************************************************/
6698 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6700 int i;
6701 int ndrivers;
6702 uint32 version;
6703 fstring *list = NULL;
6705 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6706 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6708 *returned=0;
6710 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6711 list=NULL;
6712 ndrivers=get_ntdrivers(&list, architecture, version);
6713 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6715 if(ndrivers == -1)
6716 return WERR_NOMEM;
6718 if(ndrivers != 0) {
6719 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6720 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6721 SAFE_FREE(driver_info_1);
6722 SAFE_FREE(list);
6723 return WERR_NOMEM;
6725 else driver_info_1 = tdi1;
6728 for (i=0; i<ndrivers; i++) {
6729 WERROR status;
6730 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6731 ZERO_STRUCT(driver);
6732 status = get_a_printer_driver(&driver, 3, list[i],
6733 architecture, version);
6734 if (!W_ERROR_IS_OK(status)) {
6735 SAFE_FREE(list);
6736 return status;
6738 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6739 free_a_printer_driver(driver, 3);
6742 *returned+=ndrivers;
6743 SAFE_FREE(list);
6746 /* check the required size. */
6747 for (i=0; i<*returned; i++) {
6748 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6749 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6752 if (!alloc_buffer_size(buffer, *needed)) {
6753 SAFE_FREE(driver_info_1);
6754 return WERR_INSUFFICIENT_BUFFER;
6757 /* fill the buffer with the driver structures */
6758 for (i=0; i<*returned; i++) {
6759 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6760 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6763 SAFE_FREE(driver_info_1);
6765 if (*needed > offered) {
6766 *returned=0;
6767 return WERR_INSUFFICIENT_BUFFER;
6770 return WERR_OK;
6773 /****************************************************************************
6774 Enumerates all printer drivers at level 2.
6775 ****************************************************************************/
6777 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6779 int i;
6780 int ndrivers;
6781 uint32 version;
6782 fstring *list = NULL;
6784 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6785 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6787 *returned=0;
6789 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6790 list=NULL;
6791 ndrivers=get_ntdrivers(&list, architecture, version);
6792 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6794 if(ndrivers == -1)
6795 return WERR_NOMEM;
6797 if(ndrivers != 0) {
6798 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6799 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6800 SAFE_FREE(driver_info_2);
6801 SAFE_FREE(list);
6802 return WERR_NOMEM;
6804 else driver_info_2 = tdi2;
6807 for (i=0; i<ndrivers; i++) {
6808 WERROR status;
6810 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6811 ZERO_STRUCT(driver);
6812 status = get_a_printer_driver(&driver, 3, list[i],
6813 architecture, version);
6814 if (!W_ERROR_IS_OK(status)) {
6815 SAFE_FREE(list);
6816 return status;
6818 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6819 free_a_printer_driver(driver, 3);
6822 *returned+=ndrivers;
6823 SAFE_FREE(list);
6826 /* check the required size. */
6827 for (i=0; i<*returned; i++) {
6828 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6829 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6832 if (!alloc_buffer_size(buffer, *needed)) {
6833 SAFE_FREE(driver_info_2);
6834 return WERR_INSUFFICIENT_BUFFER;
6837 /* fill the buffer with the form structures */
6838 for (i=0; i<*returned; i++) {
6839 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6840 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6843 SAFE_FREE(driver_info_2);
6845 if (*needed > offered) {
6846 *returned=0;
6847 return WERR_INSUFFICIENT_BUFFER;
6850 return WERR_OK;
6853 /****************************************************************************
6854 Enumerates all printer drivers at level 3.
6855 ****************************************************************************/
6857 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6859 int i;
6860 int ndrivers;
6861 uint32 version;
6862 fstring *list = NULL;
6864 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6865 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6867 *returned=0;
6869 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6870 list=NULL;
6871 ndrivers=get_ntdrivers(&list, architecture, version);
6872 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6874 if(ndrivers == -1)
6875 return WERR_NOMEM;
6877 if(ndrivers != 0) {
6878 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6879 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6880 SAFE_FREE(driver_info_3);
6881 SAFE_FREE(list);
6882 return WERR_NOMEM;
6884 else driver_info_3 = tdi3;
6887 for (i=0; i<ndrivers; i++) {
6888 WERROR status;
6890 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6891 ZERO_STRUCT(driver);
6892 status = get_a_printer_driver(&driver, 3, list[i],
6893 architecture, version);
6894 if (!W_ERROR_IS_OK(status)) {
6895 SAFE_FREE(list);
6896 return status;
6898 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6899 free_a_printer_driver(driver, 3);
6902 *returned+=ndrivers;
6903 SAFE_FREE(list);
6906 /* check the required size. */
6907 for (i=0; i<*returned; i++) {
6908 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6909 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6912 if (!alloc_buffer_size(buffer, *needed)) {
6913 SAFE_FREE(driver_info_3);
6914 return WERR_INSUFFICIENT_BUFFER;
6917 /* fill the buffer with the driver structures */
6918 for (i=0; i<*returned; i++) {
6919 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6920 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6923 for (i=0; i<*returned; i++)
6924 SAFE_FREE(driver_info_3[i].dependentfiles);
6926 SAFE_FREE(driver_info_3);
6928 if (*needed > offered) {
6929 *returned=0;
6930 return WERR_INSUFFICIENT_BUFFER;
6933 return WERR_OK;
6936 /****************************************************************************
6937 Enumerates all printer drivers.
6938 ****************************************************************************/
6940 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6942 uint32 level = q_u->level;
6943 NEW_BUFFER *buffer = NULL;
6944 uint32 offered = q_u->offered;
6945 uint32 *needed = &r_u->needed;
6946 uint32 *returned = &r_u->returned;
6948 fstring *list = NULL;
6949 fstring servername;
6950 fstring architecture;
6952 /* that's an [in out] buffer */
6953 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6954 buffer = r_u->buffer;
6956 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6957 *needed=0;
6958 *returned=0;
6960 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6961 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6963 if ( !is_myname_or_ipaddr( servername ) )
6964 return WERR_UNKNOWN_PRINTER_DRIVER;
6966 switch (level) {
6967 case 1:
6968 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6969 case 2:
6970 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6971 case 3:
6972 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6973 default:
6974 *returned=0;
6975 SAFE_FREE(list);
6976 return WERR_UNKNOWN_LEVEL;
6980 /****************************************************************************
6981 ****************************************************************************/
6983 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6985 form->flag=list->flag;
6986 init_unistr(&form->name, list->name);
6987 form->width=list->width;
6988 form->length=list->length;
6989 form->left=list->left;
6990 form->top=list->top;
6991 form->right=list->right;
6992 form->bottom=list->bottom;
6995 /****************************************************************************
6996 ****************************************************************************/
6998 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7000 uint32 level = q_u->level;
7001 NEW_BUFFER *buffer = NULL;
7002 uint32 offered = q_u->offered;
7003 uint32 *needed = &r_u->needed;
7004 uint32 *numofforms = &r_u->numofforms;
7005 uint32 numbuiltinforms;
7007 nt_forms_struct *list=NULL;
7008 nt_forms_struct *builtinlist=NULL;
7009 FORM_1 *forms_1;
7010 int buffer_size=0;
7011 int i;
7013 /* that's an [in out] buffer */
7014 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7015 buffer = r_u->buffer;
7017 DEBUG(4,("_spoolss_enumforms\n"));
7018 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7019 DEBUGADD(5,("Info level [%d]\n", level));
7021 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7022 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7023 *numofforms = get_ntforms(&list);
7024 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7025 *numofforms += numbuiltinforms;
7027 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
7029 switch (level) {
7030 case 1:
7031 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7032 *numofforms=0;
7033 return WERR_NOMEM;
7036 /* construct the list of form structures */
7037 for (i=0; i<numbuiltinforms; i++) {
7038 DEBUGADD(6,("Filling form number [%d]\n",i));
7039 fill_form_1(&forms_1[i], &builtinlist[i]);
7042 SAFE_FREE(builtinlist);
7044 for (; i<*numofforms; i++) {
7045 DEBUGADD(6,("Filling form number [%d]\n",i));
7046 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7049 SAFE_FREE(list);
7051 /* check the required size. */
7052 for (i=0; i<numbuiltinforms; i++) {
7053 DEBUGADD(6,("adding form [%d]'s size\n",i));
7054 buffer_size += spoolss_size_form_1(&forms_1[i]);
7056 for (; i<*numofforms; i++) {
7057 DEBUGADD(6,("adding form [%d]'s size\n",i));
7058 buffer_size += spoolss_size_form_1(&forms_1[i]);
7061 *needed=buffer_size;
7063 if (!alloc_buffer_size(buffer, buffer_size)){
7064 SAFE_FREE(forms_1);
7065 return WERR_INSUFFICIENT_BUFFER;
7068 /* fill the buffer with the form structures */
7069 for (i=0; i<numbuiltinforms; i++) {
7070 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7071 smb_io_form_1("", buffer, &forms_1[i], 0);
7073 for (; i<*numofforms; i++) {
7074 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7075 smb_io_form_1("", buffer, &forms_1[i], 0);
7078 SAFE_FREE(forms_1);
7080 if (*needed > offered) {
7081 *numofforms=0;
7082 return WERR_INSUFFICIENT_BUFFER;
7084 else
7085 return WERR_OK;
7087 default:
7088 SAFE_FREE(list);
7089 SAFE_FREE(builtinlist);
7090 return WERR_UNKNOWN_LEVEL;
7095 /****************************************************************************
7096 ****************************************************************************/
7098 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7100 uint32 level = q_u->level;
7101 UNISTR2 *uni_formname = &q_u->formname;
7102 NEW_BUFFER *buffer = NULL;
7103 uint32 offered = q_u->offered;
7104 uint32 *needed = &r_u->needed;
7106 nt_forms_struct *list=NULL;
7107 nt_forms_struct builtin_form;
7108 BOOL foundBuiltin;
7109 FORM_1 form_1;
7110 fstring form_name;
7111 int buffer_size=0;
7112 int numofforms=0, i=0;
7114 /* that's an [in out] buffer */
7115 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7116 buffer = r_u->buffer;
7118 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7120 DEBUG(4,("_spoolss_getform\n"));
7121 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7122 DEBUGADD(5,("Info level [%d]\n", level));
7124 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7125 if (!foundBuiltin) {
7126 numofforms = get_ntforms(&list);
7127 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7129 if (numofforms == 0)
7130 return WERR_BADFID;
7133 switch (level) {
7134 case 1:
7135 if (foundBuiltin) {
7136 fill_form_1(&form_1, &builtin_form);
7137 } else {
7139 /* Check if the requested name is in the list of form structures */
7140 for (i=0; i<numofforms; i++) {
7142 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7144 if (strequal(form_name, list[i].name)) {
7145 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7146 fill_form_1(&form_1, &list[i]);
7147 break;
7151 SAFE_FREE(list);
7152 if (i == numofforms) {
7153 return WERR_BADFID;
7156 /* check the required size. */
7158 *needed=spoolss_size_form_1(&form_1);
7160 if (!alloc_buffer_size(buffer, buffer_size)){
7161 return WERR_INSUFFICIENT_BUFFER;
7164 if (*needed > offered) {
7165 return WERR_INSUFFICIENT_BUFFER;
7168 /* fill the buffer with the form structures */
7169 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7170 smb_io_form_1("", buffer, &form_1, 0);
7172 return WERR_OK;
7174 default:
7175 SAFE_FREE(list);
7176 return WERR_UNKNOWN_LEVEL;
7180 /****************************************************************************
7181 ****************************************************************************/
7183 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7185 init_unistr(&port->port_name, name);
7188 /****************************************************************************
7189 ****************************************************************************/
7191 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7193 init_unistr(&port->port_name, name);
7194 init_unistr(&port->monitor_name, "Local Monitor");
7195 init_unistr(&port->description, "Local Port");
7196 port->port_type=PORT_TYPE_WRITE;
7197 port->reserved=0x0;
7200 /****************************************************************************
7201 enumports level 1.
7202 ****************************************************************************/
7204 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7206 PORT_INFO_1 *ports=NULL;
7207 int i=0;
7209 if (*lp_enumports_cmd()) {
7210 char *cmd = lp_enumports_cmd();
7211 char **qlines;
7212 pstring command;
7213 int numlines;
7214 int ret;
7215 int fd;
7217 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7219 DEBUG(10,("Running [%s]\n", command));
7220 ret = smbrun(command, &fd);
7221 DEBUG(10,("Returned [%d]\n", ret));
7222 if (ret != 0) {
7223 if (fd != -1)
7224 close(fd);
7225 /* Is this the best error to return here? */
7226 return WERR_ACCESS_DENIED;
7229 numlines = 0;
7230 qlines = fd_lines_load(fd, &numlines);
7231 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7232 close(fd);
7234 if(numlines) {
7235 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7236 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7237 dos_errstr(WERR_NOMEM)));
7238 file_lines_free(qlines);
7239 return WERR_NOMEM;
7242 for (i=0; i<numlines; i++) {
7243 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7244 fill_port_1(&ports[i], qlines[i]);
7247 file_lines_free(qlines);
7250 *returned = numlines;
7252 } else {
7253 *returned = 1; /* Sole Samba port returned. */
7255 if((ports=SMB_MALLOC_P(PORT_INFO_1)) == NULL)
7256 return WERR_NOMEM;
7258 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7260 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7263 /* check the required size. */
7264 for (i=0; i<*returned; i++) {
7265 DEBUGADD(6,("adding port [%d]'s size\n", i));
7266 *needed += spoolss_size_port_info_1(&ports[i]);
7269 if (!alloc_buffer_size(buffer, *needed)) {
7270 SAFE_FREE(ports);
7271 return WERR_INSUFFICIENT_BUFFER;
7274 /* fill the buffer with the ports structures */
7275 for (i=0; i<*returned; i++) {
7276 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7277 smb_io_port_1("", buffer, &ports[i], 0);
7280 SAFE_FREE(ports);
7282 if (*needed > offered) {
7283 *returned=0;
7284 return WERR_INSUFFICIENT_BUFFER;
7287 return WERR_OK;
7290 /****************************************************************************
7291 enumports level 2.
7292 ****************************************************************************/
7294 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7296 PORT_INFO_2 *ports=NULL;
7297 int i=0;
7299 if (*lp_enumports_cmd()) {
7300 char *cmd = lp_enumports_cmd();
7301 char *path;
7302 char **qlines;
7303 pstring tmp_file;
7304 pstring command;
7305 int numlines;
7306 int ret;
7307 int fd;
7309 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7310 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7311 else
7312 path = lp_lockdir();
7314 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7315 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7317 unlink(tmp_file);
7318 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7319 ret = smbrun(command, &fd);
7320 DEBUGADD(10,("returned [%d]\n", ret));
7321 if (ret != 0) {
7322 if (fd != -1)
7323 close(fd);
7324 /* Is this the best error to return here? */
7325 return WERR_ACCESS_DENIED;
7328 numlines = 0;
7329 qlines = fd_lines_load(fd, &numlines);
7330 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7331 close(fd);
7333 if(numlines) {
7334 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7335 file_lines_free(qlines);
7336 return WERR_NOMEM;
7339 for (i=0; i<numlines; i++) {
7340 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7341 fill_port_2(&(ports[i]), qlines[i]);
7344 file_lines_free(qlines);
7347 *returned = numlines;
7349 } else {
7351 *returned = 1;
7353 if((ports=SMB_MALLOC_P(PORT_INFO_2)) == NULL)
7354 return WERR_NOMEM;
7356 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7358 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7361 /* check the required size. */
7362 for (i=0; i<*returned; i++) {
7363 DEBUGADD(6,("adding port [%d]'s size\n", i));
7364 *needed += spoolss_size_port_info_2(&ports[i]);
7367 if (!alloc_buffer_size(buffer, *needed)) {
7368 SAFE_FREE(ports);
7369 return WERR_INSUFFICIENT_BUFFER;
7372 /* fill the buffer with the ports structures */
7373 for (i=0; i<*returned; i++) {
7374 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7375 smb_io_port_2("", buffer, &ports[i], 0);
7378 SAFE_FREE(ports);
7380 if (*needed > offered) {
7381 *returned=0;
7382 return WERR_INSUFFICIENT_BUFFER;
7385 return WERR_OK;
7388 /****************************************************************************
7389 enumports.
7390 ****************************************************************************/
7392 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7394 uint32 level = q_u->level;
7395 NEW_BUFFER *buffer = NULL;
7396 uint32 offered = q_u->offered;
7397 uint32 *needed = &r_u->needed;
7398 uint32 *returned = &r_u->returned;
7400 /* that's an [in out] buffer */
7401 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7402 buffer = r_u->buffer;
7404 DEBUG(4,("_spoolss_enumports\n"));
7406 *returned=0;
7407 *needed=0;
7409 switch (level) {
7410 case 1:
7411 return enumports_level_1(buffer, offered, needed, returned);
7412 case 2:
7413 return enumports_level_2(buffer, offered, needed, returned);
7414 default:
7415 return WERR_UNKNOWN_LEVEL;
7419 /****************************************************************************
7420 ****************************************************************************/
7422 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7423 const SPOOL_PRINTER_INFO_LEVEL *info,
7424 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7425 uint32 user_switch, const SPOOL_USER_CTR *user,
7426 POLICY_HND *handle)
7428 NT_PRINTER_INFO_LEVEL *printer = NULL;
7429 fstring name;
7430 int snum;
7431 WERROR err = WERR_OK;
7433 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7434 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7435 return WERR_NOMEM;
7438 ZERO_STRUCTP(printer);
7440 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7441 if (!convert_printer_info(info, printer, 2)) {
7442 free_a_printer(&printer, 2);
7443 return WERR_NOMEM;
7446 /* check to see if the printer already exists */
7448 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7449 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7450 printer->info_2->sharename));
7451 free_a_printer(&printer, 2);
7452 return WERR_PRINTER_ALREADY_EXISTS;
7455 /* FIXME!!! smbd should check to see if the driver is installed before
7456 trying to add a printer like this --jerry */
7458 if (*lp_addprinter_cmd() ) {
7459 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7460 free_a_printer(&printer,2);
7461 return WERR_ACCESS_DENIED;
7465 /* use our primary netbios name since get_a_printer() will convert
7466 it to what the client expects on a case by case basis */
7468 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7469 printer->info_2->sharename);
7472 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7473 free_a_printer(&printer,2);
7474 return WERR_ACCESS_DENIED;
7477 /* you must be a printer admin to add a new printer */
7478 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7479 free_a_printer(&printer,2);
7480 return WERR_ACCESS_DENIED;
7484 * Do sanity check on the requested changes for Samba.
7487 if (!check_printer_ok(printer->info_2, snum)) {
7488 free_a_printer(&printer,2);
7489 return WERR_INVALID_PARAM;
7493 * When a printer is created, the drivername bound to the printer is used
7494 * to lookup previously saved driver initialization info, which is then
7495 * bound to the new printer, simulating what happens in the Windows arch.
7498 if (!devmode)
7500 set_driver_init(printer, 2);
7502 else
7504 /* A valid devmode was included, convert and link it
7506 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7508 if (!convert_devicemode(printer->info_2->printername, devmode,
7509 &printer->info_2->devmode))
7510 return WERR_NOMEM;
7513 /* write the ASCII on disk */
7514 err = mod_a_printer(printer, 2);
7515 if (!W_ERROR_IS_OK(err)) {
7516 free_a_printer(&printer,2);
7517 return err;
7520 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7521 /* Handle open failed - remove addition. */
7522 del_a_printer(printer->info_2->sharename);
7523 free_a_printer(&printer,2);
7524 return WERR_ACCESS_DENIED;
7527 update_c_setprinter(False);
7528 free_a_printer(&printer,2);
7530 return WERR_OK;
7533 /****************************************************************************
7534 ****************************************************************************/
7536 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7538 UNISTR2 *uni_srv_name = &q_u->server_name;
7539 uint32 level = q_u->level;
7540 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7541 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7542 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7543 uint32 user_switch = q_u->user_switch;
7544 SPOOL_USER_CTR *user = &q_u->user_ctr;
7545 POLICY_HND *handle = &r_u->handle;
7547 switch (level) {
7548 case 1:
7549 /* we don't handle yet */
7550 /* but I know what to do ... */
7551 return WERR_UNKNOWN_LEVEL;
7552 case 2:
7553 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7554 devmode, sdb,
7555 user_switch, user, handle);
7556 default:
7557 return WERR_UNKNOWN_LEVEL;
7561 /****************************************************************************
7562 ****************************************************************************/
7564 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7566 uint32 level = q_u->level;
7567 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7568 WERROR err = WERR_OK;
7569 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7570 struct current_user user;
7571 fstring driver_name;
7572 uint32 version;
7574 ZERO_STRUCT(driver);
7576 get_current_user(&user, p);
7578 if (!convert_printer_driver_info(info, &driver, level)) {
7579 err = WERR_NOMEM;
7580 goto done;
7583 DEBUG(5,("Cleaning driver's information\n"));
7584 err = clean_up_driver_struct(driver, level, &user);
7585 if (!W_ERROR_IS_OK(err))
7586 goto done;
7588 DEBUG(5,("Moving driver to final destination\n"));
7589 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7590 if (W_ERROR_IS_OK(err))
7591 err = WERR_ACCESS_DENIED;
7592 goto done;
7595 if (add_a_printer_driver(driver, level)!=0) {
7596 err = WERR_ACCESS_DENIED;
7597 goto done;
7600 /* BEGIN_ADMIN_LOG */
7601 switch(level) {
7602 case 3:
7603 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7604 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7605 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7606 break;
7607 case 6:
7608 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7609 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7610 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7611 break;
7613 /* END_ADMIN_LOG */
7616 * I think this is where he DrvUpgradePrinter() hook would be
7617 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7618 * server. Right now, we just need to send ourselves a message
7619 * to update each printer bound to this driver. --jerry
7622 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7623 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7624 driver_name));
7628 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7629 * decide if the driver init data should be deleted. The rules are:
7630 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7631 * 2) delete init data only if there is no 2k/Xp driver
7632 * 3) always delete init data
7633 * The generalized rule is always use init data from the highest order driver.
7634 * It is necessary to follow the driver install by an initialization step to
7635 * finish off this process.
7637 if (level == 3)
7638 version = driver.info_3->cversion;
7639 else if (level == 6)
7640 version = driver.info_6->version;
7641 else
7642 version = -1;
7643 switch (version) {
7645 * 9x printer driver - never delete init data
7647 case 0:
7648 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7649 driver_name));
7650 break;
7653 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7654 * there is no 2k/Xp driver init data for this driver name.
7656 case 2:
7658 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7660 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7662 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7664 if (!del_driver_init(driver_name))
7665 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7666 } else {
7668 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7670 free_a_printer_driver(driver1,3);
7671 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7672 driver_name));
7675 break;
7678 * 2k or Xp printer driver - always delete init data
7680 case 3:
7681 if (!del_driver_init(driver_name))
7682 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7683 break;
7685 default:
7686 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7687 break;
7691 done:
7692 free_a_printer_driver(driver, level);
7693 return err;
7696 /********************************************************************
7697 * spoolss_addprinterdriverex
7698 ********************************************************************/
7700 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7702 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7703 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7706 * we only support the semantics of AddPrinterDriver()
7707 * i.e. only copy files that are newer than existing ones
7710 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7711 return WERR_ACCESS_DENIED;
7713 ZERO_STRUCT(q_u_local);
7714 ZERO_STRUCT(r_u_local);
7716 /* just pass the information off to _spoolss_addprinterdriver() */
7717 q_u_local.server_name_ptr = q_u->server_name_ptr;
7718 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7719 q_u_local.level = q_u->level;
7720 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7722 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7725 /****************************************************************************
7726 ****************************************************************************/
7728 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7730 init_unistr(&info->name, name);
7733 /****************************************************************************
7734 ****************************************************************************/
7736 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7738 pstring path;
7739 pstring long_archi;
7740 fstring servername;
7741 char *pservername;
7742 const char *short_archi;
7743 DRIVER_DIRECTORY_1 *info=NULL;
7745 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7746 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7748 /* check for beginning double '\'s and that the server
7749 long enough */
7751 pservername = servername;
7752 if ( *pservername == '\\' && strlen(servername)>2 ) {
7753 pservername += 2;
7756 if ( !is_myname_or_ipaddr( pservername ) )
7757 return WERR_INVALID_PARAM;
7759 if (!(short_archi = get_short_archi(long_archi)))
7760 return WERR_INVALID_ENVIRONMENT;
7762 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7763 return WERR_NOMEM;
7765 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7767 DEBUG(4,("printer driver directory: [%s]\n", path));
7769 fill_driverdir_1(info, path);
7771 *needed += spoolss_size_driverdir_info_1(info);
7773 if (!alloc_buffer_size(buffer, *needed)) {
7774 SAFE_FREE(info);
7775 return WERR_INSUFFICIENT_BUFFER;
7778 smb_io_driverdir_1("", buffer, info, 0);
7780 SAFE_FREE(info);
7782 if (*needed > offered)
7783 return WERR_INSUFFICIENT_BUFFER;
7785 return WERR_OK;
7788 /****************************************************************************
7789 ****************************************************************************/
7791 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7793 UNISTR2 *name = &q_u->name;
7794 UNISTR2 *uni_environment = &q_u->environment;
7795 uint32 level = q_u->level;
7796 NEW_BUFFER *buffer = NULL;
7797 uint32 offered = q_u->offered;
7798 uint32 *needed = &r_u->needed;
7800 /* that's an [in out] buffer */
7801 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7802 buffer = r_u->buffer;
7804 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7806 *needed=0;
7808 switch(level) {
7809 case 1:
7810 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7811 default:
7812 return WERR_UNKNOWN_LEVEL;
7816 /****************************************************************************
7817 ****************************************************************************/
7819 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7821 POLICY_HND *handle = &q_u->handle;
7822 uint32 idx = q_u->index;
7823 uint32 in_value_len = q_u->valuesize;
7824 uint32 in_data_len = q_u->datasize;
7825 uint32 *out_max_value_len = &r_u->valuesize;
7826 uint16 **out_value = &r_u->value;
7827 uint32 *out_value_len = &r_u->realvaluesize;
7828 uint32 *out_type = &r_u->type;
7829 uint32 *out_max_data_len = &r_u->datasize;
7830 uint8 **data_out = &r_u->data;
7831 uint32 *out_data_len = &r_u->realdatasize;
7833 NT_PRINTER_INFO_LEVEL *printer = NULL;
7835 uint32 biggest_valuesize;
7836 uint32 biggest_datasize;
7837 uint32 data_len;
7838 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7839 int snum;
7840 WERROR result;
7841 REGISTRY_VALUE *val = NULL;
7842 NT_PRINTER_DATA *p_data;
7843 int i, key_index, num_values;
7844 int name_length;
7846 ZERO_STRUCT( printer );
7848 *out_type = 0;
7850 *out_max_data_len = 0;
7851 *data_out = NULL;
7852 *out_data_len = 0;
7854 DEBUG(5,("spoolss_enumprinterdata\n"));
7856 if (!Printer) {
7857 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7858 return WERR_BADFID;
7861 if (!get_printer_snum(p,handle, &snum))
7862 return WERR_BADFID;
7864 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7865 if (!W_ERROR_IS_OK(result))
7866 return result;
7868 p_data = &printer->info_2->data;
7869 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7871 result = WERR_OK;
7874 * The NT machine wants to know the biggest size of value and data
7876 * cf: MSDN EnumPrinterData remark section
7879 if ( !in_value_len && !in_data_len && (key_index != -1) )
7881 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7883 biggest_valuesize = 0;
7884 biggest_datasize = 0;
7886 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7888 for ( i=0; i<num_values; i++ )
7890 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7892 name_length = strlen(val->valuename);
7893 if ( strlen(val->valuename) > biggest_valuesize )
7894 biggest_valuesize = name_length;
7896 if ( val->size > biggest_datasize )
7897 biggest_datasize = val->size;
7899 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7900 biggest_datasize));
7903 /* the value is an UNICODE string but real_value_size is the length
7904 in bytes including the trailing 0 */
7906 *out_value_len = 2 * (1+biggest_valuesize);
7907 *out_data_len = biggest_datasize;
7909 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7911 goto done;
7915 * the value len is wrong in NT sp3
7916 * that's the number of bytes not the number of unicode chars
7919 if ( key_index != -1 )
7920 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7922 if ( !val )
7925 /* out_value should default to "" or else NT4 has
7926 problems unmarshalling the response */
7928 *out_max_value_len=(in_value_len/sizeof(uint16));
7930 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7932 result = WERR_NOMEM;
7933 goto done;
7936 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7938 /* the data is counted in bytes */
7940 *out_max_data_len = in_data_len;
7941 *out_data_len = in_data_len;
7943 /* only allocate when given a non-zero data_len */
7945 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7947 result = WERR_NOMEM;
7948 goto done;
7951 result = WERR_NO_MORE_ITEMS;
7953 else
7956 * the value is:
7957 * - counted in bytes in the request
7958 * - counted in UNICODE chars in the max reply
7959 * - counted in bytes in the real size
7961 * take a pause *before* coding not *during* coding
7964 /* name */
7965 *out_max_value_len=(in_value_len/sizeof(uint16));
7966 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7968 result = WERR_NOMEM;
7969 goto done;
7972 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7974 /* type */
7976 *out_type = regval_type( val );
7978 /* data - counted in bytes */
7980 *out_max_data_len = in_data_len;
7981 if ( (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7983 result = WERR_NOMEM;
7984 goto done;
7986 data_len = (size_t)regval_size(val);
7987 memcpy( *data_out, regval_data_p(val), data_len );
7988 *out_data_len = data_len;
7991 done:
7992 free_a_printer(&printer, 2);
7993 return result;
7996 /****************************************************************************
7997 ****************************************************************************/
7999 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8001 POLICY_HND *handle = &q_u->handle;
8002 UNISTR2 *value = &q_u->value;
8003 uint32 type = q_u->type;
8004 uint8 *data = q_u->data;
8005 uint32 real_len = q_u->real_len;
8007 NT_PRINTER_INFO_LEVEL *printer = NULL;
8008 int snum=0;
8009 WERROR status = WERR_OK;
8010 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8011 fstring valuename;
8013 DEBUG(5,("spoolss_setprinterdata\n"));
8015 if (!Printer) {
8016 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8017 return WERR_BADFID;
8020 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8021 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8022 return WERR_INVALID_PARAM;
8025 if (!get_printer_snum(p,handle, &snum))
8026 return WERR_BADFID;
8029 * Access check : NT returns "access denied" if you make a
8030 * SetPrinterData call without the necessary privildge.
8031 * we were originally returning OK if nothing changed
8032 * which made Win2k issue **a lot** of SetPrinterData
8033 * when connecting to a printer --jerry
8036 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8038 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8039 status = WERR_ACCESS_DENIED;
8040 goto done;
8043 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8044 if (!W_ERROR_IS_OK(status))
8045 return status;
8047 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8050 * When client side code sets a magic printer data key, detect it and save
8051 * the current printer data and the magic key's data (its the DEVMODE) for
8052 * future printer/driver initializations.
8054 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8056 /* Set devmode and printer initialization info */
8057 status = save_driver_init( printer, 2, data, real_len );
8059 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8061 else
8063 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8064 type, data, real_len );
8065 if ( W_ERROR_IS_OK(status) )
8066 status = mod_a_printer(printer, 2);
8069 done:
8070 free_a_printer(&printer, 2);
8072 return status;
8075 /****************************************************************************
8076 ****************************************************************************/
8078 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8080 POLICY_HND *handle = &q_u->handle;
8081 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8082 int snum;
8084 DEBUG(5,("_spoolss_resetprinter\n"));
8087 * All we do is to check to see if the handle and queue is valid.
8088 * This call really doesn't mean anything to us because we only
8089 * support RAW printing. --jerry
8092 if (!Printer) {
8093 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8094 return WERR_BADFID;
8097 if (!get_printer_snum(p,handle, &snum))
8098 return WERR_BADFID;
8101 /* blindly return success */
8102 return WERR_OK;
8106 /****************************************************************************
8107 ****************************************************************************/
8109 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8111 POLICY_HND *handle = &q_u->handle;
8112 UNISTR2 *value = &q_u->valuename;
8114 NT_PRINTER_INFO_LEVEL *printer = NULL;
8115 int snum=0;
8116 WERROR status = WERR_OK;
8117 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8118 pstring valuename;
8120 DEBUG(5,("spoolss_deleteprinterdata\n"));
8122 if (!Printer) {
8123 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8124 return WERR_BADFID;
8127 if (!get_printer_snum(p, handle, &snum))
8128 return WERR_BADFID;
8130 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8131 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8132 return WERR_ACCESS_DENIED;
8135 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8136 if (!W_ERROR_IS_OK(status))
8137 return status;
8139 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8141 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8143 if ( W_ERROR_IS_OK(status) )
8144 mod_a_printer( printer, 2 );
8146 free_a_printer(&printer, 2);
8148 return status;
8151 /****************************************************************************
8152 ****************************************************************************/
8154 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8156 POLICY_HND *handle = &q_u->handle;
8157 FORM *form = &q_u->form;
8158 nt_forms_struct tmpForm;
8159 int snum;
8160 WERROR status = WERR_OK;
8161 NT_PRINTER_INFO_LEVEL *printer = NULL;
8163 int count=0;
8164 nt_forms_struct *list=NULL;
8165 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8167 DEBUG(5,("spoolss_addform\n"));
8169 if (!Printer) {
8170 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8171 return WERR_BADFID;
8175 /* forms can be added on printer of on the print server handle */
8177 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8179 if (!get_printer_snum(p,handle, &snum))
8180 return WERR_BADFID;
8182 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8183 if (!W_ERROR_IS_OK(status))
8184 goto done;
8187 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8188 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8189 status = WERR_ACCESS_DENIED;
8190 goto done;
8193 /* can't add if builtin */
8195 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8196 status = WERR_ALREADY_EXISTS;
8197 goto done;
8200 count = get_ntforms(&list);
8202 if(!add_a_form(&list, form, &count)) {
8203 status = WERR_NOMEM;
8204 goto done;
8207 write_ntforms(&list, count);
8210 * ChangeID must always be set if this is a printer
8213 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8214 status = mod_a_printer(printer, 2);
8216 done:
8217 if ( printer )
8218 free_a_printer(&printer, 2);
8219 SAFE_FREE(list);
8221 return status;
8224 /****************************************************************************
8225 ****************************************************************************/
8227 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8229 POLICY_HND *handle = &q_u->handle;
8230 UNISTR2 *form_name = &q_u->name;
8231 nt_forms_struct tmpForm;
8232 int count=0;
8233 nt_forms_struct *list=NULL;
8234 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8235 int snum;
8236 WERROR status = WERR_OK;
8237 NT_PRINTER_INFO_LEVEL *printer = NULL;
8239 DEBUG(5,("spoolss_deleteform\n"));
8241 if (!Printer) {
8242 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8243 return WERR_BADFID;
8246 /* forms can be deleted on printer of on the print server handle */
8248 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8250 if (!get_printer_snum(p,handle, &snum))
8251 return WERR_BADFID;
8253 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8254 if (!W_ERROR_IS_OK(status))
8255 goto done;
8258 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8259 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8260 status = WERR_ACCESS_DENIED;
8261 goto done;
8264 /* can't delete if builtin */
8266 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8267 status = WERR_INVALID_PARAM;
8268 goto done;
8271 count = get_ntforms(&list);
8273 if ( !delete_a_form(&list, form_name, &count, &status ))
8274 goto done;
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_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8296 POLICY_HND *handle = &q_u->handle;
8297 FORM *form = &q_u->form;
8298 nt_forms_struct tmpForm;
8299 int snum;
8300 WERROR status = WERR_OK;
8301 NT_PRINTER_INFO_LEVEL *printer = NULL;
8303 int count=0;
8304 nt_forms_struct *list=NULL;
8305 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8307 DEBUG(5,("spoolss_setform\n"));
8309 if (!Printer) {
8310 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8311 return WERR_BADFID;
8314 /* forms can be modified on printer of on the print server handle */
8316 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8318 if (!get_printer_snum(p,handle, &snum))
8319 return WERR_BADFID;
8321 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8322 if (!W_ERROR_IS_OK(status))
8323 goto done;
8326 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8327 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8328 status = WERR_ACCESS_DENIED;
8329 goto done;
8332 /* can't set if builtin */
8333 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8334 status = WERR_INVALID_PARAM;
8335 goto done;
8338 count = get_ntforms(&list);
8339 update_a_form(&list, form, count);
8340 write_ntforms(&list, count);
8343 * ChangeID must always be set if this is a printer
8346 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8347 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 enumprintprocessors level 1.
8360 ****************************************************************************/
8362 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8364 PRINTPROCESSOR_1 *info_1=NULL;
8366 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8367 return WERR_NOMEM;
8369 (*returned) = 0x1;
8371 init_unistr(&info_1->name, "winprint");
8373 *needed += spoolss_size_printprocessor_info_1(info_1);
8375 if (!alloc_buffer_size(buffer, *needed))
8376 return WERR_INSUFFICIENT_BUFFER;
8378 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8380 SAFE_FREE(info_1);
8382 if (*needed > offered) {
8383 *returned=0;
8384 return WERR_INSUFFICIENT_BUFFER;
8387 return WERR_OK;
8390 /****************************************************************************
8391 ****************************************************************************/
8393 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8395 uint32 level = q_u->level;
8396 NEW_BUFFER *buffer = NULL;
8397 uint32 offered = q_u->offered;
8398 uint32 *needed = &r_u->needed;
8399 uint32 *returned = &r_u->returned;
8401 /* that's an [in out] buffer */
8402 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8403 buffer = r_u->buffer;
8405 DEBUG(5,("spoolss_enumprintprocessors\n"));
8408 * Enumerate the print processors ...
8410 * Just reply with "winprint", to keep NT happy
8411 * and I can use my nice printer checker.
8414 *returned=0;
8415 *needed=0;
8417 switch (level) {
8418 case 1:
8419 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8420 default:
8421 return WERR_UNKNOWN_LEVEL;
8425 /****************************************************************************
8426 enumprintprocdatatypes level 1.
8427 ****************************************************************************/
8429 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8431 PRINTPROCDATATYPE_1 *info_1=NULL;
8433 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8434 return WERR_NOMEM;
8436 (*returned) = 0x1;
8438 init_unistr(&info_1->name, "RAW");
8440 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8442 if (!alloc_buffer_size(buffer, *needed))
8443 return WERR_INSUFFICIENT_BUFFER;
8445 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8447 SAFE_FREE(info_1);
8449 if (*needed > offered) {
8450 *returned=0;
8451 return WERR_INSUFFICIENT_BUFFER;
8454 return WERR_OK;
8457 /****************************************************************************
8458 ****************************************************************************/
8460 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8462 uint32 level = q_u->level;
8463 NEW_BUFFER *buffer = NULL;
8464 uint32 offered = q_u->offered;
8465 uint32 *needed = &r_u->needed;
8466 uint32 *returned = &r_u->returned;
8468 /* that's an [in out] buffer */
8469 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8470 buffer = r_u->buffer;
8472 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8474 *returned=0;
8475 *needed=0;
8477 switch (level) {
8478 case 1:
8479 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8480 default:
8481 return WERR_UNKNOWN_LEVEL;
8485 /****************************************************************************
8486 enumprintmonitors level 1.
8487 ****************************************************************************/
8489 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8491 PRINTMONITOR_1 *info_1=NULL;
8493 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8494 return WERR_NOMEM;
8496 (*returned) = 0x1;
8498 init_unistr(&info_1->name, "Local Port");
8500 *needed += spoolss_size_printmonitor_info_1(info_1);
8502 if (!alloc_buffer_size(buffer, *needed))
8503 return WERR_INSUFFICIENT_BUFFER;
8505 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8507 SAFE_FREE(info_1);
8509 if (*needed > offered) {
8510 *returned=0;
8511 return WERR_INSUFFICIENT_BUFFER;
8514 return WERR_OK;
8517 /****************************************************************************
8518 enumprintmonitors level 2.
8519 ****************************************************************************/
8521 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8523 PRINTMONITOR_2 *info_2=NULL;
8525 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8526 return WERR_NOMEM;
8528 (*returned) = 0x1;
8530 init_unistr(&info_2->name, "Local Port");
8531 init_unistr(&info_2->environment, "Windows NT X86");
8532 init_unistr(&info_2->dll_name, "localmon.dll");
8534 *needed += spoolss_size_printmonitor_info_2(info_2);
8536 if (!alloc_buffer_size(buffer, *needed))
8537 return WERR_INSUFFICIENT_BUFFER;
8539 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8541 SAFE_FREE(info_2);
8543 if (*needed > offered) {
8544 *returned=0;
8545 return WERR_INSUFFICIENT_BUFFER;
8548 return WERR_OK;
8551 /****************************************************************************
8552 ****************************************************************************/
8554 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8556 uint32 level = q_u->level;
8557 NEW_BUFFER *buffer = NULL;
8558 uint32 offered = q_u->offered;
8559 uint32 *needed = &r_u->needed;
8560 uint32 *returned = &r_u->returned;
8562 /* that's an [in out] buffer */
8563 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8564 buffer = r_u->buffer;
8566 DEBUG(5,("spoolss_enumprintmonitors\n"));
8569 * Enumerate the print monitors ...
8571 * Just reply with "Local Port", to keep NT happy
8572 * and I can use my nice printer checker.
8575 *returned=0;
8576 *needed=0;
8578 switch (level) {
8579 case 1:
8580 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8581 case 2:
8582 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8583 default:
8584 return WERR_UNKNOWN_LEVEL;
8588 /****************************************************************************
8589 ****************************************************************************/
8591 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8592 NT_PRINTER_INFO_LEVEL *ntprinter,
8593 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8594 uint32 *needed)
8596 int i=0;
8597 BOOL found=False;
8598 JOB_INFO_1 *info_1=NULL;
8600 info_1=SMB_MALLOC_P(JOB_INFO_1);
8602 if (info_1 == NULL) {
8603 return WERR_NOMEM;
8606 for (i=0; i<count && found==False; i++) {
8607 if ((*queue)[i].job==(int)jobid)
8608 found=True;
8611 if (found==False) {
8612 SAFE_FREE(info_1);
8613 /* NT treats not found as bad param... yet another bad choice */
8614 return WERR_INVALID_PARAM;
8617 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8619 *needed += spoolss_size_job_info_1(info_1);
8621 if (!alloc_buffer_size(buffer, *needed)) {
8622 SAFE_FREE(info_1);
8623 return WERR_INSUFFICIENT_BUFFER;
8626 smb_io_job_info_1("", buffer, info_1, 0);
8628 SAFE_FREE(info_1);
8630 if (*needed > offered)
8631 return WERR_INSUFFICIENT_BUFFER;
8633 return WERR_OK;
8636 /****************************************************************************
8637 ****************************************************************************/
8639 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8640 NT_PRINTER_INFO_LEVEL *ntprinter,
8641 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8642 uint32 *needed)
8644 int i = 0;
8645 BOOL found = False;
8646 JOB_INFO_2 *info_2;
8647 WERROR ret;
8648 DEVICEMODE *devmode = NULL;
8649 NT_DEVICEMODE *nt_devmode = NULL;
8651 info_2=SMB_MALLOC_P(JOB_INFO_2);
8653 ZERO_STRUCTP(info_2);
8655 if (info_2 == NULL) {
8656 ret = WERR_NOMEM;
8657 goto done;
8660 for ( i=0; i<count && found==False; i++ )
8662 if ((*queue)[i].job == (int)jobid)
8663 found = True;
8666 if ( !found )
8668 /* NT treats not found as bad param... yet another bad
8669 choice */
8670 ret = WERR_INVALID_PARAM;
8671 goto done;
8675 * if the print job does not have a DEVMODE associated with it,
8676 * just use the one for the printer. A NULL devicemode is not
8677 * a failure condition
8680 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8681 devmode = construct_dev_mode(snum);
8682 else {
8683 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8684 ZERO_STRUCTP( devmode );
8685 convert_nt_devicemode( devmode, nt_devmode );
8689 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8691 *needed += spoolss_size_job_info_2(info_2);
8693 if (!alloc_buffer_size(buffer, *needed)) {
8694 ret = WERR_INSUFFICIENT_BUFFER;
8695 goto done;
8698 smb_io_job_info_2("", buffer, info_2, 0);
8700 if (*needed > offered) {
8701 ret = WERR_INSUFFICIENT_BUFFER;
8702 goto done;
8705 ret = WERR_OK;
8707 done:
8708 /* Cleanup allocated memory */
8710 free_job_info_2(info_2); /* Also frees devmode */
8711 SAFE_FREE(info_2);
8713 return ret;
8716 /****************************************************************************
8717 ****************************************************************************/
8719 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8721 POLICY_HND *handle = &q_u->handle;
8722 uint32 jobid = q_u->jobid;
8723 uint32 level = q_u->level;
8724 NEW_BUFFER *buffer = NULL;
8725 uint32 offered = q_u->offered;
8726 uint32 *needed = &r_u->needed;
8727 WERROR wstatus = WERR_OK;
8728 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8729 int snum;
8730 int count;
8731 print_queue_struct *queue = NULL;
8732 print_status_struct prt_status;
8734 /* that's an [in out] buffer */
8735 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8736 buffer = r_u->buffer;
8738 DEBUG(5,("spoolss_getjob\n"));
8740 *needed = 0;
8742 if (!get_printer_snum(p, handle, &snum))
8743 return WERR_BADFID;
8745 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8746 if ( !W_ERROR_IS_OK(wstatus) )
8747 return wstatus;
8749 count = print_queue_status(snum, &queue, &prt_status);
8751 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8752 count, prt_status.status, prt_status.message));
8754 switch ( level ) {
8755 case 1:
8756 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8757 buffer, offered, needed);
8758 break;
8759 case 2:
8760 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8761 buffer, offered, needed);
8762 break;
8763 default:
8764 wstatus = WERR_UNKNOWN_LEVEL;
8765 break;
8768 SAFE_FREE(queue);
8769 free_a_printer( &ntprinter, 2 );
8771 return wstatus;
8774 /********************************************************************
8775 spoolss_getprinterdataex
8777 From MSDN documentation of GetPrinterDataEx: pass request
8778 to GetPrinterData if key is "PrinterDriverData".
8779 ********************************************************************/
8781 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8783 POLICY_HND *handle = &q_u->handle;
8784 uint32 in_size = q_u->size;
8785 uint32 *type = &r_u->type;
8786 uint32 *out_size = &r_u->size;
8787 uint8 **data = &r_u->data;
8788 uint32 *needed = &r_u->needed;
8789 fstring keyname, valuename;
8791 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8793 NT_PRINTER_INFO_LEVEL *printer = NULL;
8794 int snum = 0;
8795 WERROR status = WERR_OK;
8797 DEBUG(4,("_spoolss_getprinterdataex\n"));
8799 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8800 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8802 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8803 keyname, valuename));
8805 /* in case of problem, return some default values */
8807 *needed = 0;
8808 *type = 0;
8809 *out_size = in_size;
8811 if (!Printer) {
8812 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8813 status = WERR_BADFID;
8814 goto done;
8817 /* Is the handle to a printer or to the server? */
8819 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8820 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8821 status = WERR_INVALID_PARAM;
8822 goto done;
8825 if ( !get_printer_snum(p,handle, &snum) )
8826 return WERR_BADFID;
8828 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8829 if ( !W_ERROR_IS_OK(status) )
8830 goto done;
8832 /* check to see if the keyname is valid */
8833 if ( !strlen(keyname) ) {
8834 status = WERR_INVALID_PARAM;
8835 goto done;
8838 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8839 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8840 free_a_printer( &printer, 2 );
8841 status = WERR_BADFILE;
8842 goto done;
8845 /* When given a new keyname, we should just create it */
8847 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8849 if (*needed > *out_size)
8850 status = WERR_MORE_DATA;
8852 done:
8853 if ( !W_ERROR_IS_OK(status) )
8855 DEBUG(5, ("error: allocating %d\n", *out_size));
8857 /* reply this param doesn't exist */
8859 if ( *out_size )
8861 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8862 status = WERR_NOMEM;
8863 goto done;
8866 else {
8867 *data = NULL;
8871 if ( printer )
8872 free_a_printer( &printer, 2 );
8874 return status;
8877 /********************************************************************
8878 * spoolss_setprinterdataex
8879 ********************************************************************/
8881 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8883 POLICY_HND *handle = &q_u->handle;
8884 uint32 type = q_u->type;
8885 uint8 *data = q_u->data;
8886 uint32 real_len = q_u->real_len;
8888 NT_PRINTER_INFO_LEVEL *printer = NULL;
8889 int snum = 0;
8890 WERROR status = WERR_OK;
8891 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8892 fstring valuename;
8893 fstring keyname;
8894 char *oid_string;
8896 DEBUG(4,("_spoolss_setprinterdataex\n"));
8898 /* From MSDN documentation of SetPrinterDataEx: pass request to
8899 SetPrinterData if key is "PrinterDriverData" */
8901 if (!Printer) {
8902 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8903 return WERR_BADFID;
8906 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8907 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8908 return WERR_INVALID_PARAM;
8911 if ( !get_printer_snum(p,handle, &snum) )
8912 return WERR_BADFID;
8915 * Access check : NT returns "access denied" if you make a
8916 * SetPrinterData call without the necessary privildge.
8917 * we were originally returning OK if nothing changed
8918 * which made Win2k issue **a lot** of SetPrinterData
8919 * when connecting to a printer --jerry
8922 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8924 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8925 return WERR_ACCESS_DENIED;
8928 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8929 if (!W_ERROR_IS_OK(status))
8930 return status;
8932 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8933 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8935 /* check for OID in valuename */
8937 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8939 *oid_string = '\0';
8940 oid_string++;
8943 /* save the registry data */
8945 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8947 if ( W_ERROR_IS_OK(status) )
8949 /* save the OID if one was specified */
8950 if ( oid_string ) {
8951 fstrcat( keyname, "\\" );
8952 fstrcat( keyname, SPOOL_OID_KEY );
8955 * I'm not checking the status here on purpose. Don't know
8956 * if this is right, but I'm returning the status from the
8957 * previous set_printer_dataex() call. I have no idea if
8958 * this is right. --jerry
8961 set_printer_dataex( printer, keyname, valuename,
8962 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8965 status = mod_a_printer(printer, 2);
8968 free_a_printer(&printer, 2);
8970 return status;
8974 /********************************************************************
8975 * spoolss_deleteprinterdataex
8976 ********************************************************************/
8978 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8980 POLICY_HND *handle = &q_u->handle;
8981 UNISTR2 *value = &q_u->valuename;
8982 UNISTR2 *key = &q_u->keyname;
8984 NT_PRINTER_INFO_LEVEL *printer = NULL;
8985 int snum=0;
8986 WERROR status = WERR_OK;
8987 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8988 pstring valuename, keyname;
8990 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8992 if (!Printer) {
8993 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8994 return WERR_BADFID;
8997 if (!get_printer_snum(p, handle, &snum))
8998 return WERR_BADFID;
9000 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9001 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9002 return WERR_ACCESS_DENIED;
9005 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9006 if (!W_ERROR_IS_OK(status))
9007 return status;
9009 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9010 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9012 status = delete_printer_dataex( printer, keyname, valuename );
9014 if ( W_ERROR_IS_OK(status) )
9015 mod_a_printer( printer, 2 );
9017 free_a_printer(&printer, 2);
9019 return status;
9022 /********************************************************************
9023 * spoolss_enumprinterkey
9024 ********************************************************************/
9027 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9029 fstring key;
9030 fstring *keynames = NULL;
9031 uint16 *enumkeys = NULL;
9032 int num_keys;
9033 int printerkey_len;
9034 POLICY_HND *handle = &q_u->handle;
9035 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9036 NT_PRINTER_DATA *data;
9037 NT_PRINTER_INFO_LEVEL *printer = NULL;
9038 int snum = 0;
9039 WERROR status = WERR_BADFILE;
9042 DEBUG(4,("_spoolss_enumprinterkey\n"));
9044 if (!Printer) {
9045 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9046 return WERR_BADFID;
9049 if ( !get_printer_snum(p,handle, &snum) )
9050 return WERR_BADFID;
9052 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9053 if (!W_ERROR_IS_OK(status))
9054 return status;
9056 /* get the list of subkey names */
9058 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9059 data = &printer->info_2->data;
9061 num_keys = get_printer_subkeys( data, key, &keynames );
9063 if ( num_keys == -1 ) {
9064 status = WERR_BADFILE;
9065 goto done;
9068 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9070 r_u->needed = printerkey_len*2;
9072 if ( q_u->size < r_u->needed ) {
9073 status = WERR_MORE_DATA;
9074 goto done;
9077 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9078 status = WERR_NOMEM;
9079 goto done;
9082 status = WERR_OK;
9084 if ( q_u->size < r_u->needed )
9085 status = WERR_MORE_DATA;
9087 done:
9088 free_a_printer( &printer, 2 );
9089 SAFE_FREE( keynames );
9091 return status;
9094 /********************************************************************
9095 * spoolss_deleteprinterkey
9096 ********************************************************************/
9098 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9100 POLICY_HND *handle = &q_u->handle;
9101 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9102 fstring key;
9103 NT_PRINTER_INFO_LEVEL *printer = NULL;
9104 int snum=0;
9105 WERROR status;
9107 DEBUG(5,("spoolss_deleteprinterkey\n"));
9109 if (!Printer) {
9110 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9111 return WERR_BADFID;
9114 /* if keyname == NULL, return error */
9116 if ( !q_u->keyname.buffer )
9117 return WERR_INVALID_PARAM;
9119 if (!get_printer_snum(p, handle, &snum))
9120 return WERR_BADFID;
9122 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9123 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9124 return WERR_ACCESS_DENIED;
9127 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9128 if (!W_ERROR_IS_OK(status))
9129 return status;
9131 /* delete the key and all subneys */
9133 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9135 status = delete_all_printer_data( printer->info_2, key );
9137 if ( W_ERROR_IS_OK(status) )
9138 status = mod_a_printer(printer, 2);
9140 free_a_printer( &printer, 2 );
9142 return status;
9146 /********************************************************************
9147 * spoolss_enumprinterdataex
9148 ********************************************************************/
9150 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9152 POLICY_HND *handle = &q_u->handle;
9153 uint32 in_size = q_u->size;
9154 uint32 num_entries,
9155 needed;
9156 NT_PRINTER_INFO_LEVEL *printer = NULL;
9157 PRINTER_ENUM_VALUES *enum_values = NULL;
9158 NT_PRINTER_DATA *p_data;
9159 fstring key;
9160 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9161 int snum;
9162 WERROR result;
9163 int key_index;
9164 int i;
9165 REGISTRY_VALUE *val;
9166 char *value_name;
9167 int data_len;
9170 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9172 if (!Printer) {
9173 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9174 return WERR_BADFID;
9178 * first check for a keyname of NULL or "". Win2k seems to send
9179 * this a lot and we should send back WERR_INVALID_PARAM
9180 * no need to spend time looking up the printer in this case.
9181 * --jerry
9184 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9185 if ( !strlen(key) ) {
9186 result = WERR_INVALID_PARAM;
9187 goto done;
9190 /* get the printer off of disk */
9192 if (!get_printer_snum(p,handle, &snum))
9193 return WERR_BADFID;
9195 ZERO_STRUCT(printer);
9196 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9197 if (!W_ERROR_IS_OK(result))
9198 return result;
9200 /* now look for a match on the key name */
9202 p_data = &printer->info_2->data;
9204 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9205 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9207 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9208 result = WERR_INVALID_PARAM;
9209 goto done;
9212 result = WERR_OK;
9213 needed = 0;
9215 /* allocate the memory for the array of pointers -- if necessary */
9217 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9218 if ( num_entries )
9220 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9222 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9223 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9224 result = WERR_NOMEM;
9225 goto done;
9228 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9232 * loop through all params and build the array to pass
9233 * back to the client
9236 for ( i=0; i<num_entries; i++ )
9238 /* lookup the registry value */
9240 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9241 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9243 /* copy the data */
9245 value_name = regval_name( val );
9246 init_unistr( &enum_values[i].valuename, value_name );
9247 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9248 enum_values[i].type = regval_type( val );
9250 data_len = regval_size( val );
9251 if ( data_len ) {
9252 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9254 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9255 data_len ));
9256 result = WERR_NOMEM;
9257 goto done;
9260 enum_values[i].data_len = data_len;
9262 /* keep track of the size of the array in bytes */
9264 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9267 /* housekeeping information in the reply */
9269 r_u->needed = needed;
9270 r_u->returned = num_entries;
9272 if (needed > in_size) {
9273 result = WERR_MORE_DATA;
9274 goto done;
9277 /* copy data into the reply */
9279 r_u->ctr.size = r_u->needed;
9280 r_u->ctr.size_of_array = r_u->returned;
9281 r_u->ctr.values = enum_values;
9285 done:
9286 if ( printer )
9287 free_a_printer(&printer, 2);
9289 return result;
9292 /****************************************************************************
9293 ****************************************************************************/
9295 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9297 init_unistr(&info->name, name);
9300 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9301 UNISTR2 *environment,
9302 NEW_BUFFER *buffer,
9303 uint32 offered,
9304 uint32 *needed)
9306 pstring path;
9307 pstring long_archi;
9308 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9310 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9312 if (!get_short_archi(long_archi))
9313 return WERR_INVALID_ENVIRONMENT;
9315 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9316 return WERR_NOMEM;
9318 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9320 fill_printprocessordirectory_1(info, path);
9322 *needed += spoolss_size_printprocessordirectory_info_1(info);
9324 if (!alloc_buffer_size(buffer, *needed)) {
9325 safe_free(info);
9326 return WERR_INSUFFICIENT_BUFFER;
9329 smb_io_printprocessordirectory_1("", buffer, info, 0);
9331 safe_free(info);
9333 if (*needed > offered)
9334 return WERR_INSUFFICIENT_BUFFER;
9335 else
9336 return WERR_OK;
9339 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9341 uint32 level = q_u->level;
9342 NEW_BUFFER *buffer = NULL;
9343 uint32 offered = q_u->offered;
9344 uint32 *needed = &r_u->needed;
9345 WERROR result;
9347 /* that's an [in out] buffer */
9348 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9349 buffer = r_u->buffer;
9351 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9353 *needed=0;
9355 switch(level) {
9356 case 1:
9357 result = getprintprocessordirectory_level_1
9358 (&q_u->name, &q_u->environment, buffer, offered, needed);
9359 break;
9360 default:
9361 result = WERR_UNKNOWN_LEVEL;
9364 return result;
9367 #if 0
9369 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9370 SPOOL_R_REPLYOPENPRINTER *r_u)
9372 DEBUG(5,("_spoolss_replyopenprinter\n"));
9374 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9376 return WERR_OK;
9379 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9380 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9382 DEBUG(5,("_spoolss_replycloseprinter\n"));
9383 return WERR_OK;
9386 #endif