r5739: sync for 3.0.12rc1 (current with SAMBA_3_0 r5738)
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blobffeeb0af9a9da1ed6c1d7924e089f2dcf68ba6af
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 = REG_DWORD;
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 = REG_DWORD;
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 = REG_DWORD;
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 = REG_DWORD;
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 = REG_DWORD;
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 = REG_DWORD;
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 = REG_BINARY;
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 = REG_SZ;
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 = REG_SZ;
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 = REG_DWORD;
2434 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2435 return WERR_NOMEM;
2437 /* only show the publish check box if we are a
2438 memeber of a AD domain */
2440 if ( lp_security() == SEC_ADS )
2441 SIVAL(*data, 0, 0x01);
2442 else
2443 SIVAL(*data, 0, 0x00);
2445 *needed = 0x4;
2446 return WERR_OK;
2449 if (!StrCaseCmp(value, "DNSMachineName")) {
2450 pstring hostname;
2452 if (!get_mydnsfullname(hostname))
2453 return WERR_BADFILE;
2454 *type = REG_SZ;
2455 *needed = 2*(strlen(hostname)+1);
2456 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2457 return WERR_NOMEM;
2458 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2459 for (i=0; i<strlen(hostname); i++) {
2460 (*data)[2*i]=hostname[i];
2461 (*data)[2*i+1]='\0';
2463 return WERR_OK;
2467 return WERR_BADFILE;
2470 /********************************************************************
2471 * spoolss_getprinterdata
2472 ********************************************************************/
2474 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2476 POLICY_HND *handle = &q_u->handle;
2477 UNISTR2 *valuename = &q_u->valuename;
2478 uint32 in_size = q_u->size;
2479 uint32 *type = &r_u->type;
2480 uint32 *out_size = &r_u->size;
2481 uint8 **data = &r_u->data;
2482 uint32 *needed = &r_u->needed;
2483 WERROR status;
2484 fstring value;
2485 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2486 NT_PRINTER_INFO_LEVEL *printer = NULL;
2487 int snum = 0;
2490 * Reminder: when it's a string, the length is in BYTES
2491 * even if UNICODE is negociated.
2493 * JFM, 4/19/1999
2496 *out_size = in_size;
2498 /* in case of problem, return some default values */
2500 *needed = 0;
2501 *type = 0;
2503 DEBUG(4,("_spoolss_getprinterdata\n"));
2505 if ( !Printer ) {
2506 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2507 status = WERR_BADFID;
2508 goto done;
2511 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2513 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2514 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2515 else
2517 if ( !get_printer_snum(p,handle, &snum) ) {
2518 status = WERR_BADFID;
2519 goto done;
2522 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2523 if ( !W_ERROR_IS_OK(status) )
2524 goto done;
2526 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2528 if ( strequal(value, "ChangeId") ) {
2529 *type = REG_DWORD;
2530 *needed = sizeof(uint32);
2531 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2532 status = WERR_NOMEM;
2533 goto done;
2535 SIVAL( *data, 0, printer->info_2->changeid );
2536 status = WERR_OK;
2538 else
2539 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2542 if (*needed > *out_size)
2543 status = WERR_MORE_DATA;
2545 done:
2546 if ( !W_ERROR_IS_OK(status) )
2548 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2550 /* reply this param doesn't exist */
2552 if ( *out_size ) {
2553 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2554 if ( printer )
2555 free_a_printer( &printer, 2 );
2556 return WERR_NOMEM;
2559 else {
2560 *data = NULL;
2564 /* cleanup & exit */
2566 if ( printer )
2567 free_a_printer( &printer, 2 );
2569 return status;
2572 /*********************************************************
2573 Connect to the client machine.
2574 **********************************************************/
2576 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2577 struct in_addr *client_ip, const char *remote_machine)
2579 ZERO_STRUCTP(the_cli);
2581 if(cli_initialise(the_cli) == NULL) {
2582 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2583 return False;
2586 if ( is_zero_ip(*client_ip) ) {
2587 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2588 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2589 cli_shutdown(the_cli);
2590 return False;
2593 if (ismyip(the_cli->dest_ip)) {
2594 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2595 cli_shutdown(the_cli);
2596 return False;
2599 else {
2600 the_cli->dest_ip.s_addr = client_ip->s_addr;
2601 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2602 inet_ntoa(*client_ip) ));
2605 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2606 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) ));
2607 cli_shutdown(the_cli);
2608 return False;
2611 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2612 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2613 remote_machine));
2614 cli_shutdown(the_cli);
2615 return False;
2618 the_cli->protocol = PROTOCOL_NT1;
2619 cli_setup_signing_state(the_cli, lp_client_signing());
2621 if (!cli_negprot(the_cli)) {
2622 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2623 cli_shutdown(the_cli);
2624 return False;
2627 if (the_cli->protocol != PROTOCOL_NT1) {
2628 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2629 cli_shutdown(the_cli);
2630 return False;
2634 * Do an anonymous session setup.
2637 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2638 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2639 cli_shutdown(the_cli);
2640 return False;
2643 if (!(the_cli->sec_mode & 1)) {
2644 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2645 cli_shutdown(the_cli);
2646 return False;
2649 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2650 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) ));
2651 cli_shutdown(the_cli);
2652 return False;
2656 * Ok - we have an anonymous connection to the IPC$ share.
2657 * Now start the NT Domain stuff :-).
2660 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2661 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)));
2662 cli_nt_session_close(the_cli);
2663 cli_ulogoff(the_cli);
2664 cli_shutdown(the_cli);
2665 return False;
2668 return True;
2671 /***************************************************************************
2672 Connect to the client.
2673 ****************************************************************************/
2675 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2676 uint32 localprinter, uint32 type,
2677 POLICY_HND *handle, struct in_addr *client_ip)
2679 WERROR result;
2682 * If it's the first connection, contact the client
2683 * and connect to the IPC$ share anonymously
2685 if (smb_connections==0) {
2686 fstring unix_printer;
2688 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2690 ZERO_STRUCT(notify_cli);
2692 if(!spoolss_connect_to_client(&notify_cli, client_ip, unix_printer))
2693 return False;
2695 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2696 /* Tell the connections db we're now interested in printer
2697 * notify messages. */
2698 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2702 * Tell the specific printing tdb we want messages for this printer
2703 * by registering our PID.
2706 if (!print_notify_register_pid(snum))
2707 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2709 smb_connections++;
2711 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2712 type, handle);
2714 if (!W_ERROR_IS_OK(result))
2715 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2716 dos_errstr(result)));
2718 return (W_ERROR_IS_OK(result));
2721 /********************************************************************
2722 * _spoolss_rffpcnex
2723 * ReplyFindFirstPrinterChangeNotifyEx
2725 * before replying OK: status=0 a rpc call is made to the workstation
2726 * asking ReplyOpenPrinter
2728 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2729 * called from api_spoolss_rffpcnex
2730 ********************************************************************/
2732 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2734 POLICY_HND *handle = &q_u->handle;
2735 uint32 flags = q_u->flags;
2736 uint32 options = q_u->options;
2737 UNISTR2 *localmachine = &q_u->localmachine;
2738 uint32 printerlocal = q_u->printerlocal;
2739 int snum = -1;
2740 SPOOL_NOTIFY_OPTION *option = q_u->option;
2741 struct in_addr client_ip;
2743 /* store the notify value in the printer struct */
2745 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2747 if (!Printer) {
2748 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2749 return WERR_BADFID;
2752 Printer->notify.flags=flags;
2753 Printer->notify.options=options;
2754 Printer->notify.printerlocal=printerlocal;
2756 if (Printer->notify.option)
2757 free_spool_notify_option(&Printer->notify.option);
2759 Printer->notify.option=dup_spool_notify_option(option);
2761 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2762 sizeof(Printer->notify.localmachine)-1);
2764 /* Connect to the client machine and send a ReplyOpenPrinter */
2766 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2767 snum = -1;
2768 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2769 !get_printer_snum(p, handle, &snum) )
2770 return WERR_BADFID;
2772 client_ip.s_addr = inet_addr(p->conn->client_address);
2774 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2775 Printer->notify.printerlocal, 1,
2776 &Printer->notify.client_hnd, &client_ip))
2777 return WERR_SERVER_UNAVAILABLE;
2779 Printer->notify.client_connected=True;
2781 return WERR_OK;
2784 /*******************************************************************
2785 * fill a notify_info_data with the servername
2786 ********************************************************************/
2788 void spoolss_notify_server_name(int snum,
2789 SPOOL_NOTIFY_INFO_DATA *data,
2790 print_queue_struct *queue,
2791 NT_PRINTER_INFO_LEVEL *printer,
2792 TALLOC_CTX *mem_ctx)
2794 pstring temp;
2795 uint32 len;
2797 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2799 data->notify_data.data.length = len;
2800 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2802 if (!data->notify_data.data.string) {
2803 data->notify_data.data.length = 0;
2804 return;
2807 memcpy(data->notify_data.data.string, temp, len);
2810 /*******************************************************************
2811 * fill a notify_info_data with the printername (not including the servername).
2812 ********************************************************************/
2814 void spoolss_notify_printer_name(int snum,
2815 SPOOL_NOTIFY_INFO_DATA *data,
2816 print_queue_struct *queue,
2817 NT_PRINTER_INFO_LEVEL *printer,
2818 TALLOC_CTX *mem_ctx)
2820 pstring temp;
2821 uint32 len;
2823 /* the notify name should not contain the \\server\ part */
2824 char *p = strrchr(printer->info_2->printername, '\\');
2826 if (!p) {
2827 p = printer->info_2->printername;
2828 } else {
2829 p++;
2832 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2834 data->notify_data.data.length = len;
2835 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2837 if (!data->notify_data.data.string) {
2838 data->notify_data.data.length = 0;
2839 return;
2842 memcpy(data->notify_data.data.string, temp, len);
2845 /*******************************************************************
2846 * fill a notify_info_data with the servicename
2847 ********************************************************************/
2849 void spoolss_notify_share_name(int snum,
2850 SPOOL_NOTIFY_INFO_DATA *data,
2851 print_queue_struct *queue,
2852 NT_PRINTER_INFO_LEVEL *printer,
2853 TALLOC_CTX *mem_ctx)
2855 pstring temp;
2856 uint32 len;
2858 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2860 data->notify_data.data.length = len;
2861 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2863 if (!data->notify_data.data.string) {
2864 data->notify_data.data.length = 0;
2865 return;
2868 memcpy(data->notify_data.data.string, temp, len);
2871 /*******************************************************************
2872 * fill a notify_info_data with the port name
2873 ********************************************************************/
2875 void spoolss_notify_port_name(int snum,
2876 SPOOL_NOTIFY_INFO_DATA *data,
2877 print_queue_struct *queue,
2878 NT_PRINTER_INFO_LEVEL *printer,
2879 TALLOC_CTX *mem_ctx)
2881 pstring temp;
2882 uint32 len;
2884 /* even if it's strange, that's consistant in all the code */
2886 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2888 data->notify_data.data.length = len;
2889 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2891 if (!data->notify_data.data.string) {
2892 data->notify_data.data.length = 0;
2893 return;
2896 memcpy(data->notify_data.data.string, temp, len);
2899 /*******************************************************************
2900 * fill a notify_info_data with the printername
2901 * but it doesn't exist, have to see what to do
2902 ********************************************************************/
2904 void spoolss_notify_driver_name(int snum,
2905 SPOOL_NOTIFY_INFO_DATA *data,
2906 print_queue_struct *queue,
2907 NT_PRINTER_INFO_LEVEL *printer,
2908 TALLOC_CTX *mem_ctx)
2910 pstring temp;
2911 uint32 len;
2913 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2915 data->notify_data.data.length = len;
2916 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2918 if (!data->notify_data.data.string) {
2919 data->notify_data.data.length = 0;
2920 return;
2923 memcpy(data->notify_data.data.string, temp, len);
2926 /*******************************************************************
2927 * fill a notify_info_data with the comment
2928 ********************************************************************/
2930 void spoolss_notify_comment(int snum,
2931 SPOOL_NOTIFY_INFO_DATA *data,
2932 print_queue_struct *queue,
2933 NT_PRINTER_INFO_LEVEL *printer,
2934 TALLOC_CTX *mem_ctx)
2936 pstring temp;
2937 uint32 len;
2939 if (*printer->info_2->comment == '\0')
2940 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2941 else
2942 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2944 data->notify_data.data.length = len;
2945 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2947 if (!data->notify_data.data.string) {
2948 data->notify_data.data.length = 0;
2949 return;
2952 memcpy(data->notify_data.data.string, temp, len);
2955 /*******************************************************************
2956 * fill a notify_info_data with the comment
2957 * location = "Room 1, floor 2, building 3"
2958 ********************************************************************/
2960 void spoolss_notify_location(int snum,
2961 SPOOL_NOTIFY_INFO_DATA *data,
2962 print_queue_struct *queue,
2963 NT_PRINTER_INFO_LEVEL *printer,
2964 TALLOC_CTX *mem_ctx)
2966 pstring temp;
2967 uint32 len;
2969 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2971 data->notify_data.data.length = len;
2972 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2974 if (!data->notify_data.data.string) {
2975 data->notify_data.data.length = 0;
2976 return;
2979 memcpy(data->notify_data.data.string, temp, len);
2982 /*******************************************************************
2983 * fill a notify_info_data with the device mode
2984 * jfm:xxxx don't to it for know but that's a real problem !!!
2985 ********************************************************************/
2987 static void spoolss_notify_devmode(int snum,
2988 SPOOL_NOTIFY_INFO_DATA *data,
2989 print_queue_struct *queue,
2990 NT_PRINTER_INFO_LEVEL *printer,
2991 TALLOC_CTX *mem_ctx)
2995 /*******************************************************************
2996 * fill a notify_info_data with the separator file name
2997 ********************************************************************/
2999 void spoolss_notify_sepfile(int snum,
3000 SPOOL_NOTIFY_INFO_DATA *data,
3001 print_queue_struct *queue,
3002 NT_PRINTER_INFO_LEVEL *printer,
3003 TALLOC_CTX *mem_ctx)
3005 pstring temp;
3006 uint32 len;
3008 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
3010 data->notify_data.data.length = len;
3011 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3013 if (!data->notify_data.data.string) {
3014 data->notify_data.data.length = 0;
3015 return;
3018 memcpy(data->notify_data.data.string, temp, len);
3021 /*******************************************************************
3022 * fill a notify_info_data with the print processor
3023 * jfm:xxxx return always winprint to indicate we don't do anything to it
3024 ********************************************************************/
3026 void spoolss_notify_print_processor(int snum,
3027 SPOOL_NOTIFY_INFO_DATA *data,
3028 print_queue_struct *queue,
3029 NT_PRINTER_INFO_LEVEL *printer,
3030 TALLOC_CTX *mem_ctx)
3032 pstring temp;
3033 uint32 len;
3035 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3037 data->notify_data.data.length = len;
3038 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3040 if (!data->notify_data.data.string) {
3041 data->notify_data.data.length = 0;
3042 return;
3045 memcpy(data->notify_data.data.string, temp, len);
3048 /*******************************************************************
3049 * fill a notify_info_data with the print processor options
3050 * jfm:xxxx send an empty string
3051 ********************************************************************/
3053 void spoolss_notify_parameters(int snum,
3054 SPOOL_NOTIFY_INFO_DATA *data,
3055 print_queue_struct *queue,
3056 NT_PRINTER_INFO_LEVEL *printer,
3057 TALLOC_CTX *mem_ctx)
3059 pstring temp;
3060 uint32 len;
3062 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3064 data->notify_data.data.length = len;
3065 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3067 if (!data->notify_data.data.string) {
3068 data->notify_data.data.length = 0;
3069 return;
3072 memcpy(data->notify_data.data.string, temp, len);
3075 /*******************************************************************
3076 * fill a notify_info_data with the data type
3077 * jfm:xxxx always send RAW as data type
3078 ********************************************************************/
3080 void spoolss_notify_datatype(int snum,
3081 SPOOL_NOTIFY_INFO_DATA *data,
3082 print_queue_struct *queue,
3083 NT_PRINTER_INFO_LEVEL *printer,
3084 TALLOC_CTX *mem_ctx)
3086 pstring temp;
3087 uint32 len;
3089 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3091 data->notify_data.data.length = len;
3092 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3094 if (!data->notify_data.data.string) {
3095 data->notify_data.data.length = 0;
3096 return;
3099 memcpy(data->notify_data.data.string, temp, len);
3102 /*******************************************************************
3103 * fill a notify_info_data with the security descriptor
3104 * jfm:xxxx send an null pointer to say no security desc
3105 * have to implement security before !
3106 ********************************************************************/
3108 static void spoolss_notify_security_desc(int snum,
3109 SPOOL_NOTIFY_INFO_DATA *data,
3110 print_queue_struct *queue,
3111 NT_PRINTER_INFO_LEVEL *printer,
3112 TALLOC_CTX *mem_ctx)
3114 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3115 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3118 /*******************************************************************
3119 * fill a notify_info_data with the attributes
3120 * jfm:xxxx a samba printer is always shared
3121 ********************************************************************/
3123 void spoolss_notify_attributes(int snum,
3124 SPOOL_NOTIFY_INFO_DATA *data,
3125 print_queue_struct *queue,
3126 NT_PRINTER_INFO_LEVEL *printer,
3127 TALLOC_CTX *mem_ctx)
3129 data->notify_data.value[0] = printer->info_2->attributes;
3130 data->notify_data.value[1] = 0;
3133 /*******************************************************************
3134 * fill a notify_info_data with the priority
3135 ********************************************************************/
3137 static void spoolss_notify_priority(int snum,
3138 SPOOL_NOTIFY_INFO_DATA *data,
3139 print_queue_struct *queue,
3140 NT_PRINTER_INFO_LEVEL *printer,
3141 TALLOC_CTX *mem_ctx)
3143 data->notify_data.value[0] = printer->info_2->priority;
3144 data->notify_data.value[1] = 0;
3147 /*******************************************************************
3148 * fill a notify_info_data with the default priority
3149 ********************************************************************/
3151 static void spoolss_notify_default_priority(int snum,
3152 SPOOL_NOTIFY_INFO_DATA *data,
3153 print_queue_struct *queue,
3154 NT_PRINTER_INFO_LEVEL *printer,
3155 TALLOC_CTX *mem_ctx)
3157 data->notify_data.value[0] = printer->info_2->default_priority;
3158 data->notify_data.value[1] = 0;
3161 /*******************************************************************
3162 * fill a notify_info_data with the start time
3163 ********************************************************************/
3165 static void spoolss_notify_start_time(int snum,
3166 SPOOL_NOTIFY_INFO_DATA *data,
3167 print_queue_struct *queue,
3168 NT_PRINTER_INFO_LEVEL *printer,
3169 TALLOC_CTX *mem_ctx)
3171 data->notify_data.value[0] = printer->info_2->starttime;
3172 data->notify_data.value[1] = 0;
3175 /*******************************************************************
3176 * fill a notify_info_data with the until time
3177 ********************************************************************/
3179 static void spoolss_notify_until_time(int snum,
3180 SPOOL_NOTIFY_INFO_DATA *data,
3181 print_queue_struct *queue,
3182 NT_PRINTER_INFO_LEVEL *printer,
3183 TALLOC_CTX *mem_ctx)
3185 data->notify_data.value[0] = printer->info_2->untiltime;
3186 data->notify_data.value[1] = 0;
3189 /*******************************************************************
3190 * fill a notify_info_data with the status
3191 ********************************************************************/
3193 static void spoolss_notify_status(int snum,
3194 SPOOL_NOTIFY_INFO_DATA *data,
3195 print_queue_struct *queue,
3196 NT_PRINTER_INFO_LEVEL *printer,
3197 TALLOC_CTX *mem_ctx)
3199 print_status_struct status;
3201 print_queue_length(snum, &status);
3202 data->notify_data.value[0]=(uint32) status.status;
3203 data->notify_data.value[1] = 0;
3206 /*******************************************************************
3207 * fill a notify_info_data with the number of jobs queued
3208 ********************************************************************/
3210 void spoolss_notify_cjobs(int snum,
3211 SPOOL_NOTIFY_INFO_DATA *data,
3212 print_queue_struct *queue,
3213 NT_PRINTER_INFO_LEVEL *printer,
3214 TALLOC_CTX *mem_ctx)
3216 data->notify_data.value[0] = print_queue_length(snum, NULL);
3217 data->notify_data.value[1] = 0;
3220 /*******************************************************************
3221 * fill a notify_info_data with the average ppm
3222 ********************************************************************/
3224 static void spoolss_notify_average_ppm(int snum,
3225 SPOOL_NOTIFY_INFO_DATA *data,
3226 print_queue_struct *queue,
3227 NT_PRINTER_INFO_LEVEL *printer,
3228 TALLOC_CTX *mem_ctx)
3230 /* always respond 8 pages per minutes */
3231 /* a little hard ! */
3232 data->notify_data.value[0] = printer->info_2->averageppm;
3233 data->notify_data.value[1] = 0;
3236 /*******************************************************************
3237 * fill a notify_info_data with username
3238 ********************************************************************/
3240 static void spoolss_notify_username(int snum,
3241 SPOOL_NOTIFY_INFO_DATA *data,
3242 print_queue_struct *queue,
3243 NT_PRINTER_INFO_LEVEL *printer,
3244 TALLOC_CTX *mem_ctx)
3246 pstring temp;
3247 uint32 len;
3249 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3251 data->notify_data.data.length = len;
3252 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3254 if (!data->notify_data.data.string) {
3255 data->notify_data.data.length = 0;
3256 return;
3259 memcpy(data->notify_data.data.string, temp, len);
3262 /*******************************************************************
3263 * fill a notify_info_data with job status
3264 ********************************************************************/
3266 static void spoolss_notify_job_status(int snum,
3267 SPOOL_NOTIFY_INFO_DATA *data,
3268 print_queue_struct *queue,
3269 NT_PRINTER_INFO_LEVEL *printer,
3270 TALLOC_CTX *mem_ctx)
3272 data->notify_data.value[0]=nt_printj_status(queue->status);
3273 data->notify_data.value[1] = 0;
3276 /*******************************************************************
3277 * fill a notify_info_data with job name
3278 ********************************************************************/
3280 static void spoolss_notify_job_name(int snum,
3281 SPOOL_NOTIFY_INFO_DATA *data,
3282 print_queue_struct *queue,
3283 NT_PRINTER_INFO_LEVEL *printer,
3284 TALLOC_CTX *mem_ctx)
3286 pstring temp;
3287 uint32 len;
3289 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3291 data->notify_data.data.length = len;
3292 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3294 if (!data->notify_data.data.string) {
3295 data->notify_data.data.length = 0;
3296 return;
3299 memcpy(data->notify_data.data.string, temp, len);
3302 /*******************************************************************
3303 * fill a notify_info_data with job status
3304 ********************************************************************/
3306 static void spoolss_notify_job_status_string(int snum,
3307 SPOOL_NOTIFY_INFO_DATA *data,
3308 print_queue_struct *queue,
3309 NT_PRINTER_INFO_LEVEL *printer,
3310 TALLOC_CTX *mem_ctx)
3313 * Now we're returning job status codes we just return a "" here. JRA.
3316 const char *p = "";
3317 pstring temp;
3318 uint32 len;
3320 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3321 p = "unknown";
3323 switch (queue->status) {
3324 case LPQ_QUEUED:
3325 p = "Queued";
3326 break;
3327 case LPQ_PAUSED:
3328 p = ""; /* NT provides the paused string */
3329 break;
3330 case LPQ_SPOOLING:
3331 p = "Spooling";
3332 break;
3333 case LPQ_PRINTING:
3334 p = "Printing";
3335 break;
3337 #endif /* NO LONGER NEEDED. */
3339 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3341 data->notify_data.data.length = len;
3342 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3344 if (!data->notify_data.data.string) {
3345 data->notify_data.data.length = 0;
3346 return;
3349 memcpy(data->notify_data.data.string, temp, len);
3352 /*******************************************************************
3353 * fill a notify_info_data with job time
3354 ********************************************************************/
3356 static void spoolss_notify_job_time(int snum,
3357 SPOOL_NOTIFY_INFO_DATA *data,
3358 print_queue_struct *queue,
3359 NT_PRINTER_INFO_LEVEL *printer,
3360 TALLOC_CTX *mem_ctx)
3362 data->notify_data.value[0]=0x0;
3363 data->notify_data.value[1]=0;
3366 /*******************************************************************
3367 * fill a notify_info_data with job size
3368 ********************************************************************/
3370 static void spoolss_notify_job_size(int snum,
3371 SPOOL_NOTIFY_INFO_DATA *data,
3372 print_queue_struct *queue,
3373 NT_PRINTER_INFO_LEVEL *printer,
3374 TALLOC_CTX *mem_ctx)
3376 data->notify_data.value[0]=queue->size;
3377 data->notify_data.value[1]=0;
3380 /*******************************************************************
3381 * fill a notify_info_data with page info
3382 ********************************************************************/
3383 static void spoolss_notify_total_pages(int snum,
3384 SPOOL_NOTIFY_INFO_DATA *data,
3385 print_queue_struct *queue,
3386 NT_PRINTER_INFO_LEVEL *printer,
3387 TALLOC_CTX *mem_ctx)
3389 data->notify_data.value[0]=queue->page_count;
3390 data->notify_data.value[1]=0;
3393 /*******************************************************************
3394 * fill a notify_info_data with pages printed info.
3395 ********************************************************************/
3396 static void spoolss_notify_pages_printed(int snum,
3397 SPOOL_NOTIFY_INFO_DATA *data,
3398 print_queue_struct *queue,
3399 NT_PRINTER_INFO_LEVEL *printer,
3400 TALLOC_CTX *mem_ctx)
3402 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3403 data->notify_data.value[1]=0;
3406 /*******************************************************************
3407 Fill a notify_info_data with job position.
3408 ********************************************************************/
3410 static void spoolss_notify_job_position(int snum,
3411 SPOOL_NOTIFY_INFO_DATA *data,
3412 print_queue_struct *queue,
3413 NT_PRINTER_INFO_LEVEL *printer,
3414 TALLOC_CTX *mem_ctx)
3416 data->notify_data.value[0]=queue->job;
3417 data->notify_data.value[1]=0;
3420 /*******************************************************************
3421 Fill a notify_info_data with submitted time.
3422 ********************************************************************/
3424 static void spoolss_notify_submitted_time(int snum,
3425 SPOOL_NOTIFY_INFO_DATA *data,
3426 print_queue_struct *queue,
3427 NT_PRINTER_INFO_LEVEL *printer,
3428 TALLOC_CTX *mem_ctx)
3430 struct tm *t;
3431 uint32 len;
3432 SYSTEMTIME st;
3433 char *p;
3435 t=gmtime(&queue->time);
3437 len = sizeof(SYSTEMTIME);
3439 data->notify_data.data.length = len;
3440 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3442 if (!data->notify_data.data.string) {
3443 data->notify_data.data.length = 0;
3444 return;
3447 make_systemtime(&st, t);
3450 * Systemtime must be linearized as a set of UINT16's.
3451 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3454 p = (char *)data->notify_data.data.string;
3455 SSVAL(p, 0, st.year);
3456 SSVAL(p, 2, st.month);
3457 SSVAL(p, 4, st.dayofweek);
3458 SSVAL(p, 6, st.day);
3459 SSVAL(p, 8, st.hour);
3460 SSVAL(p, 10, st.minute);
3461 SSVAL(p, 12, st.second);
3462 SSVAL(p, 14, st.milliseconds);
3465 struct s_notify_info_data_table
3467 uint16 type;
3468 uint16 field;
3469 const char *name;
3470 uint32 size;
3471 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3472 print_queue_struct *queue,
3473 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3476 /* A table describing the various print notification constants and
3477 whether the notification data is a pointer to a variable sized
3478 buffer, a one value uint32 or a two value uint32. */
3480 static const struct s_notify_info_data_table notify_info_data_table[] =
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3485 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3486 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3487 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3488 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3489 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3490 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3491 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3492 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3493 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3494 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3495 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3496 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3497 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3498 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3499 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3500 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3501 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3502 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3503 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3504 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3505 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3506 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3507 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3508 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3509 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3510 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3511 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3512 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3513 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3514 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3515 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3516 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3517 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3518 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3519 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3520 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3521 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3522 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3523 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3524 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3525 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3526 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3527 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3528 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3529 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3530 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3531 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3534 /*******************************************************************
3535 Return the size of info_data structure.
3536 ********************************************************************/
3538 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3540 int i=0;
3542 for (i = 0; i < sizeof(notify_info_data_table); i++)
3544 if ( (notify_info_data_table[i].type == type)
3545 && (notify_info_data_table[i].field == field) )
3547 switch(notify_info_data_table[i].size)
3549 case NOTIFY_ONE_VALUE:
3550 case NOTIFY_TWO_VALUE:
3551 return 1;
3552 case NOTIFY_STRING:
3553 return 2;
3555 /* The only pointer notify data I have seen on
3556 the wire is the submitted time and this has
3557 the notify size set to 4. -tpot */
3559 case NOTIFY_POINTER:
3560 return 4;
3562 case NOTIFY_SECDESC:
3563 return 5;
3568 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3570 return 0;
3573 /*******************************************************************
3574 Return the type of notify_info_data.
3575 ********************************************************************/
3577 static int type_of_notify_info_data(uint16 type, uint16 field)
3579 int i=0;
3581 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3582 if (notify_info_data_table[i].type == type &&
3583 notify_info_data_table[i].field == field)
3584 return notify_info_data_table[i].size;
3587 return False;
3590 /****************************************************************************
3591 ****************************************************************************/
3593 static int search_notify(uint16 type, uint16 field, int *value)
3595 int i;
3597 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3598 if (notify_info_data_table[i].type == type &&
3599 notify_info_data_table[i].field == field &&
3600 notify_info_data_table[i].fn != NULL) {
3601 *value = i;
3602 return True;
3606 return False;
3609 /****************************************************************************
3610 ****************************************************************************/
3612 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3614 info_data->type = type;
3615 info_data->field = field;
3616 info_data->reserved = 0;
3618 info_data->size = size_of_notify_info_data(type, field);
3619 info_data->enc_type = type_of_notify_info_data(type, field);
3621 info_data->id = id;
3626 /*******************************************************************
3628 * fill a notify_info struct with info asked
3630 ********************************************************************/
3632 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3633 snum, SPOOL_NOTIFY_OPTION_TYPE
3634 *option_type, uint32 id,
3635 TALLOC_CTX *mem_ctx)
3637 int field_num,j;
3638 uint16 type;
3639 uint16 field;
3641 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3642 NT_PRINTER_INFO_LEVEL *printer = NULL;
3643 print_queue_struct *queue=NULL;
3645 type=option_type->type;
3647 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3648 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3649 option_type->count, lp_servicename(snum)));
3651 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3652 return False;
3654 for(field_num=0; field_num<option_type->count; field_num++) {
3655 field = option_type->fields[field_num];
3657 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3659 if (!search_notify(type, field, &j) )
3660 continue;
3662 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3663 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3664 return False;
3665 } else
3666 info->data = tid;
3668 current_data = &info->data[info->count];
3670 construct_info_data(current_data, type, field, id);
3672 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3673 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3675 notify_info_data_table[j].fn(snum, current_data, queue,
3676 printer, mem_ctx);
3678 info->count++;
3681 free_a_printer(&printer, 2);
3682 return True;
3685 /*******************************************************************
3687 * fill a notify_info struct with info asked
3689 ********************************************************************/
3691 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3692 SPOOL_NOTIFY_INFO *info,
3693 NT_PRINTER_INFO_LEVEL *printer,
3694 int snum, SPOOL_NOTIFY_OPTION_TYPE
3695 *option_type, uint32 id,
3696 TALLOC_CTX *mem_ctx)
3698 int field_num,j;
3699 uint16 type;
3700 uint16 field;
3702 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3704 DEBUG(4,("construct_notify_jobs_info\n"));
3706 type = option_type->type;
3708 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3709 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3710 option_type->count));
3712 for(field_num=0; field_num<option_type->count; field_num++) {
3713 field = option_type->fields[field_num];
3715 if (!search_notify(type, field, &j) )
3716 continue;
3718 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3719 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3720 return False;
3722 else info->data = tid;
3724 current_data=&(info->data[info->count]);
3726 construct_info_data(current_data, type, field, id);
3727 notify_info_data_table[j].fn(snum, current_data, queue,
3728 printer, mem_ctx);
3729 info->count++;
3732 return True;
3736 * JFM: The enumeration is not that simple, it's even non obvious.
3738 * let's take an example: I want to monitor the PRINTER SERVER for
3739 * the printer's name and the number of jobs currently queued.
3740 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3741 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3743 * I have 3 printers on the back of my server.
3745 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3746 * structures.
3747 * Number Data Id
3748 * 1 printer 1 name 1
3749 * 2 printer 1 cjob 1
3750 * 3 printer 2 name 2
3751 * 4 printer 2 cjob 2
3752 * 5 printer 3 name 3
3753 * 6 printer 3 name 3
3755 * that's the print server case, the printer case is even worse.
3758 /*******************************************************************
3760 * enumerate all printers on the printserver
3761 * fill a notify_info struct with info asked
3763 ********************************************************************/
3765 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3766 SPOOL_NOTIFY_INFO *info,
3767 TALLOC_CTX *mem_ctx)
3769 int snum;
3770 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3771 int n_services=lp_numservices();
3772 int i;
3773 SPOOL_NOTIFY_OPTION *option;
3774 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3776 DEBUG(4,("printserver_notify_info\n"));
3778 if (!Printer)
3779 return WERR_BADFID;
3781 option=Printer->notify.option;
3782 info->version=2;
3783 info->data=NULL;
3784 info->count=0;
3786 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3787 sending a ffpcn() request first */
3789 if ( !option )
3790 return WERR_BADFID;
3792 for (i=0; i<option->count; i++) {
3793 option_type=&(option->ctr.type[i]);
3795 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3796 continue;
3798 for (snum=0; snum<n_services; snum++)
3800 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3801 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3805 #if 0
3807 * Debugging information, don't delete.
3810 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3811 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3812 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3814 for (i=0; i<info->count; i++) {
3815 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3816 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3817 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3819 #endif
3821 return WERR_OK;
3824 /*******************************************************************
3826 * fill a notify_info struct with info asked
3828 ********************************************************************/
3830 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3831 TALLOC_CTX *mem_ctx)
3833 int snum;
3834 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3835 int i;
3836 uint32 id;
3837 SPOOL_NOTIFY_OPTION *option;
3838 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3839 int count,j;
3840 print_queue_struct *queue=NULL;
3841 print_status_struct status;
3843 DEBUG(4,("printer_notify_info\n"));
3845 if (!Printer)
3846 return WERR_BADFID;
3848 option=Printer->notify.option;
3849 id = 0x0;
3850 info->version=2;
3851 info->data=NULL;
3852 info->count=0;
3854 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3855 sending a ffpcn() request first */
3857 if ( !option )
3858 return WERR_BADFID;
3860 get_printer_snum(p, hnd, &snum);
3862 for (i=0; i<option->count; i++) {
3863 option_type=&option->ctr.type[i];
3865 switch ( option_type->type ) {
3866 case PRINTER_NOTIFY_TYPE:
3867 if(construct_notify_printer_info(Printer, info, snum,
3868 option_type, id,
3869 mem_ctx))
3870 id--;
3871 break;
3873 case JOB_NOTIFY_TYPE: {
3874 NT_PRINTER_INFO_LEVEL *printer = NULL;
3876 count = print_queue_status(snum, &queue, &status);
3878 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3879 goto done;
3881 for (j=0; j<count; j++) {
3882 construct_notify_jobs_info(&queue[j], info,
3883 printer, snum,
3884 option_type,
3885 queue[j].job,
3886 mem_ctx);
3889 free_a_printer(&printer, 2);
3891 done:
3892 SAFE_FREE(queue);
3893 break;
3899 * Debugging information, don't delete.
3902 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3903 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3904 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3906 for (i=0; i<info->count; i++) {
3907 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3908 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3909 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3912 return WERR_OK;
3915 /********************************************************************
3916 * spoolss_rfnpcnex
3917 ********************************************************************/
3919 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3921 POLICY_HND *handle = &q_u->handle;
3922 SPOOL_NOTIFY_INFO *info = &r_u->info;
3924 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3925 WERROR result = WERR_BADFID;
3927 /* we always have a NOTIFY_INFO struct */
3928 r_u->info_ptr=0x1;
3930 if (!Printer) {
3931 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3932 OUR_HANDLE(handle)));
3933 goto done;
3936 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3939 * We are now using the change value, and
3940 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3941 * I don't have a global notification system, I'm sending back all the
3942 * informations even when _NOTHING_ has changed.
3945 /* We need to keep track of the change value to send back in
3946 RRPCN replies otherwise our updates are ignored. */
3948 Printer->notify.fnpcn = True;
3950 if (Printer->notify.client_connected) {
3951 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3952 Printer->notify.change = q_u->change;
3955 /* just ignore the SPOOL_NOTIFY_OPTION */
3957 switch (Printer->printer_type) {
3958 case PRINTER_HANDLE_IS_PRINTSERVER:
3959 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3960 break;
3962 case PRINTER_HANDLE_IS_PRINTER:
3963 result = printer_notify_info(p, handle, info, p->mem_ctx);
3964 break;
3967 Printer->notify.fnpcn = False;
3969 done:
3970 return result;
3973 /********************************************************************
3974 * construct_printer_info_0
3975 * fill a printer_info_0 struct
3976 ********************************************************************/
3978 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3980 pstring chaine;
3981 int count;
3982 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3983 counter_printer_0 *session_counter;
3984 uint32 global_counter;
3985 struct tm *t;
3986 time_t setuptime;
3987 print_status_struct status;
3989 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3990 return False;
3992 count = print_queue_length(snum, &status);
3994 /* check if we already have a counter for this printer */
3995 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3996 if (session_counter->snum == snum)
3997 break;
4000 /* it's the first time, add it to the list */
4001 if (session_counter==NULL) {
4002 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
4003 free_a_printer(&ntprinter, 2);
4004 return False;
4006 ZERO_STRUCTP(session_counter);
4007 session_counter->snum=snum;
4008 session_counter->counter=0;
4009 DLIST_ADD(counter_list, session_counter);
4012 /* increment it */
4013 session_counter->counter++;
4015 /* JFM:
4016 * the global_counter should be stored in a TDB as it's common to all the clients
4017 * and should be zeroed on samba startup
4019 global_counter=session_counter->counter;
4021 pstrcpy(chaine,ntprinter->info_2->printername);
4023 init_unistr(&printer->printername, chaine);
4025 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
4026 init_unistr(&printer->servername, chaine);
4028 printer->cjobs = count;
4029 printer->total_jobs = 0;
4030 printer->total_bytes = 0;
4032 setuptime = (time_t)ntprinter->info_2->setuptime;
4033 t=gmtime(&setuptime);
4035 printer->year = t->tm_year+1900;
4036 printer->month = t->tm_mon+1;
4037 printer->dayofweek = t->tm_wday;
4038 printer->day = t->tm_mday;
4039 printer->hour = t->tm_hour;
4040 printer->minute = t->tm_min;
4041 printer->second = t->tm_sec;
4042 printer->milliseconds = 0;
4044 printer->global_counter = global_counter;
4045 printer->total_pages = 0;
4047 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4048 printer->major_version = 0x0005; /* NT 5 */
4049 printer->build_version = 0x0893; /* build 2195 */
4051 printer->unknown7 = 0x1;
4052 printer->unknown8 = 0x0;
4053 printer->unknown9 = 0x0;
4054 printer->session_counter = session_counter->counter;
4055 printer->unknown11 = 0x0;
4056 printer->printer_errors = 0x0; /* number of print failure */
4057 printer->unknown13 = 0x0;
4058 printer->unknown14 = 0x1;
4059 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4060 printer->unknown16 = 0x0;
4061 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4062 printer->unknown18 = 0x0;
4063 printer->status = nt_printq_status(status.status);
4064 printer->unknown20 = 0x0;
4065 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4066 printer->unknown22 = 0x0;
4067 printer->unknown23 = 0x6; /* 6 ???*/
4068 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4069 printer->unknown25 = 0;
4070 printer->unknown26 = 0;
4071 printer->unknown27 = 0;
4072 printer->unknown28 = 0;
4073 printer->unknown29 = 0;
4075 free_a_printer(&ntprinter,2);
4076 return (True);
4079 /********************************************************************
4080 * construct_printer_info_1
4081 * fill a printer_info_1 struct
4082 ********************************************************************/
4083 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4085 pstring chaine;
4086 pstring chaine2;
4087 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4089 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4090 return False;
4092 printer->flags=flags;
4094 if (*ntprinter->info_2->comment == '\0') {
4095 init_unistr(&printer->comment, lp_comment(snum));
4096 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4097 ntprinter->info_2->drivername, lp_comment(snum));
4099 else {
4100 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4101 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4102 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4105 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4107 init_unistr(&printer->description, chaine);
4108 init_unistr(&printer->name, chaine2);
4110 free_a_printer(&ntprinter,2);
4112 return True;
4115 /****************************************************************************
4116 Free a DEVMODE struct.
4117 ****************************************************************************/
4119 static void free_dev_mode(DEVICEMODE *dev)
4121 if (dev == NULL)
4122 return;
4124 SAFE_FREE(dev->private);
4125 SAFE_FREE(dev);
4129 /****************************************************************************
4130 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4131 should be valid upon entry
4132 ****************************************************************************/
4134 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4136 if ( !devmode || !ntdevmode )
4137 return False;
4139 init_unistr(&devmode->devicename, ntdevmode->devicename);
4141 init_unistr(&devmode->formname, ntdevmode->formname);
4143 devmode->specversion = ntdevmode->specversion;
4144 devmode->driverversion = ntdevmode->driverversion;
4145 devmode->size = ntdevmode->size;
4146 devmode->driverextra = ntdevmode->driverextra;
4147 devmode->fields = ntdevmode->fields;
4149 devmode->orientation = ntdevmode->orientation;
4150 devmode->papersize = ntdevmode->papersize;
4151 devmode->paperlength = ntdevmode->paperlength;
4152 devmode->paperwidth = ntdevmode->paperwidth;
4153 devmode->scale = ntdevmode->scale;
4154 devmode->copies = ntdevmode->copies;
4155 devmode->defaultsource = ntdevmode->defaultsource;
4156 devmode->printquality = ntdevmode->printquality;
4157 devmode->color = ntdevmode->color;
4158 devmode->duplex = ntdevmode->duplex;
4159 devmode->yresolution = ntdevmode->yresolution;
4160 devmode->ttoption = ntdevmode->ttoption;
4161 devmode->collate = ntdevmode->collate;
4162 devmode->icmmethod = ntdevmode->icmmethod;
4163 devmode->icmintent = ntdevmode->icmintent;
4164 devmode->mediatype = ntdevmode->mediatype;
4165 devmode->dithertype = ntdevmode->dithertype;
4167 if (ntdevmode->private != NULL) {
4168 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4169 return False;
4172 return True;
4175 /****************************************************************************
4176 Create a DEVMODE struct. Returns malloced memory.
4177 ****************************************************************************/
4179 DEVICEMODE *construct_dev_mode(int snum)
4181 NT_PRINTER_INFO_LEVEL *printer = NULL;
4182 DEVICEMODE *devmode = NULL;
4184 DEBUG(7,("construct_dev_mode\n"));
4186 DEBUGADD(8,("getting printer characteristics\n"));
4188 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4189 return NULL;
4191 if ( !printer->info_2->devmode ) {
4192 DEBUG(5, ("BONG! There was no device mode!\n"));
4193 goto done;
4196 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4197 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4198 goto done;
4201 ZERO_STRUCTP(devmode);
4203 DEBUGADD(8,("loading DEVICEMODE\n"));
4205 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4206 free_dev_mode( devmode );
4207 devmode = NULL;
4210 done:
4211 free_a_printer(&printer,2);
4213 return devmode;
4216 /********************************************************************
4217 * construct_printer_info_2
4218 * fill a printer_info_2 struct
4219 ********************************************************************/
4221 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4223 int count;
4224 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4226 print_status_struct status;
4228 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4229 return False;
4231 count = print_queue_length(snum, &status);
4233 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4234 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4235 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4236 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4237 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4239 if (*ntprinter->info_2->comment == '\0')
4240 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4241 else
4242 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4244 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4245 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4246 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4247 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4248 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4250 printer->attributes = ntprinter->info_2->attributes;
4252 printer->priority = ntprinter->info_2->priority; /* priority */
4253 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4254 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4255 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4256 printer->status = nt_printq_status(status.status); /* status */
4257 printer->cjobs = count; /* jobs */
4258 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4260 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4261 DEBUG(8, ("Returning NULL Devicemode!\n"));
4264 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4265 /* steal the printer info sec_desc structure. [badly done]. */
4266 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4267 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4268 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4269 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4271 else {
4272 printer->secdesc = NULL;
4275 free_a_printer(&ntprinter, 2);
4276 return True;
4279 /********************************************************************
4280 * construct_printer_info_3
4281 * fill a printer_info_3 struct
4282 ********************************************************************/
4284 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4286 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4287 PRINTER_INFO_3 *printer = NULL;
4289 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4290 return False;
4292 *pp_printer = NULL;
4293 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4294 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4295 return False;
4298 ZERO_STRUCTP(printer);
4300 printer->flags = 4; /* These are the components of the SD we are returning. */
4301 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4302 /* steal the printer info sec_desc structure. [badly done]. */
4303 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4305 #if 0
4307 * Set the flags for the components we are returning.
4310 if (printer->secdesc->owner_sid)
4311 printer->flags |= OWNER_SECURITY_INFORMATION;
4313 if (printer->secdesc->grp_sid)
4314 printer->flags |= GROUP_SECURITY_INFORMATION;
4316 if (printer->secdesc->dacl)
4317 printer->flags |= DACL_SECURITY_INFORMATION;
4319 if (printer->secdesc->sacl)
4320 printer->flags |= SACL_SECURITY_INFORMATION;
4321 #endif
4323 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4324 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4325 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4328 free_a_printer(&ntprinter, 2);
4330 *pp_printer = printer;
4331 return True;
4334 /********************************************************************
4335 * construct_printer_info_4
4336 * fill a printer_info_4 struct
4337 ********************************************************************/
4339 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4341 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4343 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4344 return False;
4346 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4347 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4348 printer->attributes = ntprinter->info_2->attributes;
4350 free_a_printer(&ntprinter, 2);
4351 return True;
4354 /********************************************************************
4355 * construct_printer_info_5
4356 * fill a printer_info_5 struct
4357 ********************************************************************/
4359 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4361 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4363 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4364 return False;
4366 init_unistr(&printer->printername, ntprinter->info_2->printername);
4367 init_unistr(&printer->portname, ntprinter->info_2->portname);
4368 printer->attributes = ntprinter->info_2->attributes;
4370 /* these two are not used by NT+ according to MSDN */
4372 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4373 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4375 free_a_printer(&ntprinter, 2);
4377 return True;
4380 /********************************************************************
4381 * construct_printer_info_7
4382 * fill a printer_info_7 struct
4383 ********************************************************************/
4385 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4387 char *guid_str = NULL;
4388 struct uuid guid;
4390 if (is_printer_published(print_hnd, snum, &guid)) {
4391 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4392 strupper_m(guid_str);
4393 init_unistr(&printer->guid, guid_str);
4394 printer->action = SPOOL_DS_PUBLISH;
4395 } else {
4396 init_unistr(&printer->guid, "");
4397 printer->action = SPOOL_DS_UNPUBLISH;
4400 return True;
4403 /********************************************************************
4404 Spoolss_enumprinters.
4405 ********************************************************************/
4407 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4409 int snum;
4410 int i;
4411 int n_services=lp_numservices();
4412 PRINTER_INFO_1 *tp, *printers=NULL;
4413 PRINTER_INFO_1 current_prt;
4415 DEBUG(4,("enum_all_printers_info_1\n"));
4417 for (snum=0; snum<n_services; snum++) {
4418 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4419 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4421 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4422 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4423 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4424 SAFE_FREE(printers);
4425 *returned=0;
4426 return WERR_NOMEM;
4428 else printers = tp;
4429 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4431 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4432 (*returned)++;
4437 /* check the required size. */
4438 for (i=0; i<*returned; i++)
4439 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4441 if (!alloc_buffer_size(buffer, *needed))
4442 return WERR_INSUFFICIENT_BUFFER;
4444 /* fill the buffer with the structures */
4445 for (i=0; i<*returned; i++)
4446 smb_io_printer_info_1("", buffer, &printers[i], 0);
4448 /* clear memory */
4449 SAFE_FREE(printers);
4451 if (*needed > offered) {
4452 *returned=0;
4453 return WERR_INSUFFICIENT_BUFFER;
4455 else
4456 return WERR_OK;
4459 /********************************************************************
4460 enum_all_printers_info_1_local.
4461 *********************************************************************/
4463 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4465 DEBUG(4,("enum_all_printers_info_1_local\n"));
4467 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4470 /********************************************************************
4471 enum_all_printers_info_1_name.
4472 *********************************************************************/
4474 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4476 char *s = name;
4478 DEBUG(4,("enum_all_printers_info_1_name\n"));
4480 if ((name[0] == '\\') && (name[1] == '\\'))
4481 s = name + 2;
4483 if (is_myname_or_ipaddr(s)) {
4484 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4486 else
4487 return WERR_INVALID_NAME;
4490 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4491 /********************************************************************
4492 enum_all_printers_info_1_remote.
4493 *********************************************************************/
4495 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4497 PRINTER_INFO_1 *printer;
4498 fstring printername;
4499 fstring desc;
4500 fstring comment;
4501 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4503 /* JFM: currently it's more a place holder than anything else.
4504 * In the spooler world there is a notion of server registration.
4505 * the print servers are registered on the PDC (in the same domain)
4507 * We should have a TDB here. The registration is done thru an
4508 * undocumented RPC call.
4511 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4512 return WERR_NOMEM;
4514 *returned=1;
4516 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4517 slprintf(desc, sizeof(desc)-1,"%s", name);
4518 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4520 init_unistr(&printer->description, desc);
4521 init_unistr(&printer->name, printername);
4522 init_unistr(&printer->comment, comment);
4523 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4525 /* check the required size. */
4526 *needed += spoolss_size_printer_info_1(printer);
4528 if (!alloc_buffer_size(buffer, *needed)) {
4529 SAFE_FREE(printer);
4530 return WERR_INSUFFICIENT_BUFFER;
4533 /* fill the buffer with the structures */
4534 smb_io_printer_info_1("", buffer, printer, 0);
4536 /* clear memory */
4537 SAFE_FREE(printer);
4539 if (*needed > offered) {
4540 *returned=0;
4541 return WERR_INSUFFICIENT_BUFFER;
4543 else
4544 return WERR_OK;
4547 #endif
4549 /********************************************************************
4550 enum_all_printers_info_1_network.
4551 *********************************************************************/
4553 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4555 char *s = name;
4557 DEBUG(4,("enum_all_printers_info_1_network\n"));
4559 /* If we respond to a enum_printers level 1 on our name with flags
4560 set to PRINTER_ENUM_REMOTE with a list of printers then these
4561 printers incorrectly appear in the APW browse list.
4562 Specifically the printers for the server appear at the workgroup
4563 level where all the other servers in the domain are
4564 listed. Windows responds to this call with a
4565 WERR_CAN_NOT_COMPLETE so we should do the same. */
4567 if (name[0] == '\\' && name[1] == '\\')
4568 s = name + 2;
4570 if (is_myname_or_ipaddr(s))
4571 return WERR_CAN_NOT_COMPLETE;
4573 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4576 /********************************************************************
4577 * api_spoolss_enumprinters
4579 * called from api_spoolss_enumprinters (see this to understand)
4580 ********************************************************************/
4582 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4584 int snum;
4585 int i;
4586 int n_services=lp_numservices();
4587 PRINTER_INFO_2 *tp, *printers=NULL;
4588 PRINTER_INFO_2 current_prt;
4590 for (snum=0; snum<n_services; snum++) {
4591 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4592 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4594 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4595 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) == NULL) {
4596 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4597 SAFE_FREE(printers);
4598 *returned = 0;
4599 return WERR_NOMEM;
4601 else printers = tp;
4602 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4603 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4604 (*returned)++;
4609 /* check the required size. */
4610 for (i=0; i<*returned; i++)
4611 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4613 if (!alloc_buffer_size(buffer, *needed)) {
4614 for (i=0; i<*returned; i++) {
4615 free_devmode(printers[i].devmode);
4617 SAFE_FREE(printers);
4618 return WERR_INSUFFICIENT_BUFFER;
4621 /* fill the buffer with the structures */
4622 for (i=0; i<*returned; i++)
4623 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4625 /* clear memory */
4626 for (i=0; i<*returned; i++) {
4627 free_devmode(printers[i].devmode);
4629 SAFE_FREE(printers);
4631 if (*needed > offered) {
4632 *returned=0;
4633 return WERR_INSUFFICIENT_BUFFER;
4635 else
4636 return WERR_OK;
4639 /********************************************************************
4640 * handle enumeration of printers at level 1
4641 ********************************************************************/
4643 static WERROR enumprinters_level1( uint32 flags, fstring name,
4644 NEW_BUFFER *buffer, uint32 offered,
4645 uint32 *needed, uint32 *returned)
4647 /* Not all the flags are equals */
4649 if (flags & PRINTER_ENUM_LOCAL)
4650 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4652 if (flags & PRINTER_ENUM_NAME)
4653 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4655 #if 0 /* JERRY - disabled for now */
4656 if (flags & PRINTER_ENUM_REMOTE)
4657 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4658 #endif
4660 if (flags & PRINTER_ENUM_NETWORK)
4661 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4663 return WERR_OK; /* NT4sp5 does that */
4666 /********************************************************************
4667 * handle enumeration of printers at level 2
4668 ********************************************************************/
4670 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4671 NEW_BUFFER *buffer, uint32 offered,
4672 uint32 *needed, uint32 *returned)
4674 char *s = servername;
4676 if (flags & PRINTER_ENUM_LOCAL) {
4677 return enum_all_printers_info_2(buffer, offered, needed, returned);
4680 if (flags & PRINTER_ENUM_NAME) {
4681 if ((servername[0] == '\\') && (servername[1] == '\\'))
4682 s = servername + 2;
4683 if (is_myname_or_ipaddr(s))
4684 return enum_all_printers_info_2(buffer, offered, needed, returned);
4685 else
4686 return WERR_INVALID_NAME;
4689 if (flags & PRINTER_ENUM_REMOTE)
4690 return WERR_UNKNOWN_LEVEL;
4692 return WERR_OK;
4695 /********************************************************************
4696 * handle enumeration of printers at level 5
4697 ********************************************************************/
4699 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4700 NEW_BUFFER *buffer, uint32 offered,
4701 uint32 *needed, uint32 *returned)
4703 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4704 return WERR_OK;
4707 /********************************************************************
4708 * api_spoolss_enumprinters
4710 * called from api_spoolss_enumprinters (see this to understand)
4711 ********************************************************************/
4713 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4715 uint32 flags = q_u->flags;
4716 UNISTR2 *servername = &q_u->servername;
4717 uint32 level = q_u->level;
4718 NEW_BUFFER *buffer = NULL;
4719 uint32 offered = q_u->offered;
4720 uint32 *needed = &r_u->needed;
4721 uint32 *returned = &r_u->returned;
4723 fstring name;
4725 /* that's an [in out] buffer */
4726 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4727 buffer = r_u->buffer;
4729 DEBUG(4,("_spoolss_enumprinters\n"));
4731 *needed=0;
4732 *returned=0;
4735 * Level 1:
4736 * flags==PRINTER_ENUM_NAME
4737 * if name=="" then enumerates all printers
4738 * if name!="" then enumerate the printer
4739 * flags==PRINTER_ENUM_REMOTE
4740 * name is NULL, enumerate printers
4741 * Level 2: name!="" enumerates printers, name can't be NULL
4742 * Level 3: doesn't exist
4743 * Level 4: does a local registry lookup
4744 * Level 5: same as Level 2
4747 unistr2_to_ascii(name, servername, sizeof(name)-1);
4748 strupper_m(name);
4750 switch (level) {
4751 case 1:
4752 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4753 case 2:
4754 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4755 case 5:
4756 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4757 case 3:
4758 case 4:
4759 break;
4761 return WERR_UNKNOWN_LEVEL;
4764 /****************************************************************************
4765 ****************************************************************************/
4767 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4769 PRINTER_INFO_0 *printer=NULL;
4771 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4772 return WERR_NOMEM;
4774 construct_printer_info_0(print_hnd, printer, snum);
4776 /* check the required size. */
4777 *needed += spoolss_size_printer_info_0(printer);
4779 if (!alloc_buffer_size(buffer, *needed)) {
4780 SAFE_FREE(printer);
4781 return WERR_INSUFFICIENT_BUFFER;
4784 /* fill the buffer with the structures */
4785 smb_io_printer_info_0("", buffer, printer, 0);
4787 /* clear memory */
4788 SAFE_FREE(printer);
4790 if (*needed > offered) {
4791 return WERR_INSUFFICIENT_BUFFER;
4794 return WERR_OK;
4797 /****************************************************************************
4798 ****************************************************************************/
4800 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4802 PRINTER_INFO_1 *printer=NULL;
4804 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4805 return WERR_NOMEM;
4807 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4809 /* check the required size. */
4810 *needed += spoolss_size_printer_info_1(printer);
4812 if (!alloc_buffer_size(buffer, *needed)) {
4813 SAFE_FREE(printer);
4814 return WERR_INSUFFICIENT_BUFFER;
4817 /* fill the buffer with the structures */
4818 smb_io_printer_info_1("", buffer, printer, 0);
4820 /* clear memory */
4821 SAFE_FREE(printer);
4823 if (*needed > offered) {
4824 return WERR_INSUFFICIENT_BUFFER;
4827 return WERR_OK;
4830 /****************************************************************************
4831 ****************************************************************************/
4833 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4835 PRINTER_INFO_2 *printer=NULL;
4837 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4838 return WERR_NOMEM;
4840 construct_printer_info_2(print_hnd, printer, snum);
4842 /* check the required size. */
4843 *needed += spoolss_size_printer_info_2(printer);
4845 if (!alloc_buffer_size(buffer, *needed)) {
4846 free_printer_info_2(printer);
4847 return WERR_INSUFFICIENT_BUFFER;
4850 /* fill the buffer with the structures */
4851 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4852 free_printer_info_2(printer);
4853 return WERR_NOMEM;
4856 /* clear memory */
4857 free_printer_info_2(printer);
4859 if (*needed > offered) {
4860 return WERR_INSUFFICIENT_BUFFER;
4863 return WERR_OK;
4866 /****************************************************************************
4867 ****************************************************************************/
4869 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4871 PRINTER_INFO_3 *printer=NULL;
4873 if (!construct_printer_info_3(print_hnd, &printer, snum))
4874 return WERR_NOMEM;
4876 /* check the required size. */
4877 *needed += spoolss_size_printer_info_3(printer);
4879 if (!alloc_buffer_size(buffer, *needed)) {
4880 free_printer_info_3(printer);
4881 return WERR_INSUFFICIENT_BUFFER;
4884 /* fill the buffer with the structures */
4885 smb_io_printer_info_3("", buffer, printer, 0);
4887 /* clear memory */
4888 free_printer_info_3(printer);
4890 if (*needed > offered) {
4891 return WERR_INSUFFICIENT_BUFFER;
4894 return WERR_OK;
4897 /****************************************************************************
4898 ****************************************************************************/
4900 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4902 PRINTER_INFO_4 *printer=NULL;
4904 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4905 return WERR_NOMEM;
4907 if (!construct_printer_info_4(print_hnd, printer, snum))
4908 return WERR_NOMEM;
4910 /* check the required size. */
4911 *needed += spoolss_size_printer_info_4(printer);
4913 if (!alloc_buffer_size(buffer, *needed)) {
4914 free_printer_info_4(printer);
4915 return WERR_INSUFFICIENT_BUFFER;
4918 /* fill the buffer with the structures */
4919 smb_io_printer_info_4("", buffer, printer, 0);
4921 /* clear memory */
4922 free_printer_info_4(printer);
4924 if (*needed > offered) {
4925 return WERR_INSUFFICIENT_BUFFER;
4928 return WERR_OK;
4931 /****************************************************************************
4932 ****************************************************************************/
4934 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4936 PRINTER_INFO_5 *printer=NULL;
4938 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4939 return WERR_NOMEM;
4941 if (!construct_printer_info_5(print_hnd, printer, snum))
4942 return WERR_NOMEM;
4944 /* check the required size. */
4945 *needed += spoolss_size_printer_info_5(printer);
4947 if (!alloc_buffer_size(buffer, *needed)) {
4948 free_printer_info_5(printer);
4949 return WERR_INSUFFICIENT_BUFFER;
4952 /* fill the buffer with the structures */
4953 smb_io_printer_info_5("", buffer, printer, 0);
4955 /* clear memory */
4956 free_printer_info_5(printer);
4958 if (*needed > offered) {
4959 return WERR_INSUFFICIENT_BUFFER;
4962 return WERR_OK;
4965 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4967 PRINTER_INFO_7 *printer=NULL;
4969 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4970 return WERR_NOMEM;
4972 if (!construct_printer_info_7(print_hnd, printer, snum))
4973 return WERR_NOMEM;
4975 /* check the required size. */
4976 *needed += spoolss_size_printer_info_7(printer);
4978 if (!alloc_buffer_size(buffer, *needed)) {
4979 free_printer_info_7(printer);
4980 return WERR_INSUFFICIENT_BUFFER;
4983 /* fill the buffer with the structures */
4984 smb_io_printer_info_7("", buffer, printer, 0);
4986 /* clear memory */
4987 free_printer_info_7(printer);
4989 if (*needed > offered) {
4990 return WERR_INSUFFICIENT_BUFFER;
4993 return WERR_OK;
4996 /****************************************************************************
4997 ****************************************************************************/
4999 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5001 POLICY_HND *handle = &q_u->handle;
5002 uint32 level = q_u->level;
5003 NEW_BUFFER *buffer = NULL;
5004 uint32 offered = q_u->offered;
5005 uint32 *needed = &r_u->needed;
5006 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5008 int snum;
5010 /* that's an [in out] buffer */
5011 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5012 buffer = r_u->buffer;
5014 *needed=0;
5016 if (!get_printer_snum(p, handle, &snum))
5017 return WERR_BADFID;
5019 switch (level) {
5020 case 0:
5021 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5022 case 1:
5023 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5024 case 2:
5025 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5026 case 3:
5027 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5028 case 4:
5029 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5030 case 5:
5031 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5032 case 7:
5033 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5035 return WERR_UNKNOWN_LEVEL;
5038 /********************************************************************
5039 * fill a DRIVER_INFO_1 struct
5040 ********************************************************************/
5042 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5044 init_unistr( &info->name, driver.info_3->name);
5047 /********************************************************************
5048 * construct_printer_driver_info_1
5049 ********************************************************************/
5051 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5053 NT_PRINTER_INFO_LEVEL *printer = NULL;
5054 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5056 ZERO_STRUCT(driver);
5058 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5059 return WERR_INVALID_PRINTER_NAME;
5061 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5062 return WERR_UNKNOWN_PRINTER_DRIVER;
5064 fill_printer_driver_info_1(info, driver, servername, architecture);
5066 free_a_printer(&printer,2);
5068 return WERR_OK;
5071 /********************************************************************
5072 * construct_printer_driver_info_2
5073 * fill a printer_info_2 struct
5074 ********************************************************************/
5076 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5078 pstring temp;
5080 info->version=driver.info_3->cversion;
5082 init_unistr( &info->name, driver.info_3->name );
5083 init_unistr( &info->architecture, driver.info_3->environment );
5086 if (strlen(driver.info_3->driverpath)) {
5087 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5088 init_unistr( &info->driverpath, temp );
5089 } else
5090 init_unistr( &info->driverpath, "" );
5092 if (strlen(driver.info_3->datafile)) {
5093 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5094 init_unistr( &info->datafile, temp );
5095 } else
5096 init_unistr( &info->datafile, "" );
5098 if (strlen(driver.info_3->configfile)) {
5099 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5100 init_unistr( &info->configfile, temp );
5101 } else
5102 init_unistr( &info->configfile, "" );
5105 /********************************************************************
5106 * construct_printer_driver_info_2
5107 * fill a printer_info_2 struct
5108 ********************************************************************/
5110 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5112 NT_PRINTER_INFO_LEVEL *printer = NULL;
5113 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5115 ZERO_STRUCT(printer);
5116 ZERO_STRUCT(driver);
5118 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5119 return WERR_INVALID_PRINTER_NAME;
5121 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5122 return WERR_UNKNOWN_PRINTER_DRIVER;
5124 fill_printer_driver_info_2(info, driver, servername);
5126 free_a_printer(&printer,2);
5128 return WERR_OK;
5131 /********************************************************************
5132 * copy a strings array and convert to UNICODE
5134 * convert an array of ascii string to a UNICODE string
5135 ********************************************************************/
5137 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5139 int i=0;
5140 int j=0;
5141 const char *v;
5142 pstring line;
5143 uint16 *tuary;
5145 DEBUG(6,("init_unistr_array\n"));
5146 *uni_array=NULL;
5148 while (True)
5150 if ( !char_array )
5151 v = "";
5152 else
5154 v = char_array[i];
5155 if (!v)
5156 v = ""; /* hack to handle null lists */
5159 /* hack to allow this to be used in places other than when generating
5160 the list of dependent files */
5162 if ( servername )
5163 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5164 else
5165 pstrcpy( line, v );
5167 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5169 /* add one extra unit16 for the second terminating NULL */
5171 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5172 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5173 return 0;
5174 } else
5175 *uni_array = tuary;
5177 if ( !strlen(v) )
5178 break;
5180 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5181 i++;
5184 if (*uni_array) {
5185 /* special case for ""; we need to add both NULL's here */
5186 if (!j)
5187 (*uni_array)[j++]=0x0000;
5188 (*uni_array)[j]=0x0000;
5191 DEBUGADD(6,("last one:done\n"));
5193 /* return size of array in uint16's */
5195 return j+1;
5198 /********************************************************************
5199 * construct_printer_info_3
5200 * fill a printer_info_3 struct
5201 ********************************************************************/
5203 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5205 pstring temp;
5207 ZERO_STRUCTP(info);
5209 info->version=driver.info_3->cversion;
5211 init_unistr( &info->name, driver.info_3->name );
5212 init_unistr( &info->architecture, driver.info_3->environment );
5214 if (strlen(driver.info_3->driverpath)) {
5215 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5216 init_unistr( &info->driverpath, temp );
5217 } else
5218 init_unistr( &info->driverpath, "" );
5220 if (strlen(driver.info_3->datafile)) {
5221 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5222 init_unistr( &info->datafile, temp );
5223 } else
5224 init_unistr( &info->datafile, "" );
5226 if (strlen(driver.info_3->configfile)) {
5227 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5228 init_unistr( &info->configfile, temp );
5229 } else
5230 init_unistr( &info->configfile, "" );
5232 if (strlen(driver.info_3->helpfile)) {
5233 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5234 init_unistr( &info->helpfile, temp );
5235 } else
5236 init_unistr( &info->helpfile, "" );
5238 init_unistr( &info->monitorname, driver.info_3->monitorname );
5239 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5241 info->dependentfiles=NULL;
5242 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5245 /********************************************************************
5246 * construct_printer_info_3
5247 * fill a printer_info_3 struct
5248 ********************************************************************/
5250 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5252 NT_PRINTER_INFO_LEVEL *printer = NULL;
5253 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5254 WERROR status;
5255 ZERO_STRUCT(driver);
5257 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5258 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5259 if (!W_ERROR_IS_OK(status))
5260 return WERR_INVALID_PRINTER_NAME;
5262 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5263 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5265 #if 0 /* JERRY */
5268 * I put this code in during testing. Helpful when commenting out the
5269 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5270 * as win2k always queries the driver using an infor level of 6.
5271 * I've left it in (but ifdef'd out) because I'll probably
5272 * use it in experimentation again in the future. --jerry 22/01/2002
5275 if (!W_ERROR_IS_OK(status)) {
5277 * Is this a W2k client ?
5279 if (version == 3) {
5280 /* Yes - try again with a WinNT driver. */
5281 version = 2;
5282 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5283 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5285 #endif
5287 if (!W_ERROR_IS_OK(status)) {
5288 free_a_printer(&printer,2);
5289 return WERR_UNKNOWN_PRINTER_DRIVER;
5292 #if 0 /* JERRY */
5294 #endif
5297 fill_printer_driver_info_3(info, driver, servername);
5299 free_a_printer(&printer,2);
5301 return WERR_OK;
5304 /********************************************************************
5305 * construct_printer_info_6
5306 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5307 ********************************************************************/
5309 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5311 pstring temp;
5312 fstring nullstr;
5314 ZERO_STRUCTP(info);
5315 memset(&nullstr, '\0', sizeof(fstring));
5317 info->version=driver.info_3->cversion;
5319 init_unistr( &info->name, driver.info_3->name );
5320 init_unistr( &info->architecture, driver.info_3->environment );
5322 if (strlen(driver.info_3->driverpath)) {
5323 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5324 init_unistr( &info->driverpath, temp );
5325 } else
5326 init_unistr( &info->driverpath, "" );
5328 if (strlen(driver.info_3->datafile)) {
5329 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5330 init_unistr( &info->datafile, temp );
5331 } else
5332 init_unistr( &info->datafile, "" );
5334 if (strlen(driver.info_3->configfile)) {
5335 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5336 init_unistr( &info->configfile, temp );
5337 } else
5338 init_unistr( &info->configfile, "" );
5340 if (strlen(driver.info_3->helpfile)) {
5341 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5342 init_unistr( &info->helpfile, temp );
5343 } else
5344 init_unistr( &info->helpfile, "" );
5346 init_unistr( &info->monitorname, driver.info_3->monitorname );
5347 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5349 info->dependentfiles = NULL;
5350 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5352 info->previousdrivernames=NULL;
5353 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5355 info->driver_date.low=0;
5356 info->driver_date.high=0;
5358 info->padding=0;
5359 info->driver_version_low=0;
5360 info->driver_version_high=0;
5362 init_unistr( &info->mfgname, "");
5363 init_unistr( &info->oem_url, "");
5364 init_unistr( &info->hardware_id, "");
5365 init_unistr( &info->provider, "");
5368 /********************************************************************
5369 * construct_printer_info_6
5370 * fill a printer_info_6 struct
5371 ********************************************************************/
5373 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5374 fstring servername, fstring architecture, uint32 version)
5376 NT_PRINTER_INFO_LEVEL *printer = NULL;
5377 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5378 WERROR status;
5380 ZERO_STRUCT(driver);
5382 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5384 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5386 if (!W_ERROR_IS_OK(status))
5387 return WERR_INVALID_PRINTER_NAME;
5389 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5391 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5393 if (!W_ERROR_IS_OK(status))
5396 * Is this a W2k client ?
5399 if (version < 3) {
5400 free_a_printer(&printer,2);
5401 return WERR_UNKNOWN_PRINTER_DRIVER;
5404 /* Yes - try again with a WinNT driver. */
5405 version = 2;
5406 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5407 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5408 if (!W_ERROR_IS_OK(status)) {
5409 free_a_printer(&printer,2);
5410 return WERR_UNKNOWN_PRINTER_DRIVER;
5414 fill_printer_driver_info_6(info, driver, servername);
5416 free_a_printer(&printer,2);
5417 free_a_printer_driver(driver, 3);
5419 return WERR_OK;
5422 /****************************************************************************
5423 ****************************************************************************/
5425 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5427 SAFE_FREE(info->dependentfiles);
5430 /****************************************************************************
5431 ****************************************************************************/
5433 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5435 SAFE_FREE(info->dependentfiles);
5439 /****************************************************************************
5440 ****************************************************************************/
5442 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5444 DRIVER_INFO_1 *info=NULL;
5445 WERROR status;
5447 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5448 return WERR_NOMEM;
5450 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5451 if (!W_ERROR_IS_OK(status)) {
5452 SAFE_FREE(info);
5453 return status;
5456 /* check the required size. */
5457 *needed += spoolss_size_printer_driver_info_1(info);
5459 if (!alloc_buffer_size(buffer, *needed)) {
5460 SAFE_FREE(info);
5461 return WERR_INSUFFICIENT_BUFFER;
5464 /* fill the buffer with the structures */
5465 smb_io_printer_driver_info_1("", buffer, info, 0);
5467 /* clear memory */
5468 SAFE_FREE(info);
5470 if (*needed > offered)
5471 return WERR_INSUFFICIENT_BUFFER;
5473 return WERR_OK;
5476 /****************************************************************************
5477 ****************************************************************************/
5479 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5481 DRIVER_INFO_2 *info=NULL;
5482 WERROR status;
5484 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5485 return WERR_NOMEM;
5487 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5488 if (!W_ERROR_IS_OK(status)) {
5489 SAFE_FREE(info);
5490 return status;
5493 /* check the required size. */
5494 *needed += spoolss_size_printer_driver_info_2(info);
5496 if (!alloc_buffer_size(buffer, *needed)) {
5497 SAFE_FREE(info);
5498 return WERR_INSUFFICIENT_BUFFER;
5501 /* fill the buffer with the structures */
5502 smb_io_printer_driver_info_2("", buffer, info, 0);
5504 /* clear memory */
5505 SAFE_FREE(info);
5507 if (*needed > offered)
5508 return WERR_INSUFFICIENT_BUFFER;
5510 return WERR_OK;
5513 /****************************************************************************
5514 ****************************************************************************/
5516 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5518 DRIVER_INFO_3 info;
5519 WERROR status;
5521 ZERO_STRUCT(info);
5523 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5524 if (!W_ERROR_IS_OK(status)) {
5525 return status;
5528 /* check the required size. */
5529 *needed += spoolss_size_printer_driver_info_3(&info);
5531 if (!alloc_buffer_size(buffer, *needed)) {
5532 free_printer_driver_info_3(&info);
5533 return WERR_INSUFFICIENT_BUFFER;
5536 /* fill the buffer with the structures */
5537 smb_io_printer_driver_info_3("", buffer, &info, 0);
5539 free_printer_driver_info_3(&info);
5541 if (*needed > offered)
5542 return WERR_INSUFFICIENT_BUFFER;
5544 return WERR_OK;
5547 /****************************************************************************
5548 ****************************************************************************/
5550 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5552 DRIVER_INFO_6 info;
5553 WERROR status;
5555 ZERO_STRUCT(info);
5557 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5558 if (!W_ERROR_IS_OK(status)) {
5559 return status;
5562 /* check the required size. */
5563 *needed += spoolss_size_printer_driver_info_6(&info);
5565 if (!alloc_buffer_size(buffer, *needed)) {
5566 free_printer_driver_info_6(&info);
5567 return WERR_INSUFFICIENT_BUFFER;
5570 /* fill the buffer with the structures */
5571 smb_io_printer_driver_info_6("", buffer, &info, 0);
5573 free_printer_driver_info_6(&info);
5575 if (*needed > offered)
5576 return WERR_INSUFFICIENT_BUFFER;
5578 return WERR_OK;
5581 /****************************************************************************
5582 ****************************************************************************/
5584 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5586 POLICY_HND *handle = &q_u->handle;
5587 UNISTR2 *uni_arch = &q_u->architecture;
5588 uint32 level = q_u->level;
5589 uint32 clientmajorversion = q_u->clientmajorversion;
5590 NEW_BUFFER *buffer = NULL;
5591 uint32 offered = q_u->offered;
5592 uint32 *needed = &r_u->needed;
5593 uint32 *servermajorversion = &r_u->servermajorversion;
5594 uint32 *serverminorversion = &r_u->serverminorversion;
5595 Printer_entry *printer;
5597 fstring servername;
5598 fstring architecture;
5599 int snum;
5601 /* that's an [in out] buffer */
5602 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5603 buffer = r_u->buffer;
5605 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5607 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5608 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5609 return WERR_INVALID_PRINTER_NAME;
5612 *needed = 0;
5613 *servermajorversion = 0;
5614 *serverminorversion = 0;
5616 fstrcpy(servername, get_server_name( printer ));
5617 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5619 if (!get_printer_snum(p, handle, &snum))
5620 return WERR_BADFID;
5622 switch (level) {
5623 case 1:
5624 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5625 case 2:
5626 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5627 case 3:
5628 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5629 case 6:
5630 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5631 #if 0 /* JERRY */
5632 case 101:
5633 /* apparently this call is the equivalent of
5634 EnumPrinterDataEx() for the DsDriver key */
5635 break;
5636 #endif
5639 return WERR_UNKNOWN_LEVEL;
5642 /****************************************************************************
5643 ****************************************************************************/
5645 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5647 POLICY_HND *handle = &q_u->handle;
5649 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5651 if (!Printer) {
5652 DEBUG(3,("Error in startpageprinter printer handle\n"));
5653 return WERR_BADFID;
5656 Printer->page_started=True;
5657 return WERR_OK;
5660 /****************************************************************************
5661 ****************************************************************************/
5663 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5665 POLICY_HND *handle = &q_u->handle;
5666 int snum;
5668 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5670 if (!Printer) {
5671 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5672 return WERR_BADFID;
5675 if (!get_printer_snum(p, handle, &snum))
5676 return WERR_BADFID;
5678 Printer->page_started=False;
5679 print_job_endpage(snum, Printer->jobid);
5681 return WERR_OK;
5684 /********************************************************************
5685 * api_spoolss_getprinter
5686 * called from the spoolss dispatcher
5688 ********************************************************************/
5690 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5692 POLICY_HND *handle = &q_u->handle;
5693 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5694 uint32 *jobid = &r_u->jobid;
5696 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5697 int snum;
5698 pstring jobname;
5699 fstring datatype;
5700 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5701 struct current_user user;
5703 if (!Printer) {
5704 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5705 return WERR_BADFID;
5708 get_current_user(&user, p);
5711 * a nice thing with NT is it doesn't listen to what you tell it.
5712 * when asked to send _only_ RAW datas, it tries to send datas
5713 * in EMF format.
5715 * So I add checks like in NT Server ...
5718 if (info_1->p_datatype != 0) {
5719 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5720 if (strcmp(datatype, "RAW") != 0) {
5721 (*jobid)=0;
5722 return WERR_INVALID_DATATYPE;
5726 /* get the share number of the printer */
5727 if (!get_printer_snum(p, handle, &snum)) {
5728 return WERR_BADFID;
5731 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5733 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5735 /* An error occured in print_job_start() so return an appropriate
5736 NT error code. */
5738 if (Printer->jobid == -1) {
5739 return map_werror_from_unix(errno);
5742 Printer->document_started=True;
5743 (*jobid) = Printer->jobid;
5745 return WERR_OK;
5748 /********************************************************************
5749 * api_spoolss_getprinter
5750 * called from the spoolss dispatcher
5752 ********************************************************************/
5754 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5756 POLICY_HND *handle = &q_u->handle;
5758 return _spoolss_enddocprinter_internal(p, handle);
5761 /****************************************************************************
5762 ****************************************************************************/
5764 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5766 POLICY_HND *handle = &q_u->handle;
5767 uint32 buffer_size = q_u->buffer_size;
5768 uint8 *buffer = q_u->buffer;
5769 uint32 *buffer_written = &q_u->buffer_size2;
5770 int snum;
5771 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5773 if (!Printer) {
5774 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5775 r_u->buffer_written = q_u->buffer_size2;
5776 return WERR_BADFID;
5779 if (!get_printer_snum(p, handle, &snum))
5780 return WERR_BADFID;
5782 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5783 if (*buffer_written == -1) {
5784 r_u->buffer_written = 0;
5785 if (errno == ENOSPC)
5786 return WERR_NO_SPOOL_SPACE;
5787 else
5788 return WERR_ACCESS_DENIED;
5791 r_u->buffer_written = q_u->buffer_size2;
5793 return WERR_OK;
5796 /********************************************************************
5797 * api_spoolss_getprinter
5798 * called from the spoolss dispatcher
5800 ********************************************************************/
5802 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5803 pipes_struct *p)
5805 struct current_user user;
5806 int snum;
5807 WERROR errcode = WERR_BADFUNC;
5808 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5810 get_current_user(&user, p);
5812 if (!Printer) {
5813 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5814 return WERR_BADFID;
5817 if (!get_printer_snum(p, handle, &snum))
5818 return WERR_BADFID;
5820 switch (command) {
5821 case PRINTER_CONTROL_PAUSE:
5822 if (print_queue_pause(&user, snum, &errcode)) {
5823 errcode = WERR_OK;
5825 break;
5826 case PRINTER_CONTROL_RESUME:
5827 case PRINTER_CONTROL_UNPAUSE:
5828 if (print_queue_resume(&user, snum, &errcode)) {
5829 errcode = WERR_OK;
5831 break;
5832 case PRINTER_CONTROL_PURGE:
5833 if (print_queue_purge(&user, snum, &errcode)) {
5834 errcode = WERR_OK;
5836 break;
5837 default:
5838 return WERR_UNKNOWN_LEVEL;
5841 return errcode;
5844 /********************************************************************
5845 * api_spoolss_abortprinter
5846 * From MSDN: "Deletes printer's spool file if printer is configured
5847 * for spooling"
5848 ********************************************************************/
5850 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5852 POLICY_HND *handle = &q_u->handle;
5853 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5854 int snum;
5855 struct current_user user;
5856 WERROR errcode = WERR_OK;
5858 if (!Printer) {
5859 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5860 return WERR_BADFID;
5863 if (!get_printer_snum(p, handle, &snum))
5864 return WERR_BADFID;
5866 get_current_user( &user, p );
5868 print_job_delete( &user, snum, Printer->jobid, &errcode );
5870 return errcode;
5873 /********************************************************************
5874 * called by spoolss_api_setprinter
5875 * when updating a printer description
5876 ********************************************************************/
5878 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5879 const SPOOL_PRINTER_INFO_LEVEL *info,
5880 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5882 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5883 WERROR result;
5884 int snum;
5886 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5888 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5889 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5890 OUR_HANDLE(handle)));
5892 result = WERR_BADFID;
5893 goto done;
5896 /* Check the user has permissions to change the security
5897 descriptor. By experimentation with two NT machines, the user
5898 requires Full Access to the printer to change security
5899 information. */
5901 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5902 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5903 result = WERR_ACCESS_DENIED;
5904 goto done;
5907 /* NT seems to like setting the security descriptor even though
5908 nothing may have actually changed. */
5910 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5912 if (DEBUGLEVEL >= 10) {
5913 SEC_ACL *the_acl;
5914 int i;
5916 the_acl = old_secdesc_ctr->sec->dacl;
5917 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5918 PRINTERNAME(snum), the_acl->num_aces));
5920 for (i = 0; i < the_acl->num_aces; i++) {
5921 fstring sid_str;
5923 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5925 DEBUG(10, ("%s 0x%08x\n", sid_str,
5926 the_acl->ace[i].info.mask));
5929 the_acl = secdesc_ctr->sec->dacl;
5931 if (the_acl) {
5932 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5933 PRINTERNAME(snum), the_acl->num_aces));
5935 for (i = 0; i < the_acl->num_aces; i++) {
5936 fstring sid_str;
5938 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5940 DEBUG(10, ("%s 0x%08x\n", sid_str,
5941 the_acl->ace[i].info.mask));
5943 } else {
5944 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5948 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5950 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5951 result = WERR_OK;
5952 goto done;
5955 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5957 done:
5959 return result;
5962 /********************************************************************
5963 Canonicalize printer info from a client
5965 ATTN: It does not matter what we set the servername to hear
5966 since we do the necessary work in get_a_printer() to set it to
5967 the correct value based on what the client sent in the
5968 _spoolss_open_printer_ex().
5969 ********************************************************************/
5971 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5973 fstring printername;
5974 const char *p;
5976 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5977 "portname=%s drivername=%s comment=%s location=%s\n",
5978 info->servername, info->printername, info->sharename,
5979 info->portname, info->drivername, info->comment, info->location));
5981 /* we force some elements to "correct" values */
5982 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5983 fstrcpy(info->sharename, lp_servicename(snum));
5985 /* check to see if we allow printername != sharename */
5987 if ( lp_force_printername(snum) ) {
5988 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5989 global_myname(), info->sharename );
5990 } else {
5992 /* make sure printername is in \\server\printername format */
5994 fstrcpy( printername, info->printername );
5995 p = printername;
5996 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5997 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5998 p++;
6001 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6002 global_myname(), p );
6005 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6006 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6010 return True;
6013 /****************************************************************************
6014 ****************************************************************************/
6016 static BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6018 extern userdom_struct current_user_info;
6019 char *cmd = lp_addprinter_cmd();
6020 char **qlines;
6021 pstring command;
6022 int numlines;
6023 int ret;
6024 int fd;
6025 fstring remote_machine = "%m";
6026 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6027 BOOL is_print_op;
6029 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6031 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6032 cmd, printer->info_2->printername, printer->info_2->sharename,
6033 printer->info_2->portname, printer->info_2->drivername,
6034 printer->info_2->location, printer->info_2->comment, remote_machine);
6036 is_print_op = user_has_privileges( token, &se_printop );
6038 DEBUG(10,("Running [%s]\n", command));
6040 /********* BEGIN SePrintOperatorPrivilege **********/
6042 if ( is_print_op )
6043 become_root();
6045 if ( (ret = smbrun(command, &fd)) == 0 ) {
6046 /* Tell everyone we updated smb.conf. */
6047 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6050 if ( is_print_op )
6051 unbecome_root();
6053 /********* END SePrintOperatorPrivilege **********/
6055 DEBUGADD(10,("returned [%d]\n", ret));
6057 if ( ret != 0 ) {
6058 if (fd != -1)
6059 close(fd);
6060 return False;
6063 /* reload our services immediately */
6064 reload_services( False );
6066 numlines = 0;
6067 /* Get lines and convert them back to dos-codepage */
6068 qlines = fd_lines_load(fd, &numlines);
6069 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6070 close(fd);
6072 /* Set the portname to what the script says the portname should be. */
6073 /* but don't require anything to be return from the script exit a good error code */
6075 if (numlines) {
6076 /* Set the portname to what the script says the portname should be. */
6077 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6078 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6081 file_lines_free(qlines);
6082 return True;
6085 /********************************************************************
6086 * Called by spoolss_api_setprinter
6087 * when updating a printer description.
6088 ********************************************************************/
6090 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6091 const SPOOL_PRINTER_INFO_LEVEL *info,
6092 DEVICEMODE *devmode)
6094 int snum;
6095 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6096 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6097 WERROR result;
6098 UNISTR2 buffer;
6099 fstring asc_buffer;
6101 DEBUG(8,("update_printer\n"));
6103 result = WERR_OK;
6105 if (!Printer) {
6106 result = WERR_BADFID;
6107 goto done;
6110 if (!get_printer_snum(p, handle, &snum)) {
6111 result = WERR_BADFID;
6112 goto done;
6115 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6116 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6117 result = WERR_BADFID;
6118 goto done;
6121 DEBUGADD(8,("Converting info_2 struct\n"));
6124 * convert_printer_info converts the incoming
6125 * info from the client and overwrites the info
6126 * just read from the tdb in the pointer 'printer'.
6129 if (!convert_printer_info(info, printer, level)) {
6130 result = WERR_NOMEM;
6131 goto done;
6134 if (devmode) {
6135 /* we have a valid devmode
6136 convert it and link it*/
6138 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6139 if (!convert_devicemode(printer->info_2->printername, devmode,
6140 &printer->info_2->devmode)) {
6141 result = WERR_NOMEM;
6142 goto done;
6146 /* Do sanity check on the requested changes for Samba */
6148 if (!check_printer_ok(printer->info_2, snum)) {
6149 result = WERR_INVALID_PARAM;
6150 goto done;
6153 /* FIXME!!! If the driver has changed we really should verify that
6154 it is installed before doing much else --jerry */
6156 /* Check calling user has permission to update printer description */
6158 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6159 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6160 result = WERR_ACCESS_DENIED;
6161 goto done;
6164 /* Call addprinter hook */
6165 /* Check changes to see if this is really needed */
6167 if ( *lp_addprinter_cmd()
6168 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6169 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6170 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6171 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6173 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6174 result = WERR_ACCESS_DENIED;
6175 goto done;
6179 * make sure we actually reload the services after
6180 * this as smb.conf could have a new section in it
6181 * .... shouldn't .... but could
6183 reload_services(False);
6187 * When a *new* driver is bound to a printer, the drivername is used to
6188 * lookup previously saved driver initialization info, which is then
6189 * bound to the printer, simulating what happens in the Windows arch.
6191 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6193 if (!set_driver_init(printer, 2))
6195 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6196 printer->info_2->drivername));
6199 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6200 printer->info_2->drivername));
6202 notify_printer_driver(snum, printer->info_2->drivername);
6206 * flag which changes actually occured. This is a small subset of
6207 * all the possible changes. We also have to update things in the
6208 * DsSpooler key.
6211 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6212 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6213 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6214 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6216 notify_printer_comment(snum, printer->info_2->comment);
6219 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6220 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6221 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6222 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6224 notify_printer_sharename(snum, printer->info_2->sharename);
6227 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6228 char *pname;
6230 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6231 pname++;
6232 else
6233 pname = printer->info_2->printername;
6236 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6237 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6238 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6240 notify_printer_printername( snum, pname );
6243 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6244 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6245 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6246 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6248 notify_printer_port(snum, printer->info_2->portname);
6251 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6252 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6253 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6254 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6256 notify_printer_location(snum, printer->info_2->location);
6259 /* here we need to update some more DsSpooler keys */
6260 /* uNCName, serverName, shortServerName */
6262 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6263 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6264 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6265 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6266 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6268 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6269 global_myname(), printer->info_2->sharename );
6270 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6271 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6272 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6274 /* Update printer info */
6275 result = mod_a_printer(printer, 2);
6277 done:
6278 free_a_printer(&printer, 2);
6279 free_a_printer(&old_printer, 2);
6282 return result;
6285 /****************************************************************************
6286 ****************************************************************************/
6287 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6288 const SPOOL_PRINTER_INFO_LEVEL *info)
6290 #ifdef HAVE_ADS
6291 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6292 int snum;
6293 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6295 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6297 if (!Printer)
6298 return WERR_BADFID;
6300 if (!get_printer_snum(p, handle, &snum))
6301 return WERR_BADFID;
6303 nt_printer_publish(Printer, snum, info7->action);
6305 return WERR_OK;
6306 #else
6307 return WERR_UNKNOWN_LEVEL;
6308 #endif
6310 /****************************************************************************
6311 ****************************************************************************/
6313 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6315 POLICY_HND *handle = &q_u->handle;
6316 uint32 level = q_u->level;
6317 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6318 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6319 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6320 uint32 command = q_u->command;
6321 WERROR result;
6323 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6325 if (!Printer) {
6326 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6327 return WERR_BADFID;
6330 /* check the level */
6331 switch (level) {
6332 case 0:
6333 return control_printer(handle, command, p);
6334 case 2:
6335 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6336 if (!W_ERROR_IS_OK(result))
6337 return result;
6338 if (secdesc_ctr)
6339 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6340 return result;
6341 case 3:
6342 return update_printer_sec(handle, level, info, p,
6343 secdesc_ctr);
6344 case 7:
6345 return publish_or_unpublish_printer(p, handle, info);
6346 default:
6347 return WERR_UNKNOWN_LEVEL;
6351 /****************************************************************************
6352 ****************************************************************************/
6354 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6356 POLICY_HND *handle = &q_u->handle;
6357 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6359 if (!Printer) {
6360 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6361 return WERR_BADFID;
6364 if (Printer->notify.client_connected==True) {
6365 int snum = -1;
6367 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6368 snum = -1;
6369 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6370 !get_printer_snum(p, handle, &snum) )
6371 return WERR_BADFID;
6373 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6376 Printer->notify.flags=0;
6377 Printer->notify.options=0;
6378 Printer->notify.localmachine[0]='\0';
6379 Printer->notify.printerlocal=0;
6380 if (Printer->notify.option)
6381 free_spool_notify_option(&Printer->notify.option);
6382 Printer->notify.client_connected=False;
6384 return WERR_OK;
6387 /****************************************************************************
6388 ****************************************************************************/
6390 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6392 /* that's an [in out] buffer (despite appearences to the contrary) */
6393 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6395 r_u->needed = 0;
6396 return WERR_INVALID_PARAM; /* this is what a NT server
6397 returns for AddJob. AddJob
6398 must fail on non-local
6399 printers */
6402 /****************************************************************************
6403 ****************************************************************************/
6405 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6406 int position, int snum,
6407 NT_PRINTER_INFO_LEVEL *ntprinter)
6409 struct tm *t;
6411 t=gmtime(&queue->time);
6413 job_info->jobid=queue->job;
6414 init_unistr(&job_info->printername, lp_servicename(snum));
6415 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6416 init_unistr(&job_info->username, queue->fs_user);
6417 init_unistr(&job_info->document, queue->fs_file);
6418 init_unistr(&job_info->datatype, "RAW");
6419 init_unistr(&job_info->text_status, "");
6420 job_info->status=nt_printj_status(queue->status);
6421 job_info->priority=queue->priority;
6422 job_info->position=position;
6423 job_info->totalpages=queue->page_count;
6424 job_info->pagesprinted=0;
6426 make_systemtime(&job_info->submitted, t);
6429 /****************************************************************************
6430 ****************************************************************************/
6432 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6433 int position, int snum,
6434 NT_PRINTER_INFO_LEVEL *ntprinter,
6435 DEVICEMODE *devmode)
6437 struct tm *t;
6439 t=gmtime(&queue->time);
6441 job_info->jobid=queue->job;
6443 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6445 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6446 init_unistr(&job_info->username, queue->fs_user);
6447 init_unistr(&job_info->document, queue->fs_file);
6448 init_unistr(&job_info->notifyname, queue->fs_user);
6449 init_unistr(&job_info->datatype, "RAW");
6450 init_unistr(&job_info->printprocessor, "winprint");
6451 init_unistr(&job_info->parameters, "");
6452 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6453 init_unistr(&job_info->text_status, "");
6455 /* and here the security descriptor */
6457 job_info->status=nt_printj_status(queue->status);
6458 job_info->priority=queue->priority;
6459 job_info->position=position;
6460 job_info->starttime=0;
6461 job_info->untiltime=0;
6462 job_info->totalpages=queue->page_count;
6463 job_info->size=queue->size;
6464 make_systemtime(&(job_info->submitted), t);
6465 job_info->timeelapsed=0;
6466 job_info->pagesprinted=0;
6468 job_info->devmode = devmode;
6470 return (True);
6473 /****************************************************************************
6474 Enumjobs at level 1.
6475 ****************************************************************************/
6477 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6478 NT_PRINTER_INFO_LEVEL *ntprinter,
6479 NEW_BUFFER *buffer, uint32 offered,
6480 uint32 *needed, uint32 *returned)
6482 JOB_INFO_1 *info;
6483 int i;
6485 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6486 if (info==NULL) {
6487 SAFE_FREE(queue);
6488 *returned=0;
6489 return WERR_NOMEM;
6492 for (i=0; i<*returned; i++)
6493 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6495 SAFE_FREE(queue);
6497 /* check the required size. */
6498 for (i=0; i<*returned; i++)
6499 (*needed) += spoolss_size_job_info_1(&info[i]);
6501 if (!alloc_buffer_size(buffer, *needed)) {
6502 SAFE_FREE(info);
6503 return WERR_INSUFFICIENT_BUFFER;
6506 /* fill the buffer with the structures */
6507 for (i=0; i<*returned; i++)
6508 smb_io_job_info_1("", buffer, &info[i], 0);
6510 /* clear memory */
6511 SAFE_FREE(info);
6513 if (*needed > offered) {
6514 *returned=0;
6515 return WERR_INSUFFICIENT_BUFFER;
6518 return WERR_OK;
6521 /****************************************************************************
6522 Enumjobs at level 2.
6523 ****************************************************************************/
6525 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6526 NT_PRINTER_INFO_LEVEL *ntprinter,
6527 NEW_BUFFER *buffer, uint32 offered,
6528 uint32 *needed, uint32 *returned)
6530 JOB_INFO_2 *info = NULL;
6531 int i;
6532 WERROR result;
6533 DEVICEMODE *devmode = NULL;
6535 info=SMB_MALLOC_ARRAY(JOB_INFO_2,*returned);
6536 if (info==NULL) {
6537 *returned=0;
6538 result = WERR_NOMEM;
6539 goto done;
6542 /* this should not be a failure condition if the devmode is NULL */
6544 devmode = construct_dev_mode(snum);
6546 for (i=0; i<*returned; i++)
6547 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6548 devmode);
6550 free_a_printer(&ntprinter, 2);
6551 SAFE_FREE(queue);
6553 /* check the required size. */
6554 for (i=0; i<*returned; i++)
6555 (*needed) += spoolss_size_job_info_2(&info[i]);
6557 if (*needed > offered) {
6558 *returned=0;
6559 result = WERR_INSUFFICIENT_BUFFER;
6560 goto done;
6563 if (!alloc_buffer_size(buffer, *needed)) {
6564 SAFE_FREE(info);
6565 result = WERR_INSUFFICIENT_BUFFER;
6566 goto done;
6569 /* fill the buffer with the structures */
6570 for (i=0; i<*returned; i++)
6571 smb_io_job_info_2("", buffer, &info[i], 0);
6573 result = WERR_OK;
6575 done:
6576 free_a_printer(&ntprinter, 2);
6577 free_devmode(devmode);
6578 SAFE_FREE(queue);
6579 SAFE_FREE(info);
6581 return result;
6585 /****************************************************************************
6586 Enumjobs.
6587 ****************************************************************************/
6589 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6591 POLICY_HND *handle = &q_u->handle;
6592 uint32 level = q_u->level;
6593 NEW_BUFFER *buffer = NULL;
6594 uint32 offered = q_u->offered;
6595 uint32 *needed = &r_u->needed;
6596 uint32 *returned = &r_u->returned;
6597 WERROR wret;
6598 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6599 int snum;
6600 print_status_struct prt_status;
6601 print_queue_struct *queue=NULL;
6603 /* that's an [in out] buffer */
6604 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6605 buffer = r_u->buffer;
6607 DEBUG(4,("_spoolss_enumjobs\n"));
6609 *needed=0;
6610 *returned=0;
6612 /* lookup the printer snum and tdb entry */
6614 if (!get_printer_snum(p, handle, &snum))
6615 return WERR_BADFID;
6617 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6618 if ( !W_ERROR_IS_OK(wret) )
6619 return wret;
6621 *returned = print_queue_status(snum, &queue, &prt_status);
6622 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6624 if (*returned == 0) {
6625 SAFE_FREE(queue);
6626 return WERR_OK;
6629 switch (level) {
6630 case 1:
6631 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6632 return wret;
6633 case 2:
6634 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6635 return wret;
6636 default:
6637 SAFE_FREE(queue);
6638 *returned=0;
6639 wret = WERR_UNKNOWN_LEVEL;
6642 free_a_printer( &ntprinter, 2 );
6643 return wret;
6646 /****************************************************************************
6647 ****************************************************************************/
6649 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6651 return WERR_OK;
6654 /****************************************************************************
6655 ****************************************************************************/
6657 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6659 POLICY_HND *handle = &q_u->handle;
6660 uint32 jobid = q_u->jobid;
6661 uint32 command = q_u->command;
6663 struct current_user user;
6664 int snum;
6665 WERROR errcode = WERR_BADFUNC;
6667 if (!get_printer_snum(p, handle, &snum)) {
6668 return WERR_BADFID;
6671 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6672 return WERR_INVALID_PRINTER_NAME;
6675 get_current_user(&user, p);
6677 switch (command) {
6678 case JOB_CONTROL_CANCEL:
6679 case JOB_CONTROL_DELETE:
6680 if (print_job_delete(&user, snum, jobid, &errcode)) {
6681 errcode = WERR_OK;
6683 break;
6684 case JOB_CONTROL_PAUSE:
6685 if (print_job_pause(&user, snum, jobid, &errcode)) {
6686 errcode = WERR_OK;
6688 break;
6689 case JOB_CONTROL_RESTART:
6690 case JOB_CONTROL_RESUME:
6691 if (print_job_resume(&user, snum, jobid, &errcode)) {
6692 errcode = WERR_OK;
6694 break;
6695 default:
6696 return WERR_UNKNOWN_LEVEL;
6699 return errcode;
6702 /****************************************************************************
6703 Enumerates all printer drivers at level 1.
6704 ****************************************************************************/
6706 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6708 int i;
6709 int ndrivers;
6710 uint32 version;
6711 fstring *list = NULL;
6713 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6714 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6716 *returned=0;
6718 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6719 list=NULL;
6720 ndrivers=get_ntdrivers(&list, architecture, version);
6721 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6723 if(ndrivers == -1)
6724 return WERR_NOMEM;
6726 if(ndrivers != 0) {
6727 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6728 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6729 SAFE_FREE(driver_info_1);
6730 SAFE_FREE(list);
6731 return WERR_NOMEM;
6733 else driver_info_1 = tdi1;
6736 for (i=0; i<ndrivers; i++) {
6737 WERROR status;
6738 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6739 ZERO_STRUCT(driver);
6740 status = get_a_printer_driver(&driver, 3, list[i],
6741 architecture, version);
6742 if (!W_ERROR_IS_OK(status)) {
6743 SAFE_FREE(list);
6744 return status;
6746 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6747 free_a_printer_driver(driver, 3);
6750 *returned+=ndrivers;
6751 SAFE_FREE(list);
6754 /* check the required size. */
6755 for (i=0; i<*returned; i++) {
6756 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6757 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6760 if (!alloc_buffer_size(buffer, *needed)) {
6761 SAFE_FREE(driver_info_1);
6762 return WERR_INSUFFICIENT_BUFFER;
6765 /* fill the buffer with the driver structures */
6766 for (i=0; i<*returned; i++) {
6767 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6768 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6771 SAFE_FREE(driver_info_1);
6773 if (*needed > offered) {
6774 *returned=0;
6775 return WERR_INSUFFICIENT_BUFFER;
6778 return WERR_OK;
6781 /****************************************************************************
6782 Enumerates all printer drivers at level 2.
6783 ****************************************************************************/
6785 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6787 int i;
6788 int ndrivers;
6789 uint32 version;
6790 fstring *list = NULL;
6792 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6793 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6795 *returned=0;
6797 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6798 list=NULL;
6799 ndrivers=get_ntdrivers(&list, architecture, version);
6800 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6802 if(ndrivers == -1)
6803 return WERR_NOMEM;
6805 if(ndrivers != 0) {
6806 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6807 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6808 SAFE_FREE(driver_info_2);
6809 SAFE_FREE(list);
6810 return WERR_NOMEM;
6812 else driver_info_2 = tdi2;
6815 for (i=0; i<ndrivers; i++) {
6816 WERROR status;
6818 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6819 ZERO_STRUCT(driver);
6820 status = get_a_printer_driver(&driver, 3, list[i],
6821 architecture, version);
6822 if (!W_ERROR_IS_OK(status)) {
6823 SAFE_FREE(list);
6824 return status;
6826 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6827 free_a_printer_driver(driver, 3);
6830 *returned+=ndrivers;
6831 SAFE_FREE(list);
6834 /* check the required size. */
6835 for (i=0; i<*returned; i++) {
6836 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6837 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6840 if (!alloc_buffer_size(buffer, *needed)) {
6841 SAFE_FREE(driver_info_2);
6842 return WERR_INSUFFICIENT_BUFFER;
6845 /* fill the buffer with the form structures */
6846 for (i=0; i<*returned; i++) {
6847 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6848 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6851 SAFE_FREE(driver_info_2);
6853 if (*needed > offered) {
6854 *returned=0;
6855 return WERR_INSUFFICIENT_BUFFER;
6858 return WERR_OK;
6861 /****************************************************************************
6862 Enumerates all printer drivers at level 3.
6863 ****************************************************************************/
6865 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6867 int i;
6868 int ndrivers;
6869 uint32 version;
6870 fstring *list = NULL;
6872 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6873 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6875 *returned=0;
6877 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6878 list=NULL;
6879 ndrivers=get_ntdrivers(&list, architecture, version);
6880 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6882 if(ndrivers == -1)
6883 return WERR_NOMEM;
6885 if(ndrivers != 0) {
6886 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6887 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6888 SAFE_FREE(driver_info_3);
6889 SAFE_FREE(list);
6890 return WERR_NOMEM;
6892 else driver_info_3 = tdi3;
6895 for (i=0; i<ndrivers; i++) {
6896 WERROR status;
6898 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6899 ZERO_STRUCT(driver);
6900 status = get_a_printer_driver(&driver, 3, list[i],
6901 architecture, version);
6902 if (!W_ERROR_IS_OK(status)) {
6903 SAFE_FREE(list);
6904 return status;
6906 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6907 free_a_printer_driver(driver, 3);
6910 *returned+=ndrivers;
6911 SAFE_FREE(list);
6914 /* check the required size. */
6915 for (i=0; i<*returned; i++) {
6916 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6917 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6920 if (!alloc_buffer_size(buffer, *needed)) {
6921 SAFE_FREE(driver_info_3);
6922 return WERR_INSUFFICIENT_BUFFER;
6925 /* fill the buffer with the driver structures */
6926 for (i=0; i<*returned; i++) {
6927 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6928 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6931 for (i=0; i<*returned; i++)
6932 SAFE_FREE(driver_info_3[i].dependentfiles);
6934 SAFE_FREE(driver_info_3);
6936 if (*needed > offered) {
6937 *returned=0;
6938 return WERR_INSUFFICIENT_BUFFER;
6941 return WERR_OK;
6944 /****************************************************************************
6945 Enumerates all printer drivers.
6946 ****************************************************************************/
6948 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6950 uint32 level = q_u->level;
6951 NEW_BUFFER *buffer = NULL;
6952 uint32 offered = q_u->offered;
6953 uint32 *needed = &r_u->needed;
6954 uint32 *returned = &r_u->returned;
6956 fstring *list = NULL;
6957 fstring servername;
6958 fstring architecture;
6960 /* that's an [in out] buffer */
6961 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6962 buffer = r_u->buffer;
6964 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6965 *needed=0;
6966 *returned=0;
6968 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6969 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6971 if ( !is_myname_or_ipaddr( servername ) )
6972 return WERR_UNKNOWN_PRINTER_DRIVER;
6974 switch (level) {
6975 case 1:
6976 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6977 case 2:
6978 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6979 case 3:
6980 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6981 default:
6982 *returned=0;
6983 SAFE_FREE(list);
6984 return WERR_UNKNOWN_LEVEL;
6988 /****************************************************************************
6989 ****************************************************************************/
6991 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6993 form->flag=list->flag;
6994 init_unistr(&form->name, list->name);
6995 form->width=list->width;
6996 form->length=list->length;
6997 form->left=list->left;
6998 form->top=list->top;
6999 form->right=list->right;
7000 form->bottom=list->bottom;
7003 /****************************************************************************
7004 ****************************************************************************/
7006 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7008 uint32 level = q_u->level;
7009 NEW_BUFFER *buffer = NULL;
7010 uint32 offered = q_u->offered;
7011 uint32 *needed = &r_u->needed;
7012 uint32 *numofforms = &r_u->numofforms;
7013 uint32 numbuiltinforms;
7015 nt_forms_struct *list=NULL;
7016 nt_forms_struct *builtinlist=NULL;
7017 FORM_1 *forms_1;
7018 int buffer_size=0;
7019 int i;
7021 /* that's an [in out] buffer */
7022 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7023 buffer = r_u->buffer;
7025 DEBUG(4,("_spoolss_enumforms\n"));
7026 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7027 DEBUGADD(5,("Info level [%d]\n", level));
7029 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7030 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7031 *numofforms = get_ntforms(&list);
7032 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7033 *numofforms += numbuiltinforms;
7035 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
7037 switch (level) {
7038 case 1:
7039 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7040 *numofforms=0;
7041 return WERR_NOMEM;
7044 /* construct the list of form structures */
7045 for (i=0; i<numbuiltinforms; i++) {
7046 DEBUGADD(6,("Filling form number [%d]\n",i));
7047 fill_form_1(&forms_1[i], &builtinlist[i]);
7050 SAFE_FREE(builtinlist);
7052 for (; i<*numofforms; i++) {
7053 DEBUGADD(6,("Filling form number [%d]\n",i));
7054 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7057 SAFE_FREE(list);
7059 /* check the required size. */
7060 for (i=0; i<numbuiltinforms; i++) {
7061 DEBUGADD(6,("adding form [%d]'s size\n",i));
7062 buffer_size += spoolss_size_form_1(&forms_1[i]);
7064 for (; i<*numofforms; i++) {
7065 DEBUGADD(6,("adding form [%d]'s size\n",i));
7066 buffer_size += spoolss_size_form_1(&forms_1[i]);
7069 *needed=buffer_size;
7071 if (!alloc_buffer_size(buffer, buffer_size)){
7072 SAFE_FREE(forms_1);
7073 return WERR_INSUFFICIENT_BUFFER;
7076 /* fill the buffer with the form structures */
7077 for (i=0; i<numbuiltinforms; i++) {
7078 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7079 smb_io_form_1("", buffer, &forms_1[i], 0);
7081 for (; i<*numofforms; i++) {
7082 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7083 smb_io_form_1("", buffer, &forms_1[i], 0);
7086 SAFE_FREE(forms_1);
7088 if (*needed > offered) {
7089 *numofforms=0;
7090 return WERR_INSUFFICIENT_BUFFER;
7092 else
7093 return WERR_OK;
7095 default:
7096 SAFE_FREE(list);
7097 SAFE_FREE(builtinlist);
7098 return WERR_UNKNOWN_LEVEL;
7103 /****************************************************************************
7104 ****************************************************************************/
7106 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7108 uint32 level = q_u->level;
7109 UNISTR2 *uni_formname = &q_u->formname;
7110 NEW_BUFFER *buffer = NULL;
7111 uint32 offered = q_u->offered;
7112 uint32 *needed = &r_u->needed;
7114 nt_forms_struct *list=NULL;
7115 nt_forms_struct builtin_form;
7116 BOOL foundBuiltin;
7117 FORM_1 form_1;
7118 fstring form_name;
7119 int buffer_size=0;
7120 int numofforms=0, i=0;
7122 /* that's an [in out] buffer */
7123 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7124 buffer = r_u->buffer;
7126 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7128 DEBUG(4,("_spoolss_getform\n"));
7129 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7130 DEBUGADD(5,("Info level [%d]\n", level));
7132 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7133 if (!foundBuiltin) {
7134 numofforms = get_ntforms(&list);
7135 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7137 if (numofforms == 0)
7138 return WERR_BADFID;
7141 switch (level) {
7142 case 1:
7143 if (foundBuiltin) {
7144 fill_form_1(&form_1, &builtin_form);
7145 } else {
7147 /* Check if the requested name is in the list of form structures */
7148 for (i=0; i<numofforms; i++) {
7150 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7152 if (strequal(form_name, list[i].name)) {
7153 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7154 fill_form_1(&form_1, &list[i]);
7155 break;
7159 SAFE_FREE(list);
7160 if (i == numofforms) {
7161 return WERR_BADFID;
7164 /* check the required size. */
7166 *needed=spoolss_size_form_1(&form_1);
7168 if (!alloc_buffer_size(buffer, buffer_size)){
7169 return WERR_INSUFFICIENT_BUFFER;
7172 if (*needed > offered) {
7173 return WERR_INSUFFICIENT_BUFFER;
7176 /* fill the buffer with the form structures */
7177 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7178 smb_io_form_1("", buffer, &form_1, 0);
7180 return WERR_OK;
7182 default:
7183 SAFE_FREE(list);
7184 return WERR_UNKNOWN_LEVEL;
7188 /****************************************************************************
7189 ****************************************************************************/
7191 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7193 init_unistr(&port->port_name, name);
7196 /****************************************************************************
7197 ****************************************************************************/
7199 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7201 init_unistr(&port->port_name, name);
7202 init_unistr(&port->monitor_name, "Local Monitor");
7203 init_unistr(&port->description, "Local Port");
7204 port->port_type=PORT_TYPE_WRITE;
7205 port->reserved=0x0;
7208 /****************************************************************************
7209 enumports level 1.
7210 ****************************************************************************/
7212 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7214 PORT_INFO_1 *ports=NULL;
7215 int i=0;
7217 if (*lp_enumports_cmd()) {
7218 char *cmd = lp_enumports_cmd();
7219 char **qlines;
7220 pstring command;
7221 int numlines;
7222 int ret;
7223 int fd;
7225 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7227 DEBUG(10,("Running [%s]\n", command));
7228 ret = smbrun(command, &fd);
7229 DEBUG(10,("Returned [%d]\n", ret));
7230 if (ret != 0) {
7231 if (fd != -1)
7232 close(fd);
7233 /* Is this the best error to return here? */
7234 return WERR_ACCESS_DENIED;
7237 numlines = 0;
7238 qlines = fd_lines_load(fd, &numlines);
7239 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7240 close(fd);
7242 if(numlines) {
7243 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7244 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7245 dos_errstr(WERR_NOMEM)));
7246 file_lines_free(qlines);
7247 return WERR_NOMEM;
7250 for (i=0; i<numlines; i++) {
7251 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7252 fill_port_1(&ports[i], qlines[i]);
7255 file_lines_free(qlines);
7258 *returned = numlines;
7260 } else {
7261 *returned = 1; /* Sole Samba port returned. */
7263 if((ports=SMB_MALLOC_P(PORT_INFO_1)) == NULL)
7264 return WERR_NOMEM;
7266 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7268 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7271 /* check the required size. */
7272 for (i=0; i<*returned; i++) {
7273 DEBUGADD(6,("adding port [%d]'s size\n", i));
7274 *needed += spoolss_size_port_info_1(&ports[i]);
7277 if (!alloc_buffer_size(buffer, *needed)) {
7278 SAFE_FREE(ports);
7279 return WERR_INSUFFICIENT_BUFFER;
7282 /* fill the buffer with the ports structures */
7283 for (i=0; i<*returned; i++) {
7284 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7285 smb_io_port_1("", buffer, &ports[i], 0);
7288 SAFE_FREE(ports);
7290 if (*needed > offered) {
7291 *returned=0;
7292 return WERR_INSUFFICIENT_BUFFER;
7295 return WERR_OK;
7298 /****************************************************************************
7299 enumports level 2.
7300 ****************************************************************************/
7302 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7304 PORT_INFO_2 *ports=NULL;
7305 int i=0;
7307 if (*lp_enumports_cmd()) {
7308 char *cmd = lp_enumports_cmd();
7309 char *path;
7310 char **qlines;
7311 pstring tmp_file;
7312 pstring command;
7313 int numlines;
7314 int ret;
7315 int fd;
7317 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7318 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7319 else
7320 path = lp_lockdir();
7322 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7323 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7325 unlink(tmp_file);
7326 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7327 ret = smbrun(command, &fd);
7328 DEBUGADD(10,("returned [%d]\n", ret));
7329 if (ret != 0) {
7330 if (fd != -1)
7331 close(fd);
7332 /* Is this the best error to return here? */
7333 return WERR_ACCESS_DENIED;
7336 numlines = 0;
7337 qlines = fd_lines_load(fd, &numlines);
7338 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7339 close(fd);
7341 if(numlines) {
7342 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7343 file_lines_free(qlines);
7344 return WERR_NOMEM;
7347 for (i=0; i<numlines; i++) {
7348 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7349 fill_port_2(&(ports[i]), qlines[i]);
7352 file_lines_free(qlines);
7355 *returned = numlines;
7357 } else {
7359 *returned = 1;
7361 if((ports=SMB_MALLOC_P(PORT_INFO_2)) == NULL)
7362 return WERR_NOMEM;
7364 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7366 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7369 /* check the required size. */
7370 for (i=0; i<*returned; i++) {
7371 DEBUGADD(6,("adding port [%d]'s size\n", i));
7372 *needed += spoolss_size_port_info_2(&ports[i]);
7375 if (!alloc_buffer_size(buffer, *needed)) {
7376 SAFE_FREE(ports);
7377 return WERR_INSUFFICIENT_BUFFER;
7380 /* fill the buffer with the ports structures */
7381 for (i=0; i<*returned; i++) {
7382 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7383 smb_io_port_2("", buffer, &ports[i], 0);
7386 SAFE_FREE(ports);
7388 if (*needed > offered) {
7389 *returned=0;
7390 return WERR_INSUFFICIENT_BUFFER;
7393 return WERR_OK;
7396 /****************************************************************************
7397 enumports.
7398 ****************************************************************************/
7400 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7402 uint32 level = q_u->level;
7403 NEW_BUFFER *buffer = NULL;
7404 uint32 offered = q_u->offered;
7405 uint32 *needed = &r_u->needed;
7406 uint32 *returned = &r_u->returned;
7408 /* that's an [in out] buffer */
7409 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7410 buffer = r_u->buffer;
7412 DEBUG(4,("_spoolss_enumports\n"));
7414 *returned=0;
7415 *needed=0;
7417 switch (level) {
7418 case 1:
7419 return enumports_level_1(buffer, offered, needed, returned);
7420 case 2:
7421 return enumports_level_2(buffer, offered, needed, returned);
7422 default:
7423 return WERR_UNKNOWN_LEVEL;
7427 /****************************************************************************
7428 ****************************************************************************/
7430 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7431 const SPOOL_PRINTER_INFO_LEVEL *info,
7432 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7433 uint32 user_switch, const SPOOL_USER_CTR *user,
7434 POLICY_HND *handle)
7436 NT_PRINTER_INFO_LEVEL *printer = NULL;
7437 fstring name;
7438 int snum;
7439 WERROR err = WERR_OK;
7441 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7442 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7443 return WERR_NOMEM;
7446 ZERO_STRUCTP(printer);
7448 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7449 if (!convert_printer_info(info, printer, 2)) {
7450 free_a_printer(&printer, 2);
7451 return WERR_NOMEM;
7454 /* check to see if the printer already exists */
7456 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7457 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7458 printer->info_2->sharename));
7459 free_a_printer(&printer, 2);
7460 return WERR_PRINTER_ALREADY_EXISTS;
7463 /* FIXME!!! smbd should check to see if the driver is installed before
7464 trying to add a printer like this --jerry */
7466 if (*lp_addprinter_cmd() ) {
7467 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7468 free_a_printer(&printer,2);
7469 return WERR_ACCESS_DENIED;
7473 /* use our primary netbios name since get_a_printer() will convert
7474 it to what the client expects on a case by case basis */
7476 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7477 printer->info_2->sharename);
7480 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7481 free_a_printer(&printer,2);
7482 return WERR_ACCESS_DENIED;
7485 /* you must be a printer admin to add a new printer */
7486 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7487 free_a_printer(&printer,2);
7488 return WERR_ACCESS_DENIED;
7492 * Do sanity check on the requested changes for Samba.
7495 if (!check_printer_ok(printer->info_2, snum)) {
7496 free_a_printer(&printer,2);
7497 return WERR_INVALID_PARAM;
7501 * When a printer is created, the drivername bound to the printer is used
7502 * to lookup previously saved driver initialization info, which is then
7503 * bound to the new printer, simulating what happens in the Windows arch.
7506 if (!devmode)
7508 set_driver_init(printer, 2);
7510 else
7512 /* A valid devmode was included, convert and link it
7514 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7516 if (!convert_devicemode(printer->info_2->printername, devmode,
7517 &printer->info_2->devmode))
7518 return WERR_NOMEM;
7521 /* write the ASCII on disk */
7522 err = mod_a_printer(printer, 2);
7523 if (!W_ERROR_IS_OK(err)) {
7524 free_a_printer(&printer,2);
7525 return err;
7528 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7529 /* Handle open failed - remove addition. */
7530 del_a_printer(printer->info_2->sharename);
7531 free_a_printer(&printer,2);
7532 return WERR_ACCESS_DENIED;
7535 update_c_setprinter(False);
7536 free_a_printer(&printer,2);
7538 return WERR_OK;
7541 /****************************************************************************
7542 ****************************************************************************/
7544 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7546 UNISTR2 *uni_srv_name = &q_u->server_name;
7547 uint32 level = q_u->level;
7548 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7549 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7550 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7551 uint32 user_switch = q_u->user_switch;
7552 SPOOL_USER_CTR *user = &q_u->user_ctr;
7553 POLICY_HND *handle = &r_u->handle;
7555 switch (level) {
7556 case 1:
7557 /* we don't handle yet */
7558 /* but I know what to do ... */
7559 return WERR_UNKNOWN_LEVEL;
7560 case 2:
7561 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7562 devmode, sdb,
7563 user_switch, user, handle);
7564 default:
7565 return WERR_UNKNOWN_LEVEL;
7569 /****************************************************************************
7570 ****************************************************************************/
7572 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7574 uint32 level = q_u->level;
7575 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7576 WERROR err = WERR_OK;
7577 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7578 struct current_user user;
7579 fstring driver_name;
7580 uint32 version;
7582 ZERO_STRUCT(driver);
7584 get_current_user(&user, p);
7586 if (!convert_printer_driver_info(info, &driver, level)) {
7587 err = WERR_NOMEM;
7588 goto done;
7591 DEBUG(5,("Cleaning driver's information\n"));
7592 err = clean_up_driver_struct(driver, level, &user);
7593 if (!W_ERROR_IS_OK(err))
7594 goto done;
7596 DEBUG(5,("Moving driver to final destination\n"));
7597 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7598 if (W_ERROR_IS_OK(err))
7599 err = WERR_ACCESS_DENIED;
7600 goto done;
7603 if (add_a_printer_driver(driver, level)!=0) {
7604 err = WERR_ACCESS_DENIED;
7605 goto done;
7608 /* BEGIN_ADMIN_LOG */
7609 switch(level) {
7610 case 3:
7611 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7612 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7613 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7614 break;
7615 case 6:
7616 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7617 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7618 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7619 break;
7621 /* END_ADMIN_LOG */
7624 * I think this is where he DrvUpgradePrinter() hook would be
7625 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7626 * server. Right now, we just need to send ourselves a message
7627 * to update each printer bound to this driver. --jerry
7630 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7631 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7632 driver_name));
7636 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7637 * decide if the driver init data should be deleted. The rules are:
7638 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7639 * 2) delete init data only if there is no 2k/Xp driver
7640 * 3) always delete init data
7641 * The generalized rule is always use init data from the highest order driver.
7642 * It is necessary to follow the driver install by an initialization step to
7643 * finish off this process.
7645 if (level == 3)
7646 version = driver.info_3->cversion;
7647 else if (level == 6)
7648 version = driver.info_6->version;
7649 else
7650 version = -1;
7651 switch (version) {
7653 * 9x printer driver - never delete init data
7655 case 0:
7656 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7657 driver_name));
7658 break;
7661 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7662 * there is no 2k/Xp driver init data for this driver name.
7664 case 2:
7666 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7668 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7670 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7672 if (!del_driver_init(driver_name))
7673 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7674 } else {
7676 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7678 free_a_printer_driver(driver1,3);
7679 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7680 driver_name));
7683 break;
7686 * 2k or Xp printer driver - always delete init data
7688 case 3:
7689 if (!del_driver_init(driver_name))
7690 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7691 break;
7693 default:
7694 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7695 break;
7699 done:
7700 free_a_printer_driver(driver, level);
7701 return err;
7704 /********************************************************************
7705 * spoolss_addprinterdriverex
7706 ********************************************************************/
7708 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7710 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7711 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7714 * we only support the semantics of AddPrinterDriver()
7715 * i.e. only copy files that are newer than existing ones
7718 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7719 return WERR_ACCESS_DENIED;
7721 ZERO_STRUCT(q_u_local);
7722 ZERO_STRUCT(r_u_local);
7724 /* just pass the information off to _spoolss_addprinterdriver() */
7725 q_u_local.server_name_ptr = q_u->server_name_ptr;
7726 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7727 q_u_local.level = q_u->level;
7728 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7730 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7733 /****************************************************************************
7734 ****************************************************************************/
7736 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7738 init_unistr(&info->name, name);
7741 /****************************************************************************
7742 ****************************************************************************/
7744 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7746 pstring path;
7747 pstring long_archi;
7748 fstring servername;
7749 char *pservername;
7750 const char *short_archi;
7751 DRIVER_DIRECTORY_1 *info=NULL;
7753 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7754 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7756 /* check for beginning double '\'s and that the server
7757 long enough */
7759 pservername = servername;
7760 if ( *pservername == '\\' && strlen(servername)>2 ) {
7761 pservername += 2;
7764 if ( !is_myname_or_ipaddr( pservername ) )
7765 return WERR_INVALID_PARAM;
7767 if (!(short_archi = get_short_archi(long_archi)))
7768 return WERR_INVALID_ENVIRONMENT;
7770 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7771 return WERR_NOMEM;
7773 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7775 DEBUG(4,("printer driver directory: [%s]\n", path));
7777 fill_driverdir_1(info, path);
7779 *needed += spoolss_size_driverdir_info_1(info);
7781 if (!alloc_buffer_size(buffer, *needed)) {
7782 SAFE_FREE(info);
7783 return WERR_INSUFFICIENT_BUFFER;
7786 smb_io_driverdir_1("", buffer, info, 0);
7788 SAFE_FREE(info);
7790 if (*needed > offered)
7791 return WERR_INSUFFICIENT_BUFFER;
7793 return WERR_OK;
7796 /****************************************************************************
7797 ****************************************************************************/
7799 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7801 UNISTR2 *name = &q_u->name;
7802 UNISTR2 *uni_environment = &q_u->environment;
7803 uint32 level = q_u->level;
7804 NEW_BUFFER *buffer = NULL;
7805 uint32 offered = q_u->offered;
7806 uint32 *needed = &r_u->needed;
7808 /* that's an [in out] buffer */
7809 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7810 buffer = r_u->buffer;
7812 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7814 *needed=0;
7816 switch(level) {
7817 case 1:
7818 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7819 default:
7820 return WERR_UNKNOWN_LEVEL;
7824 /****************************************************************************
7825 ****************************************************************************/
7827 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7829 POLICY_HND *handle = &q_u->handle;
7830 uint32 idx = q_u->index;
7831 uint32 in_value_len = q_u->valuesize;
7832 uint32 in_data_len = q_u->datasize;
7833 uint32 *out_max_value_len = &r_u->valuesize;
7834 uint16 **out_value = &r_u->value;
7835 uint32 *out_value_len = &r_u->realvaluesize;
7836 uint32 *out_type = &r_u->type;
7837 uint32 *out_max_data_len = &r_u->datasize;
7838 uint8 **data_out = &r_u->data;
7839 uint32 *out_data_len = &r_u->realdatasize;
7841 NT_PRINTER_INFO_LEVEL *printer = NULL;
7843 uint32 biggest_valuesize;
7844 uint32 biggest_datasize;
7845 uint32 data_len;
7846 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7847 int snum;
7848 WERROR result;
7849 REGISTRY_VALUE *val = NULL;
7850 NT_PRINTER_DATA *p_data;
7851 int i, key_index, num_values;
7852 int name_length;
7854 ZERO_STRUCT( printer );
7856 *out_type = 0;
7858 *out_max_data_len = 0;
7859 *data_out = NULL;
7860 *out_data_len = 0;
7862 DEBUG(5,("spoolss_enumprinterdata\n"));
7864 if (!Printer) {
7865 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7866 return WERR_BADFID;
7869 if (!get_printer_snum(p,handle, &snum))
7870 return WERR_BADFID;
7872 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7873 if (!W_ERROR_IS_OK(result))
7874 return result;
7876 p_data = &printer->info_2->data;
7877 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7879 result = WERR_OK;
7882 * The NT machine wants to know the biggest size of value and data
7884 * cf: MSDN EnumPrinterData remark section
7887 if ( !in_value_len && !in_data_len && (key_index != -1) )
7889 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7891 biggest_valuesize = 0;
7892 biggest_datasize = 0;
7894 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7896 for ( i=0; i<num_values; i++ )
7898 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7900 name_length = strlen(val->valuename);
7901 if ( strlen(val->valuename) > biggest_valuesize )
7902 biggest_valuesize = name_length;
7904 if ( val->size > biggest_datasize )
7905 biggest_datasize = val->size;
7907 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7908 biggest_datasize));
7911 /* the value is an UNICODE string but real_value_size is the length
7912 in bytes including the trailing 0 */
7914 *out_value_len = 2 * (1+biggest_valuesize);
7915 *out_data_len = biggest_datasize;
7917 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7919 goto done;
7923 * the value len is wrong in NT sp3
7924 * that's the number of bytes not the number of unicode chars
7927 if ( key_index != -1 )
7928 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7930 if ( !val )
7933 /* out_value should default to "" or else NT4 has
7934 problems unmarshalling the response */
7936 *out_max_value_len=(in_value_len/sizeof(uint16));
7938 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7940 result = WERR_NOMEM;
7941 goto done;
7944 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7946 /* the data is counted in bytes */
7948 *out_max_data_len = in_data_len;
7949 *out_data_len = in_data_len;
7951 /* only allocate when given a non-zero data_len */
7953 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7955 result = WERR_NOMEM;
7956 goto done;
7959 result = WERR_NO_MORE_ITEMS;
7961 else
7964 * the value is:
7965 * - counted in bytes in the request
7966 * - counted in UNICODE chars in the max reply
7967 * - counted in bytes in the real size
7969 * take a pause *before* coding not *during* coding
7972 /* name */
7973 *out_max_value_len=(in_value_len/sizeof(uint16));
7974 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7976 result = WERR_NOMEM;
7977 goto done;
7980 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7982 /* type */
7984 *out_type = regval_type( val );
7986 /* data - counted in bytes */
7988 *out_max_data_len = in_data_len;
7989 if ( (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7991 result = WERR_NOMEM;
7992 goto done;
7994 data_len = (size_t)regval_size(val);
7995 memcpy( *data_out, regval_data_p(val), data_len );
7996 *out_data_len = data_len;
7999 done:
8000 free_a_printer(&printer, 2);
8001 return result;
8004 /****************************************************************************
8005 ****************************************************************************/
8007 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8009 POLICY_HND *handle = &q_u->handle;
8010 UNISTR2 *value = &q_u->value;
8011 uint32 type = q_u->type;
8012 uint8 *data = q_u->data;
8013 uint32 real_len = q_u->real_len;
8015 NT_PRINTER_INFO_LEVEL *printer = NULL;
8016 int snum=0;
8017 WERROR status = WERR_OK;
8018 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8019 fstring valuename;
8021 DEBUG(5,("spoolss_setprinterdata\n"));
8023 if (!Printer) {
8024 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8025 return WERR_BADFID;
8028 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8029 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8030 return WERR_INVALID_PARAM;
8033 if (!get_printer_snum(p,handle, &snum))
8034 return WERR_BADFID;
8037 * Access check : NT returns "access denied" if you make a
8038 * SetPrinterData call without the necessary privildge.
8039 * we were originally returning OK if nothing changed
8040 * which made Win2k issue **a lot** of SetPrinterData
8041 * when connecting to a printer --jerry
8044 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8046 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8047 status = WERR_ACCESS_DENIED;
8048 goto done;
8051 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8052 if (!W_ERROR_IS_OK(status))
8053 return status;
8055 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8058 * When client side code sets a magic printer data key, detect it and save
8059 * the current printer data and the magic key's data (its the DEVMODE) for
8060 * future printer/driver initializations.
8062 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8064 /* Set devmode and printer initialization info */
8065 status = save_driver_init( printer, 2, data, real_len );
8067 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8069 else
8071 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8072 type, data, real_len );
8073 if ( W_ERROR_IS_OK(status) )
8074 status = mod_a_printer(printer, 2);
8077 done:
8078 free_a_printer(&printer, 2);
8080 return status;
8083 /****************************************************************************
8084 ****************************************************************************/
8086 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8088 POLICY_HND *handle = &q_u->handle;
8089 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8090 int snum;
8092 DEBUG(5,("_spoolss_resetprinter\n"));
8095 * All we do is to check to see if the handle and queue is valid.
8096 * This call really doesn't mean anything to us because we only
8097 * support RAW printing. --jerry
8100 if (!Printer) {
8101 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8102 return WERR_BADFID;
8105 if (!get_printer_snum(p,handle, &snum))
8106 return WERR_BADFID;
8109 /* blindly return success */
8110 return WERR_OK;
8114 /****************************************************************************
8115 ****************************************************************************/
8117 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8119 POLICY_HND *handle = &q_u->handle;
8120 UNISTR2 *value = &q_u->valuename;
8122 NT_PRINTER_INFO_LEVEL *printer = NULL;
8123 int snum=0;
8124 WERROR status = WERR_OK;
8125 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8126 pstring valuename;
8128 DEBUG(5,("spoolss_deleteprinterdata\n"));
8130 if (!Printer) {
8131 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8132 return WERR_BADFID;
8135 if (!get_printer_snum(p, handle, &snum))
8136 return WERR_BADFID;
8138 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8139 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8140 return WERR_ACCESS_DENIED;
8143 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8144 if (!W_ERROR_IS_OK(status))
8145 return status;
8147 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8149 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8151 if ( W_ERROR_IS_OK(status) )
8152 mod_a_printer( printer, 2 );
8154 free_a_printer(&printer, 2);
8156 return status;
8159 /****************************************************************************
8160 ****************************************************************************/
8162 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8164 POLICY_HND *handle = &q_u->handle;
8165 FORM *form = &q_u->form;
8166 nt_forms_struct tmpForm;
8167 int snum;
8168 WERROR status = WERR_OK;
8169 NT_PRINTER_INFO_LEVEL *printer = NULL;
8171 int count=0;
8172 nt_forms_struct *list=NULL;
8173 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8175 DEBUG(5,("spoolss_addform\n"));
8177 if (!Printer) {
8178 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8179 return WERR_BADFID;
8183 /* forms can be added on printer of on the print server handle */
8185 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8187 if (!get_printer_snum(p,handle, &snum))
8188 return WERR_BADFID;
8190 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8191 if (!W_ERROR_IS_OK(status))
8192 goto done;
8195 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8196 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8197 status = WERR_ACCESS_DENIED;
8198 goto done;
8201 /* can't add if builtin */
8203 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8204 status = WERR_ALREADY_EXISTS;
8205 goto done;
8208 count = get_ntforms(&list);
8210 if(!add_a_form(&list, form, &count)) {
8211 status = WERR_NOMEM;
8212 goto done;
8215 write_ntforms(&list, count);
8218 * ChangeID must always be set if this is a printer
8221 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8222 status = mod_a_printer(printer, 2);
8224 done:
8225 if ( printer )
8226 free_a_printer(&printer, 2);
8227 SAFE_FREE(list);
8229 return status;
8232 /****************************************************************************
8233 ****************************************************************************/
8235 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8237 POLICY_HND *handle = &q_u->handle;
8238 UNISTR2 *form_name = &q_u->name;
8239 nt_forms_struct tmpForm;
8240 int count=0;
8241 nt_forms_struct *list=NULL;
8242 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8243 int snum;
8244 WERROR status = WERR_OK;
8245 NT_PRINTER_INFO_LEVEL *printer = NULL;
8247 DEBUG(5,("spoolss_deleteform\n"));
8249 if (!Printer) {
8250 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8251 return WERR_BADFID;
8254 /* forms can be deleted on printer of on the print server handle */
8256 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8258 if (!get_printer_snum(p,handle, &snum))
8259 return WERR_BADFID;
8261 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8262 if (!W_ERROR_IS_OK(status))
8263 goto done;
8266 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8267 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8268 status = WERR_ACCESS_DENIED;
8269 goto done;
8272 /* can't delete if builtin */
8274 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8275 status = WERR_INVALID_PARAM;
8276 goto done;
8279 count = get_ntforms(&list);
8281 if ( !delete_a_form(&list, form_name, &count, &status ))
8282 goto done;
8285 * ChangeID must always be set if this is a printer
8288 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8289 status = mod_a_printer(printer, 2);
8291 done:
8292 if ( printer )
8293 free_a_printer(&printer, 2);
8294 SAFE_FREE(list);
8296 return status;
8299 /****************************************************************************
8300 ****************************************************************************/
8302 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8304 POLICY_HND *handle = &q_u->handle;
8305 FORM *form = &q_u->form;
8306 nt_forms_struct tmpForm;
8307 int snum;
8308 WERROR status = WERR_OK;
8309 NT_PRINTER_INFO_LEVEL *printer = NULL;
8311 int count=0;
8312 nt_forms_struct *list=NULL;
8313 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8315 DEBUG(5,("spoolss_setform\n"));
8317 if (!Printer) {
8318 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8319 return WERR_BADFID;
8322 /* forms can be modified on printer of on the print server handle */
8324 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8326 if (!get_printer_snum(p,handle, &snum))
8327 return WERR_BADFID;
8329 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8330 if (!W_ERROR_IS_OK(status))
8331 goto done;
8334 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8335 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8336 status = WERR_ACCESS_DENIED;
8337 goto done;
8340 /* can't set if builtin */
8341 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8342 status = WERR_INVALID_PARAM;
8343 goto done;
8346 count = get_ntforms(&list);
8347 update_a_form(&list, form, count);
8348 write_ntforms(&list, count);
8351 * ChangeID must always be set if this is a printer
8354 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8355 status = mod_a_printer(printer, 2);
8358 done:
8359 if ( printer )
8360 free_a_printer(&printer, 2);
8361 SAFE_FREE(list);
8363 return status;
8366 /****************************************************************************
8367 enumprintprocessors level 1.
8368 ****************************************************************************/
8370 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8372 PRINTPROCESSOR_1 *info_1=NULL;
8374 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8375 return WERR_NOMEM;
8377 (*returned) = 0x1;
8379 init_unistr(&info_1->name, "winprint");
8381 *needed += spoolss_size_printprocessor_info_1(info_1);
8383 if (!alloc_buffer_size(buffer, *needed))
8384 return WERR_INSUFFICIENT_BUFFER;
8386 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8388 SAFE_FREE(info_1);
8390 if (*needed > offered) {
8391 *returned=0;
8392 return WERR_INSUFFICIENT_BUFFER;
8395 return WERR_OK;
8398 /****************************************************************************
8399 ****************************************************************************/
8401 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8403 uint32 level = q_u->level;
8404 NEW_BUFFER *buffer = NULL;
8405 uint32 offered = q_u->offered;
8406 uint32 *needed = &r_u->needed;
8407 uint32 *returned = &r_u->returned;
8409 /* that's an [in out] buffer */
8410 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8411 buffer = r_u->buffer;
8413 DEBUG(5,("spoolss_enumprintprocessors\n"));
8416 * Enumerate the print processors ...
8418 * Just reply with "winprint", to keep NT happy
8419 * and I can use my nice printer checker.
8422 *returned=0;
8423 *needed=0;
8425 switch (level) {
8426 case 1:
8427 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8428 default:
8429 return WERR_UNKNOWN_LEVEL;
8433 /****************************************************************************
8434 enumprintprocdatatypes level 1.
8435 ****************************************************************************/
8437 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8439 PRINTPROCDATATYPE_1 *info_1=NULL;
8441 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8442 return WERR_NOMEM;
8444 (*returned) = 0x1;
8446 init_unistr(&info_1->name, "RAW");
8448 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8450 if (!alloc_buffer_size(buffer, *needed))
8451 return WERR_INSUFFICIENT_BUFFER;
8453 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8455 SAFE_FREE(info_1);
8457 if (*needed > offered) {
8458 *returned=0;
8459 return WERR_INSUFFICIENT_BUFFER;
8462 return WERR_OK;
8465 /****************************************************************************
8466 ****************************************************************************/
8468 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8470 uint32 level = q_u->level;
8471 NEW_BUFFER *buffer = NULL;
8472 uint32 offered = q_u->offered;
8473 uint32 *needed = &r_u->needed;
8474 uint32 *returned = &r_u->returned;
8476 /* that's an [in out] buffer */
8477 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8478 buffer = r_u->buffer;
8480 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8482 *returned=0;
8483 *needed=0;
8485 switch (level) {
8486 case 1:
8487 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8488 default:
8489 return WERR_UNKNOWN_LEVEL;
8493 /****************************************************************************
8494 enumprintmonitors level 1.
8495 ****************************************************************************/
8497 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8499 PRINTMONITOR_1 *info_1=NULL;
8501 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8502 return WERR_NOMEM;
8504 (*returned) = 0x1;
8506 init_unistr(&info_1->name, "Local Port");
8508 *needed += spoolss_size_printmonitor_info_1(info_1);
8510 if (!alloc_buffer_size(buffer, *needed))
8511 return WERR_INSUFFICIENT_BUFFER;
8513 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8515 SAFE_FREE(info_1);
8517 if (*needed > offered) {
8518 *returned=0;
8519 return WERR_INSUFFICIENT_BUFFER;
8522 return WERR_OK;
8525 /****************************************************************************
8526 enumprintmonitors level 2.
8527 ****************************************************************************/
8529 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8531 PRINTMONITOR_2 *info_2=NULL;
8533 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8534 return WERR_NOMEM;
8536 (*returned) = 0x1;
8538 init_unistr(&info_2->name, "Local Port");
8539 init_unistr(&info_2->environment, "Windows NT X86");
8540 init_unistr(&info_2->dll_name, "localmon.dll");
8542 *needed += spoolss_size_printmonitor_info_2(info_2);
8544 if (!alloc_buffer_size(buffer, *needed))
8545 return WERR_INSUFFICIENT_BUFFER;
8547 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8549 SAFE_FREE(info_2);
8551 if (*needed > offered) {
8552 *returned=0;
8553 return WERR_INSUFFICIENT_BUFFER;
8556 return WERR_OK;
8559 /****************************************************************************
8560 ****************************************************************************/
8562 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8564 uint32 level = q_u->level;
8565 NEW_BUFFER *buffer = NULL;
8566 uint32 offered = q_u->offered;
8567 uint32 *needed = &r_u->needed;
8568 uint32 *returned = &r_u->returned;
8570 /* that's an [in out] buffer */
8571 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8572 buffer = r_u->buffer;
8574 DEBUG(5,("spoolss_enumprintmonitors\n"));
8577 * Enumerate the print monitors ...
8579 * Just reply with "Local Port", to keep NT happy
8580 * and I can use my nice printer checker.
8583 *returned=0;
8584 *needed=0;
8586 switch (level) {
8587 case 1:
8588 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8589 case 2:
8590 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8591 default:
8592 return WERR_UNKNOWN_LEVEL;
8596 /****************************************************************************
8597 ****************************************************************************/
8599 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8600 NT_PRINTER_INFO_LEVEL *ntprinter,
8601 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8602 uint32 *needed)
8604 int i=0;
8605 BOOL found=False;
8606 JOB_INFO_1 *info_1=NULL;
8608 info_1=SMB_MALLOC_P(JOB_INFO_1);
8610 if (info_1 == NULL) {
8611 return WERR_NOMEM;
8614 for (i=0; i<count && found==False; i++) {
8615 if ((*queue)[i].job==(int)jobid)
8616 found=True;
8619 if (found==False) {
8620 SAFE_FREE(info_1);
8621 /* NT treats not found as bad param... yet another bad choice */
8622 return WERR_INVALID_PARAM;
8625 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8627 *needed += spoolss_size_job_info_1(info_1);
8629 if (!alloc_buffer_size(buffer, *needed)) {
8630 SAFE_FREE(info_1);
8631 return WERR_INSUFFICIENT_BUFFER;
8634 smb_io_job_info_1("", buffer, info_1, 0);
8636 SAFE_FREE(info_1);
8638 if (*needed > offered)
8639 return WERR_INSUFFICIENT_BUFFER;
8641 return WERR_OK;
8644 /****************************************************************************
8645 ****************************************************************************/
8647 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8648 NT_PRINTER_INFO_LEVEL *ntprinter,
8649 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8650 uint32 *needed)
8652 int i = 0;
8653 BOOL found = False;
8654 JOB_INFO_2 *info_2;
8655 WERROR ret;
8656 DEVICEMODE *devmode = NULL;
8657 NT_DEVICEMODE *nt_devmode = NULL;
8659 info_2=SMB_MALLOC_P(JOB_INFO_2);
8661 ZERO_STRUCTP(info_2);
8663 if (info_2 == NULL) {
8664 ret = WERR_NOMEM;
8665 goto done;
8668 for ( i=0; i<count && found==False; i++ )
8670 if ((*queue)[i].job == (int)jobid)
8671 found = True;
8674 if ( !found )
8676 /* NT treats not found as bad param... yet another bad
8677 choice */
8678 ret = WERR_INVALID_PARAM;
8679 goto done;
8683 * if the print job does not have a DEVMODE associated with it,
8684 * just use the one for the printer. A NULL devicemode is not
8685 * a failure condition
8688 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8689 devmode = construct_dev_mode(snum);
8690 else {
8691 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8692 ZERO_STRUCTP( devmode );
8693 convert_nt_devicemode( devmode, nt_devmode );
8697 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8699 *needed += spoolss_size_job_info_2(info_2);
8701 if (!alloc_buffer_size(buffer, *needed)) {
8702 ret = WERR_INSUFFICIENT_BUFFER;
8703 goto done;
8706 smb_io_job_info_2("", buffer, info_2, 0);
8708 if (*needed > offered) {
8709 ret = WERR_INSUFFICIENT_BUFFER;
8710 goto done;
8713 ret = WERR_OK;
8715 done:
8716 /* Cleanup allocated memory */
8718 free_job_info_2(info_2); /* Also frees devmode */
8719 SAFE_FREE(info_2);
8721 return ret;
8724 /****************************************************************************
8725 ****************************************************************************/
8727 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8729 POLICY_HND *handle = &q_u->handle;
8730 uint32 jobid = q_u->jobid;
8731 uint32 level = q_u->level;
8732 NEW_BUFFER *buffer = NULL;
8733 uint32 offered = q_u->offered;
8734 uint32 *needed = &r_u->needed;
8735 WERROR wstatus = WERR_OK;
8736 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8737 int snum;
8738 int count;
8739 print_queue_struct *queue = NULL;
8740 print_status_struct prt_status;
8742 /* that's an [in out] buffer */
8743 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8744 buffer = r_u->buffer;
8746 DEBUG(5,("spoolss_getjob\n"));
8748 *needed = 0;
8750 if (!get_printer_snum(p, handle, &snum))
8751 return WERR_BADFID;
8753 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8754 if ( !W_ERROR_IS_OK(wstatus) )
8755 return wstatus;
8757 count = print_queue_status(snum, &queue, &prt_status);
8759 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8760 count, prt_status.status, prt_status.message));
8762 switch ( level ) {
8763 case 1:
8764 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8765 buffer, offered, needed);
8766 break;
8767 case 2:
8768 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8769 buffer, offered, needed);
8770 break;
8771 default:
8772 wstatus = WERR_UNKNOWN_LEVEL;
8773 break;
8776 SAFE_FREE(queue);
8777 free_a_printer( &ntprinter, 2 );
8779 return wstatus;
8782 /********************************************************************
8783 spoolss_getprinterdataex
8785 From MSDN documentation of GetPrinterDataEx: pass request
8786 to GetPrinterData if key is "PrinterDriverData".
8787 ********************************************************************/
8789 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8791 POLICY_HND *handle = &q_u->handle;
8792 uint32 in_size = q_u->size;
8793 uint32 *type = &r_u->type;
8794 uint32 *out_size = &r_u->size;
8795 uint8 **data = &r_u->data;
8796 uint32 *needed = &r_u->needed;
8797 fstring keyname, valuename;
8799 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8801 NT_PRINTER_INFO_LEVEL *printer = NULL;
8802 int snum = 0;
8803 WERROR status = WERR_OK;
8805 DEBUG(4,("_spoolss_getprinterdataex\n"));
8807 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8808 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8810 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8811 keyname, valuename));
8813 /* in case of problem, return some default values */
8815 *needed = 0;
8816 *type = 0;
8817 *out_size = in_size;
8819 if (!Printer) {
8820 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8821 status = WERR_BADFID;
8822 goto done;
8825 /* Is the handle to a printer or to the server? */
8827 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8828 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8829 status = WERR_INVALID_PARAM;
8830 goto done;
8833 if ( !get_printer_snum(p,handle, &snum) )
8834 return WERR_BADFID;
8836 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8837 if ( !W_ERROR_IS_OK(status) )
8838 goto done;
8840 /* check to see if the keyname is valid */
8841 if ( !strlen(keyname) ) {
8842 status = WERR_INVALID_PARAM;
8843 goto done;
8846 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8847 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8848 free_a_printer( &printer, 2 );
8849 status = WERR_BADFILE;
8850 goto done;
8853 /* When given a new keyname, we should just create it */
8855 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8857 if (*needed > *out_size)
8858 status = WERR_MORE_DATA;
8860 done:
8861 if ( !W_ERROR_IS_OK(status) )
8863 DEBUG(5, ("error: allocating %d\n", *out_size));
8865 /* reply this param doesn't exist */
8867 if ( *out_size )
8869 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8870 status = WERR_NOMEM;
8871 goto done;
8874 else {
8875 *data = NULL;
8879 if ( printer )
8880 free_a_printer( &printer, 2 );
8882 return status;
8885 /********************************************************************
8886 * spoolss_setprinterdataex
8887 ********************************************************************/
8889 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8891 POLICY_HND *handle = &q_u->handle;
8892 uint32 type = q_u->type;
8893 uint8 *data = q_u->data;
8894 uint32 real_len = q_u->real_len;
8896 NT_PRINTER_INFO_LEVEL *printer = NULL;
8897 int snum = 0;
8898 WERROR status = WERR_OK;
8899 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8900 fstring valuename;
8901 fstring keyname;
8902 char *oid_string;
8904 DEBUG(4,("_spoolss_setprinterdataex\n"));
8906 /* From MSDN documentation of SetPrinterDataEx: pass request to
8907 SetPrinterData if key is "PrinterDriverData" */
8909 if (!Printer) {
8910 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8911 return WERR_BADFID;
8914 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8915 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8916 return WERR_INVALID_PARAM;
8919 if ( !get_printer_snum(p,handle, &snum) )
8920 return WERR_BADFID;
8923 * Access check : NT returns "access denied" if you make a
8924 * SetPrinterData call without the necessary privildge.
8925 * we were originally returning OK if nothing changed
8926 * which made Win2k issue **a lot** of SetPrinterData
8927 * when connecting to a printer --jerry
8930 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8932 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8933 return WERR_ACCESS_DENIED;
8936 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8937 if (!W_ERROR_IS_OK(status))
8938 return status;
8940 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8941 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8943 /* check for OID in valuename */
8945 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8947 *oid_string = '\0';
8948 oid_string++;
8951 /* save the registry data */
8953 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8955 if ( W_ERROR_IS_OK(status) )
8957 /* save the OID if one was specified */
8958 if ( oid_string ) {
8959 fstrcat( keyname, "\\" );
8960 fstrcat( keyname, SPOOL_OID_KEY );
8963 * I'm not checking the status here on purpose. Don't know
8964 * if this is right, but I'm returning the status from the
8965 * previous set_printer_dataex() call. I have no idea if
8966 * this is right. --jerry
8969 set_printer_dataex( printer, keyname, valuename,
8970 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8973 status = mod_a_printer(printer, 2);
8976 free_a_printer(&printer, 2);
8978 return status;
8982 /********************************************************************
8983 * spoolss_deleteprinterdataex
8984 ********************************************************************/
8986 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8988 POLICY_HND *handle = &q_u->handle;
8989 UNISTR2 *value = &q_u->valuename;
8990 UNISTR2 *key = &q_u->keyname;
8992 NT_PRINTER_INFO_LEVEL *printer = NULL;
8993 int snum=0;
8994 WERROR status = WERR_OK;
8995 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8996 pstring valuename, keyname;
8998 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9000 if (!Printer) {
9001 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9002 return WERR_BADFID;
9005 if (!get_printer_snum(p, handle, &snum))
9006 return WERR_BADFID;
9008 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9009 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9010 return WERR_ACCESS_DENIED;
9013 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9014 if (!W_ERROR_IS_OK(status))
9015 return status;
9017 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9018 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9020 status = delete_printer_dataex( printer, keyname, valuename );
9022 if ( W_ERROR_IS_OK(status) )
9023 mod_a_printer( printer, 2 );
9025 free_a_printer(&printer, 2);
9027 return status;
9030 /********************************************************************
9031 * spoolss_enumprinterkey
9032 ********************************************************************/
9035 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9037 fstring key;
9038 fstring *keynames = NULL;
9039 uint16 *enumkeys = NULL;
9040 int num_keys;
9041 int printerkey_len;
9042 POLICY_HND *handle = &q_u->handle;
9043 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9044 NT_PRINTER_DATA *data;
9045 NT_PRINTER_INFO_LEVEL *printer = NULL;
9046 int snum = 0;
9047 WERROR status = WERR_BADFILE;
9050 DEBUG(4,("_spoolss_enumprinterkey\n"));
9052 if (!Printer) {
9053 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9054 return WERR_BADFID;
9057 if ( !get_printer_snum(p,handle, &snum) )
9058 return WERR_BADFID;
9060 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9061 if (!W_ERROR_IS_OK(status))
9062 return status;
9064 /* get the list of subkey names */
9066 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9067 data = &printer->info_2->data;
9069 num_keys = get_printer_subkeys( data, key, &keynames );
9071 if ( num_keys == -1 ) {
9072 status = WERR_BADFILE;
9073 goto done;
9076 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9078 r_u->needed = printerkey_len*2;
9080 if ( q_u->size < r_u->needed ) {
9081 status = WERR_MORE_DATA;
9082 goto done;
9085 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9086 status = WERR_NOMEM;
9087 goto done;
9090 status = WERR_OK;
9092 if ( q_u->size < r_u->needed )
9093 status = WERR_MORE_DATA;
9095 done:
9096 free_a_printer( &printer, 2 );
9097 SAFE_FREE( keynames );
9099 return status;
9102 /********************************************************************
9103 * spoolss_deleteprinterkey
9104 ********************************************************************/
9106 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9108 POLICY_HND *handle = &q_u->handle;
9109 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9110 fstring key;
9111 NT_PRINTER_INFO_LEVEL *printer = NULL;
9112 int snum=0;
9113 WERROR status;
9115 DEBUG(5,("spoolss_deleteprinterkey\n"));
9117 if (!Printer) {
9118 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9119 return WERR_BADFID;
9122 /* if keyname == NULL, return error */
9124 if ( !q_u->keyname.buffer )
9125 return WERR_INVALID_PARAM;
9127 if (!get_printer_snum(p, handle, &snum))
9128 return WERR_BADFID;
9130 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9131 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9132 return WERR_ACCESS_DENIED;
9135 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9136 if (!W_ERROR_IS_OK(status))
9137 return status;
9139 /* delete the key and all subneys */
9141 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9143 status = delete_all_printer_data( printer->info_2, key );
9145 if ( W_ERROR_IS_OK(status) )
9146 status = mod_a_printer(printer, 2);
9148 free_a_printer( &printer, 2 );
9150 return status;
9154 /********************************************************************
9155 * spoolss_enumprinterdataex
9156 ********************************************************************/
9158 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9160 POLICY_HND *handle = &q_u->handle;
9161 uint32 in_size = q_u->size;
9162 uint32 num_entries,
9163 needed;
9164 NT_PRINTER_INFO_LEVEL *printer = NULL;
9165 PRINTER_ENUM_VALUES *enum_values = NULL;
9166 NT_PRINTER_DATA *p_data;
9167 fstring key;
9168 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9169 int snum;
9170 WERROR result;
9171 int key_index;
9172 int i;
9173 REGISTRY_VALUE *val;
9174 char *value_name;
9175 int data_len;
9178 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9180 if (!Printer) {
9181 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9182 return WERR_BADFID;
9186 * first check for a keyname of NULL or "". Win2k seems to send
9187 * this a lot and we should send back WERR_INVALID_PARAM
9188 * no need to spend time looking up the printer in this case.
9189 * --jerry
9192 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9193 if ( !strlen(key) ) {
9194 result = WERR_INVALID_PARAM;
9195 goto done;
9198 /* get the printer off of disk */
9200 if (!get_printer_snum(p,handle, &snum))
9201 return WERR_BADFID;
9203 ZERO_STRUCT(printer);
9204 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9205 if (!W_ERROR_IS_OK(result))
9206 return result;
9208 /* now look for a match on the key name */
9210 p_data = &printer->info_2->data;
9212 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9213 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9215 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9216 result = WERR_INVALID_PARAM;
9217 goto done;
9220 result = WERR_OK;
9221 needed = 0;
9223 /* allocate the memory for the array of pointers -- if necessary */
9225 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9226 if ( num_entries )
9228 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9230 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9231 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9232 result = WERR_NOMEM;
9233 goto done;
9236 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9240 * loop through all params and build the array to pass
9241 * back to the client
9244 for ( i=0; i<num_entries; i++ )
9246 /* lookup the registry value */
9248 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9249 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9251 /* copy the data */
9253 value_name = regval_name( val );
9254 init_unistr( &enum_values[i].valuename, value_name );
9255 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9256 enum_values[i].type = regval_type( val );
9258 data_len = regval_size( val );
9259 if ( data_len ) {
9260 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9262 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9263 data_len ));
9264 result = WERR_NOMEM;
9265 goto done;
9268 enum_values[i].data_len = data_len;
9270 /* keep track of the size of the array in bytes */
9272 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9275 /* housekeeping information in the reply */
9277 r_u->needed = needed;
9278 r_u->returned = num_entries;
9280 if (needed > in_size) {
9281 result = WERR_MORE_DATA;
9282 goto done;
9285 /* copy data into the reply */
9287 r_u->ctr.size = r_u->needed;
9288 r_u->ctr.size_of_array = r_u->returned;
9289 r_u->ctr.values = enum_values;
9293 done:
9294 if ( printer )
9295 free_a_printer(&printer, 2);
9297 return result;
9300 /****************************************************************************
9301 ****************************************************************************/
9303 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9305 init_unistr(&info->name, name);
9308 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9309 UNISTR2 *environment,
9310 NEW_BUFFER *buffer,
9311 uint32 offered,
9312 uint32 *needed)
9314 pstring path;
9315 pstring long_archi;
9316 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9318 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9320 if (!get_short_archi(long_archi))
9321 return WERR_INVALID_ENVIRONMENT;
9323 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9324 return WERR_NOMEM;
9326 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9328 fill_printprocessordirectory_1(info, path);
9330 *needed += spoolss_size_printprocessordirectory_info_1(info);
9332 if (!alloc_buffer_size(buffer, *needed)) {
9333 safe_free(info);
9334 return WERR_INSUFFICIENT_BUFFER;
9337 smb_io_printprocessordirectory_1("", buffer, info, 0);
9339 safe_free(info);
9341 if (*needed > offered)
9342 return WERR_INSUFFICIENT_BUFFER;
9343 else
9344 return WERR_OK;
9347 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9349 uint32 level = q_u->level;
9350 NEW_BUFFER *buffer = NULL;
9351 uint32 offered = q_u->offered;
9352 uint32 *needed = &r_u->needed;
9353 WERROR result;
9355 /* that's an [in out] buffer */
9356 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9357 buffer = r_u->buffer;
9359 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9361 *needed=0;
9363 switch(level) {
9364 case 1:
9365 result = getprintprocessordirectory_level_1
9366 (&q_u->name, &q_u->environment, buffer, offered, needed);
9367 break;
9368 default:
9369 result = WERR_UNKNOWN_LEVEL;
9372 return result;
9375 #if 0
9377 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9378 SPOOL_R_REPLYOPENPRINTER *r_u)
9380 DEBUG(5,("_spoolss_replyopenprinter\n"));
9382 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9384 return WERR_OK;
9387 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9388 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9390 DEBUG(5,("_spoolss_replycloseprinter\n"));
9391 return WERR_OK;
9394 #endif