r3049: fixing some calls in the printing code to stanard_sub_basic(); fix standard_su...
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob2bdcfeff4da35d846419cd3691c0f10f578ae1a5
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 = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(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 if (del_a_printer( Printer->sharename ) != 0) {
384 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
385 return WERR_BADFID;
388 if (*lp_deleteprinter_cmd()) {
390 char *cmd = lp_deleteprinter_cmd();
391 pstring command;
392 int ret;
394 pstr_sprintf(command, "%s \"%s\"", cmd, Printer->sharename);
396 DEBUG(10,("Running [%s]\n", command));
397 ret = smbrun(command, NULL);
398 if (ret != 0) {
399 return WERR_BADFID; /* What to return here? */
401 DEBUGADD(10,("returned [%d]\n", ret));
403 /* Send SIGHUP to process group... is there a better way? */
404 kill(0, SIGHUP);
406 /* go ahead and re-read the services immediately */
407 reload_services( False );
409 if ( lp_servicenumber( Printer->sharename ) < 0 )
410 return WERR_ACCESS_DENIED;
413 return WERR_OK;
416 /****************************************************************************
417 Return the snum of a printer corresponding to an handle.
418 ****************************************************************************/
420 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
422 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
424 if (!Printer) {
425 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
426 return False;
429 switch (Printer->printer_type) {
430 case PRINTER_HANDLE_IS_PRINTER:
431 DEBUG(4,("short name:%s\n", Printer->sharename));
432 *number = print_queue_snum(Printer->sharename);
433 return (*number != -1);
434 case PRINTER_HANDLE_IS_PRINTSERVER:
435 return False;
436 default:
437 return False;
441 /****************************************************************************
442 Set printer handle type.
443 Check if it's \\server or \\server\printer
444 ****************************************************************************/
446 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
448 DEBUG(3,("Setting printer type=%s\n", handlename));
450 if ( strlen(handlename) < 3 ) {
451 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
452 return False;
455 /* it's a print server */
456 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
457 DEBUGADD(4,("Printer is a print server\n"));
458 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
460 /* it's a printer */
461 else {
462 DEBUGADD(4,("Printer is a printer\n"));
463 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
466 return True;
469 /****************************************************************************
470 Set printer handle name.
471 ****************************************************************************/
473 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
475 int snum;
476 int n_services=lp_numservices();
477 char *aprinter, *printername;
478 const char *servername;
479 fstring sname;
480 BOOL found=False;
481 NT_PRINTER_INFO_LEVEL *printer;
482 WERROR result;
484 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
486 aprinter = handlename;
487 if ( *handlename == '\\' ) {
488 servername = handlename + 2;
489 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
490 *aprinter = '\0';
491 aprinter++;
494 else {
495 servername = "";
498 /* save the servername to fill in replies on this handle */
500 if ( !is_myname_or_ipaddr( servername ) )
501 return False;
503 fstrcpy( Printer->servername, servername );
505 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
506 return True;
508 if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
509 return False;
511 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
513 /* Search all sharenames first as this is easier than pulling
514 the printer_info_2 off of disk */
516 for (snum=0; !found && snum<n_services; snum++) {
518 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
519 continue;
521 /* ------ sharename ------ */
523 fstrcpy(sname, lp_servicename(snum));
525 DEBUGADD(10, ("share: %s\n",sname));
527 if ( strequal(sname, aprinter) ) {
528 found = True;
532 /* do another loop to look for printernames */
534 for (snum=0; !found && snum<n_services; snum++) {
536 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
537 continue;
539 fstrcpy(sname, lp_servicename(snum));
541 printer = NULL;
542 result = get_a_printer( NULL, &printer, 2, sname );
543 if ( !W_ERROR_IS_OK(result) ) {
544 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
545 sname, dos_errstr(result)));
546 continue;
549 /* printername is always returned as \\server\printername */
550 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
551 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
552 printer->info_2->printername));
553 free_a_printer( &printer, 2);
554 continue;
557 printername++;
559 if ( strequal(printername, aprinter) ) {
560 found = True;
563 DEBUGADD(10, ("printername: %s\n", printername));
565 free_a_printer( &printer, 2);
568 if ( !found ) {
569 DEBUGADD(4,("Printer not found\n"));
570 return False;
573 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
575 fstrcpy(Printer->sharename, sname);
577 return True;
580 /****************************************************************************
581 Find first available printer slot. creates a printer handle for you.
582 ****************************************************************************/
584 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
586 Printer_entry *new_printer;
588 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
590 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
591 return False;
593 ZERO_STRUCTP(new_printer);
595 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
596 SAFE_FREE(new_printer);
597 return False;
600 /* Add to the internal list. */
601 DLIST_ADD(printers_list, new_printer);
603 new_printer->notify.option=NULL;
605 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
606 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
607 close_printer_handle(p, hnd);
608 return False;
611 if (!set_printer_hnd_printertype(new_printer, name)) {
612 close_printer_handle(p, hnd);
613 return False;
616 if (!set_printer_hnd_name(new_printer, name)) {
617 close_printer_handle(p, hnd);
618 return False;
621 new_printer->access_granted = access_granted;
623 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
625 return True;
628 /****************************************************************************
629 Allocate more memory for a BUFFER.
630 ****************************************************************************/
632 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
634 prs_struct *ps;
635 uint32 extra_space;
636 uint32 old_offset;
638 ps= &buffer->prs;
640 /* damn, I'm doing the reverse operation of prs_grow() :) */
641 if (buffer_size < prs_data_size(ps))
642 extra_space=0;
643 else
644 extra_space = buffer_size - prs_data_size(ps);
647 * save the offset and move to the end of the buffer
648 * prs_grow() checks the extra_space against the offset
650 old_offset=prs_offset(ps);
651 prs_set_offset(ps, prs_data_size(ps));
653 if (!prs_grow(ps, extra_space))
654 return False;
656 prs_set_offset(ps, old_offset);
658 buffer->string_at_end=prs_data_size(ps);
660 return True;
663 /***************************************************************************
664 check to see if the client motify handle is monitoring the notification
665 given by (notify_type, notify_field).
666 **************************************************************************/
668 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
669 uint16 notify_field)
671 return True;
674 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
675 uint16 notify_field)
677 SPOOL_NOTIFY_OPTION *option = p->notify.option;
678 uint32 i, j;
681 * Flags should always be zero when the change notify
682 * is registered by the client's spooler. A user Win32 app
683 * might use the flags though instead of the NOTIFY_OPTION_INFO
684 * --jerry
687 if (!option) {
688 return False;
691 if (p->notify.flags)
692 return is_monitoring_event_flags(
693 p->notify.flags, notify_type, notify_field);
695 for (i = 0; i < option->count; i++) {
697 /* Check match for notify_type */
699 if (option->ctr.type[i].type != notify_type)
700 continue;
702 /* Check match for field */
704 for (j = 0; j < option->ctr.type[i].count; j++) {
705 if (option->ctr.type[i].fields[j] == notify_field) {
706 return True;
711 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
712 p->servername, p->sharename, notify_type, notify_field));
714 return False;
717 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
719 static void notify_one_value(struct spoolss_notify_msg *msg,
720 SPOOL_NOTIFY_INFO_DATA *data,
721 TALLOC_CTX *mem_ctx)
723 data->notify_data.value[0] = msg->notify.value[0];
724 data->notify_data.value[1] = 0;
727 static void notify_string(struct spoolss_notify_msg *msg,
728 SPOOL_NOTIFY_INFO_DATA *data,
729 TALLOC_CTX *mem_ctx)
731 UNISTR2 unistr;
733 /* The length of the message includes the trailing \0 */
735 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
737 data->notify_data.data.length = msg->len * 2;
738 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
740 if (!data->notify_data.data.string) {
741 data->notify_data.data.length = 0;
742 return;
745 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
748 static void notify_system_time(struct spoolss_notify_msg *msg,
749 SPOOL_NOTIFY_INFO_DATA *data,
750 TALLOC_CTX *mem_ctx)
752 SYSTEMTIME systime;
753 prs_struct ps;
755 if (msg->len != sizeof(time_t)) {
756 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
757 msg->len));
758 return;
761 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
762 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
763 return;
766 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
767 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
768 return;
771 if (!spoolss_io_system_time("", &ps, 0, &systime))
772 return;
774 data->notify_data.data.length = prs_offset(&ps);
775 data->notify_data.data.string = talloc(mem_ctx, prs_offset(&ps));
777 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
779 prs_mem_free(&ps);
782 struct notify2_message_table {
783 const char *name;
784 void (*fn)(struct spoolss_notify_msg *msg,
785 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
788 static struct notify2_message_table printer_notify_table[] = {
789 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
790 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
791 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
792 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
793 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
794 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
795 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
796 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
797 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
798 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
799 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
800 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
801 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
802 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
803 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
804 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
805 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
806 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
807 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
810 static struct notify2_message_table job_notify_table[] = {
811 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
812 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
813 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
814 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
815 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
816 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
817 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
818 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
819 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
820 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
821 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
822 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
823 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
824 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
825 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
826 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
827 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
828 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
829 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
830 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
831 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
832 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
833 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
834 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
838 /***********************************************************************
839 Allocate talloc context for container object
840 **********************************************************************/
842 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
844 if ( !ctr )
845 return;
847 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
849 return;
852 /***********************************************************************
853 release all allocated memory and zero out structure
854 **********************************************************************/
856 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
858 if ( !ctr )
859 return;
861 if ( ctr->ctx )
862 talloc_destroy(ctr->ctx);
864 ZERO_STRUCTP(ctr);
866 return;
869 /***********************************************************************
870 **********************************************************************/
872 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
874 if ( !ctr )
875 return NULL;
877 return ctr->ctx;
880 /***********************************************************************
881 **********************************************************************/
883 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
885 if ( !ctr || !ctr->msg_groups )
886 return NULL;
888 if ( idx >= ctr->num_groups )
889 return NULL;
891 return &ctr->msg_groups[idx];
895 /***********************************************************************
896 How many groups of change messages do we have ?
897 **********************************************************************/
899 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
901 if ( !ctr )
902 return 0;
904 return ctr->num_groups;
907 /***********************************************************************
908 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
909 **********************************************************************/
911 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
913 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
914 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
915 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
916 int i, new_slot;
918 if ( !ctr || !msg )
919 return 0;
921 /* loop over all groups looking for a matching printer name */
923 for ( i=0; i<ctr->num_groups; i++ ) {
924 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
925 break;
928 /* add a new group? */
930 if ( i == ctr->num_groups ) {
931 ctr->num_groups++;
933 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
934 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
935 return 0;
937 ctr->msg_groups = groups;
939 /* clear the new entry and set the printer name */
941 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
942 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
945 /* add the change messages; 'i' is the correct index now regardless */
947 msg_grp = &ctr->msg_groups[i];
949 msg_grp->num_msgs++;
951 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
952 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
953 return 0;
955 msg_grp->msgs = msg_list;
957 new_slot = msg_grp->num_msgs-1;
958 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
960 /* need to allocate own copy of data */
962 if ( msg->len != 0 )
963 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
965 return ctr->num_groups;
968 /***********************************************************************
969 Send a change notication message on all handles which have a call
970 back registered
971 **********************************************************************/
973 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
975 Printer_entry *p;
976 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
977 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
978 SPOOLSS_NOTIFY_MSG *messages;
979 int sending_msg_count;
981 if ( !msg_group ) {
982 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
983 return;
986 messages = msg_group->msgs;
988 if ( !messages ) {
989 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
990 return;
993 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
995 /* loop over all printers */
997 for (p = printers_list; p; p = p->next) {
998 SPOOL_NOTIFY_INFO_DATA *data;
999 uint32 data_len = 0;
1000 uint32 id;
1001 int i;
1003 /* Is there notification on this handle? */
1005 if ( !p->notify.client_connected )
1006 continue;
1008 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
1010 /* For this printer? Print servers always receive
1011 notifications. */
1013 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
1014 ( !strequal(msg_group->printername, p->sharename) ) )
1015 continue;
1017 DEBUG(10,("Our printer\n"));
1019 /* allocate the max entries possible */
1021 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
1022 ZERO_STRUCTP(data);
1024 /* build the array of change notifications */
1026 sending_msg_count = 0;
1028 for ( i=0; i<msg_group->num_msgs; i++ ) {
1029 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1031 /* Are we monitoring this event? */
1033 if (!is_monitoring_event(p, msg->type, msg->field))
1034 continue;
1036 sending_msg_count++;
1039 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1040 msg->type, msg->field, p->sharename));
1043 * if the is a printer notification handle and not a job notification
1044 * type, then set the id to 0. Other wise just use what was specified
1045 * in the message.
1047 * When registering change notification on a print server handle
1048 * we always need to send back the id (snum) matching the printer
1049 * for which the change took place. For change notify registered
1050 * on a printer handle, this does not matter and the id should be 0.
1052 * --jerry
1055 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1056 id = 0;
1057 else
1058 id = msg->id;
1061 /* Convert unix jobid to smb jobid */
1063 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1064 id = sysjob_to_jobid(msg->id);
1066 if (id == -1) {
1067 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1068 goto done;
1072 construct_info_data( &data[data_len], msg->type, msg->field, id );
1074 switch(msg->type) {
1075 case PRINTER_NOTIFY_TYPE:
1076 if ( printer_notify_table[msg->field].fn )
1077 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1078 break;
1080 case JOB_NOTIFY_TYPE:
1081 if ( job_notify_table[msg->field].fn )
1082 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1083 break;
1085 default:
1086 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1087 goto done;
1090 data_len++;
1093 if ( sending_msg_count ) {
1094 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
1095 data_len, data, p->notify.change, 0 );
1099 done:
1100 DEBUG(8,("send_notify2_changes: Exit...\n"));
1101 return;
1104 /***********************************************************************
1105 **********************************************************************/
1107 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1110 uint32 tv_sec, tv_usec;
1111 size_t offset = 0;
1113 /* Unpack message */
1115 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1116 msg->printer);
1118 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1119 &tv_sec, &tv_usec,
1120 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1122 if (msg->len == 0)
1123 tdb_unpack((char *)buf + offset, len - offset, "dd",
1124 &msg->notify.value[0], &msg->notify.value[1]);
1125 else
1126 tdb_unpack((char *)buf + offset, len - offset, "B",
1127 &msg->len, &msg->notify.data);
1129 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1130 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1132 tv->tv_sec = tv_sec;
1133 tv->tv_usec = tv_usec;
1135 if (msg->len == 0)
1136 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1137 msg->notify.value[1]));
1138 else
1139 dump_data(3, msg->notify.data, msg->len);
1141 return True;
1144 /********************************************************************
1145 Receive a notify2 message list
1146 ********************************************************************/
1148 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1150 size_t msg_count, i;
1151 char *buf = (char *)msg;
1152 char *msg_ptr;
1153 size_t msg_len;
1154 SPOOLSS_NOTIFY_MSG notify;
1155 SPOOLSS_NOTIFY_MSG_CTR messages;
1156 int num_groups;
1158 if (len < 4) {
1159 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1160 return;
1163 msg_count = IVAL(buf, 0);
1164 msg_ptr = buf + 4;
1166 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1168 if (msg_count == 0) {
1169 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1170 return;
1173 /* initialize the container */
1175 ZERO_STRUCT( messages );
1176 notify_msg_ctr_init( &messages );
1179 * build message groups for each printer identified
1180 * in a change_notify msg. Remember that a PCN message
1181 * includes the handle returned for the srv_spoolss_replyopenprinter()
1182 * call. Therefore messages are grouped according to printer handle.
1185 for ( i=0; i<msg_count; i++ ) {
1186 struct timeval msg_tv;
1188 if (msg_ptr + 4 - buf > len) {
1189 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1190 return;
1193 msg_len = IVAL(msg_ptr,0);
1194 msg_ptr += 4;
1196 if (msg_ptr + msg_len - buf > len) {
1197 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1198 return;
1201 /* unpack messages */
1203 ZERO_STRUCT( notify );
1204 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1205 msg_ptr += msg_len;
1207 /* add to correct list in container */
1209 notify_msg_ctr_addmsg( &messages, &notify );
1211 /* free memory that might have been allocated by notify2_unpack_msg() */
1213 if ( notify.len != 0 )
1214 SAFE_FREE( notify.notify.data );
1217 /* process each group of messages */
1219 num_groups = notify_msg_ctr_numgroups( &messages );
1220 for ( i=0; i<num_groups; i++ )
1221 send_notify2_changes( &messages, i );
1224 /* cleanup */
1226 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1228 notify_msg_ctr_destroy( &messages );
1230 return;
1233 /********************************************************************
1234 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1235 one smbd, all of processes must clear their printer cache immediately.
1236 ********************************************************************/
1238 void receive_printer_mod_msg(int msg_type, pid_t src, void *buf, size_t len)
1240 fstring printername;
1242 fstrcpy( printername, buf );
1244 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername ));
1246 invalidate_printer_hnd_cache( printername );
1249 /********************************************************************
1250 Send a message to ourself about new driver being installed
1251 so we can upgrade the information for each printer bound to this
1252 driver
1253 ********************************************************************/
1255 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1257 int len = strlen(drivername);
1259 if (!len)
1260 return False;
1262 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1263 drivername));
1265 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1267 return True;
1270 /**********************************************************************
1271 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1272 over all printers, upgrading ones as necessary
1273 **********************************************************************/
1275 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1277 fstring drivername;
1278 int snum;
1279 int n_services = lp_numservices();
1281 len = MIN(len,sizeof(drivername)-1);
1282 strncpy(drivername, buf, len);
1284 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1286 /* Iterate the printer list */
1288 for (snum=0; snum<n_services; snum++)
1290 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1292 WERROR result;
1293 NT_PRINTER_INFO_LEVEL *printer = NULL;
1295 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1296 if (!W_ERROR_IS_OK(result))
1297 continue;
1299 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1301 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1303 /* all we care about currently is the change_id */
1305 result = mod_a_printer(printer, 2);
1306 if (!W_ERROR_IS_OK(result)) {
1307 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1308 dos_errstr(result)));
1312 free_a_printer(&printer, 2);
1316 /* all done */
1319 /********************************************************************
1320 Update the cache for all printq's with a registered client
1321 connection
1322 ********************************************************************/
1324 void update_monitored_printq_cache( void )
1326 Printer_entry *printer = printers_list;
1327 int snum;
1329 /* loop through all printers and update the cache where
1330 client_connected == True */
1331 while ( printer )
1333 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1334 && printer->notify.client_connected )
1336 snum = print_queue_snum(printer->sharename);
1337 print_queue_status( snum, NULL, NULL );
1340 printer = printer->next;
1343 return;
1345 /********************************************************************
1346 Send a message to ourself about new driver being installed
1347 so we can upgrade the information for each printer bound to this
1348 driver
1349 ********************************************************************/
1351 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1353 int len = strlen(drivername);
1355 if (!len)
1356 return False;
1358 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1359 drivername));
1361 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1363 return True;
1366 /**********************************************************************
1367 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1368 over all printers, resetting printer data as neessary
1369 **********************************************************************/
1371 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1373 fstring drivername;
1374 int snum;
1375 int n_services = lp_numservices();
1377 len = MIN( len, sizeof(drivername)-1 );
1378 strncpy( drivername, buf, len );
1380 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1382 /* Iterate the printer list */
1384 for ( snum=0; snum<n_services; snum++ )
1386 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1388 WERROR result;
1389 NT_PRINTER_INFO_LEVEL *printer = NULL;
1391 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1392 if ( !W_ERROR_IS_OK(result) )
1393 continue;
1396 * if the printer is bound to the driver,
1397 * then reset to the new driver initdata
1400 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1402 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1404 if ( !set_driver_init(printer, 2) ) {
1405 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1406 printer->info_2->printername, printer->info_2->drivername));
1409 result = mod_a_printer( printer, 2 );
1410 if ( !W_ERROR_IS_OK(result) ) {
1411 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1412 get_dos_error_msg(result)));
1416 free_a_printer( &printer, 2 );
1420 /* all done */
1422 return;
1425 /********************************************************************
1426 Copy routines used by convert_to_openprinterex()
1427 *******************************************************************/
1429 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1431 DEVICEMODE *d;
1432 int len;
1434 if (!devmode)
1435 return NULL;
1437 DEBUG (8,("dup_devmode\n"));
1439 /* bulk copy first */
1441 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1442 if (!d)
1443 return NULL;
1445 /* dup the pointer members separately */
1447 len = unistrlen(devmode->devicename.buffer);
1448 if (len != -1) {
1449 d->devicename.buffer = talloc(ctx, len*2);
1450 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1451 return NULL;
1455 len = unistrlen(devmode->formname.buffer);
1456 if (len != -1) {
1457 d->devicename.buffer = talloc(ctx, len*2);
1458 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1459 return NULL;
1462 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1464 return d;
1467 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1469 if (!new_ctr || !ctr)
1470 return;
1472 DEBUG(8,("copy_devmode_ctr\n"));
1474 new_ctr->size = ctr->size;
1475 new_ctr->devmode_ptr = ctr->devmode_ptr;
1477 if(ctr->devmode_ptr)
1478 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1481 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1483 if (!new_def || !def)
1484 return;
1486 DEBUG(8,("copy_printer_defaults\n"));
1488 new_def->datatype_ptr = def->datatype_ptr;
1490 if (def->datatype_ptr)
1491 copy_unistr2(&new_def->datatype, &def->datatype);
1493 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1495 new_def->access_required = def->access_required;
1498 /********************************************************************
1499 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1500 * SPOOL_Q_OPEN_PRINTER_EX structure
1501 ********************************************************************/
1503 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1505 if (!q_u_ex || !q_u)
1506 return;
1508 DEBUG(8,("convert_to_openprinterex\n"));
1510 q_u_ex->printername_ptr = q_u->printername_ptr;
1512 if (q_u->printername_ptr)
1513 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1515 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1518 /********************************************************************
1519 * spoolss_open_printer
1521 * called from the spoolss dispatcher
1522 ********************************************************************/
1524 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1526 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1527 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1529 if (!q_u || !r_u)
1530 return WERR_NOMEM;
1532 ZERO_STRUCT(q_u_ex);
1533 ZERO_STRUCT(r_u_ex);
1535 /* convert the OpenPrinter() call to OpenPrinterEx() */
1537 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1539 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1541 /* convert back to OpenPrinter() */
1543 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1545 return r_u->status;
1548 /********************************************************************
1549 * spoolss_open_printer
1551 * If the openprinterex rpc call contains a devmode,
1552 * it's a per-user one. This per-user devmode is derivated
1553 * from the global devmode. Openprinterex() contains a per-user
1554 * devmode for when you do EMF printing and spooling.
1555 * In the EMF case, the NT workstation is only doing half the job
1556 * of rendering the page. The other half is done by running the printer
1557 * driver on the server.
1558 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1559 * The EMF file only contains what is to be printed on the page.
1560 * So in order for the server to know how to print, the NT client sends
1561 * a devicemode attached to the openprinterex call.
1562 * But this devicemode is short lived, it's only valid for the current print job.
1564 * If Samba would have supported EMF spooling, this devicemode would
1565 * have been attached to the handle, to sent it to the driver to correctly
1566 * rasterize the EMF file.
1568 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1569 * we just act as a pass-thru between windows and the printer.
1571 * In order to know that Samba supports only RAW spooling, NT has to call
1572 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1573 * and until NT sends a RAW job, we refuse it.
1575 * But to call getprinter() or startdoc(), you first need a valid handle,
1576 * and to get an handle you have to call openprintex(). Hence why you have
1577 * a devicemode in the openprinterex() call.
1580 * Differences between NT4 and NT 2000.
1581 * NT4:
1582 * ---
1583 * On NT4, you only have a global devicemode. This global devicemode can be changed
1584 * by the administrator (or by a user with enough privs). Everytime a user
1585 * wants to print, the devicemode is resetted to the default. In Word, everytime
1586 * you print, the printer's characteristics are always reset to the global devicemode.
1588 * NT 2000:
1589 * -------
1590 * In W2K, there is the notion of per-user devicemode. The first time you use
1591 * a printer, a per-user devicemode is build from the global devicemode.
1592 * If you change your per-user devicemode, it is saved in the registry, under the
1593 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1594 * printer preferences available.
1596 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1597 * on the General Tab of the printer properties windows.
1599 * To change the global devicemode: it's the "Printing Defaults..." button
1600 * on the Advanced Tab of the printer properties window.
1602 * JFM.
1603 ********************************************************************/
1605 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1607 UNISTR2 *printername = NULL;
1608 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1609 POLICY_HND *handle = &r_u->handle;
1611 fstring name;
1612 int snum;
1613 struct current_user user;
1614 Printer_entry *Printer=NULL;
1616 if (q_u->printername_ptr != 0)
1617 printername = &q_u->printername;
1619 if (printername == NULL)
1620 return WERR_INVALID_PRINTER_NAME;
1622 /* some sanity check because you can open a printer or a print server */
1623 /* aka: \\server\printer or \\server */
1624 unistr2_to_ascii(name, printername, sizeof(name)-1);
1626 DEBUGADD(3,("checking name: %s\n",name));
1628 if (!open_printer_hnd(p, handle, name, 0))
1629 return WERR_INVALID_PRINTER_NAME;
1631 Printer=find_printer_index_by_hnd(p, handle);
1632 if ( !Printer ) {
1633 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1634 "handle we created for printer %s\n", name ));
1635 close_printer_handle(p,handle);
1636 return WERR_INVALID_PRINTER_NAME;
1639 get_current_user(&user, p);
1642 * First case: the user is opening the print server:
1644 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1645 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1647 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1648 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1649 * or if the user is listed in the smb.conf printer admin parameter.
1651 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1652 * client view printer folder, but does not show the MSAPW.
1654 * Note: this test needs code to check access rights here too. Jeremy
1655 * could you look at this?
1657 * Second case: the user is opening a printer:
1658 * NT doesn't let us connect to a printer if the connecting user
1659 * doesn't have print permission.
1662 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1664 /* Printserver handles use global struct... */
1666 snum = -1;
1668 /* Map standard access rights to object specific access rights */
1670 se_map_standard(&printer_default->access_required,
1671 &printserver_std_mapping);
1673 /* Deny any object specific bits that don't apply to print
1674 servers (i.e printer and job specific bits) */
1676 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1678 if (printer_default->access_required &
1679 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1680 DEBUG(3, ("access DENIED for non-printserver bits"));
1681 close_printer_handle(p, handle);
1682 return WERR_ACCESS_DENIED;
1685 /* Allow admin access */
1687 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1689 if (!lp_ms_add_printer_wizard()) {
1690 close_printer_handle(p, handle);
1691 return WERR_ACCESS_DENIED;
1694 /* if the user is not root and not a printer admin, then fail */
1696 if ( user.uid != 0
1697 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1699 close_printer_handle(p, handle);
1700 return WERR_ACCESS_DENIED;
1703 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1705 else
1707 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1710 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1711 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1713 /* We fall through to return WERR_OK */
1716 else
1718 /* NT doesn't let us connect to a printer if the connecting user
1719 doesn't have print permission. */
1721 if (!get_printer_snum(p, handle, &snum)) {
1722 close_printer_handle(p, handle);
1723 return WERR_BADFID;
1726 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1728 /* map an empty access mask to the minimum access mask */
1729 if (printer_default->access_required == 0x0)
1730 printer_default->access_required = PRINTER_ACCESS_USE;
1733 * If we are not serving the printer driver for this printer,
1734 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1735 * will keep NT clients happy --jerry
1738 if (lp_use_client_driver(snum)
1739 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1741 printer_default->access_required = PRINTER_ACCESS_USE;
1744 /* check smb.conf parameters and the the sec_desc */
1746 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1747 DEBUG(3, ("access DENIED for printer open\n"));
1748 close_printer_handle(p, handle);
1749 return WERR_ACCESS_DENIED;
1752 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1753 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1754 close_printer_handle(p, handle);
1755 return WERR_ACCESS_DENIED;
1758 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1759 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1760 else
1761 printer_default->access_required = PRINTER_ACCESS_USE;
1763 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1764 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1768 Printer->access_granted = printer_default->access_required;
1771 * If the client sent a devmode in the OpenPrinter() call, then
1772 * save it here in case we get a job submission on this handle
1775 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1776 && q_u->printer_default.devmode_cont.devmode_ptr )
1778 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1779 &Printer->nt_devmode );
1782 #if 0 /* JERRY -- I'm doubtful this is really effective */
1783 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1784 optimization in Windows 2000 clients --jerry */
1786 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1787 && (RA_WIN2K == get_remote_arch()) )
1789 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1790 sys_usleep( 500000 );
1792 #endif
1794 return WERR_OK;
1797 /****************************************************************************
1798 ****************************************************************************/
1800 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1801 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1803 BOOL ret = True;
1805 switch (level) {
1806 case 2:
1807 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1808 break;
1809 default:
1810 break;
1813 return ret;
1816 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1817 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1819 BOOL result = True;
1821 switch (level) {
1822 case 3:
1823 printer->info_3=NULL;
1824 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1825 result = False;
1826 break;
1827 case 6:
1828 printer->info_6=NULL;
1829 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1830 result = False;
1831 break;
1832 default:
1833 break;
1836 return result;
1839 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1840 NT_DEVICEMODE **pp_nt_devmode)
1842 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1845 * Ensure nt_devmode is a valid pointer
1846 * as we will be overwriting it.
1849 if (nt_devmode == NULL) {
1850 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1851 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1852 return False;
1855 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1856 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1858 nt_devmode->specversion=devmode->specversion;
1859 nt_devmode->driverversion=devmode->driverversion;
1860 nt_devmode->size=devmode->size;
1861 nt_devmode->fields=devmode->fields;
1862 nt_devmode->orientation=devmode->orientation;
1863 nt_devmode->papersize=devmode->papersize;
1864 nt_devmode->paperlength=devmode->paperlength;
1865 nt_devmode->paperwidth=devmode->paperwidth;
1866 nt_devmode->scale=devmode->scale;
1867 nt_devmode->copies=devmode->copies;
1868 nt_devmode->defaultsource=devmode->defaultsource;
1869 nt_devmode->printquality=devmode->printquality;
1870 nt_devmode->color=devmode->color;
1871 nt_devmode->duplex=devmode->duplex;
1872 nt_devmode->yresolution=devmode->yresolution;
1873 nt_devmode->ttoption=devmode->ttoption;
1874 nt_devmode->collate=devmode->collate;
1876 nt_devmode->logpixels=devmode->logpixels;
1877 nt_devmode->bitsperpel=devmode->bitsperpel;
1878 nt_devmode->pelswidth=devmode->pelswidth;
1879 nt_devmode->pelsheight=devmode->pelsheight;
1880 nt_devmode->displayflags=devmode->displayflags;
1881 nt_devmode->displayfrequency=devmode->displayfrequency;
1882 nt_devmode->icmmethod=devmode->icmmethod;
1883 nt_devmode->icmintent=devmode->icmintent;
1884 nt_devmode->mediatype=devmode->mediatype;
1885 nt_devmode->dithertype=devmode->dithertype;
1886 nt_devmode->reserved1=devmode->reserved1;
1887 nt_devmode->reserved2=devmode->reserved2;
1888 nt_devmode->panningwidth=devmode->panningwidth;
1889 nt_devmode->panningheight=devmode->panningheight;
1892 * Only change private and driverextra if the incoming devmode
1893 * has a new one. JRA.
1896 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1897 SAFE_FREE(nt_devmode->private);
1898 nt_devmode->driverextra=devmode->driverextra;
1899 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1900 return False;
1901 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1904 *pp_nt_devmode = nt_devmode;
1906 return True;
1909 /********************************************************************
1910 * _spoolss_enddocprinter_internal.
1911 ********************************************************************/
1913 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1915 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1916 int snum;
1918 if (!Printer) {
1919 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1920 return WERR_BADFID;
1923 if (!get_printer_snum(p, handle, &snum))
1924 return WERR_BADFID;
1926 Printer->document_started=False;
1927 print_job_end(snum, Printer->jobid,True);
1928 /* error codes unhandled so far ... */
1930 return WERR_OK;
1933 /********************************************************************
1934 * api_spoolss_closeprinter
1935 ********************************************************************/
1937 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1939 POLICY_HND *handle = &q_u->handle;
1941 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1943 if (Printer && Printer->document_started)
1944 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1946 if (!close_printer_handle(p, handle))
1947 return WERR_BADFID;
1949 /* clear the returned printer handle. Observed behavior
1950 from Win2k server. Don't think this really matters.
1951 Previous code just copied the value of the closed
1952 handle. --jerry */
1954 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1956 return WERR_OK;
1959 /********************************************************************
1960 * api_spoolss_deleteprinter
1962 ********************************************************************/
1964 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1966 POLICY_HND *handle = &q_u->handle;
1967 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1968 WERROR result;
1970 if (Printer && Printer->document_started)
1971 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1973 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1975 result = delete_printer_handle(p, handle);
1977 update_c_setprinter(False);
1979 return result;
1982 /*******************************************************************
1983 * static function to lookup the version id corresponding to an
1984 * long architecture string
1985 ******************************************************************/
1987 static int get_version_id (char * arch)
1989 int i;
1990 struct table_node archi_table[]= {
1992 {"Windows 4.0", "WIN40", 0 },
1993 {"Windows NT x86", "W32X86", 2 },
1994 {"Windows NT R4000", "W32MIPS", 2 },
1995 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1996 {"Windows NT PowerPC", "W32PPC", 2 },
1997 {"Windows IA64", "IA64", 3 },
1998 {"Windows x64", "x64", 3 },
1999 {NULL, "", -1 }
2002 for (i=0; archi_table[i].long_archi != NULL; i++)
2004 if (strcmp(arch, archi_table[i].long_archi) == 0)
2005 return (archi_table[i].version);
2008 return -1;
2011 /********************************************************************
2012 * _spoolss_deleteprinterdriver
2013 ********************************************************************/
2015 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2017 fstring driver;
2018 fstring arch;
2019 NT_PRINTER_DRIVER_INFO_LEVEL info;
2020 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2021 int version;
2022 struct current_user user;
2023 WERROR status;
2024 WERROR status_win2k = WERR_ACCESS_DENIED;
2026 get_current_user(&user, p);
2028 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2029 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2031 /* check that we have a valid driver name first */
2033 if ((version=get_version_id(arch)) == -1)
2034 return WERR_INVALID_ENVIRONMENT;
2036 ZERO_STRUCT(info);
2037 ZERO_STRUCT(info_win2k);
2039 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2041 /* try for Win2k driver if "Windows NT x86" */
2043 if ( version == 2 ) {
2044 version = 3;
2045 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2046 status = WERR_UNKNOWN_PRINTER_DRIVER;
2047 goto done;
2050 /* otherwise it was a failure */
2051 else {
2052 status = WERR_UNKNOWN_PRINTER_DRIVER;
2053 goto done;
2058 if (printer_driver_in_use(info.info_3)) {
2059 status = WERR_PRINTER_DRIVER_IN_USE;
2060 goto done;
2063 if ( version == 2 )
2065 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2067 /* if we get to here, we now have 2 driver info structures to remove */
2068 /* remove the Win2k driver first*/
2070 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2071 free_a_printer_driver( info_win2k, 3 );
2073 /* this should not have failed---if it did, report to client */
2074 if ( !W_ERROR_IS_OK(status_win2k) )
2075 goto done;
2079 status = delete_printer_driver(info.info_3, &user, version, False);
2081 /* if at least one of the deletes succeeded return OK */
2083 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2084 status = WERR_OK;
2086 done:
2087 free_a_printer_driver( info, 3 );
2089 return status;
2092 /********************************************************************
2093 * spoolss_deleteprinterdriverex
2094 ********************************************************************/
2096 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2098 fstring driver;
2099 fstring arch;
2100 NT_PRINTER_DRIVER_INFO_LEVEL info;
2101 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2102 int version;
2103 uint32 flags = q_u->delete_flags;
2104 BOOL delete_files;
2105 struct current_user user;
2106 WERROR status;
2107 WERROR status_win2k = WERR_ACCESS_DENIED;
2109 get_current_user(&user, p);
2111 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2112 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2114 /* check that we have a valid driver name first */
2115 if ((version=get_version_id(arch)) == -1) {
2116 /* this is what NT returns */
2117 return WERR_INVALID_ENVIRONMENT;
2120 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2121 version = q_u->version;
2123 ZERO_STRUCT(info);
2124 ZERO_STRUCT(info_win2k);
2126 status = get_a_printer_driver(&info, 3, driver, arch, version);
2128 if ( !W_ERROR_IS_OK(status) )
2131 * if the client asked for a specific version,
2132 * or this is something other than Windows NT x86,
2133 * then we've failed
2136 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2137 goto done;
2139 /* try for Win2k driver if "Windows NT x86" */
2141 version = 3;
2142 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2143 status = WERR_UNKNOWN_PRINTER_DRIVER;
2144 goto done;
2148 if ( printer_driver_in_use(info.info_3) ) {
2149 status = WERR_PRINTER_DRIVER_IN_USE;
2150 goto done;
2154 * we have a couple of cases to consider.
2155 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2156 * then the delete should fail if **any** files overlap with
2157 * other drivers
2158 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2159 * non-overlapping files
2160 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2161 * is set, the do not delete any files
2162 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2165 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2167 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2169 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2170 /* no idea of the correct error here */
2171 status = WERR_ACCESS_DENIED;
2172 goto done;
2176 /* also check for W32X86/3 if necessary; maybe we already have? */
2178 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2179 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2182 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2183 /* no idea of the correct error here */
2184 free_a_printer_driver( info_win2k, 3 );
2185 status = WERR_ACCESS_DENIED;
2186 goto done;
2189 /* if we get to here, we now have 2 driver info structures to remove */
2190 /* remove the Win2k driver first*/
2192 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2193 free_a_printer_driver( info_win2k, 3 );
2195 /* this should not have failed---if it did, report to client */
2197 if ( !W_ERROR_IS_OK(status_win2k) )
2198 goto done;
2202 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2204 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2205 status = WERR_OK;
2206 done:
2207 free_a_printer_driver( info, 3 );
2209 return status;
2213 /****************************************************************************
2214 Internal routine for retreiving printerdata
2215 ***************************************************************************/
2217 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2218 const char *key, const char *value, uint32 *type, uint8 **data,
2219 uint32 *needed, uint32 in_size )
2221 REGISTRY_VALUE *val;
2222 int size, data_len;
2224 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2225 return WERR_BADFILE;
2227 *type = regval_type( val );
2229 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2231 size = regval_size( val );
2233 /* copy the min(in_size, len) */
2235 if ( in_size ) {
2236 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2238 /* special case for 0 length values */
2239 if ( data_len ) {
2240 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2241 return WERR_NOMEM;
2243 else {
2244 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2245 return WERR_NOMEM;
2248 else
2249 *data = NULL;
2251 *needed = size;
2253 DEBUG(5,("get_printer_dataex: copy done\n"));
2255 return WERR_OK;
2258 /****************************************************************************
2259 Internal routine for removing printerdata
2260 ***************************************************************************/
2262 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2264 return delete_printer_data( printer->info_2, key, value );
2267 /****************************************************************************
2268 Internal routine for storing printerdata
2269 ***************************************************************************/
2271 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2272 uint32 type, uint8 *data, int real_len )
2274 delete_printer_data( printer->info_2, key, value );
2276 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2279 /********************************************************************
2280 GetPrinterData on a printer server Handle.
2281 ********************************************************************/
2283 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2285 int i;
2287 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2289 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2290 *type = 0x4;
2291 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2292 return WERR_NOMEM;
2293 *needed = 0x4;
2294 return WERR_OK;
2297 if (!StrCaseCmp(value, "BeepEnabled")) {
2298 *type = 0x4;
2299 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2300 return WERR_NOMEM;
2301 SIVAL(*data, 0, 0x00);
2302 *needed = 0x4;
2303 return WERR_OK;
2306 if (!StrCaseCmp(value, "EventLog")) {
2307 *type = 0x4;
2308 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2309 return WERR_NOMEM;
2310 /* formally was 0x1b */
2311 SIVAL(*data, 0, 0x0);
2312 *needed = 0x4;
2313 return WERR_OK;
2316 if (!StrCaseCmp(value, "NetPopup")) {
2317 *type = 0x4;
2318 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2319 return WERR_NOMEM;
2320 SIVAL(*data, 0, 0x00);
2321 *needed = 0x4;
2322 return WERR_OK;
2325 if (!StrCaseCmp(value, "MajorVersion")) {
2326 *type = 0x4;
2327 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2328 return WERR_NOMEM;
2330 /* Windows NT 4.0 seems to not allow uploading of drivers
2331 to a server that reports 0x3 as the MajorVersion.
2332 need to investigate more how Win2k gets around this .
2333 -- jerry */
2335 if ( RA_WINNT == get_remote_arch() )
2336 SIVAL(*data, 0, 2);
2337 else
2338 SIVAL(*data, 0, 3);
2340 *needed = 0x4;
2341 return WERR_OK;
2344 if (!StrCaseCmp(value, "MinorVersion")) {
2345 *type = 0x4;
2346 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2347 return WERR_NOMEM;
2348 SIVAL(*data, 0, 0);
2349 *needed = 0x4;
2350 return WERR_OK;
2353 /* REG_BINARY
2354 * uint32 size = 0x114
2355 * uint32 major = 5
2356 * uint32 minor = [0|1]
2357 * uint32 build = [2195|2600]
2358 * extra unicode string = e.g. "Service Pack 3"
2360 if (!StrCaseCmp(value, "OSVersion")) {
2361 *type = 0x3;
2362 *needed = 0x114;
2364 if((*data = (uint8 *)talloc(ctx, (*needed)*sizeof(uint8) )) == NULL)
2365 return WERR_NOMEM;
2366 ZERO_STRUCTP( *data );
2368 SIVAL(*data, 0, *needed); /* size */
2369 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2370 SIVAL(*data, 8, 0);
2371 SIVAL(*data, 12, 2195); /* build */
2373 /* leave extra string empty */
2375 return WERR_OK;
2379 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2380 const char *string="C:\\PRINTERS";
2381 *type = 0x1;
2382 *needed = 2*(strlen(string)+1);
2383 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2384 return WERR_NOMEM;
2385 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2387 /* it's done by hand ready to go on the wire */
2388 for (i=0; i<strlen(string); i++) {
2389 (*data)[2*i]=string[i];
2390 (*data)[2*i+1]='\0';
2392 return WERR_OK;
2395 if (!StrCaseCmp(value, "Architecture")) {
2396 const char *string="Windows NT x86";
2397 *type = 0x1;
2398 *needed = 2*(strlen(string)+1);
2399 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2400 return WERR_NOMEM;
2401 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2402 for (i=0; i<strlen(string); i++) {
2403 (*data)[2*i]=string[i];
2404 (*data)[2*i+1]='\0';
2406 return WERR_OK;
2409 if (!StrCaseCmp(value, "DsPresent")) {
2410 *type = 0x4;
2411 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2412 return WERR_NOMEM;
2413 SIVAL(*data, 0, 0x01);
2414 *needed = 0x4;
2415 return WERR_OK;
2418 if (!StrCaseCmp(value, "DNSMachineName")) {
2419 pstring hostname;
2421 if (!get_mydnsfullname(hostname))
2422 return WERR_BADFILE;
2423 *type = 0x1;
2424 *needed = 2*(strlen(hostname)+1);
2425 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2426 return WERR_NOMEM;
2427 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2428 for (i=0; i<strlen(hostname); i++) {
2429 (*data)[2*i]=hostname[i];
2430 (*data)[2*i+1]='\0';
2432 return WERR_OK;
2436 return WERR_BADFILE;
2439 /********************************************************************
2440 * spoolss_getprinterdata
2441 ********************************************************************/
2443 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2445 POLICY_HND *handle = &q_u->handle;
2446 UNISTR2 *valuename = &q_u->valuename;
2447 uint32 in_size = q_u->size;
2448 uint32 *type = &r_u->type;
2449 uint32 *out_size = &r_u->size;
2450 uint8 **data = &r_u->data;
2451 uint32 *needed = &r_u->needed;
2452 WERROR status;
2453 fstring value;
2454 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2455 NT_PRINTER_INFO_LEVEL *printer = NULL;
2456 int snum = 0;
2459 * Reminder: when it's a string, the length is in BYTES
2460 * even if UNICODE is negociated.
2462 * JFM, 4/19/1999
2465 *out_size = in_size;
2467 /* in case of problem, return some default values */
2469 *needed = 0;
2470 *type = 0;
2472 DEBUG(4,("_spoolss_getprinterdata\n"));
2474 if ( !Printer ) {
2475 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2476 status = WERR_BADFID;
2477 goto done;
2480 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2482 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2483 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2484 else
2486 if ( !get_printer_snum(p,handle, &snum) ) {
2487 status = WERR_BADFID;
2488 goto done;
2491 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2492 if ( !W_ERROR_IS_OK(status) )
2493 goto done;
2495 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2497 if ( strequal(value, "ChangeId") ) {
2498 *type = REG_DWORD;
2499 *needed = sizeof(uint32);
2500 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2501 status = WERR_NOMEM;
2502 goto done;
2504 SIVAL( *data, 0, printer->info_2->changeid );
2505 status = WERR_OK;
2507 else
2508 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2511 if (*needed > *out_size)
2512 status = WERR_MORE_DATA;
2514 done:
2515 if ( !W_ERROR_IS_OK(status) )
2517 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2519 /* reply this param doesn't exist */
2521 if ( *out_size ) {
2522 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2523 if ( printer )
2524 free_a_printer( &printer, 2 );
2525 return WERR_NOMEM;
2528 else {
2529 *data = NULL;
2533 /* cleanup & exit */
2535 if ( printer )
2536 free_a_printer( &printer, 2 );
2538 return status;
2541 /*********************************************************
2542 Connect to the client machine.
2543 **********************************************************/
2545 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2546 struct in_addr *client_ip, const char *remote_machine)
2548 ZERO_STRUCTP(the_cli);
2550 if(cli_initialise(the_cli) == NULL) {
2551 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2552 return False;
2555 if ( is_zero_ip(*client_ip) ) {
2556 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2557 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2558 cli_shutdown(the_cli);
2559 return False;
2562 if (ismyip(the_cli->dest_ip)) {
2563 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2564 cli_shutdown(the_cli);
2565 return False;
2568 else {
2569 the_cli->dest_ip.s_addr = client_ip->s_addr;
2570 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2571 inet_ntoa(*client_ip) ));
2574 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2575 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) ));
2576 cli_shutdown(the_cli);
2577 return False;
2580 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2581 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2582 remote_machine));
2583 cli_shutdown(the_cli);
2584 return False;
2587 the_cli->protocol = PROTOCOL_NT1;
2588 cli_setup_signing_state(the_cli, lp_client_signing());
2590 if (!cli_negprot(the_cli)) {
2591 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2592 cli_shutdown(the_cli);
2593 return False;
2596 if (the_cli->protocol != PROTOCOL_NT1) {
2597 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2598 cli_shutdown(the_cli);
2599 return False;
2603 * Do an anonymous session setup.
2606 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2607 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2608 cli_shutdown(the_cli);
2609 return False;
2612 if (!(the_cli->sec_mode & 1)) {
2613 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2614 cli_shutdown(the_cli);
2615 return False;
2618 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2619 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) ));
2620 cli_shutdown(the_cli);
2621 return False;
2625 * Ok - we have an anonymous connection to the IPC$ share.
2626 * Now start the NT Domain stuff :-).
2629 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2630 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)));
2631 cli_nt_session_close(the_cli);
2632 cli_ulogoff(the_cli);
2633 cli_shutdown(the_cli);
2634 return False;
2637 return True;
2640 /***************************************************************************
2641 Connect to the client.
2642 ****************************************************************************/
2644 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2645 uint32 localprinter, uint32 type,
2646 POLICY_HND *handle, struct in_addr *client_ip)
2648 WERROR result;
2651 * If it's the first connection, contact the client
2652 * and connect to the IPC$ share anonymously
2654 if (smb_connections==0) {
2655 fstring unix_printer;
2657 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2659 ZERO_STRUCT(notify_cli);
2661 if(!spoolss_connect_to_client(&notify_cli, client_ip, unix_printer))
2662 return False;
2664 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2665 /* Tell the connections db we're now interested in printer
2666 * notify messages. */
2667 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2671 * Tell the specific printing tdb we want messages for this printer
2672 * by registering our PID.
2675 if (!print_notify_register_pid(snum))
2676 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2678 smb_connections++;
2680 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2681 type, handle);
2683 if (!W_ERROR_IS_OK(result))
2684 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2685 dos_errstr(result)));
2687 return (W_ERROR_IS_OK(result));
2690 /********************************************************************
2691 * _spoolss_rffpcnex
2692 * ReplyFindFirstPrinterChangeNotifyEx
2694 * before replying OK: status=0 a rpc call is made to the workstation
2695 * asking ReplyOpenPrinter
2697 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2698 * called from api_spoolss_rffpcnex
2699 ********************************************************************/
2701 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2703 POLICY_HND *handle = &q_u->handle;
2704 uint32 flags = q_u->flags;
2705 uint32 options = q_u->options;
2706 UNISTR2 *localmachine = &q_u->localmachine;
2707 uint32 printerlocal = q_u->printerlocal;
2708 int snum = -1;
2709 SPOOL_NOTIFY_OPTION *option = q_u->option;
2710 struct in_addr client_ip;
2712 /* store the notify value in the printer struct */
2714 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2716 if (!Printer) {
2717 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2718 return WERR_BADFID;
2721 Printer->notify.flags=flags;
2722 Printer->notify.options=options;
2723 Printer->notify.printerlocal=printerlocal;
2725 if (Printer->notify.option)
2726 free_spool_notify_option(&Printer->notify.option);
2728 Printer->notify.option=dup_spool_notify_option(option);
2730 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2731 sizeof(Printer->notify.localmachine)-1);
2733 /* Connect to the client machine and send a ReplyOpenPrinter */
2735 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2736 snum = -1;
2737 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2738 !get_printer_snum(p, handle, &snum) )
2739 return WERR_BADFID;
2741 client_ip.s_addr = inet_addr(p->conn->client_address);
2743 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2744 Printer->notify.printerlocal, 1,
2745 &Printer->notify.client_hnd, &client_ip))
2746 return WERR_SERVER_UNAVAILABLE;
2748 Printer->notify.client_connected=True;
2750 return WERR_OK;
2753 #if 0 /* JERRY -- disabled; not used for now */
2755 /*******************************************************************
2756 * fill a notify_info_data with the servername
2757 ********************************************************************/
2759 void spoolss_notify_server_name(int snum,
2760 SPOOL_NOTIFY_INFO_DATA *data,
2761 print_queue_struct *queue,
2762 NT_PRINTER_INFO_LEVEL *printer,
2763 TALLOC_CTX *mem_ctx)
2765 pstring temp_name, temp;
2766 uint32 len;
2768 fstrcpy( temp_name, "\\\\%L" );
2769 standard_sub_basic( "", temp_name, sizeof(temp_name)-1 );
2772 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2774 data->notify_data.data.length = len;
2775 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2777 if (!data->notify_data.data.string) {
2778 data->notify_data.data.length = 0;
2779 return;
2782 memcpy(data->notify_data.data.string, temp, len);
2785 #endif
2788 /*******************************************************************
2789 * fill a notify_info_data with the printername (not including the servername).
2790 ********************************************************************/
2792 void spoolss_notify_printer_name(int snum,
2793 SPOOL_NOTIFY_INFO_DATA *data,
2794 print_queue_struct *queue,
2795 NT_PRINTER_INFO_LEVEL *printer,
2796 TALLOC_CTX *mem_ctx)
2798 pstring temp;
2799 uint32 len;
2801 /* the notify name should not contain the \\server\ part */
2802 char *p = strrchr(printer->info_2->printername, '\\');
2804 if (!p) {
2805 p = printer->info_2->printername;
2806 } else {
2807 p++;
2810 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2812 data->notify_data.data.length = len;
2813 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2815 if (!data->notify_data.data.string) {
2816 data->notify_data.data.length = 0;
2817 return;
2820 memcpy(data->notify_data.data.string, temp, len);
2823 /*******************************************************************
2824 * fill a notify_info_data with the servicename
2825 ********************************************************************/
2827 void spoolss_notify_share_name(int snum,
2828 SPOOL_NOTIFY_INFO_DATA *data,
2829 print_queue_struct *queue,
2830 NT_PRINTER_INFO_LEVEL *printer,
2831 TALLOC_CTX *mem_ctx)
2833 pstring temp;
2834 uint32 len;
2836 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2838 data->notify_data.data.length = len;
2839 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2841 if (!data->notify_data.data.string) {
2842 data->notify_data.data.length = 0;
2843 return;
2846 memcpy(data->notify_data.data.string, temp, len);
2849 /*******************************************************************
2850 * fill a notify_info_data with the port name
2851 ********************************************************************/
2853 void spoolss_notify_port_name(int snum,
2854 SPOOL_NOTIFY_INFO_DATA *data,
2855 print_queue_struct *queue,
2856 NT_PRINTER_INFO_LEVEL *printer,
2857 TALLOC_CTX *mem_ctx)
2859 pstring temp;
2860 uint32 len;
2862 /* even if it's strange, that's consistant in all the code */
2864 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2866 data->notify_data.data.length = len;
2867 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2869 if (!data->notify_data.data.string) {
2870 data->notify_data.data.length = 0;
2871 return;
2874 memcpy(data->notify_data.data.string, temp, len);
2877 /*******************************************************************
2878 * fill a notify_info_data with the printername
2879 * but it doesn't exist, have to see what to do
2880 ********************************************************************/
2882 void spoolss_notify_driver_name(int snum,
2883 SPOOL_NOTIFY_INFO_DATA *data,
2884 print_queue_struct *queue,
2885 NT_PRINTER_INFO_LEVEL *printer,
2886 TALLOC_CTX *mem_ctx)
2888 pstring temp;
2889 uint32 len;
2891 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2893 data->notify_data.data.length = len;
2894 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2896 if (!data->notify_data.data.string) {
2897 data->notify_data.data.length = 0;
2898 return;
2901 memcpy(data->notify_data.data.string, temp, len);
2904 /*******************************************************************
2905 * fill a notify_info_data with the comment
2906 ********************************************************************/
2908 void spoolss_notify_comment(int snum,
2909 SPOOL_NOTIFY_INFO_DATA *data,
2910 print_queue_struct *queue,
2911 NT_PRINTER_INFO_LEVEL *printer,
2912 TALLOC_CTX *mem_ctx)
2914 pstring temp;
2915 uint32 len;
2917 if (*printer->info_2->comment == '\0')
2918 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2919 else
2920 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2922 data->notify_data.data.length = len;
2923 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2925 if (!data->notify_data.data.string) {
2926 data->notify_data.data.length = 0;
2927 return;
2930 memcpy(data->notify_data.data.string, temp, len);
2933 /*******************************************************************
2934 * fill a notify_info_data with the comment
2935 * location = "Room 1, floor 2, building 3"
2936 ********************************************************************/
2938 void spoolss_notify_location(int snum,
2939 SPOOL_NOTIFY_INFO_DATA *data,
2940 print_queue_struct *queue,
2941 NT_PRINTER_INFO_LEVEL *printer,
2942 TALLOC_CTX *mem_ctx)
2944 pstring temp;
2945 uint32 len;
2947 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2949 data->notify_data.data.length = len;
2950 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2952 if (!data->notify_data.data.string) {
2953 data->notify_data.data.length = 0;
2954 return;
2957 memcpy(data->notify_data.data.string, temp, len);
2960 /*******************************************************************
2961 * fill a notify_info_data with the device mode
2962 * jfm:xxxx don't to it for know but that's a real problem !!!
2963 ********************************************************************/
2965 static void spoolss_notify_devmode(int snum,
2966 SPOOL_NOTIFY_INFO_DATA *data,
2967 print_queue_struct *queue,
2968 NT_PRINTER_INFO_LEVEL *printer,
2969 TALLOC_CTX *mem_ctx)
2973 /*******************************************************************
2974 * fill a notify_info_data with the separator file name
2975 ********************************************************************/
2977 void spoolss_notify_sepfile(int snum,
2978 SPOOL_NOTIFY_INFO_DATA *data,
2979 print_queue_struct *queue,
2980 NT_PRINTER_INFO_LEVEL *printer,
2981 TALLOC_CTX *mem_ctx)
2983 pstring temp;
2984 uint32 len;
2986 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2988 data->notify_data.data.length = len;
2989 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2991 if (!data->notify_data.data.string) {
2992 data->notify_data.data.length = 0;
2993 return;
2996 memcpy(data->notify_data.data.string, temp, len);
2999 /*******************************************************************
3000 * fill a notify_info_data with the print processor
3001 * jfm:xxxx return always winprint to indicate we don't do anything to it
3002 ********************************************************************/
3004 void spoolss_notify_print_processor(int snum,
3005 SPOOL_NOTIFY_INFO_DATA *data,
3006 print_queue_struct *queue,
3007 NT_PRINTER_INFO_LEVEL *printer,
3008 TALLOC_CTX *mem_ctx)
3010 pstring temp;
3011 uint32 len;
3013 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3015 data->notify_data.data.length = len;
3016 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3018 if (!data->notify_data.data.string) {
3019 data->notify_data.data.length = 0;
3020 return;
3023 memcpy(data->notify_data.data.string, temp, len);
3026 /*******************************************************************
3027 * fill a notify_info_data with the print processor options
3028 * jfm:xxxx send an empty string
3029 ********************************************************************/
3031 void spoolss_notify_parameters(int snum,
3032 SPOOL_NOTIFY_INFO_DATA *data,
3033 print_queue_struct *queue,
3034 NT_PRINTER_INFO_LEVEL *printer,
3035 TALLOC_CTX *mem_ctx)
3037 pstring temp;
3038 uint32 len;
3040 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3042 data->notify_data.data.length = len;
3043 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3045 if (!data->notify_data.data.string) {
3046 data->notify_data.data.length = 0;
3047 return;
3050 memcpy(data->notify_data.data.string, temp, len);
3053 /*******************************************************************
3054 * fill a notify_info_data with the data type
3055 * jfm:xxxx always send RAW as data type
3056 ********************************************************************/
3058 void spoolss_notify_datatype(int snum,
3059 SPOOL_NOTIFY_INFO_DATA *data,
3060 print_queue_struct *queue,
3061 NT_PRINTER_INFO_LEVEL *printer,
3062 TALLOC_CTX *mem_ctx)
3064 pstring temp;
3065 uint32 len;
3067 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3069 data->notify_data.data.length = len;
3070 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3072 if (!data->notify_data.data.string) {
3073 data->notify_data.data.length = 0;
3074 return;
3077 memcpy(data->notify_data.data.string, temp, len);
3080 /*******************************************************************
3081 * fill a notify_info_data with the security descriptor
3082 * jfm:xxxx send an null pointer to say no security desc
3083 * have to implement security before !
3084 ********************************************************************/
3086 static void spoolss_notify_security_desc(int snum,
3087 SPOOL_NOTIFY_INFO_DATA *data,
3088 print_queue_struct *queue,
3089 NT_PRINTER_INFO_LEVEL *printer,
3090 TALLOC_CTX *mem_ctx)
3092 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3093 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3096 /*******************************************************************
3097 * fill a notify_info_data with the attributes
3098 * jfm:xxxx a samba printer is always shared
3099 ********************************************************************/
3101 void spoolss_notify_attributes(int snum,
3102 SPOOL_NOTIFY_INFO_DATA *data,
3103 print_queue_struct *queue,
3104 NT_PRINTER_INFO_LEVEL *printer,
3105 TALLOC_CTX *mem_ctx)
3107 data->notify_data.value[0] = printer->info_2->attributes;
3108 data->notify_data.value[1] = 0;
3111 /*******************************************************************
3112 * fill a notify_info_data with the priority
3113 ********************************************************************/
3115 static void spoolss_notify_priority(int snum,
3116 SPOOL_NOTIFY_INFO_DATA *data,
3117 print_queue_struct *queue,
3118 NT_PRINTER_INFO_LEVEL *printer,
3119 TALLOC_CTX *mem_ctx)
3121 data->notify_data.value[0] = printer->info_2->priority;
3122 data->notify_data.value[1] = 0;
3125 /*******************************************************************
3126 * fill a notify_info_data with the default priority
3127 ********************************************************************/
3129 static void spoolss_notify_default_priority(int snum,
3130 SPOOL_NOTIFY_INFO_DATA *data,
3131 print_queue_struct *queue,
3132 NT_PRINTER_INFO_LEVEL *printer,
3133 TALLOC_CTX *mem_ctx)
3135 data->notify_data.value[0] = printer->info_2->default_priority;
3136 data->notify_data.value[1] = 0;
3139 /*******************************************************************
3140 * fill a notify_info_data with the start time
3141 ********************************************************************/
3143 static void spoolss_notify_start_time(int snum,
3144 SPOOL_NOTIFY_INFO_DATA *data,
3145 print_queue_struct *queue,
3146 NT_PRINTER_INFO_LEVEL *printer,
3147 TALLOC_CTX *mem_ctx)
3149 data->notify_data.value[0] = printer->info_2->starttime;
3150 data->notify_data.value[1] = 0;
3153 /*******************************************************************
3154 * fill a notify_info_data with the until time
3155 ********************************************************************/
3157 static void spoolss_notify_until_time(int snum,
3158 SPOOL_NOTIFY_INFO_DATA *data,
3159 print_queue_struct *queue,
3160 NT_PRINTER_INFO_LEVEL *printer,
3161 TALLOC_CTX *mem_ctx)
3163 data->notify_data.value[0] = printer->info_2->untiltime;
3164 data->notify_data.value[1] = 0;
3167 /*******************************************************************
3168 * fill a notify_info_data with the status
3169 ********************************************************************/
3171 static void spoolss_notify_status(int snum,
3172 SPOOL_NOTIFY_INFO_DATA *data,
3173 print_queue_struct *queue,
3174 NT_PRINTER_INFO_LEVEL *printer,
3175 TALLOC_CTX *mem_ctx)
3177 print_status_struct status;
3179 print_queue_length(snum, &status);
3180 data->notify_data.value[0]=(uint32) status.status;
3181 data->notify_data.value[1] = 0;
3184 /*******************************************************************
3185 * fill a notify_info_data with the number of jobs queued
3186 ********************************************************************/
3188 void spoolss_notify_cjobs(int snum,
3189 SPOOL_NOTIFY_INFO_DATA *data,
3190 print_queue_struct *queue,
3191 NT_PRINTER_INFO_LEVEL *printer,
3192 TALLOC_CTX *mem_ctx)
3194 data->notify_data.value[0] = print_queue_length(snum, NULL);
3195 data->notify_data.value[1] = 0;
3198 /*******************************************************************
3199 * fill a notify_info_data with the average ppm
3200 ********************************************************************/
3202 static void spoolss_notify_average_ppm(int snum,
3203 SPOOL_NOTIFY_INFO_DATA *data,
3204 print_queue_struct *queue,
3205 NT_PRINTER_INFO_LEVEL *printer,
3206 TALLOC_CTX *mem_ctx)
3208 /* always respond 8 pages per minutes */
3209 /* a little hard ! */
3210 data->notify_data.value[0] = printer->info_2->averageppm;
3211 data->notify_data.value[1] = 0;
3214 /*******************************************************************
3215 * fill a notify_info_data with username
3216 ********************************************************************/
3218 static void spoolss_notify_username(int snum,
3219 SPOOL_NOTIFY_INFO_DATA *data,
3220 print_queue_struct *queue,
3221 NT_PRINTER_INFO_LEVEL *printer,
3222 TALLOC_CTX *mem_ctx)
3224 pstring temp;
3225 uint32 len;
3227 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3229 data->notify_data.data.length = len;
3230 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3232 if (!data->notify_data.data.string) {
3233 data->notify_data.data.length = 0;
3234 return;
3237 memcpy(data->notify_data.data.string, temp, len);
3240 /*******************************************************************
3241 * fill a notify_info_data with job status
3242 ********************************************************************/
3244 static void spoolss_notify_job_status(int snum,
3245 SPOOL_NOTIFY_INFO_DATA *data,
3246 print_queue_struct *queue,
3247 NT_PRINTER_INFO_LEVEL *printer,
3248 TALLOC_CTX *mem_ctx)
3250 data->notify_data.value[0]=nt_printj_status(queue->status);
3251 data->notify_data.value[1] = 0;
3254 /*******************************************************************
3255 * fill a notify_info_data with job name
3256 ********************************************************************/
3258 static void spoolss_notify_job_name(int snum,
3259 SPOOL_NOTIFY_INFO_DATA *data,
3260 print_queue_struct *queue,
3261 NT_PRINTER_INFO_LEVEL *printer,
3262 TALLOC_CTX *mem_ctx)
3264 pstring temp;
3265 uint32 len;
3267 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3269 data->notify_data.data.length = len;
3270 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3272 if (!data->notify_data.data.string) {
3273 data->notify_data.data.length = 0;
3274 return;
3277 memcpy(data->notify_data.data.string, temp, len);
3280 /*******************************************************************
3281 * fill a notify_info_data with job status
3282 ********************************************************************/
3284 static void spoolss_notify_job_status_string(int snum,
3285 SPOOL_NOTIFY_INFO_DATA *data,
3286 print_queue_struct *queue,
3287 NT_PRINTER_INFO_LEVEL *printer,
3288 TALLOC_CTX *mem_ctx)
3291 * Now we're returning job status codes we just return a "" here. JRA.
3294 const char *p = "";
3295 pstring temp;
3296 uint32 len;
3298 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3299 p = "unknown";
3301 switch (queue->status) {
3302 case LPQ_QUEUED:
3303 p = "Queued";
3304 break;
3305 case LPQ_PAUSED:
3306 p = ""; /* NT provides the paused string */
3307 break;
3308 case LPQ_SPOOLING:
3309 p = "Spooling";
3310 break;
3311 case LPQ_PRINTING:
3312 p = "Printing";
3313 break;
3315 #endif /* NO LONGER NEEDED. */
3317 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3319 data->notify_data.data.length = len;
3320 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3322 if (!data->notify_data.data.string) {
3323 data->notify_data.data.length = 0;
3324 return;
3327 memcpy(data->notify_data.data.string, temp, len);
3330 /*******************************************************************
3331 * fill a notify_info_data with job time
3332 ********************************************************************/
3334 static void spoolss_notify_job_time(int snum,
3335 SPOOL_NOTIFY_INFO_DATA *data,
3336 print_queue_struct *queue,
3337 NT_PRINTER_INFO_LEVEL *printer,
3338 TALLOC_CTX *mem_ctx)
3340 data->notify_data.value[0]=0x0;
3341 data->notify_data.value[1]=0;
3344 /*******************************************************************
3345 * fill a notify_info_data with job size
3346 ********************************************************************/
3348 static void spoolss_notify_job_size(int snum,
3349 SPOOL_NOTIFY_INFO_DATA *data,
3350 print_queue_struct *queue,
3351 NT_PRINTER_INFO_LEVEL *printer,
3352 TALLOC_CTX *mem_ctx)
3354 data->notify_data.value[0]=queue->size;
3355 data->notify_data.value[1]=0;
3358 /*******************************************************************
3359 * fill a notify_info_data with page info
3360 ********************************************************************/
3361 static void spoolss_notify_total_pages(int snum,
3362 SPOOL_NOTIFY_INFO_DATA *data,
3363 print_queue_struct *queue,
3364 NT_PRINTER_INFO_LEVEL *printer,
3365 TALLOC_CTX *mem_ctx)
3367 data->notify_data.value[0]=queue->page_count;
3368 data->notify_data.value[1]=0;
3371 /*******************************************************************
3372 * fill a notify_info_data with pages printed info.
3373 ********************************************************************/
3374 static void spoolss_notify_pages_printed(int snum,
3375 SPOOL_NOTIFY_INFO_DATA *data,
3376 print_queue_struct *queue,
3377 NT_PRINTER_INFO_LEVEL *printer,
3378 TALLOC_CTX *mem_ctx)
3380 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3381 data->notify_data.value[1]=0;
3384 /*******************************************************************
3385 Fill a notify_info_data with job position.
3386 ********************************************************************/
3388 static void spoolss_notify_job_position(int snum,
3389 SPOOL_NOTIFY_INFO_DATA *data,
3390 print_queue_struct *queue,
3391 NT_PRINTER_INFO_LEVEL *printer,
3392 TALLOC_CTX *mem_ctx)
3394 data->notify_data.value[0]=queue->job;
3395 data->notify_data.value[1]=0;
3398 /*******************************************************************
3399 Fill a notify_info_data with submitted time.
3400 ********************************************************************/
3402 static void spoolss_notify_submitted_time(int snum,
3403 SPOOL_NOTIFY_INFO_DATA *data,
3404 print_queue_struct *queue,
3405 NT_PRINTER_INFO_LEVEL *printer,
3406 TALLOC_CTX *mem_ctx)
3408 struct tm *t;
3409 uint32 len;
3410 SYSTEMTIME st;
3411 char *p;
3413 t=gmtime(&queue->time);
3415 len = sizeof(SYSTEMTIME);
3417 data->notify_data.data.length = len;
3418 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3420 if (!data->notify_data.data.string) {
3421 data->notify_data.data.length = 0;
3422 return;
3425 make_systemtime(&st, t);
3428 * Systemtime must be linearized as a set of UINT16's.
3429 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3432 p = (char *)data->notify_data.data.string;
3433 SSVAL(p, 0, st.year);
3434 SSVAL(p, 2, st.month);
3435 SSVAL(p, 4, st.dayofweek);
3436 SSVAL(p, 6, st.day);
3437 SSVAL(p, 8, st.hour);
3438 SSVAL(p, 10, st.minute);
3439 SSVAL(p, 12, st.second);
3440 SSVAL(p, 14, st.milliseconds);
3443 struct s_notify_info_data_table
3445 uint16 type;
3446 uint16 field;
3447 const char *name;
3448 uint32 size;
3449 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3450 print_queue_struct *queue,
3451 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3454 /* A table describing the various print notification constants and
3455 whether the notification data is a pointer to a variable sized
3456 buffer, a one value uint32 or a two value uint32. */
3458 static const struct s_notify_info_data_table notify_info_data_table[] =
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, NULL},
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3485 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, NULL},
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3508 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3509 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3512 /*******************************************************************
3513 Return the size of info_data structure.
3514 ********************************************************************/
3516 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3518 int i=0;
3520 for (i = 0; i < sizeof(notify_info_data_table); i++)
3522 if ( (notify_info_data_table[i].type == type)
3523 && (notify_info_data_table[i].field == field) )
3525 switch(notify_info_data_table[i].size)
3527 case NOTIFY_ONE_VALUE:
3528 case NOTIFY_TWO_VALUE:
3529 return 1;
3530 case NOTIFY_STRING:
3531 return 2;
3533 /* The only pointer notify data I have seen on
3534 the wire is the submitted time and this has
3535 the notify size set to 4. -tpot */
3537 case NOTIFY_POINTER:
3538 return 4;
3540 case NOTIFY_SECDESC:
3541 return 5;
3546 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3548 return 0;
3551 /*******************************************************************
3552 Return the type of notify_info_data.
3553 ********************************************************************/
3555 static int type_of_notify_info_data(uint16 type, uint16 field)
3557 int i=0;
3559 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3560 if (notify_info_data_table[i].type == type &&
3561 notify_info_data_table[i].field == field)
3562 return notify_info_data_table[i].size;
3565 return False;
3568 /****************************************************************************
3569 ****************************************************************************/
3571 static int search_notify(uint16 type, uint16 field, int *value)
3573 int i;
3575 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3576 if (notify_info_data_table[i].type == type &&
3577 notify_info_data_table[i].field == field &&
3578 notify_info_data_table[i].fn != NULL) {
3579 *value = i;
3580 return True;
3584 return False;
3587 /****************************************************************************
3588 ****************************************************************************/
3590 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3592 info_data->type = type;
3593 info_data->field = field;
3594 info_data->reserved = 0;
3596 info_data->size = size_of_notify_info_data(type, field);
3597 info_data->enc_type = type_of_notify_info_data(type, field);
3599 info_data->id = id;
3604 /*******************************************************************
3606 * fill a notify_info struct with info asked
3608 ********************************************************************/
3610 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3611 snum, SPOOL_NOTIFY_OPTION_TYPE
3612 *option_type, uint32 id,
3613 TALLOC_CTX *mem_ctx)
3615 int field_num,j;
3616 uint16 type;
3617 uint16 field;
3619 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3620 NT_PRINTER_INFO_LEVEL *printer = NULL;
3621 print_queue_struct *queue=NULL;
3623 type=option_type->type;
3625 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3626 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3627 option_type->count, lp_servicename(snum)));
3629 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3630 return False;
3632 for(field_num=0; field_num<option_type->count; field_num++) {
3633 field = option_type->fields[field_num];
3635 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3637 if (!search_notify(type, field, &j) )
3638 continue;
3640 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3641 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3642 return False;
3643 } else
3644 info->data = tid;
3646 current_data = &info->data[info->count];
3648 construct_info_data(current_data, type, field, id);
3650 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3651 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3653 notify_info_data_table[j].fn(snum, current_data, queue,
3654 printer, mem_ctx);
3656 info->count++;
3659 free_a_printer(&printer, 2);
3660 return True;
3663 /*******************************************************************
3665 * fill a notify_info struct with info asked
3667 ********************************************************************/
3669 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3670 SPOOL_NOTIFY_INFO *info,
3671 NT_PRINTER_INFO_LEVEL *printer,
3672 int snum, SPOOL_NOTIFY_OPTION_TYPE
3673 *option_type, uint32 id,
3674 TALLOC_CTX *mem_ctx)
3676 int field_num,j;
3677 uint16 type;
3678 uint16 field;
3680 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3682 DEBUG(4,("construct_notify_jobs_info\n"));
3684 type = option_type->type;
3686 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3687 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3688 option_type->count));
3690 for(field_num=0; field_num<option_type->count; field_num++) {
3691 field = option_type->fields[field_num];
3693 if (!search_notify(type, field, &j) )
3694 continue;
3696 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3697 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3698 return False;
3700 else info->data = tid;
3702 current_data=&(info->data[info->count]);
3704 construct_info_data(current_data, type, field, id);
3705 notify_info_data_table[j].fn(snum, current_data, queue,
3706 printer, mem_ctx);
3707 info->count++;
3710 return True;
3714 * JFM: The enumeration is not that simple, it's even non obvious.
3716 * let's take an example: I want to monitor the PRINTER SERVER for
3717 * the printer's name and the number of jobs currently queued.
3718 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3719 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3721 * I have 3 printers on the back of my server.
3723 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3724 * structures.
3725 * Number Data Id
3726 * 1 printer 1 name 1
3727 * 2 printer 1 cjob 1
3728 * 3 printer 2 name 2
3729 * 4 printer 2 cjob 2
3730 * 5 printer 3 name 3
3731 * 6 printer 3 name 3
3733 * that's the print server case, the printer case is even worse.
3736 /*******************************************************************
3738 * enumerate all printers on the printserver
3739 * fill a notify_info struct with info asked
3741 ********************************************************************/
3743 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3744 SPOOL_NOTIFY_INFO *info,
3745 TALLOC_CTX *mem_ctx)
3747 int snum;
3748 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3749 int n_services=lp_numservices();
3750 int i;
3751 SPOOL_NOTIFY_OPTION *option;
3752 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3754 DEBUG(4,("printserver_notify_info\n"));
3756 if (!Printer)
3757 return WERR_BADFID;
3759 option=Printer->notify.option;
3760 info->version=2;
3761 info->data=NULL;
3762 info->count=0;
3764 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3765 sending a ffpcn() request first */
3767 if ( !option )
3768 return WERR_BADFID;
3770 for (i=0; i<option->count; i++) {
3771 option_type=&(option->ctr.type[i]);
3773 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3774 continue;
3776 for (snum=0; snum<n_services; snum++)
3778 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3779 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3783 #if 0
3785 * Debugging information, don't delete.
3788 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3789 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3790 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3792 for (i=0; i<info->count; i++) {
3793 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3794 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3795 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3797 #endif
3799 return WERR_OK;
3802 /*******************************************************************
3804 * fill a notify_info struct with info asked
3806 ********************************************************************/
3808 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3809 TALLOC_CTX *mem_ctx)
3811 int snum;
3812 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3813 int i;
3814 uint32 id;
3815 SPOOL_NOTIFY_OPTION *option;
3816 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3817 int count,j;
3818 print_queue_struct *queue=NULL;
3819 print_status_struct status;
3821 DEBUG(4,("printer_notify_info\n"));
3823 if (!Printer)
3824 return WERR_BADFID;
3826 option=Printer->notify.option;
3827 id = 0x0;
3828 info->version=2;
3829 info->data=NULL;
3830 info->count=0;
3832 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3833 sending a ffpcn() request first */
3835 if ( !option )
3836 return WERR_BADFID;
3838 get_printer_snum(p, hnd, &snum);
3840 for (i=0; i<option->count; i++) {
3841 option_type=&option->ctr.type[i];
3843 switch ( option_type->type ) {
3844 case PRINTER_NOTIFY_TYPE:
3845 if(construct_notify_printer_info(Printer, info, snum,
3846 option_type, id,
3847 mem_ctx))
3848 id--;
3849 break;
3851 case JOB_NOTIFY_TYPE: {
3852 NT_PRINTER_INFO_LEVEL *printer = NULL;
3854 count = print_queue_status(snum, &queue, &status);
3856 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3857 goto done;
3859 for (j=0; j<count; j++) {
3860 construct_notify_jobs_info(&queue[j], info,
3861 printer, snum,
3862 option_type,
3863 queue[j].job,
3864 mem_ctx);
3867 free_a_printer(&printer, 2);
3869 done:
3870 SAFE_FREE(queue);
3871 break;
3877 * Debugging information, don't delete.
3880 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3881 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3882 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3884 for (i=0; i<info->count; i++) {
3885 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3886 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3887 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3890 return WERR_OK;
3893 /********************************************************************
3894 * spoolss_rfnpcnex
3895 ********************************************************************/
3897 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3899 POLICY_HND *handle = &q_u->handle;
3900 SPOOL_NOTIFY_INFO *info = &r_u->info;
3902 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3903 WERROR result = WERR_BADFID;
3905 /* we always have a NOTIFY_INFO struct */
3906 r_u->info_ptr=0x1;
3908 if (!Printer) {
3909 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3910 OUR_HANDLE(handle)));
3911 goto done;
3914 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3917 * We are now using the change value, and
3918 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3919 * I don't have a global notification system, I'm sending back all the
3920 * informations even when _NOTHING_ has changed.
3923 /* We need to keep track of the change value to send back in
3924 RRPCN replies otherwise our updates are ignored. */
3926 Printer->notify.fnpcn = True;
3928 if (Printer->notify.client_connected) {
3929 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3930 Printer->notify.change = q_u->change;
3933 /* just ignore the SPOOL_NOTIFY_OPTION */
3935 switch (Printer->printer_type) {
3936 case PRINTER_HANDLE_IS_PRINTSERVER:
3937 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3938 break;
3940 case PRINTER_HANDLE_IS_PRINTER:
3941 result = printer_notify_info(p, handle, info, p->mem_ctx);
3942 break;
3945 Printer->notify.fnpcn = False;
3947 done:
3948 return result;
3951 /********************************************************************
3952 * construct_printer_info_0
3953 * fill a printer_info_0 struct
3954 ********************************************************************/
3956 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3958 pstring chaine;
3959 int count;
3960 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3961 counter_printer_0 *session_counter;
3962 uint32 global_counter;
3963 struct tm *t;
3964 time_t setuptime;
3965 print_status_struct status;
3967 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3968 return False;
3970 count = print_queue_length(snum, &status);
3972 /* check if we already have a counter for this printer */
3973 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3974 if (session_counter->snum == snum)
3975 break;
3978 /* it's the first time, add it to the list */
3979 if (session_counter==NULL) {
3980 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3981 free_a_printer(&ntprinter, 2);
3982 return False;
3984 ZERO_STRUCTP(session_counter);
3985 session_counter->snum=snum;
3986 session_counter->counter=0;
3987 DLIST_ADD(counter_list, session_counter);
3990 /* increment it */
3991 session_counter->counter++;
3993 /* JFM:
3994 * the global_counter should be stored in a TDB as it's common to all the clients
3995 * and should be zeroed on samba startup
3997 global_counter=session_counter->counter;
3999 pstrcpy(chaine,ntprinter->info_2->printername);
4001 init_unistr(&printer->printername, chaine);
4003 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
4004 init_unistr(&printer->servername, chaine);
4006 printer->cjobs = count;
4007 printer->total_jobs = 0;
4008 printer->total_bytes = 0;
4010 setuptime = (time_t)ntprinter->info_2->setuptime;
4011 t=gmtime(&setuptime);
4013 printer->year = t->tm_year+1900;
4014 printer->month = t->tm_mon+1;
4015 printer->dayofweek = t->tm_wday;
4016 printer->day = t->tm_mday;
4017 printer->hour = t->tm_hour;
4018 printer->minute = t->tm_min;
4019 printer->second = t->tm_sec;
4020 printer->milliseconds = 0;
4022 printer->global_counter = global_counter;
4023 printer->total_pages = 0;
4025 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4026 printer->major_version = 0x0005; /* NT 5 */
4027 printer->build_version = 0x0893; /* build 2195 */
4029 printer->unknown7 = 0x1;
4030 printer->unknown8 = 0x0;
4031 printer->unknown9 = 0x0;
4032 printer->session_counter = session_counter->counter;
4033 printer->unknown11 = 0x0;
4034 printer->printer_errors = 0x0; /* number of print failure */
4035 printer->unknown13 = 0x0;
4036 printer->unknown14 = 0x1;
4037 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4038 printer->unknown16 = 0x0;
4039 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4040 printer->unknown18 = 0x0;
4041 printer->status = nt_printq_status(status.status);
4042 printer->unknown20 = 0x0;
4043 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4044 printer->unknown22 = 0x0;
4045 printer->unknown23 = 0x6; /* 6 ???*/
4046 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4047 printer->unknown25 = 0;
4048 printer->unknown26 = 0;
4049 printer->unknown27 = 0;
4050 printer->unknown28 = 0;
4051 printer->unknown29 = 0;
4053 free_a_printer(&ntprinter,2);
4054 return (True);
4057 /********************************************************************
4058 * construct_printer_info_1
4059 * fill a printer_info_1 struct
4060 ********************************************************************/
4061 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4063 pstring chaine;
4064 pstring chaine2;
4065 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4067 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4068 return False;
4070 printer->flags=flags;
4072 if (*ntprinter->info_2->comment == '\0') {
4073 init_unistr(&printer->comment, lp_comment(snum));
4074 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4075 ntprinter->info_2->drivername, lp_comment(snum));
4077 else {
4078 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4079 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4080 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4083 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4085 init_unistr(&printer->description, chaine);
4086 init_unistr(&printer->name, chaine2);
4088 free_a_printer(&ntprinter,2);
4090 return True;
4093 /****************************************************************************
4094 Free a DEVMODE struct.
4095 ****************************************************************************/
4097 static void free_dev_mode(DEVICEMODE *dev)
4099 if (dev == NULL)
4100 return;
4102 SAFE_FREE(dev->private);
4103 SAFE_FREE(dev);
4107 /****************************************************************************
4108 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4109 should be valid upon entry
4110 ****************************************************************************/
4112 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4114 if ( !devmode || !ntdevmode )
4115 return False;
4117 init_unistr(&devmode->devicename, ntdevmode->devicename);
4119 init_unistr(&devmode->formname, ntdevmode->formname);
4121 devmode->specversion = ntdevmode->specversion;
4122 devmode->driverversion = ntdevmode->driverversion;
4123 devmode->size = ntdevmode->size;
4124 devmode->driverextra = ntdevmode->driverextra;
4125 devmode->fields = ntdevmode->fields;
4127 devmode->orientation = ntdevmode->orientation;
4128 devmode->papersize = ntdevmode->papersize;
4129 devmode->paperlength = ntdevmode->paperlength;
4130 devmode->paperwidth = ntdevmode->paperwidth;
4131 devmode->scale = ntdevmode->scale;
4132 devmode->copies = ntdevmode->copies;
4133 devmode->defaultsource = ntdevmode->defaultsource;
4134 devmode->printquality = ntdevmode->printquality;
4135 devmode->color = ntdevmode->color;
4136 devmode->duplex = ntdevmode->duplex;
4137 devmode->yresolution = ntdevmode->yresolution;
4138 devmode->ttoption = ntdevmode->ttoption;
4139 devmode->collate = ntdevmode->collate;
4140 devmode->icmmethod = ntdevmode->icmmethod;
4141 devmode->icmintent = ntdevmode->icmintent;
4142 devmode->mediatype = ntdevmode->mediatype;
4143 devmode->dithertype = ntdevmode->dithertype;
4145 if (ntdevmode->private != NULL) {
4146 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4147 return False;
4150 return True;
4153 /****************************************************************************
4154 Create a DEVMODE struct. Returns malloced memory.
4155 ****************************************************************************/
4157 DEVICEMODE *construct_dev_mode(int snum)
4159 NT_PRINTER_INFO_LEVEL *printer = NULL;
4160 DEVICEMODE *devmode = NULL;
4162 DEBUG(7,("construct_dev_mode\n"));
4164 DEBUGADD(8,("getting printer characteristics\n"));
4166 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4167 return NULL;
4169 if ( !printer->info_2->devmode ) {
4170 DEBUG(5, ("BONG! There was no device mode!\n"));
4171 goto done;
4174 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4175 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4176 goto done;
4179 ZERO_STRUCTP(devmode);
4181 DEBUGADD(8,("loading DEVICEMODE\n"));
4183 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4184 free_dev_mode( devmode );
4185 devmode = NULL;
4188 done:
4189 free_a_printer(&printer,2);
4191 return devmode;
4194 /********************************************************************
4195 * construct_printer_info_2
4196 * fill a printer_info_2 struct
4197 ********************************************************************/
4199 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4201 int count;
4202 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4204 print_status_struct status;
4206 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4207 return False;
4209 count = print_queue_length(snum, &status);
4211 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4212 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4213 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4214 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4215 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4217 if (*ntprinter->info_2->comment == '\0')
4218 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4219 else
4220 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4222 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4223 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4224 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4225 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4226 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4228 printer->attributes = ntprinter->info_2->attributes;
4230 printer->priority = ntprinter->info_2->priority; /* priority */
4231 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4232 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4233 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4234 printer->status = nt_printq_status(status.status); /* status */
4235 printer->cjobs = count; /* jobs */
4236 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4238 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4239 DEBUG(8, ("Returning NULL Devicemode!\n"));
4242 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4243 /* steal the printer info sec_desc structure. [badly done]. */
4244 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4245 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4246 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4247 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4249 else {
4250 printer->secdesc = NULL;
4253 free_a_printer(&ntprinter, 2);
4254 return True;
4257 /********************************************************************
4258 * construct_printer_info_3
4259 * fill a printer_info_3 struct
4260 ********************************************************************/
4262 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4264 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4265 PRINTER_INFO_3 *printer = NULL;
4267 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4268 return False;
4270 *pp_printer = NULL;
4271 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4272 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4273 return False;
4276 ZERO_STRUCTP(printer);
4278 printer->flags = 4; /* These are the components of the SD we are returning. */
4279 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4280 /* steal the printer info sec_desc structure. [badly done]. */
4281 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4283 #if 0
4285 * Set the flags for the components we are returning.
4288 if (printer->secdesc->owner_sid)
4289 printer->flags |= OWNER_SECURITY_INFORMATION;
4291 if (printer->secdesc->grp_sid)
4292 printer->flags |= GROUP_SECURITY_INFORMATION;
4294 if (printer->secdesc->dacl)
4295 printer->flags |= DACL_SECURITY_INFORMATION;
4297 if (printer->secdesc->sacl)
4298 printer->flags |= SACL_SECURITY_INFORMATION;
4299 #endif
4301 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4302 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4303 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4306 free_a_printer(&ntprinter, 2);
4308 *pp_printer = printer;
4309 return True;
4312 /********************************************************************
4313 * construct_printer_info_4
4314 * fill a printer_info_4 struct
4315 ********************************************************************/
4317 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4319 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4321 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4322 return False;
4324 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4325 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4326 printer->attributes = ntprinter->info_2->attributes;
4328 free_a_printer(&ntprinter, 2);
4329 return True;
4332 /********************************************************************
4333 * construct_printer_info_5
4334 * fill a printer_info_5 struct
4335 ********************************************************************/
4337 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4339 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4341 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4342 return False;
4344 init_unistr(&printer->printername, ntprinter->info_2->printername);
4345 init_unistr(&printer->portname, ntprinter->info_2->portname);
4346 printer->attributes = ntprinter->info_2->attributes;
4348 /* these two are not used by NT+ according to MSDN */
4350 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4351 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4353 free_a_printer(&ntprinter, 2);
4355 return True;
4358 /********************************************************************
4359 * construct_printer_info_7
4360 * fill a printer_info_7 struct
4361 ********************************************************************/
4363 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4365 char *guid_str = NULL;
4366 struct uuid guid;
4368 if (is_printer_published(print_hnd, snum, &guid)) {
4369 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4370 strupper_m(guid_str);
4371 init_unistr(&printer->guid, guid_str);
4372 printer->action = SPOOL_DS_PUBLISH;
4373 } else {
4374 init_unistr(&printer->guid, "");
4375 printer->action = SPOOL_DS_UNPUBLISH;
4378 return True;
4381 /********************************************************************
4382 Spoolss_enumprinters.
4383 ********************************************************************/
4385 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4387 int snum;
4388 int i;
4389 int n_services=lp_numservices();
4390 PRINTER_INFO_1 *tp, *printers=NULL;
4391 PRINTER_INFO_1 current_prt;
4393 DEBUG(4,("enum_all_printers_info_1\n"));
4395 for (snum=0; snum<n_services; snum++) {
4396 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4397 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4399 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4400 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4401 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4402 SAFE_FREE(printers);
4403 *returned=0;
4404 return WERR_NOMEM;
4406 else printers = tp;
4407 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4409 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4410 (*returned)++;
4415 /* check the required size. */
4416 for (i=0; i<*returned; i++)
4417 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4419 if (!alloc_buffer_size(buffer, *needed))
4420 return WERR_INSUFFICIENT_BUFFER;
4422 /* fill the buffer with the structures */
4423 for (i=0; i<*returned; i++)
4424 smb_io_printer_info_1("", buffer, &printers[i], 0);
4426 /* clear memory */
4427 SAFE_FREE(printers);
4429 if (*needed > offered) {
4430 *returned=0;
4431 return WERR_INSUFFICIENT_BUFFER;
4433 else
4434 return WERR_OK;
4437 /********************************************************************
4438 enum_all_printers_info_1_local.
4439 *********************************************************************/
4441 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4443 DEBUG(4,("enum_all_printers_info_1_local\n"));
4445 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4448 /********************************************************************
4449 enum_all_printers_info_1_name.
4450 *********************************************************************/
4452 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4454 char *s = name;
4456 DEBUG(4,("enum_all_printers_info_1_name\n"));
4458 if ((name[0] == '\\') && (name[1] == '\\'))
4459 s = name + 2;
4461 if (is_myname_or_ipaddr(s)) {
4462 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4464 else
4465 return WERR_INVALID_NAME;
4468 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4469 /********************************************************************
4470 enum_all_printers_info_1_remote.
4471 *********************************************************************/
4473 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4475 PRINTER_INFO_1 *printer;
4476 fstring printername;
4477 fstring desc;
4478 fstring comment;
4479 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4481 /* JFM: currently it's more a place holder than anything else.
4482 * In the spooler world there is a notion of server registration.
4483 * the print servers are registered on the PDC (in the same domain)
4485 * We should have a TDB here. The registration is done thru an
4486 * undocumented RPC call.
4489 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4490 return WERR_NOMEM;
4492 *returned=1;
4494 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4495 slprintf(desc, sizeof(desc)-1,"%s", name);
4496 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4498 init_unistr(&printer->description, desc);
4499 init_unistr(&printer->name, printername);
4500 init_unistr(&printer->comment, comment);
4501 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4503 /* check the required size. */
4504 *needed += spoolss_size_printer_info_1(printer);
4506 if (!alloc_buffer_size(buffer, *needed)) {
4507 SAFE_FREE(printer);
4508 return WERR_INSUFFICIENT_BUFFER;
4511 /* fill the buffer with the structures */
4512 smb_io_printer_info_1("", buffer, printer, 0);
4514 /* clear memory */
4515 SAFE_FREE(printer);
4517 if (*needed > offered) {
4518 *returned=0;
4519 return WERR_INSUFFICIENT_BUFFER;
4521 else
4522 return WERR_OK;
4525 #endif
4527 /********************************************************************
4528 enum_all_printers_info_1_network.
4529 *********************************************************************/
4531 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4533 char *s = name;
4535 DEBUG(4,("enum_all_printers_info_1_network\n"));
4537 /* If we respond to a enum_printers level 1 on our name with flags
4538 set to PRINTER_ENUM_REMOTE with a list of printers then these
4539 printers incorrectly appear in the APW browse list.
4540 Specifically the printers for the server appear at the workgroup
4541 level where all the other servers in the domain are
4542 listed. Windows responds to this call with a
4543 WERR_CAN_NOT_COMPLETE so we should do the same. */
4545 if (name[0] == '\\' && name[1] == '\\')
4546 s = name + 2;
4548 if (is_myname_or_ipaddr(s))
4549 return WERR_CAN_NOT_COMPLETE;
4551 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4554 /********************************************************************
4555 * api_spoolss_enumprinters
4557 * called from api_spoolss_enumprinters (see this to understand)
4558 ********************************************************************/
4560 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4562 int snum;
4563 int i;
4564 int n_services=lp_numservices();
4565 PRINTER_INFO_2 *tp, *printers=NULL;
4566 PRINTER_INFO_2 current_prt;
4568 for (snum=0; snum<n_services; snum++) {
4569 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4570 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4572 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4573 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4574 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4575 SAFE_FREE(printers);
4576 *returned = 0;
4577 return WERR_NOMEM;
4579 else printers = tp;
4580 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4581 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4582 (*returned)++;
4587 /* check the required size. */
4588 for (i=0; i<*returned; i++)
4589 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4591 if (!alloc_buffer_size(buffer, *needed)) {
4592 for (i=0; i<*returned; i++) {
4593 free_devmode(printers[i].devmode);
4595 SAFE_FREE(printers);
4596 return WERR_INSUFFICIENT_BUFFER;
4599 /* fill the buffer with the structures */
4600 for (i=0; i<*returned; i++)
4601 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4603 /* clear memory */
4604 for (i=0; i<*returned; i++) {
4605 free_devmode(printers[i].devmode);
4607 SAFE_FREE(printers);
4609 if (*needed > offered) {
4610 *returned=0;
4611 return WERR_INSUFFICIENT_BUFFER;
4613 else
4614 return WERR_OK;
4617 /********************************************************************
4618 * handle enumeration of printers at level 1
4619 ********************************************************************/
4621 static WERROR enumprinters_level1( uint32 flags, fstring name,
4622 NEW_BUFFER *buffer, uint32 offered,
4623 uint32 *needed, uint32 *returned)
4625 /* Not all the flags are equals */
4627 if (flags & PRINTER_ENUM_LOCAL)
4628 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4630 if (flags & PRINTER_ENUM_NAME)
4631 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4633 #if 0 /* JERRY - disabled for now */
4634 if (flags & PRINTER_ENUM_REMOTE)
4635 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4636 #endif
4638 if (flags & PRINTER_ENUM_NETWORK)
4639 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4641 return WERR_OK; /* NT4sp5 does that */
4644 /********************************************************************
4645 * handle enumeration of printers at level 2
4646 ********************************************************************/
4648 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4649 NEW_BUFFER *buffer, uint32 offered,
4650 uint32 *needed, uint32 *returned)
4652 char *s = servername;
4654 if (flags & PRINTER_ENUM_LOCAL) {
4655 return enum_all_printers_info_2(buffer, offered, needed, returned);
4658 if (flags & PRINTER_ENUM_NAME) {
4659 if ((servername[0] == '\\') && (servername[1] == '\\'))
4660 s = servername + 2;
4661 if (is_myname_or_ipaddr(s))
4662 return enum_all_printers_info_2(buffer, offered, needed, returned);
4663 else
4664 return WERR_INVALID_NAME;
4667 if (flags & PRINTER_ENUM_REMOTE)
4668 return WERR_UNKNOWN_LEVEL;
4670 return WERR_OK;
4673 /********************************************************************
4674 * handle enumeration of printers at level 5
4675 ********************************************************************/
4677 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4678 NEW_BUFFER *buffer, uint32 offered,
4679 uint32 *needed, uint32 *returned)
4681 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4682 return WERR_OK;
4685 /********************************************************************
4686 * api_spoolss_enumprinters
4688 * called from api_spoolss_enumprinters (see this to understand)
4689 ********************************************************************/
4691 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4693 uint32 flags = q_u->flags;
4694 UNISTR2 *servername = &q_u->servername;
4695 uint32 level = q_u->level;
4696 NEW_BUFFER *buffer = NULL;
4697 uint32 offered = q_u->offered;
4698 uint32 *needed = &r_u->needed;
4699 uint32 *returned = &r_u->returned;
4701 fstring name;
4703 /* that's an [in out] buffer */
4704 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4705 buffer = r_u->buffer;
4707 DEBUG(4,("_spoolss_enumprinters\n"));
4709 *needed=0;
4710 *returned=0;
4713 * Level 1:
4714 * flags==PRINTER_ENUM_NAME
4715 * if name=="" then enumerates all printers
4716 * if name!="" then enumerate the printer
4717 * flags==PRINTER_ENUM_REMOTE
4718 * name is NULL, enumerate printers
4719 * Level 2: name!="" enumerates printers, name can't be NULL
4720 * Level 3: doesn't exist
4721 * Level 4: does a local registry lookup
4722 * Level 5: same as Level 2
4725 unistr2_to_ascii(name, servername, sizeof(name)-1);
4726 strupper_m(name);
4728 switch (level) {
4729 case 1:
4730 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4731 case 2:
4732 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4733 case 5:
4734 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4735 case 3:
4736 case 4:
4737 break;
4739 return WERR_UNKNOWN_LEVEL;
4742 /****************************************************************************
4743 ****************************************************************************/
4745 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4747 PRINTER_INFO_0 *printer=NULL;
4749 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4750 return WERR_NOMEM;
4752 construct_printer_info_0(print_hnd, printer, snum);
4754 /* check the required size. */
4755 *needed += spoolss_size_printer_info_0(printer);
4757 if (!alloc_buffer_size(buffer, *needed)) {
4758 SAFE_FREE(printer);
4759 return WERR_INSUFFICIENT_BUFFER;
4762 /* fill the buffer with the structures */
4763 smb_io_printer_info_0("", buffer, printer, 0);
4765 /* clear memory */
4766 SAFE_FREE(printer);
4768 if (*needed > offered) {
4769 return WERR_INSUFFICIENT_BUFFER;
4772 return WERR_OK;
4775 /****************************************************************************
4776 ****************************************************************************/
4778 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4780 PRINTER_INFO_1 *printer=NULL;
4782 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4783 return WERR_NOMEM;
4785 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4787 /* check the required size. */
4788 *needed += spoolss_size_printer_info_1(printer);
4790 if (!alloc_buffer_size(buffer, *needed)) {
4791 SAFE_FREE(printer);
4792 return WERR_INSUFFICIENT_BUFFER;
4795 /* fill the buffer with the structures */
4796 smb_io_printer_info_1("", buffer, printer, 0);
4798 /* clear memory */
4799 SAFE_FREE(printer);
4801 if (*needed > offered) {
4802 return WERR_INSUFFICIENT_BUFFER;
4805 return WERR_OK;
4808 /****************************************************************************
4809 ****************************************************************************/
4811 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4813 PRINTER_INFO_2 *printer=NULL;
4815 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4816 return WERR_NOMEM;
4818 construct_printer_info_2(print_hnd, printer, snum);
4820 /* check the required size. */
4821 *needed += spoolss_size_printer_info_2(printer);
4823 if (!alloc_buffer_size(buffer, *needed)) {
4824 free_printer_info_2(printer);
4825 return WERR_INSUFFICIENT_BUFFER;
4828 /* fill the buffer with the structures */
4829 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4830 free_printer_info_2(printer);
4831 return WERR_NOMEM;
4834 /* clear memory */
4835 free_printer_info_2(printer);
4837 if (*needed > offered) {
4838 return WERR_INSUFFICIENT_BUFFER;
4841 return WERR_OK;
4844 /****************************************************************************
4845 ****************************************************************************/
4847 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4849 PRINTER_INFO_3 *printer=NULL;
4851 if (!construct_printer_info_3(print_hnd, &printer, snum))
4852 return WERR_NOMEM;
4854 /* check the required size. */
4855 *needed += spoolss_size_printer_info_3(printer);
4857 if (!alloc_buffer_size(buffer, *needed)) {
4858 free_printer_info_3(printer);
4859 return WERR_INSUFFICIENT_BUFFER;
4862 /* fill the buffer with the structures */
4863 smb_io_printer_info_3("", buffer, printer, 0);
4865 /* clear memory */
4866 free_printer_info_3(printer);
4868 if (*needed > offered) {
4869 return WERR_INSUFFICIENT_BUFFER;
4872 return WERR_OK;
4875 /****************************************************************************
4876 ****************************************************************************/
4878 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4880 PRINTER_INFO_4 *printer=NULL;
4882 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4883 return WERR_NOMEM;
4885 if (!construct_printer_info_4(print_hnd, printer, snum))
4886 return WERR_NOMEM;
4888 /* check the required size. */
4889 *needed += spoolss_size_printer_info_4(printer);
4891 if (!alloc_buffer_size(buffer, *needed)) {
4892 free_printer_info_4(printer);
4893 return WERR_INSUFFICIENT_BUFFER;
4896 /* fill the buffer with the structures */
4897 smb_io_printer_info_4("", buffer, printer, 0);
4899 /* clear memory */
4900 free_printer_info_4(printer);
4902 if (*needed > offered) {
4903 return WERR_INSUFFICIENT_BUFFER;
4906 return WERR_OK;
4909 /****************************************************************************
4910 ****************************************************************************/
4912 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4914 PRINTER_INFO_5 *printer=NULL;
4916 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4917 return WERR_NOMEM;
4919 if (!construct_printer_info_5(print_hnd, printer, snum))
4920 return WERR_NOMEM;
4922 /* check the required size. */
4923 *needed += spoolss_size_printer_info_5(printer);
4925 if (!alloc_buffer_size(buffer, *needed)) {
4926 free_printer_info_5(printer);
4927 return WERR_INSUFFICIENT_BUFFER;
4930 /* fill the buffer with the structures */
4931 smb_io_printer_info_5("", buffer, printer, 0);
4933 /* clear memory */
4934 free_printer_info_5(printer);
4936 if (*needed > offered) {
4937 return WERR_INSUFFICIENT_BUFFER;
4940 return WERR_OK;
4943 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4945 PRINTER_INFO_7 *printer=NULL;
4947 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4948 return WERR_NOMEM;
4950 if (!construct_printer_info_7(print_hnd, printer, snum))
4951 return WERR_NOMEM;
4953 /* check the required size. */
4954 *needed += spoolss_size_printer_info_7(printer);
4956 if (!alloc_buffer_size(buffer, *needed)) {
4957 free_printer_info_7(printer);
4958 return WERR_INSUFFICIENT_BUFFER;
4961 /* fill the buffer with the structures */
4962 smb_io_printer_info_7("", buffer, printer, 0);
4964 /* clear memory */
4965 free_printer_info_7(printer);
4967 if (*needed > offered) {
4968 return WERR_INSUFFICIENT_BUFFER;
4971 return WERR_OK;
4974 /****************************************************************************
4975 ****************************************************************************/
4977 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4979 POLICY_HND *handle = &q_u->handle;
4980 uint32 level = q_u->level;
4981 NEW_BUFFER *buffer = NULL;
4982 uint32 offered = q_u->offered;
4983 uint32 *needed = &r_u->needed;
4984 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4986 int snum;
4988 /* that's an [in out] buffer */
4989 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4990 buffer = r_u->buffer;
4992 *needed=0;
4994 if (!get_printer_snum(p, handle, &snum))
4995 return WERR_BADFID;
4997 switch (level) {
4998 case 0:
4999 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5000 case 1:
5001 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5002 case 2:
5003 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5004 case 3:
5005 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5006 case 4:
5007 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5008 case 5:
5009 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5010 case 7:
5011 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5013 return WERR_UNKNOWN_LEVEL;
5016 /********************************************************************
5017 * fill a DRIVER_INFO_1 struct
5018 ********************************************************************/
5020 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5022 init_unistr( &info->name, driver.info_3->name);
5025 /********************************************************************
5026 * construct_printer_driver_info_1
5027 ********************************************************************/
5029 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5031 NT_PRINTER_INFO_LEVEL *printer = NULL;
5032 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5034 ZERO_STRUCT(driver);
5036 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5037 return WERR_INVALID_PRINTER_NAME;
5039 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5040 return WERR_UNKNOWN_PRINTER_DRIVER;
5042 fill_printer_driver_info_1(info, driver, servername, architecture);
5044 free_a_printer(&printer,2);
5046 return WERR_OK;
5049 /********************************************************************
5050 * construct_printer_driver_info_2
5051 * fill a printer_info_2 struct
5052 ********************************************************************/
5054 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5056 pstring temp;
5058 info->version=driver.info_3->cversion;
5060 init_unistr( &info->name, driver.info_3->name );
5061 init_unistr( &info->architecture, driver.info_3->environment );
5064 if (strlen(driver.info_3->driverpath)) {
5065 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5066 init_unistr( &info->driverpath, temp );
5067 } else
5068 init_unistr( &info->driverpath, "" );
5070 if (strlen(driver.info_3->datafile)) {
5071 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5072 init_unistr( &info->datafile, temp );
5073 } else
5074 init_unistr( &info->datafile, "" );
5076 if (strlen(driver.info_3->configfile)) {
5077 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5078 init_unistr( &info->configfile, temp );
5079 } else
5080 init_unistr( &info->configfile, "" );
5083 /********************************************************************
5084 * construct_printer_driver_info_2
5085 * fill a printer_info_2 struct
5086 ********************************************************************/
5088 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5090 NT_PRINTER_INFO_LEVEL *printer = NULL;
5091 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5093 ZERO_STRUCT(printer);
5094 ZERO_STRUCT(driver);
5096 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5097 return WERR_INVALID_PRINTER_NAME;
5099 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5100 return WERR_UNKNOWN_PRINTER_DRIVER;
5102 fill_printer_driver_info_2(info, driver, servername);
5104 free_a_printer(&printer,2);
5106 return WERR_OK;
5109 /********************************************************************
5110 * copy a strings array and convert to UNICODE
5112 * convert an array of ascii string to a UNICODE string
5113 ********************************************************************/
5115 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5117 int i=0;
5118 int j=0;
5119 const char *v;
5120 pstring line;
5121 uint16 *tuary;
5123 DEBUG(6,("init_unistr_array\n"));
5124 *uni_array=NULL;
5126 while (True)
5128 if ( !char_array )
5129 v = "";
5130 else
5132 v = char_array[i];
5133 if (!v)
5134 v = ""; /* hack to handle null lists */
5137 /* hack to allow this to be used in places other than when generating
5138 the list of dependent files */
5140 if ( servername )
5141 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5142 else
5143 pstrcpy( line, v );
5145 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5147 /* add one extra unit16 for the second terminating NULL */
5149 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5150 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5151 return 0;
5152 } else
5153 *uni_array = tuary;
5155 if ( !strlen(v) )
5156 break;
5158 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5159 i++;
5162 if (*uni_array) {
5163 /* special case for ""; we need to add both NULL's here */
5164 if (!j)
5165 (*uni_array)[j++]=0x0000;
5166 (*uni_array)[j]=0x0000;
5169 DEBUGADD(6,("last one:done\n"));
5171 /* return size of array in uint16's */
5173 return j+1;
5176 /********************************************************************
5177 * construct_printer_info_3
5178 * fill a printer_info_3 struct
5179 ********************************************************************/
5181 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5183 pstring temp;
5185 ZERO_STRUCTP(info);
5187 info->version=driver.info_3->cversion;
5189 init_unistr( &info->name, driver.info_3->name );
5190 init_unistr( &info->architecture, driver.info_3->environment );
5192 if (strlen(driver.info_3->driverpath)) {
5193 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5194 init_unistr( &info->driverpath, temp );
5195 } else
5196 init_unistr( &info->driverpath, "" );
5198 if (strlen(driver.info_3->datafile)) {
5199 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5200 init_unistr( &info->datafile, temp );
5201 } else
5202 init_unistr( &info->datafile, "" );
5204 if (strlen(driver.info_3->configfile)) {
5205 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5206 init_unistr( &info->configfile, temp );
5207 } else
5208 init_unistr( &info->configfile, "" );
5210 if (strlen(driver.info_3->helpfile)) {
5211 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5212 init_unistr( &info->helpfile, temp );
5213 } else
5214 init_unistr( &info->helpfile, "" );
5216 init_unistr( &info->monitorname, driver.info_3->monitorname );
5217 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5219 info->dependentfiles=NULL;
5220 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5223 /********************************************************************
5224 * construct_printer_info_3
5225 * fill a printer_info_3 struct
5226 ********************************************************************/
5228 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5230 NT_PRINTER_INFO_LEVEL *printer = NULL;
5231 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5232 WERROR status;
5233 ZERO_STRUCT(driver);
5235 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5236 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5237 if (!W_ERROR_IS_OK(status))
5238 return WERR_INVALID_PRINTER_NAME;
5240 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5241 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5243 #if 0 /* JERRY */
5246 * I put this code in during testing. Helpful when commenting out the
5247 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5248 * as win2k always queries the driver using an infor level of 6.
5249 * I've left it in (but ifdef'd out) because I'll probably
5250 * use it in experimentation again in the future. --jerry 22/01/2002
5253 if (!W_ERROR_IS_OK(status)) {
5255 * Is this a W2k client ?
5257 if (version == 3) {
5258 /* Yes - try again with a WinNT driver. */
5259 version = 2;
5260 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5261 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5263 #endif
5265 if (!W_ERROR_IS_OK(status)) {
5266 free_a_printer(&printer,2);
5267 return WERR_UNKNOWN_PRINTER_DRIVER;
5270 #if 0 /* JERRY */
5272 #endif
5275 fill_printer_driver_info_3(info, driver, servername);
5277 free_a_printer(&printer,2);
5279 return WERR_OK;
5282 /********************************************************************
5283 * construct_printer_info_6
5284 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5285 ********************************************************************/
5287 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5289 pstring temp;
5290 fstring nullstr;
5292 ZERO_STRUCTP(info);
5293 memset(&nullstr, '\0', sizeof(fstring));
5295 info->version=driver.info_3->cversion;
5297 init_unistr( &info->name, driver.info_3->name );
5298 init_unistr( &info->architecture, driver.info_3->environment );
5300 if (strlen(driver.info_3->driverpath)) {
5301 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5302 init_unistr( &info->driverpath, temp );
5303 } else
5304 init_unistr( &info->driverpath, "" );
5306 if (strlen(driver.info_3->datafile)) {
5307 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5308 init_unistr( &info->datafile, temp );
5309 } else
5310 init_unistr( &info->datafile, "" );
5312 if (strlen(driver.info_3->configfile)) {
5313 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5314 init_unistr( &info->configfile, temp );
5315 } else
5316 init_unistr( &info->configfile, "" );
5318 if (strlen(driver.info_3->helpfile)) {
5319 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5320 init_unistr( &info->helpfile, temp );
5321 } else
5322 init_unistr( &info->helpfile, "" );
5324 init_unistr( &info->monitorname, driver.info_3->monitorname );
5325 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5327 info->dependentfiles = NULL;
5328 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5330 info->previousdrivernames=NULL;
5331 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5333 info->driver_date.low=0;
5334 info->driver_date.high=0;
5336 info->padding=0;
5337 info->driver_version_low=0;
5338 info->driver_version_high=0;
5340 init_unistr( &info->mfgname, "");
5341 init_unistr( &info->oem_url, "");
5342 init_unistr( &info->hardware_id, "");
5343 init_unistr( &info->provider, "");
5346 /********************************************************************
5347 * construct_printer_info_6
5348 * fill a printer_info_6 struct
5349 ********************************************************************/
5351 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5352 fstring servername, fstring architecture, uint32 version)
5354 NT_PRINTER_INFO_LEVEL *printer = NULL;
5355 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5356 WERROR status;
5358 ZERO_STRUCT(driver);
5360 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5362 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5364 if (!W_ERROR_IS_OK(status))
5365 return WERR_INVALID_PRINTER_NAME;
5367 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5369 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5371 if (!W_ERROR_IS_OK(status))
5374 * Is this a W2k client ?
5377 if (version < 3) {
5378 free_a_printer(&printer,2);
5379 return WERR_UNKNOWN_PRINTER_DRIVER;
5382 /* Yes - try again with a WinNT driver. */
5383 version = 2;
5384 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5385 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5386 if (!W_ERROR_IS_OK(status)) {
5387 free_a_printer(&printer,2);
5388 return WERR_UNKNOWN_PRINTER_DRIVER;
5392 fill_printer_driver_info_6(info, driver, servername);
5394 free_a_printer(&printer,2);
5395 free_a_printer_driver(driver, 3);
5397 return WERR_OK;
5400 /****************************************************************************
5401 ****************************************************************************/
5403 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5405 SAFE_FREE(info->dependentfiles);
5408 /****************************************************************************
5409 ****************************************************************************/
5411 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5413 SAFE_FREE(info->dependentfiles);
5417 /****************************************************************************
5418 ****************************************************************************/
5420 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5422 DRIVER_INFO_1 *info=NULL;
5423 WERROR status;
5425 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5426 return WERR_NOMEM;
5428 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5429 if (!W_ERROR_IS_OK(status)) {
5430 SAFE_FREE(info);
5431 return status;
5434 /* check the required size. */
5435 *needed += spoolss_size_printer_driver_info_1(info);
5437 if (!alloc_buffer_size(buffer, *needed)) {
5438 SAFE_FREE(info);
5439 return WERR_INSUFFICIENT_BUFFER;
5442 /* fill the buffer with the structures */
5443 smb_io_printer_driver_info_1("", buffer, info, 0);
5445 /* clear memory */
5446 SAFE_FREE(info);
5448 if (*needed > offered)
5449 return WERR_INSUFFICIENT_BUFFER;
5451 return WERR_OK;
5454 /****************************************************************************
5455 ****************************************************************************/
5457 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5459 DRIVER_INFO_2 *info=NULL;
5460 WERROR status;
5462 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5463 return WERR_NOMEM;
5465 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5466 if (!W_ERROR_IS_OK(status)) {
5467 SAFE_FREE(info);
5468 return status;
5471 /* check the required size. */
5472 *needed += spoolss_size_printer_driver_info_2(info);
5474 if (!alloc_buffer_size(buffer, *needed)) {
5475 SAFE_FREE(info);
5476 return WERR_INSUFFICIENT_BUFFER;
5479 /* fill the buffer with the structures */
5480 smb_io_printer_driver_info_2("", buffer, info, 0);
5482 /* clear memory */
5483 SAFE_FREE(info);
5485 if (*needed > offered)
5486 return WERR_INSUFFICIENT_BUFFER;
5488 return WERR_OK;
5491 /****************************************************************************
5492 ****************************************************************************/
5494 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5496 DRIVER_INFO_3 info;
5497 WERROR status;
5499 ZERO_STRUCT(info);
5501 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5502 if (!W_ERROR_IS_OK(status)) {
5503 return status;
5506 /* check the required size. */
5507 *needed += spoolss_size_printer_driver_info_3(&info);
5509 if (!alloc_buffer_size(buffer, *needed)) {
5510 free_printer_driver_info_3(&info);
5511 return WERR_INSUFFICIENT_BUFFER;
5514 /* fill the buffer with the structures */
5515 smb_io_printer_driver_info_3("", buffer, &info, 0);
5517 free_printer_driver_info_3(&info);
5519 if (*needed > offered)
5520 return WERR_INSUFFICIENT_BUFFER;
5522 return WERR_OK;
5525 /****************************************************************************
5526 ****************************************************************************/
5528 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5530 DRIVER_INFO_6 info;
5531 WERROR status;
5533 ZERO_STRUCT(info);
5535 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5536 if (!W_ERROR_IS_OK(status)) {
5537 return status;
5540 /* check the required size. */
5541 *needed += spoolss_size_printer_driver_info_6(&info);
5543 if (!alloc_buffer_size(buffer, *needed)) {
5544 free_printer_driver_info_6(&info);
5545 return WERR_INSUFFICIENT_BUFFER;
5548 /* fill the buffer with the structures */
5549 smb_io_printer_driver_info_6("", buffer, &info, 0);
5551 free_printer_driver_info_6(&info);
5553 if (*needed > offered)
5554 return WERR_INSUFFICIENT_BUFFER;
5556 return WERR_OK;
5559 /****************************************************************************
5560 ****************************************************************************/
5562 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5564 POLICY_HND *handle = &q_u->handle;
5565 UNISTR2 *uni_arch = &q_u->architecture;
5566 uint32 level = q_u->level;
5567 uint32 clientmajorversion = q_u->clientmajorversion;
5568 NEW_BUFFER *buffer = NULL;
5569 uint32 offered = q_u->offered;
5570 uint32 *needed = &r_u->needed;
5571 uint32 *servermajorversion = &r_u->servermajorversion;
5572 uint32 *serverminorversion = &r_u->serverminorversion;
5573 Printer_entry *printer;
5575 fstring servername;
5576 fstring architecture;
5577 int snum;
5579 /* that's an [in out] buffer */
5580 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5581 buffer = r_u->buffer;
5583 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5585 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5586 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5587 return WERR_INVALID_PRINTER_NAME;
5590 *needed = 0;
5591 *servermajorversion = 0;
5592 *serverminorversion = 0;
5594 fstrcpy(servername, get_server_name( printer ));
5595 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5597 if (!get_printer_snum(p, handle, &snum))
5598 return WERR_BADFID;
5600 switch (level) {
5601 case 1:
5602 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5603 case 2:
5604 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5605 case 3:
5606 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5607 case 6:
5608 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5609 #if 0 /* JERRY */
5610 case 101:
5611 /* apparently this call is the equivalent of
5612 EnumPrinterDataEx() for the DsDriver key */
5613 break;
5614 #endif
5617 return WERR_UNKNOWN_LEVEL;
5620 /****************************************************************************
5621 ****************************************************************************/
5623 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5625 POLICY_HND *handle = &q_u->handle;
5627 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5629 if (!Printer) {
5630 DEBUG(3,("Error in startpageprinter printer handle\n"));
5631 return WERR_BADFID;
5634 Printer->page_started=True;
5635 return WERR_OK;
5638 /****************************************************************************
5639 ****************************************************************************/
5641 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5643 POLICY_HND *handle = &q_u->handle;
5644 int snum;
5646 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5648 if (!Printer) {
5649 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5650 return WERR_BADFID;
5653 if (!get_printer_snum(p, handle, &snum))
5654 return WERR_BADFID;
5656 Printer->page_started=False;
5657 print_job_endpage(snum, Printer->jobid);
5659 return WERR_OK;
5662 /********************************************************************
5663 * api_spoolss_getprinter
5664 * called from the spoolss dispatcher
5666 ********************************************************************/
5668 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5670 POLICY_HND *handle = &q_u->handle;
5671 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5672 uint32 *jobid = &r_u->jobid;
5674 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5675 int snum;
5676 pstring jobname;
5677 fstring datatype;
5678 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5679 struct current_user user;
5681 if (!Printer) {
5682 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5683 return WERR_BADFID;
5686 get_current_user(&user, p);
5689 * a nice thing with NT is it doesn't listen to what you tell it.
5690 * when asked to send _only_ RAW datas, it tries to send datas
5691 * in EMF format.
5693 * So I add checks like in NT Server ...
5696 if (info_1->p_datatype != 0) {
5697 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5698 if (strcmp(datatype, "RAW") != 0) {
5699 (*jobid)=0;
5700 return WERR_INVALID_DATATYPE;
5704 /* get the share number of the printer */
5705 if (!get_printer_snum(p, handle, &snum)) {
5706 return WERR_BADFID;
5709 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5711 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5713 /* An error occured in print_job_start() so return an appropriate
5714 NT error code. */
5716 if (Printer->jobid == -1) {
5717 return map_werror_from_unix(errno);
5720 Printer->document_started=True;
5721 (*jobid) = Printer->jobid;
5723 return WERR_OK;
5726 /********************************************************************
5727 * api_spoolss_getprinter
5728 * called from the spoolss dispatcher
5730 ********************************************************************/
5732 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5734 POLICY_HND *handle = &q_u->handle;
5736 return _spoolss_enddocprinter_internal(p, handle);
5739 /****************************************************************************
5740 ****************************************************************************/
5742 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5744 POLICY_HND *handle = &q_u->handle;
5745 uint32 buffer_size = q_u->buffer_size;
5746 uint8 *buffer = q_u->buffer;
5747 uint32 *buffer_written = &q_u->buffer_size2;
5748 int snum;
5749 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5751 if (!Printer) {
5752 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5753 r_u->buffer_written = q_u->buffer_size2;
5754 return WERR_BADFID;
5757 if (!get_printer_snum(p, handle, &snum))
5758 return WERR_BADFID;
5760 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5761 if (*buffer_written == -1) {
5762 r_u->buffer_written = 0;
5763 if (errno == ENOSPC)
5764 return WERR_NO_SPOOL_SPACE;
5765 else
5766 return WERR_ACCESS_DENIED;
5769 r_u->buffer_written = q_u->buffer_size2;
5771 return WERR_OK;
5774 /********************************************************************
5775 * api_spoolss_getprinter
5776 * called from the spoolss dispatcher
5778 ********************************************************************/
5780 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5781 pipes_struct *p)
5783 struct current_user user;
5784 int snum;
5785 WERROR errcode = WERR_BADFUNC;
5786 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5788 get_current_user(&user, p);
5790 if (!Printer) {
5791 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5792 return WERR_BADFID;
5795 if (!get_printer_snum(p, handle, &snum))
5796 return WERR_BADFID;
5798 switch (command) {
5799 case PRINTER_CONTROL_PAUSE:
5800 if (print_queue_pause(&user, snum, &errcode)) {
5801 errcode = WERR_OK;
5803 break;
5804 case PRINTER_CONTROL_RESUME:
5805 case PRINTER_CONTROL_UNPAUSE:
5806 if (print_queue_resume(&user, snum, &errcode)) {
5807 errcode = WERR_OK;
5809 break;
5810 case PRINTER_CONTROL_PURGE:
5811 if (print_queue_purge(&user, snum, &errcode)) {
5812 errcode = WERR_OK;
5814 break;
5815 default:
5816 return WERR_UNKNOWN_LEVEL;
5819 return errcode;
5822 /********************************************************************
5823 * api_spoolss_abortprinter
5824 * From MSDN: "Deletes printer's spool file if printer is configured
5825 * for spooling"
5826 ********************************************************************/
5828 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5830 POLICY_HND *handle = &q_u->handle;
5831 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5832 int snum;
5833 struct current_user user;
5834 WERROR errcode = WERR_OK;
5836 if (!Printer) {
5837 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5838 return WERR_BADFID;
5841 if (!get_printer_snum(p, handle, &snum))
5842 return WERR_BADFID;
5844 get_current_user( &user, p );
5846 print_job_delete( &user, snum, Printer->jobid, &errcode );
5848 return errcode;
5851 /********************************************************************
5852 * called by spoolss_api_setprinter
5853 * when updating a printer description
5854 ********************************************************************/
5856 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5857 const SPOOL_PRINTER_INFO_LEVEL *info,
5858 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5860 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5861 struct current_user user;
5862 WERROR result;
5863 int snum;
5865 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5867 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5868 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5869 OUR_HANDLE(handle)));
5871 result = WERR_BADFID;
5872 goto done;
5875 /* NT seems to like setting the security descriptor even though
5876 nothing may have actually changed. */
5878 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5880 if (DEBUGLEVEL >= 10) {
5881 SEC_ACL *the_acl;
5882 int i;
5884 the_acl = old_secdesc_ctr->sec->dacl;
5885 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5886 PRINTERNAME(snum), the_acl->num_aces));
5888 for (i = 0; i < the_acl->num_aces; i++) {
5889 fstring sid_str;
5891 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5893 DEBUG(10, ("%s 0x%08x\n", sid_str,
5894 the_acl->ace[i].info.mask));
5897 the_acl = secdesc_ctr->sec->dacl;
5899 if (the_acl) {
5900 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5901 PRINTERNAME(snum), the_acl->num_aces));
5903 for (i = 0; i < the_acl->num_aces; i++) {
5904 fstring sid_str;
5906 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5908 DEBUG(10, ("%s 0x%08x\n", sid_str,
5909 the_acl->ace[i].info.mask));
5911 } else {
5912 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5916 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5918 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5919 result = WERR_OK;
5920 goto done;
5923 /* Work out which user is performing the operation */
5925 get_current_user(&user, p);
5927 /* Check the user has permissions to change the security
5928 descriptor. By experimentation with two NT machines, the user
5929 requires Full Access to the printer to change security
5930 information. */
5932 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5933 result = WERR_ACCESS_DENIED;
5934 goto done;
5937 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5939 done:
5941 return result;
5944 /********************************************************************
5945 Canonicalize printer info from a client
5947 ATTN: It does not matter what we set the servername to hear
5948 since we do the necessary work in get_a_printer() to set it to
5949 the correct value based on what the client sent in the
5950 _spoolss_open_printer_ex().
5951 ********************************************************************/
5953 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5955 fstring printername;
5956 const char *p;
5958 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5959 "portname=%s drivername=%s comment=%s location=%s\n",
5960 info->servername, info->printername, info->sharename,
5961 info->portname, info->drivername, info->comment, info->location));
5963 /* we force some elements to "correct" values */
5964 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5965 fstrcpy(info->sharename, lp_servicename(snum));
5967 /* make sure printername is in \\server\printername format */
5969 fstrcpy( printername, info->printername );
5970 p = printername;
5971 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5972 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5973 p++;
5976 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5977 global_myname(), p );
5979 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5980 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5984 return True;
5987 /****************************************************************************
5988 ****************************************************************************/
5990 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5992 extern userdom_struct current_user_info;
5993 char *cmd = lp_addprinter_cmd();
5994 char **qlines;
5995 pstring command;
5996 int numlines;
5997 int ret;
5998 int fd;
5999 fstring remote_machine = "%m";
6001 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6003 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6004 cmd, printer->info_2->printername, printer->info_2->sharename,
6005 printer->info_2->portname, printer->info_2->drivername,
6006 printer->info_2->location, printer->info_2->comment, remote_machine);
6008 DEBUG(10,("Running [%s]\n", command));
6009 ret = smbrun(command, &fd);
6010 DEBUGADD(10,("returned [%d]\n", ret));
6012 if ( ret != 0 ) {
6013 if (fd != -1)
6014 close(fd);
6015 return False;
6018 numlines = 0;
6019 /* Get lines and convert them back to dos-codepage */
6020 qlines = fd_lines_load(fd, &numlines);
6021 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6022 close(fd);
6024 if(numlines) {
6025 /* Set the portname to what the script says the portname should be. */
6026 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6027 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6029 /* Send SIGHUP to process group... is there a better way? */
6030 kill(0, SIGHUP);
6032 /* reload our services immediately */
6033 reload_services( False );
6036 file_lines_free(qlines);
6037 return True;
6040 /********************************************************************
6041 * Called by spoolss_api_setprinter
6042 * when updating a printer description.
6043 ********************************************************************/
6045 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6046 const SPOOL_PRINTER_INFO_LEVEL *info,
6047 DEVICEMODE *devmode)
6049 int snum;
6050 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6051 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6052 WERROR result;
6053 UNISTR2 buffer;
6054 fstring asc_buffer;
6056 DEBUG(8,("update_printer\n"));
6058 result = WERR_OK;
6060 if (!Printer) {
6061 result = WERR_BADFID;
6062 goto done;
6065 if (!get_printer_snum(p, handle, &snum)) {
6066 result = WERR_BADFID;
6067 goto done;
6070 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6071 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6072 result = WERR_BADFID;
6073 goto done;
6076 DEBUGADD(8,("Converting info_2 struct\n"));
6079 * convert_printer_info converts the incoming
6080 * info from the client and overwrites the info
6081 * just read from the tdb in the pointer 'printer'.
6084 if (!convert_printer_info(info, printer, level)) {
6085 result = WERR_NOMEM;
6086 goto done;
6089 if (devmode) {
6090 /* we have a valid devmode
6091 convert it and link it*/
6093 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6094 if (!convert_devicemode(printer->info_2->printername, devmode,
6095 &printer->info_2->devmode)) {
6096 result = WERR_NOMEM;
6097 goto done;
6101 /* Do sanity check on the requested changes for Samba */
6103 if (!check_printer_ok(printer->info_2, snum)) {
6104 result = WERR_INVALID_PARAM;
6105 goto done;
6108 /* FIXME!!! If the driver has changed we really should verify that
6109 it is installed before doing much else --jerry */
6111 /* Check calling user has permission to update printer description */
6113 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6114 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6115 result = WERR_ACCESS_DENIED;
6116 goto done;
6119 /* Call addprinter hook */
6120 /* Check changes to see if this is really needed */
6122 if ( *lp_addprinter_cmd()
6123 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6124 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6125 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6126 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6128 if ( !add_printer_hook(printer) ) {
6129 result = WERR_ACCESS_DENIED;
6130 goto done;
6134 * make sure we actually reload the services after
6135 * this as smb.conf could have a new section in it
6136 * .... shouldn't .... but could
6138 reload_services(False);
6142 * When a *new* driver is bound to a printer, the drivername is used to
6143 * lookup previously saved driver initialization info, which is then
6144 * bound to the printer, simulating what happens in the Windows arch.
6146 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6148 if (!set_driver_init(printer, 2))
6150 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6151 printer->info_2->drivername));
6154 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6155 printer->info_2->drivername));
6157 notify_printer_driver(snum, printer->info_2->drivername);
6161 * flag which changes actually occured. This is a small subset of
6162 * all the possible changes. We also have to update things in the
6163 * DsSpooler key.
6166 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6167 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6168 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6169 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6171 notify_printer_comment(snum, printer->info_2->comment);
6174 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6175 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6176 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6177 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6179 notify_printer_sharename(snum, printer->info_2->sharename);
6182 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6183 char *pname;
6185 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6186 pname++;
6187 else
6188 pname = printer->info_2->printername;
6191 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6192 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6193 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6195 notify_printer_printername( snum, pname );
6198 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6199 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6200 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6201 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6203 notify_printer_port(snum, printer->info_2->portname);
6206 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6207 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6208 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6209 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6211 notify_printer_location(snum, printer->info_2->location);
6214 /* here we need to update some more DsSpooler keys */
6215 /* uNCName, serverName, shortServerName */
6217 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6218 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6219 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6220 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6221 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6223 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6224 global_myname(), printer->info_2->sharename );
6225 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6226 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6227 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6229 /* Update printer info */
6230 result = mod_a_printer(printer, 2);
6232 done:
6233 free_a_printer(&printer, 2);
6234 free_a_printer(&old_printer, 2);
6237 return result;
6240 /****************************************************************************
6241 ****************************************************************************/
6242 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6243 const SPOOL_PRINTER_INFO_LEVEL *info)
6245 #ifdef HAVE_ADS
6246 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6247 int snum;
6248 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6250 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6252 if (!Printer)
6253 return WERR_BADFID;
6255 if (!get_printer_snum(p, handle, &snum))
6256 return WERR_BADFID;
6258 nt_printer_publish(Printer, snum, info7->action);
6260 return WERR_OK;
6261 #else
6262 return WERR_UNKNOWN_LEVEL;
6263 #endif
6265 /****************************************************************************
6266 ****************************************************************************/
6268 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6270 POLICY_HND *handle = &q_u->handle;
6271 uint32 level = q_u->level;
6272 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6273 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6274 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6275 uint32 command = q_u->command;
6276 WERROR result;
6278 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6280 if (!Printer) {
6281 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6282 return WERR_BADFID;
6285 /* check the level */
6286 switch (level) {
6287 case 0:
6288 return control_printer(handle, command, p);
6289 case 2:
6290 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6291 if (!W_ERROR_IS_OK(result))
6292 return result;
6293 if (secdesc_ctr)
6294 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6295 return result;
6296 case 3:
6297 return update_printer_sec(handle, level, info, p,
6298 secdesc_ctr);
6299 case 7:
6300 return publish_or_unpublish_printer(p, handle, info);
6301 default:
6302 return WERR_UNKNOWN_LEVEL;
6306 /****************************************************************************
6307 ****************************************************************************/
6309 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6311 POLICY_HND *handle = &q_u->handle;
6312 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6314 if (!Printer) {
6315 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6316 return WERR_BADFID;
6319 if (Printer->notify.client_connected==True) {
6320 int snum = -1;
6322 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6323 snum = -1;
6324 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6325 !get_printer_snum(p, handle, &snum) )
6326 return WERR_BADFID;
6328 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6331 Printer->notify.flags=0;
6332 Printer->notify.options=0;
6333 Printer->notify.localmachine[0]='\0';
6334 Printer->notify.printerlocal=0;
6335 if (Printer->notify.option)
6336 free_spool_notify_option(&Printer->notify.option);
6337 Printer->notify.client_connected=False;
6339 return WERR_OK;
6342 /****************************************************************************
6343 ****************************************************************************/
6345 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6347 /* that's an [in out] buffer (despite appearences to the contrary) */
6348 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6350 r_u->needed = 0;
6351 return WERR_INVALID_PARAM; /* this is what a NT server
6352 returns for AddJob. AddJob
6353 must fail on non-local
6354 printers */
6357 /****************************************************************************
6358 ****************************************************************************/
6360 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6361 int position, int snum,
6362 NT_PRINTER_INFO_LEVEL *ntprinter)
6364 struct tm *t;
6366 t=gmtime(&queue->time);
6368 job_info->jobid=queue->job;
6369 init_unistr(&job_info->printername, lp_servicename(snum));
6370 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6371 init_unistr(&job_info->username, queue->fs_user);
6372 init_unistr(&job_info->document, queue->fs_file);
6373 init_unistr(&job_info->datatype, "RAW");
6374 init_unistr(&job_info->text_status, "");
6375 job_info->status=nt_printj_status(queue->status);
6376 job_info->priority=queue->priority;
6377 job_info->position=position;
6378 job_info->totalpages=queue->page_count;
6379 job_info->pagesprinted=0;
6381 make_systemtime(&job_info->submitted, t);
6384 /****************************************************************************
6385 ****************************************************************************/
6387 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6388 int position, int snum,
6389 NT_PRINTER_INFO_LEVEL *ntprinter,
6390 DEVICEMODE *devmode)
6392 struct tm *t;
6394 t=gmtime(&queue->time);
6396 job_info->jobid=queue->job;
6398 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6400 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6401 init_unistr(&job_info->username, queue->fs_user);
6402 init_unistr(&job_info->document, queue->fs_file);
6403 init_unistr(&job_info->notifyname, queue->fs_user);
6404 init_unistr(&job_info->datatype, "RAW");
6405 init_unistr(&job_info->printprocessor, "winprint");
6406 init_unistr(&job_info->parameters, "");
6407 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6408 init_unistr(&job_info->text_status, "");
6410 /* and here the security descriptor */
6412 job_info->status=nt_printj_status(queue->status);
6413 job_info->priority=queue->priority;
6414 job_info->position=position;
6415 job_info->starttime=0;
6416 job_info->untiltime=0;
6417 job_info->totalpages=queue->page_count;
6418 job_info->size=queue->size;
6419 make_systemtime(&(job_info->submitted), t);
6420 job_info->timeelapsed=0;
6421 job_info->pagesprinted=0;
6423 job_info->devmode = devmode;
6425 return (True);
6428 /****************************************************************************
6429 Enumjobs at level 1.
6430 ****************************************************************************/
6432 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6433 NT_PRINTER_INFO_LEVEL *ntprinter,
6434 NEW_BUFFER *buffer, uint32 offered,
6435 uint32 *needed, uint32 *returned)
6437 JOB_INFO_1 *info;
6438 int i;
6440 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6441 if (info==NULL) {
6442 SAFE_FREE(queue);
6443 *returned=0;
6444 return WERR_NOMEM;
6447 for (i=0; i<*returned; i++)
6448 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6450 SAFE_FREE(queue);
6452 /* check the required size. */
6453 for (i=0; i<*returned; i++)
6454 (*needed) += spoolss_size_job_info_1(&info[i]);
6456 if (!alloc_buffer_size(buffer, *needed)) {
6457 SAFE_FREE(info);
6458 return WERR_INSUFFICIENT_BUFFER;
6461 /* fill the buffer with the structures */
6462 for (i=0; i<*returned; i++)
6463 smb_io_job_info_1("", buffer, &info[i], 0);
6465 /* clear memory */
6466 SAFE_FREE(info);
6468 if (*needed > offered) {
6469 *returned=0;
6470 return WERR_INSUFFICIENT_BUFFER;
6473 return WERR_OK;
6476 /****************************************************************************
6477 Enumjobs at level 2.
6478 ****************************************************************************/
6480 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6481 NT_PRINTER_INFO_LEVEL *ntprinter,
6482 NEW_BUFFER *buffer, uint32 offered,
6483 uint32 *needed, uint32 *returned)
6485 JOB_INFO_2 *info = NULL;
6486 int i;
6487 WERROR result;
6488 DEVICEMODE *devmode = NULL;
6490 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6491 if (info==NULL) {
6492 *returned=0;
6493 result = WERR_NOMEM;
6494 goto done;
6497 /* this should not be a failure condition if the devmode is NULL */
6499 devmode = construct_dev_mode(snum);
6501 for (i=0; i<*returned; i++)
6502 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6503 devmode);
6505 free_a_printer(&ntprinter, 2);
6506 SAFE_FREE(queue);
6508 /* check the required size. */
6509 for (i=0; i<*returned; i++)
6510 (*needed) += spoolss_size_job_info_2(&info[i]);
6512 if (*needed > offered) {
6513 *returned=0;
6514 result = WERR_INSUFFICIENT_BUFFER;
6515 goto done;
6518 if (!alloc_buffer_size(buffer, *needed)) {
6519 SAFE_FREE(info);
6520 result = WERR_INSUFFICIENT_BUFFER;
6521 goto done;
6524 /* fill the buffer with the structures */
6525 for (i=0; i<*returned; i++)
6526 smb_io_job_info_2("", buffer, &info[i], 0);
6528 result = WERR_OK;
6530 done:
6531 free_a_printer(&ntprinter, 2);
6532 free_devmode(devmode);
6533 SAFE_FREE(queue);
6534 SAFE_FREE(info);
6536 return result;
6540 /****************************************************************************
6541 Enumjobs.
6542 ****************************************************************************/
6544 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6546 POLICY_HND *handle = &q_u->handle;
6547 uint32 level = q_u->level;
6548 NEW_BUFFER *buffer = NULL;
6549 uint32 offered = q_u->offered;
6550 uint32 *needed = &r_u->needed;
6551 uint32 *returned = &r_u->returned;
6552 WERROR wret;
6553 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6554 int snum;
6555 print_status_struct prt_status;
6556 print_queue_struct *queue=NULL;
6558 /* that's an [in out] buffer */
6559 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6560 buffer = r_u->buffer;
6562 DEBUG(4,("_spoolss_enumjobs\n"));
6564 *needed=0;
6565 *returned=0;
6567 /* lookup the printer snum and tdb entry */
6569 if (!get_printer_snum(p, handle, &snum))
6570 return WERR_BADFID;
6572 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6573 if ( !W_ERROR_IS_OK(wret) )
6574 return wret;
6576 *returned = print_queue_status(snum, &queue, &prt_status);
6577 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6579 if (*returned == 0) {
6580 SAFE_FREE(queue);
6581 return WERR_OK;
6584 switch (level) {
6585 case 1:
6586 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6587 return wret;
6588 case 2:
6589 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6590 return wret;
6591 default:
6592 SAFE_FREE(queue);
6593 *returned=0;
6594 wret = WERR_UNKNOWN_LEVEL;
6597 free_a_printer( &ntprinter, 2 );
6598 return wret;
6601 /****************************************************************************
6602 ****************************************************************************/
6604 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6606 return WERR_OK;
6609 /****************************************************************************
6610 ****************************************************************************/
6612 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6614 POLICY_HND *handle = &q_u->handle;
6615 uint32 jobid = q_u->jobid;
6616 uint32 command = q_u->command;
6618 struct current_user user;
6619 int snum;
6620 WERROR errcode = WERR_BADFUNC;
6622 if (!get_printer_snum(p, handle, &snum)) {
6623 return WERR_BADFID;
6626 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6627 return WERR_INVALID_PRINTER_NAME;
6630 get_current_user(&user, p);
6632 switch (command) {
6633 case JOB_CONTROL_CANCEL:
6634 case JOB_CONTROL_DELETE:
6635 if (print_job_delete(&user, snum, jobid, &errcode)) {
6636 errcode = WERR_OK;
6638 break;
6639 case JOB_CONTROL_PAUSE:
6640 if (print_job_pause(&user, snum, jobid, &errcode)) {
6641 errcode = WERR_OK;
6643 break;
6644 case JOB_CONTROL_RESTART:
6645 case JOB_CONTROL_RESUME:
6646 if (print_job_resume(&user, snum, jobid, &errcode)) {
6647 errcode = WERR_OK;
6649 break;
6650 default:
6651 return WERR_UNKNOWN_LEVEL;
6654 return errcode;
6657 /****************************************************************************
6658 Enumerates all printer drivers at level 1.
6659 ****************************************************************************/
6661 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6663 int i;
6664 int ndrivers;
6665 uint32 version;
6666 fstring *list = NULL;
6668 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6669 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6671 *returned=0;
6673 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6674 list=NULL;
6675 ndrivers=get_ntdrivers(&list, architecture, version);
6676 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6678 if(ndrivers == -1)
6679 return WERR_NOMEM;
6681 if(ndrivers != 0) {
6682 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6683 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6684 SAFE_FREE(driver_info_1);
6685 SAFE_FREE(list);
6686 return WERR_NOMEM;
6688 else driver_info_1 = tdi1;
6691 for (i=0; i<ndrivers; i++) {
6692 WERROR status;
6693 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6694 ZERO_STRUCT(driver);
6695 status = get_a_printer_driver(&driver, 3, list[i],
6696 architecture, version);
6697 if (!W_ERROR_IS_OK(status)) {
6698 SAFE_FREE(list);
6699 return status;
6701 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6702 free_a_printer_driver(driver, 3);
6705 *returned+=ndrivers;
6706 SAFE_FREE(list);
6709 /* check the required size. */
6710 for (i=0; i<*returned; i++) {
6711 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6712 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6715 if (!alloc_buffer_size(buffer, *needed)) {
6716 SAFE_FREE(driver_info_1);
6717 return WERR_INSUFFICIENT_BUFFER;
6720 /* fill the buffer with the driver structures */
6721 for (i=0; i<*returned; i++) {
6722 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6723 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6726 SAFE_FREE(driver_info_1);
6728 if (*needed > offered) {
6729 *returned=0;
6730 return WERR_INSUFFICIENT_BUFFER;
6733 return WERR_OK;
6736 /****************************************************************************
6737 Enumerates all printer drivers at level 2.
6738 ****************************************************************************/
6740 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6742 int i;
6743 int ndrivers;
6744 uint32 version;
6745 fstring *list = NULL;
6747 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6748 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6750 *returned=0;
6752 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6753 list=NULL;
6754 ndrivers=get_ntdrivers(&list, architecture, version);
6755 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6757 if(ndrivers == -1)
6758 return WERR_NOMEM;
6760 if(ndrivers != 0) {
6761 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6762 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6763 SAFE_FREE(driver_info_2);
6764 SAFE_FREE(list);
6765 return WERR_NOMEM;
6767 else driver_info_2 = tdi2;
6770 for (i=0; i<ndrivers; i++) {
6771 WERROR status;
6773 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6774 ZERO_STRUCT(driver);
6775 status = get_a_printer_driver(&driver, 3, list[i],
6776 architecture, version);
6777 if (!W_ERROR_IS_OK(status)) {
6778 SAFE_FREE(list);
6779 return status;
6781 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6782 free_a_printer_driver(driver, 3);
6785 *returned+=ndrivers;
6786 SAFE_FREE(list);
6789 /* check the required size. */
6790 for (i=0; i<*returned; i++) {
6791 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6792 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6795 if (!alloc_buffer_size(buffer, *needed)) {
6796 SAFE_FREE(driver_info_2);
6797 return WERR_INSUFFICIENT_BUFFER;
6800 /* fill the buffer with the form structures */
6801 for (i=0; i<*returned; i++) {
6802 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6803 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6806 SAFE_FREE(driver_info_2);
6808 if (*needed > offered) {
6809 *returned=0;
6810 return WERR_INSUFFICIENT_BUFFER;
6813 return WERR_OK;
6816 /****************************************************************************
6817 Enumerates all printer drivers at level 3.
6818 ****************************************************************************/
6820 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6822 int i;
6823 int ndrivers;
6824 uint32 version;
6825 fstring *list = NULL;
6827 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6828 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6830 *returned=0;
6832 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6833 list=NULL;
6834 ndrivers=get_ntdrivers(&list, architecture, version);
6835 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6837 if(ndrivers == -1)
6838 return WERR_NOMEM;
6840 if(ndrivers != 0) {
6841 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6842 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6843 SAFE_FREE(driver_info_3);
6844 SAFE_FREE(list);
6845 return WERR_NOMEM;
6847 else driver_info_3 = tdi3;
6850 for (i=0; i<ndrivers; i++) {
6851 WERROR status;
6853 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6854 ZERO_STRUCT(driver);
6855 status = get_a_printer_driver(&driver, 3, list[i],
6856 architecture, version);
6857 if (!W_ERROR_IS_OK(status)) {
6858 SAFE_FREE(list);
6859 return status;
6861 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6862 free_a_printer_driver(driver, 3);
6865 *returned+=ndrivers;
6866 SAFE_FREE(list);
6869 /* check the required size. */
6870 for (i=0; i<*returned; i++) {
6871 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6872 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6875 if (!alloc_buffer_size(buffer, *needed)) {
6876 SAFE_FREE(driver_info_3);
6877 return WERR_INSUFFICIENT_BUFFER;
6880 /* fill the buffer with the driver structures */
6881 for (i=0; i<*returned; i++) {
6882 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6883 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6886 for (i=0; i<*returned; i++)
6887 SAFE_FREE(driver_info_3[i].dependentfiles);
6889 SAFE_FREE(driver_info_3);
6891 if (*needed > offered) {
6892 *returned=0;
6893 return WERR_INSUFFICIENT_BUFFER;
6896 return WERR_OK;
6899 /****************************************************************************
6900 Enumerates all printer drivers.
6901 ****************************************************************************/
6903 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6905 uint32 level = q_u->level;
6906 NEW_BUFFER *buffer = NULL;
6907 uint32 offered = q_u->offered;
6908 uint32 *needed = &r_u->needed;
6909 uint32 *returned = &r_u->returned;
6911 fstring *list = NULL;
6912 fstring servername;
6913 fstring architecture;
6915 /* that's an [in out] buffer */
6916 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6917 buffer = r_u->buffer;
6919 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6920 *needed=0;
6921 *returned=0;
6923 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6924 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6926 if ( !is_myname_or_ipaddr( servername ) )
6927 return WERR_UNKNOWN_PRINTER_DRIVER;
6929 switch (level) {
6930 case 1:
6931 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6932 case 2:
6933 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6934 case 3:
6935 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6936 default:
6937 *returned=0;
6938 SAFE_FREE(list);
6939 return WERR_UNKNOWN_LEVEL;
6943 /****************************************************************************
6944 ****************************************************************************/
6946 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6948 form->flag=list->flag;
6949 init_unistr(&form->name, list->name);
6950 form->width=list->width;
6951 form->length=list->length;
6952 form->left=list->left;
6953 form->top=list->top;
6954 form->right=list->right;
6955 form->bottom=list->bottom;
6958 /****************************************************************************
6959 ****************************************************************************/
6961 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6963 uint32 level = q_u->level;
6964 NEW_BUFFER *buffer = NULL;
6965 uint32 offered = q_u->offered;
6966 uint32 *needed = &r_u->needed;
6967 uint32 *numofforms = &r_u->numofforms;
6968 uint32 numbuiltinforms;
6970 nt_forms_struct *list=NULL;
6971 nt_forms_struct *builtinlist=NULL;
6972 FORM_1 *forms_1;
6973 int buffer_size=0;
6974 int i;
6976 /* that's an [in out] buffer */
6977 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6978 buffer = r_u->buffer;
6980 DEBUG(4,("_spoolss_enumforms\n"));
6981 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6982 DEBUGADD(5,("Info level [%d]\n", level));
6984 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6985 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6986 *numofforms = get_ntforms(&list);
6987 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6988 *numofforms += numbuiltinforms;
6990 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6992 switch (level) {
6993 case 1:
6994 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6995 *numofforms=0;
6996 return WERR_NOMEM;
6999 /* construct the list of form structures */
7000 for (i=0; i<numbuiltinforms; i++) {
7001 DEBUGADD(6,("Filling form number [%d]\n",i));
7002 fill_form_1(&forms_1[i], &builtinlist[i]);
7005 SAFE_FREE(builtinlist);
7007 for (; i<*numofforms; i++) {
7008 DEBUGADD(6,("Filling form number [%d]\n",i));
7009 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7012 SAFE_FREE(list);
7014 /* check the required size. */
7015 for (i=0; i<numbuiltinforms; i++) {
7016 DEBUGADD(6,("adding form [%d]'s size\n",i));
7017 buffer_size += spoolss_size_form_1(&forms_1[i]);
7019 for (; i<*numofforms; i++) {
7020 DEBUGADD(6,("adding form [%d]'s size\n",i));
7021 buffer_size += spoolss_size_form_1(&forms_1[i]);
7024 *needed=buffer_size;
7026 if (!alloc_buffer_size(buffer, buffer_size)){
7027 SAFE_FREE(forms_1);
7028 return WERR_INSUFFICIENT_BUFFER;
7031 /* fill the buffer with the form structures */
7032 for (i=0; i<numbuiltinforms; i++) {
7033 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7034 smb_io_form_1("", buffer, &forms_1[i], 0);
7036 for (; i<*numofforms; i++) {
7037 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7038 smb_io_form_1("", buffer, &forms_1[i], 0);
7041 SAFE_FREE(forms_1);
7043 if (*needed > offered) {
7044 *numofforms=0;
7045 return WERR_INSUFFICIENT_BUFFER;
7047 else
7048 return WERR_OK;
7050 default:
7051 SAFE_FREE(list);
7052 SAFE_FREE(builtinlist);
7053 return WERR_UNKNOWN_LEVEL;
7058 /****************************************************************************
7059 ****************************************************************************/
7061 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7063 uint32 level = q_u->level;
7064 UNISTR2 *uni_formname = &q_u->formname;
7065 NEW_BUFFER *buffer = NULL;
7066 uint32 offered = q_u->offered;
7067 uint32 *needed = &r_u->needed;
7069 nt_forms_struct *list=NULL;
7070 nt_forms_struct builtin_form;
7071 BOOL foundBuiltin;
7072 FORM_1 form_1;
7073 fstring form_name;
7074 int buffer_size=0;
7075 int numofforms=0, i=0;
7077 /* that's an [in out] buffer */
7078 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7079 buffer = r_u->buffer;
7081 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7083 DEBUG(4,("_spoolss_getform\n"));
7084 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7085 DEBUGADD(5,("Info level [%d]\n", level));
7087 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7088 if (!foundBuiltin) {
7089 numofforms = get_ntforms(&list);
7090 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7092 if (numofforms == 0)
7093 return WERR_BADFID;
7096 switch (level) {
7097 case 1:
7098 if (foundBuiltin) {
7099 fill_form_1(&form_1, &builtin_form);
7100 } else {
7102 /* Check if the requested name is in the list of form structures */
7103 for (i=0; i<numofforms; i++) {
7105 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7107 if (strequal(form_name, list[i].name)) {
7108 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7109 fill_form_1(&form_1, &list[i]);
7110 break;
7114 SAFE_FREE(list);
7115 if (i == numofforms) {
7116 return WERR_BADFID;
7119 /* check the required size. */
7121 *needed=spoolss_size_form_1(&form_1);
7123 if (!alloc_buffer_size(buffer, buffer_size)){
7124 return WERR_INSUFFICIENT_BUFFER;
7127 if (*needed > offered) {
7128 return WERR_INSUFFICIENT_BUFFER;
7131 /* fill the buffer with the form structures */
7132 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7133 smb_io_form_1("", buffer, &form_1, 0);
7135 return WERR_OK;
7137 default:
7138 SAFE_FREE(list);
7139 return WERR_UNKNOWN_LEVEL;
7143 /****************************************************************************
7144 ****************************************************************************/
7146 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7148 init_unistr(&port->port_name, name);
7151 /****************************************************************************
7152 ****************************************************************************/
7154 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7156 init_unistr(&port->port_name, name);
7157 init_unistr(&port->monitor_name, "Local Monitor");
7158 init_unistr(&port->description, "Local Port");
7159 port->port_type=PORT_TYPE_WRITE;
7160 port->reserved=0x0;
7163 /****************************************************************************
7164 enumports level 1.
7165 ****************************************************************************/
7167 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7169 PORT_INFO_1 *ports=NULL;
7170 int i=0;
7172 if (*lp_enumports_cmd()) {
7173 char *cmd = lp_enumports_cmd();
7174 char **qlines;
7175 pstring command;
7176 int numlines;
7177 int ret;
7178 int fd;
7180 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7182 DEBUG(10,("Running [%s]\n", command));
7183 ret = smbrun(command, &fd);
7184 DEBUG(10,("Returned [%d]\n", ret));
7185 if (ret != 0) {
7186 if (fd != -1)
7187 close(fd);
7188 /* Is this the best error to return here? */
7189 return WERR_ACCESS_DENIED;
7192 numlines = 0;
7193 qlines = fd_lines_load(fd, &numlines);
7194 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7195 close(fd);
7197 if(numlines) {
7198 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7199 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7200 dos_errstr(WERR_NOMEM)));
7201 file_lines_free(qlines);
7202 return WERR_NOMEM;
7205 for (i=0; i<numlines; i++) {
7206 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7207 fill_port_1(&ports[i], qlines[i]);
7210 file_lines_free(qlines);
7213 *returned = numlines;
7215 } else {
7216 *returned = 1; /* Sole Samba port returned. */
7218 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7219 return WERR_NOMEM;
7221 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7223 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7226 /* check the required size. */
7227 for (i=0; i<*returned; i++) {
7228 DEBUGADD(6,("adding port [%d]'s size\n", i));
7229 *needed += spoolss_size_port_info_1(&ports[i]);
7232 if (!alloc_buffer_size(buffer, *needed)) {
7233 SAFE_FREE(ports);
7234 return WERR_INSUFFICIENT_BUFFER;
7237 /* fill the buffer with the ports structures */
7238 for (i=0; i<*returned; i++) {
7239 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7240 smb_io_port_1("", buffer, &ports[i], 0);
7243 SAFE_FREE(ports);
7245 if (*needed > offered) {
7246 *returned=0;
7247 return WERR_INSUFFICIENT_BUFFER;
7250 return WERR_OK;
7253 /****************************************************************************
7254 enumports level 2.
7255 ****************************************************************************/
7257 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7259 PORT_INFO_2 *ports=NULL;
7260 int i=0;
7262 if (*lp_enumports_cmd()) {
7263 char *cmd = lp_enumports_cmd();
7264 char *path;
7265 char **qlines;
7266 pstring tmp_file;
7267 pstring command;
7268 int numlines;
7269 int ret;
7270 int fd;
7272 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7273 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7274 else
7275 path = lp_lockdir();
7277 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7278 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7280 unlink(tmp_file);
7281 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7282 ret = smbrun(command, &fd);
7283 DEBUGADD(10,("returned [%d]\n", ret));
7284 if (ret != 0) {
7285 if (fd != -1)
7286 close(fd);
7287 /* Is this the best error to return here? */
7288 return WERR_ACCESS_DENIED;
7291 numlines = 0;
7292 qlines = fd_lines_load(fd, &numlines);
7293 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7294 close(fd);
7296 if(numlines) {
7297 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7298 file_lines_free(qlines);
7299 return WERR_NOMEM;
7302 for (i=0; i<numlines; i++) {
7303 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7304 fill_port_2(&(ports[i]), qlines[i]);
7307 file_lines_free(qlines);
7310 *returned = numlines;
7312 } else {
7314 *returned = 1;
7316 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7317 return WERR_NOMEM;
7319 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7321 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7324 /* check the required size. */
7325 for (i=0; i<*returned; i++) {
7326 DEBUGADD(6,("adding port [%d]'s size\n", i));
7327 *needed += spoolss_size_port_info_2(&ports[i]);
7330 if (!alloc_buffer_size(buffer, *needed)) {
7331 SAFE_FREE(ports);
7332 return WERR_INSUFFICIENT_BUFFER;
7335 /* fill the buffer with the ports structures */
7336 for (i=0; i<*returned; i++) {
7337 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7338 smb_io_port_2("", buffer, &ports[i], 0);
7341 SAFE_FREE(ports);
7343 if (*needed > offered) {
7344 *returned=0;
7345 return WERR_INSUFFICIENT_BUFFER;
7348 return WERR_OK;
7351 /****************************************************************************
7352 enumports.
7353 ****************************************************************************/
7355 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7357 uint32 level = q_u->level;
7358 NEW_BUFFER *buffer = NULL;
7359 uint32 offered = q_u->offered;
7360 uint32 *needed = &r_u->needed;
7361 uint32 *returned = &r_u->returned;
7363 /* that's an [in out] buffer */
7364 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7365 buffer = r_u->buffer;
7367 DEBUG(4,("_spoolss_enumports\n"));
7369 *returned=0;
7370 *needed=0;
7372 switch (level) {
7373 case 1:
7374 return enumports_level_1(buffer, offered, needed, returned);
7375 case 2:
7376 return enumports_level_2(buffer, offered, needed, returned);
7377 default:
7378 return WERR_UNKNOWN_LEVEL;
7382 /****************************************************************************
7383 ****************************************************************************/
7385 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7386 const SPOOL_PRINTER_INFO_LEVEL *info,
7387 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7388 uint32 user_switch, const SPOOL_USER_CTR *user,
7389 POLICY_HND *handle)
7391 NT_PRINTER_INFO_LEVEL *printer = NULL;
7392 fstring name;
7393 int snum;
7394 WERROR err = WERR_OK;
7396 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7397 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7398 return WERR_NOMEM;
7401 ZERO_STRUCTP(printer);
7403 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7404 if (!convert_printer_info(info, printer, 2)) {
7405 free_a_printer(&printer, 2);
7406 return WERR_NOMEM;
7409 /* check to see if the printer already exists */
7411 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7412 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7413 printer->info_2->sharename));
7414 free_a_printer(&printer, 2);
7415 return WERR_PRINTER_ALREADY_EXISTS;
7418 /* FIXME!!! smbd should check to see if the driver is installed before
7419 trying to add a printer like this --jerry */
7421 if (*lp_addprinter_cmd() ) {
7422 if ( !add_printer_hook(printer) ) {
7423 free_a_printer(&printer,2);
7424 return WERR_ACCESS_DENIED;
7428 /* use our primary netbios name since get_a_printer() will convert
7429 it to what the client expects on a case by case basis */
7431 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7432 printer->info_2->sharename);
7435 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7436 free_a_printer(&printer,2);
7437 return WERR_ACCESS_DENIED;
7440 /* you must be a printer admin to add a new printer */
7441 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7442 free_a_printer(&printer,2);
7443 return WERR_ACCESS_DENIED;
7447 * Do sanity check on the requested changes for Samba.
7450 if (!check_printer_ok(printer->info_2, snum)) {
7451 free_a_printer(&printer,2);
7452 return WERR_INVALID_PARAM;
7456 * When a printer is created, the drivername bound to the printer is used
7457 * to lookup previously saved driver initialization info, which is then
7458 * bound to the new printer, simulating what happens in the Windows arch.
7461 if (!devmode)
7463 set_driver_init(printer, 2);
7465 else
7467 /* A valid devmode was included, convert and link it
7469 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7471 if (!convert_devicemode(printer->info_2->printername, devmode,
7472 &printer->info_2->devmode))
7473 return WERR_NOMEM;
7476 /* write the ASCII on disk */
7477 err = mod_a_printer(printer, 2);
7478 if (!W_ERROR_IS_OK(err)) {
7479 free_a_printer(&printer,2);
7480 return err;
7483 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7484 /* Handle open failed - remove addition. */
7485 del_a_printer(printer->info_2->sharename);
7486 free_a_printer(&printer,2);
7487 return WERR_ACCESS_DENIED;
7490 update_c_setprinter(False);
7491 free_a_printer(&printer,2);
7493 return WERR_OK;
7496 /****************************************************************************
7497 ****************************************************************************/
7499 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7501 UNISTR2 *uni_srv_name = &q_u->server_name;
7502 uint32 level = q_u->level;
7503 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7504 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7505 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7506 uint32 user_switch = q_u->user_switch;
7507 SPOOL_USER_CTR *user = &q_u->user_ctr;
7508 POLICY_HND *handle = &r_u->handle;
7510 switch (level) {
7511 case 1:
7512 /* we don't handle yet */
7513 /* but I know what to do ... */
7514 return WERR_UNKNOWN_LEVEL;
7515 case 2:
7516 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7517 devmode, sdb,
7518 user_switch, user, handle);
7519 default:
7520 return WERR_UNKNOWN_LEVEL;
7524 /****************************************************************************
7525 ****************************************************************************/
7527 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7529 uint32 level = q_u->level;
7530 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7531 WERROR err = WERR_OK;
7532 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7533 struct current_user user;
7534 fstring driver_name;
7535 uint32 version;
7537 ZERO_STRUCT(driver);
7539 get_current_user(&user, p);
7541 if (!convert_printer_driver_info(info, &driver, level)) {
7542 err = WERR_NOMEM;
7543 goto done;
7546 DEBUG(5,("Cleaning driver's information\n"));
7547 err = clean_up_driver_struct(driver, level, &user);
7548 if (!W_ERROR_IS_OK(err))
7549 goto done;
7551 DEBUG(5,("Moving driver to final destination\n"));
7552 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7553 if (W_ERROR_IS_OK(err))
7554 err = WERR_ACCESS_DENIED;
7555 goto done;
7558 if (add_a_printer_driver(driver, level)!=0) {
7559 err = WERR_ACCESS_DENIED;
7560 goto done;
7563 /* BEGIN_ADMIN_LOG */
7564 switch(level) {
7565 case 3:
7566 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7567 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7568 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7569 break;
7570 case 6:
7571 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7572 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7573 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7574 break;
7576 /* END_ADMIN_LOG */
7579 * I think this is where he DrvUpgradePrinter() hook would be
7580 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7581 * server. Right now, we just need to send ourselves a message
7582 * to update each printer bound to this driver. --jerry
7585 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7586 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7587 driver_name));
7591 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7592 * decide if the driver init data should be deleted. The rules are:
7593 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7594 * 2) delete init data only if there is no 2k/Xp driver
7595 * 3) always delete init data
7596 * The generalized rule is always use init data from the highest order driver.
7597 * It is necessary to follow the driver install by an initialization step to
7598 * finish off this process.
7600 if (level == 3)
7601 version = driver.info_3->cversion;
7602 else if (level == 6)
7603 version = driver.info_6->version;
7604 else
7605 version = -1;
7606 switch (version) {
7608 * 9x printer driver - never delete init data
7610 case 0:
7611 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7612 driver_name));
7613 break;
7616 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7617 * there is no 2k/Xp driver init data for this driver name.
7619 case 2:
7621 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7623 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7625 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7627 if (!del_driver_init(driver_name))
7628 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7629 } else {
7631 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7633 free_a_printer_driver(driver1,3);
7634 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7635 driver_name));
7638 break;
7641 * 2k or Xp printer driver - always delete init data
7643 case 3:
7644 if (!del_driver_init(driver_name))
7645 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7646 break;
7648 default:
7649 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7650 break;
7654 done:
7655 free_a_printer_driver(driver, level);
7656 return err;
7659 /********************************************************************
7660 * spoolss_addprinterdriverex
7661 ********************************************************************/
7663 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7665 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7666 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7669 * we only support the semantics of AddPrinterDriver()
7670 * i.e. only copy files that are newer than existing ones
7673 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7674 return WERR_ACCESS_DENIED;
7676 ZERO_STRUCT(q_u_local);
7677 ZERO_STRUCT(r_u_local);
7679 /* just pass the information off to _spoolss_addprinterdriver() */
7680 q_u_local.server_name_ptr = q_u->server_name_ptr;
7681 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7682 q_u_local.level = q_u->level;
7683 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7685 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7688 /****************************************************************************
7689 ****************************************************************************/
7691 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7693 init_unistr(&info->name, name);
7696 /****************************************************************************
7697 ****************************************************************************/
7699 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7701 pstring path;
7702 pstring long_archi;
7703 fstring servername;
7704 char *pservername;
7705 const char *short_archi;
7706 DRIVER_DIRECTORY_1 *info=NULL;
7708 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7709 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7711 /* check for beginning double '\'s and that the server
7712 long enough */
7714 pservername = servername;
7715 if ( *pservername == '\\' && strlen(servername)>2 ) {
7716 pservername += 2;
7719 if ( !is_myname_or_ipaddr( pservername ) )
7720 return WERR_INVALID_PARAM;
7722 if (!(short_archi = get_short_archi(long_archi)))
7723 return WERR_INVALID_ENVIRONMENT;
7725 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7726 return WERR_NOMEM;
7728 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7730 DEBUG(4,("printer driver directory: [%s]\n", path));
7732 fill_driverdir_1(info, path);
7734 *needed += spoolss_size_driverdir_info_1(info);
7736 if (!alloc_buffer_size(buffer, *needed)) {
7737 SAFE_FREE(info);
7738 return WERR_INSUFFICIENT_BUFFER;
7741 smb_io_driverdir_1("", buffer, info, 0);
7743 SAFE_FREE(info);
7745 if (*needed > offered)
7746 return WERR_INSUFFICIENT_BUFFER;
7748 return WERR_OK;
7751 /****************************************************************************
7752 ****************************************************************************/
7754 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7756 UNISTR2 *name = &q_u->name;
7757 UNISTR2 *uni_environment = &q_u->environment;
7758 uint32 level = q_u->level;
7759 NEW_BUFFER *buffer = NULL;
7760 uint32 offered = q_u->offered;
7761 uint32 *needed = &r_u->needed;
7763 /* that's an [in out] buffer */
7764 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7765 buffer = r_u->buffer;
7767 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7769 *needed=0;
7771 switch(level) {
7772 case 1:
7773 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7774 default:
7775 return WERR_UNKNOWN_LEVEL;
7779 /****************************************************************************
7780 ****************************************************************************/
7782 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7784 POLICY_HND *handle = &q_u->handle;
7785 uint32 idx = q_u->index;
7786 uint32 in_value_len = q_u->valuesize;
7787 uint32 in_data_len = q_u->datasize;
7788 uint32 *out_max_value_len = &r_u->valuesize;
7789 uint16 **out_value = &r_u->value;
7790 uint32 *out_value_len = &r_u->realvaluesize;
7791 uint32 *out_type = &r_u->type;
7792 uint32 *out_max_data_len = &r_u->datasize;
7793 uint8 **data_out = &r_u->data;
7794 uint32 *out_data_len = &r_u->realdatasize;
7796 NT_PRINTER_INFO_LEVEL *printer = NULL;
7798 uint32 biggest_valuesize;
7799 uint32 biggest_datasize;
7800 uint32 data_len;
7801 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7802 int snum;
7803 WERROR result;
7804 REGISTRY_VALUE *val = NULL;
7805 NT_PRINTER_DATA *p_data;
7806 int i, key_index, num_values;
7807 int name_length;
7809 ZERO_STRUCT( printer );
7811 *out_type = 0;
7813 *out_max_data_len = 0;
7814 *data_out = NULL;
7815 *out_data_len = 0;
7817 DEBUG(5,("spoolss_enumprinterdata\n"));
7819 if (!Printer) {
7820 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7821 return WERR_BADFID;
7824 if (!get_printer_snum(p,handle, &snum))
7825 return WERR_BADFID;
7827 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7828 if (!W_ERROR_IS_OK(result))
7829 return result;
7831 p_data = &printer->info_2->data;
7832 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7834 result = WERR_OK;
7837 * The NT machine wants to know the biggest size of value and data
7839 * cf: MSDN EnumPrinterData remark section
7842 if ( !in_value_len && !in_data_len && (key_index != -1) )
7844 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7846 biggest_valuesize = 0;
7847 biggest_datasize = 0;
7849 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7851 for ( i=0; i<num_values; i++ )
7853 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7855 name_length = strlen(val->valuename);
7856 if ( strlen(val->valuename) > biggest_valuesize )
7857 biggest_valuesize = name_length;
7859 if ( val->size > biggest_datasize )
7860 biggest_datasize = val->size;
7862 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7863 biggest_datasize));
7866 /* the value is an UNICODE string but real_value_size is the length
7867 in bytes including the trailing 0 */
7869 *out_value_len = 2 * (1+biggest_valuesize);
7870 *out_data_len = biggest_datasize;
7872 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7874 goto done;
7878 * the value len is wrong in NT sp3
7879 * that's the number of bytes not the number of unicode chars
7882 if ( key_index != -1 )
7883 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7885 if ( !val )
7888 /* out_value should default to "" or else NT4 has
7889 problems unmarshalling the response */
7891 *out_max_value_len=(in_value_len/sizeof(uint16));
7893 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7895 result = WERR_NOMEM;
7896 goto done;
7899 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7901 /* the data is counted in bytes */
7903 *out_max_data_len = in_data_len;
7904 *out_data_len = in_data_len;
7906 /* only allocate when given a non-zero data_len */
7908 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7910 result = WERR_NOMEM;
7911 goto done;
7914 result = WERR_NO_MORE_ITEMS;
7916 else
7919 * the value is:
7920 * - counted in bytes in the request
7921 * - counted in UNICODE chars in the max reply
7922 * - counted in bytes in the real size
7924 * take a pause *before* coding not *during* coding
7927 /* name */
7928 *out_max_value_len=(in_value_len/sizeof(uint16));
7929 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7931 result = WERR_NOMEM;
7932 goto done;
7935 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7937 /* type */
7939 *out_type = regval_type( val );
7941 /* data - counted in bytes */
7943 *out_max_data_len = in_data_len;
7944 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7946 result = WERR_NOMEM;
7947 goto done;
7949 data_len = (size_t)regval_size(val);
7950 memcpy( *data_out, regval_data_p(val), data_len );
7951 *out_data_len = data_len;
7954 done:
7955 free_a_printer(&printer, 2);
7956 return result;
7959 /****************************************************************************
7960 ****************************************************************************/
7962 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7964 POLICY_HND *handle = &q_u->handle;
7965 UNISTR2 *value = &q_u->value;
7966 uint32 type = q_u->type;
7967 uint8 *data = q_u->data;
7968 uint32 real_len = q_u->real_len;
7970 NT_PRINTER_INFO_LEVEL *printer = NULL;
7971 int snum=0;
7972 WERROR status = WERR_OK;
7973 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7974 fstring valuename;
7976 DEBUG(5,("spoolss_setprinterdata\n"));
7978 if (!Printer) {
7979 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7980 return WERR_BADFID;
7983 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7984 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7985 return WERR_INVALID_PARAM;
7988 if (!get_printer_snum(p,handle, &snum))
7989 return WERR_BADFID;
7992 * Access check : NT returns "access denied" if you make a
7993 * SetPrinterData call without the necessary privildge.
7994 * we were originally returning OK if nothing changed
7995 * which made Win2k issue **a lot** of SetPrinterData
7996 * when connecting to a printer --jerry
7999 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8001 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8002 status = WERR_ACCESS_DENIED;
8003 goto done;
8006 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8007 if (!W_ERROR_IS_OK(status))
8008 return status;
8010 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8013 * When client side code sets a magic printer data key, detect it and save
8014 * the current printer data and the magic key's data (its the DEVMODE) for
8015 * future printer/driver initializations.
8017 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8019 /* Set devmode and printer initialization info */
8020 status = save_driver_init( printer, 2, data, real_len );
8022 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8024 else
8026 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8027 type, data, real_len );
8028 if ( W_ERROR_IS_OK(status) )
8029 status = mod_a_printer(printer, 2);
8032 done:
8033 free_a_printer(&printer, 2);
8035 return status;
8038 /****************************************************************************
8039 ****************************************************************************/
8041 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8043 POLICY_HND *handle = &q_u->handle;
8044 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8045 int snum;
8047 DEBUG(5,("_spoolss_resetprinter\n"));
8050 * All we do is to check to see if the handle and queue is valid.
8051 * This call really doesn't mean anything to us because we only
8052 * support RAW printing. --jerry
8055 if (!Printer) {
8056 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8057 return WERR_BADFID;
8060 if (!get_printer_snum(p,handle, &snum))
8061 return WERR_BADFID;
8064 /* blindly return success */
8065 return WERR_OK;
8069 /****************************************************************************
8070 ****************************************************************************/
8072 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8074 POLICY_HND *handle = &q_u->handle;
8075 UNISTR2 *value = &q_u->valuename;
8077 NT_PRINTER_INFO_LEVEL *printer = NULL;
8078 int snum=0;
8079 WERROR status = WERR_OK;
8080 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8081 pstring valuename;
8083 DEBUG(5,("spoolss_deleteprinterdata\n"));
8085 if (!Printer) {
8086 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8087 return WERR_BADFID;
8090 if (!get_printer_snum(p, handle, &snum))
8091 return WERR_BADFID;
8093 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8094 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8095 return WERR_ACCESS_DENIED;
8098 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8099 if (!W_ERROR_IS_OK(status))
8100 return status;
8102 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8104 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8106 if ( W_ERROR_IS_OK(status) )
8107 mod_a_printer( printer, 2 );
8109 free_a_printer(&printer, 2);
8111 return status;
8114 /****************************************************************************
8115 ****************************************************************************/
8117 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8119 POLICY_HND *handle = &q_u->handle;
8120 FORM *form = &q_u->form;
8121 nt_forms_struct tmpForm;
8122 int snum;
8123 WERROR status = WERR_OK;
8124 NT_PRINTER_INFO_LEVEL *printer = NULL;
8126 int count=0;
8127 nt_forms_struct *list=NULL;
8128 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8130 DEBUG(5,("spoolss_addform\n"));
8132 if (!Printer) {
8133 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8134 return WERR_BADFID;
8138 /* forms can be added on printer of on the print server handle */
8140 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8142 if (!get_printer_snum(p,handle, &snum))
8143 return WERR_BADFID;
8145 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8146 if (!W_ERROR_IS_OK(status))
8147 goto done;
8150 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8151 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8152 status = WERR_ACCESS_DENIED;
8153 goto done;
8156 /* can't add if builtin */
8158 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8159 status = WERR_ALREADY_EXISTS;
8160 goto done;
8163 count = get_ntforms(&list);
8165 if(!add_a_form(&list, form, &count)) {
8166 status = WERR_NOMEM;
8167 goto done;
8170 write_ntforms(&list, count);
8173 * ChangeID must always be set if this is a printer
8176 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8177 status = mod_a_printer(printer, 2);
8179 done:
8180 if ( printer )
8181 free_a_printer(&printer, 2);
8182 SAFE_FREE(list);
8184 return status;
8187 /****************************************************************************
8188 ****************************************************************************/
8190 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8192 POLICY_HND *handle = &q_u->handle;
8193 UNISTR2 *form_name = &q_u->name;
8194 nt_forms_struct tmpForm;
8195 int count=0;
8196 nt_forms_struct *list=NULL;
8197 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8198 int snum;
8199 WERROR status = WERR_OK;
8200 NT_PRINTER_INFO_LEVEL *printer = NULL;
8202 DEBUG(5,("spoolss_deleteform\n"));
8204 if (!Printer) {
8205 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8206 return WERR_BADFID;
8209 /* forms can be deleted on printer of on the print server handle */
8211 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8213 if (!get_printer_snum(p,handle, &snum))
8214 return WERR_BADFID;
8216 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8217 if (!W_ERROR_IS_OK(status))
8218 goto done;
8221 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8222 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8223 status = WERR_ACCESS_DENIED;
8224 goto done;
8227 /* can't delete if builtin */
8229 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8230 status = WERR_INVALID_PARAM;
8231 goto done;
8234 count = get_ntforms(&list);
8236 if ( !delete_a_form(&list, form_name, &count, &status ))
8237 goto done;
8240 * ChangeID must always be set if this is a printer
8243 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8244 status = mod_a_printer(printer, 2);
8246 done:
8247 if ( printer )
8248 free_a_printer(&printer, 2);
8249 SAFE_FREE(list);
8251 return status;
8254 /****************************************************************************
8255 ****************************************************************************/
8257 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8259 POLICY_HND *handle = &q_u->handle;
8260 FORM *form = &q_u->form;
8261 nt_forms_struct tmpForm;
8262 int snum;
8263 WERROR status = WERR_OK;
8264 NT_PRINTER_INFO_LEVEL *printer = NULL;
8266 int count=0;
8267 nt_forms_struct *list=NULL;
8268 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8270 DEBUG(5,("spoolss_setform\n"));
8272 if (!Printer) {
8273 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8274 return WERR_BADFID;
8277 /* forms can be modified on printer of on the print server handle */
8279 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8281 if (!get_printer_snum(p,handle, &snum))
8282 return WERR_BADFID;
8284 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8285 if (!W_ERROR_IS_OK(status))
8286 goto done;
8289 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8290 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8291 status = WERR_ACCESS_DENIED;
8292 goto done;
8295 /* can't set if builtin */
8296 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8297 status = WERR_INVALID_PARAM;
8298 goto done;
8301 count = get_ntforms(&list);
8302 update_a_form(&list, form, count);
8303 write_ntforms(&list, count);
8306 * ChangeID must always be set if this is a printer
8309 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8310 status = mod_a_printer(printer, 2);
8313 done:
8314 if ( printer )
8315 free_a_printer(&printer, 2);
8316 SAFE_FREE(list);
8318 return status;
8321 /****************************************************************************
8322 enumprintprocessors level 1.
8323 ****************************************************************************/
8325 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8327 PRINTPROCESSOR_1 *info_1=NULL;
8329 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8330 return WERR_NOMEM;
8332 (*returned) = 0x1;
8334 init_unistr(&info_1->name, "winprint");
8336 *needed += spoolss_size_printprocessor_info_1(info_1);
8338 if (!alloc_buffer_size(buffer, *needed))
8339 return WERR_INSUFFICIENT_BUFFER;
8341 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8343 SAFE_FREE(info_1);
8345 if (*needed > offered) {
8346 *returned=0;
8347 return WERR_INSUFFICIENT_BUFFER;
8350 return WERR_OK;
8353 /****************************************************************************
8354 ****************************************************************************/
8356 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8358 uint32 level = q_u->level;
8359 NEW_BUFFER *buffer = NULL;
8360 uint32 offered = q_u->offered;
8361 uint32 *needed = &r_u->needed;
8362 uint32 *returned = &r_u->returned;
8364 /* that's an [in out] buffer */
8365 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8366 buffer = r_u->buffer;
8368 DEBUG(5,("spoolss_enumprintprocessors\n"));
8371 * Enumerate the print processors ...
8373 * Just reply with "winprint", to keep NT happy
8374 * and I can use my nice printer checker.
8377 *returned=0;
8378 *needed=0;
8380 switch (level) {
8381 case 1:
8382 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8383 default:
8384 return WERR_UNKNOWN_LEVEL;
8388 /****************************************************************************
8389 enumprintprocdatatypes level 1.
8390 ****************************************************************************/
8392 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8394 PRINTPROCDATATYPE_1 *info_1=NULL;
8396 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8397 return WERR_NOMEM;
8399 (*returned) = 0x1;
8401 init_unistr(&info_1->name, "RAW");
8403 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8405 if (!alloc_buffer_size(buffer, *needed))
8406 return WERR_INSUFFICIENT_BUFFER;
8408 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8410 SAFE_FREE(info_1);
8412 if (*needed > offered) {
8413 *returned=0;
8414 return WERR_INSUFFICIENT_BUFFER;
8417 return WERR_OK;
8420 /****************************************************************************
8421 ****************************************************************************/
8423 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8425 uint32 level = q_u->level;
8426 NEW_BUFFER *buffer = NULL;
8427 uint32 offered = q_u->offered;
8428 uint32 *needed = &r_u->needed;
8429 uint32 *returned = &r_u->returned;
8431 /* that's an [in out] buffer */
8432 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8433 buffer = r_u->buffer;
8435 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8437 *returned=0;
8438 *needed=0;
8440 switch (level) {
8441 case 1:
8442 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8443 default:
8444 return WERR_UNKNOWN_LEVEL;
8448 /****************************************************************************
8449 enumprintmonitors level 1.
8450 ****************************************************************************/
8452 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8454 PRINTMONITOR_1 *info_1=NULL;
8456 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8457 return WERR_NOMEM;
8459 (*returned) = 0x1;
8461 init_unistr(&info_1->name, "Local Port");
8463 *needed += spoolss_size_printmonitor_info_1(info_1);
8465 if (!alloc_buffer_size(buffer, *needed))
8466 return WERR_INSUFFICIENT_BUFFER;
8468 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8470 SAFE_FREE(info_1);
8472 if (*needed > offered) {
8473 *returned=0;
8474 return WERR_INSUFFICIENT_BUFFER;
8477 return WERR_OK;
8480 /****************************************************************************
8481 enumprintmonitors level 2.
8482 ****************************************************************************/
8484 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8486 PRINTMONITOR_2 *info_2=NULL;
8488 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8489 return WERR_NOMEM;
8491 (*returned) = 0x1;
8493 init_unistr(&info_2->name, "Local Port");
8494 init_unistr(&info_2->environment, "Windows NT X86");
8495 init_unistr(&info_2->dll_name, "localmon.dll");
8497 *needed += spoolss_size_printmonitor_info_2(info_2);
8499 if (!alloc_buffer_size(buffer, *needed))
8500 return WERR_INSUFFICIENT_BUFFER;
8502 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8504 SAFE_FREE(info_2);
8506 if (*needed > offered) {
8507 *returned=0;
8508 return WERR_INSUFFICIENT_BUFFER;
8511 return WERR_OK;
8514 /****************************************************************************
8515 ****************************************************************************/
8517 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8519 uint32 level = q_u->level;
8520 NEW_BUFFER *buffer = NULL;
8521 uint32 offered = q_u->offered;
8522 uint32 *needed = &r_u->needed;
8523 uint32 *returned = &r_u->returned;
8525 /* that's an [in out] buffer */
8526 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8527 buffer = r_u->buffer;
8529 DEBUG(5,("spoolss_enumprintmonitors\n"));
8532 * Enumerate the print monitors ...
8534 * Just reply with "Local Port", to keep NT happy
8535 * and I can use my nice printer checker.
8538 *returned=0;
8539 *needed=0;
8541 switch (level) {
8542 case 1:
8543 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8544 case 2:
8545 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8546 default:
8547 return WERR_UNKNOWN_LEVEL;
8551 /****************************************************************************
8552 ****************************************************************************/
8554 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8555 NT_PRINTER_INFO_LEVEL *ntprinter,
8556 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8557 uint32 *needed)
8559 int i=0;
8560 BOOL found=False;
8561 JOB_INFO_1 *info_1=NULL;
8563 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8565 if (info_1 == NULL) {
8566 return WERR_NOMEM;
8569 for (i=0; i<count && found==False; i++) {
8570 if ((*queue)[i].job==(int)jobid)
8571 found=True;
8574 if (found==False) {
8575 SAFE_FREE(info_1);
8576 /* NT treats not found as bad param... yet another bad choice */
8577 return WERR_INVALID_PARAM;
8580 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8582 *needed += spoolss_size_job_info_1(info_1);
8584 if (!alloc_buffer_size(buffer, *needed)) {
8585 SAFE_FREE(info_1);
8586 return WERR_INSUFFICIENT_BUFFER;
8589 smb_io_job_info_1("", buffer, info_1, 0);
8591 SAFE_FREE(info_1);
8593 if (*needed > offered)
8594 return WERR_INSUFFICIENT_BUFFER;
8596 return WERR_OK;
8599 /****************************************************************************
8600 ****************************************************************************/
8602 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8603 NT_PRINTER_INFO_LEVEL *ntprinter,
8604 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8605 uint32 *needed)
8607 int i = 0;
8608 BOOL found = False;
8609 JOB_INFO_2 *info_2;
8610 WERROR ret;
8611 DEVICEMODE *devmode = NULL;
8612 NT_DEVICEMODE *nt_devmode = NULL;
8614 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8616 ZERO_STRUCTP(info_2);
8618 if (info_2 == NULL) {
8619 ret = WERR_NOMEM;
8620 goto done;
8623 for ( i=0; i<count && found==False; i++ )
8625 if ((*queue)[i].job == (int)jobid)
8626 found = True;
8629 if ( !found )
8631 /* NT treats not found as bad param... yet another bad
8632 choice */
8633 ret = WERR_INVALID_PARAM;
8634 goto done;
8638 * if the print job does not have a DEVMODE associated with it,
8639 * just use the one for the printer. A NULL devicemode is not
8640 * a failure condition
8643 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8644 devmode = construct_dev_mode(snum);
8645 else {
8646 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8647 ZERO_STRUCTP( devmode );
8648 convert_nt_devicemode( devmode, nt_devmode );
8652 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8654 *needed += spoolss_size_job_info_2(info_2);
8656 if (!alloc_buffer_size(buffer, *needed)) {
8657 ret = WERR_INSUFFICIENT_BUFFER;
8658 goto done;
8661 smb_io_job_info_2("", buffer, info_2, 0);
8663 if (*needed > offered) {
8664 ret = WERR_INSUFFICIENT_BUFFER;
8665 goto done;
8668 ret = WERR_OK;
8670 done:
8671 /* Cleanup allocated memory */
8673 free_job_info_2(info_2); /* Also frees devmode */
8674 SAFE_FREE(info_2);
8675 free_a_printer(&ntprinter, 2);
8677 return ret;
8680 /****************************************************************************
8681 ****************************************************************************/
8683 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8685 POLICY_HND *handle = &q_u->handle;
8686 uint32 jobid = q_u->jobid;
8687 uint32 level = q_u->level;
8688 NEW_BUFFER *buffer = NULL;
8689 uint32 offered = q_u->offered;
8690 uint32 *needed = &r_u->needed;
8691 WERROR wstatus = WERR_OK;
8692 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8693 int snum;
8694 int count;
8695 print_queue_struct *queue = NULL;
8696 print_status_struct prt_status;
8698 /* that's an [in out] buffer */
8699 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8700 buffer = r_u->buffer;
8702 DEBUG(5,("spoolss_getjob\n"));
8704 *needed = 0;
8706 if (!get_printer_snum(p, handle, &snum))
8707 return WERR_BADFID;
8709 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8710 if ( !W_ERROR_IS_OK(wstatus) )
8711 return wstatus;
8713 count = print_queue_status(snum, &queue, &prt_status);
8715 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8716 count, prt_status.status, prt_status.message));
8718 switch ( level ) {
8719 case 1:
8720 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8721 buffer, offered, needed);
8722 break;
8723 case 2:
8724 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8725 buffer, offered, needed);
8726 break;
8727 default:
8728 wstatus = WERR_UNKNOWN_LEVEL;
8729 break;
8732 SAFE_FREE(queue);
8733 free_a_printer( &ntprinter, 2 );
8735 return wstatus;
8738 /********************************************************************
8739 spoolss_getprinterdataex
8741 From MSDN documentation of GetPrinterDataEx: pass request
8742 to GetPrinterData if key is "PrinterDriverData".
8743 ********************************************************************/
8745 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8747 POLICY_HND *handle = &q_u->handle;
8748 uint32 in_size = q_u->size;
8749 uint32 *type = &r_u->type;
8750 uint32 *out_size = &r_u->size;
8751 uint8 **data = &r_u->data;
8752 uint32 *needed = &r_u->needed;
8753 fstring keyname, valuename;
8755 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8757 NT_PRINTER_INFO_LEVEL *printer = NULL;
8758 int snum = 0;
8759 WERROR status = WERR_OK;
8761 DEBUG(4,("_spoolss_getprinterdataex\n"));
8763 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8764 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8766 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8767 keyname, valuename));
8769 /* in case of problem, return some default values */
8771 *needed = 0;
8772 *type = 0;
8773 *out_size = in_size;
8775 if (!Printer) {
8776 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8777 status = WERR_BADFID;
8778 goto done;
8781 /* Is the handle to a printer or to the server? */
8783 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8784 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8785 status = WERR_INVALID_PARAM;
8786 goto done;
8789 if ( !get_printer_snum(p,handle, &snum) )
8790 return WERR_BADFID;
8792 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8793 if ( !W_ERROR_IS_OK(status) )
8794 goto done;
8796 /* check to see if the keyname is valid */
8797 if ( !strlen(keyname) ) {
8798 status = WERR_INVALID_PARAM;
8799 goto done;
8802 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8803 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8804 free_a_printer( &printer, 2 );
8805 status = WERR_BADFILE;
8806 goto done;
8809 /* When given a new keyname, we should just create it */
8811 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8813 if (*needed > *out_size)
8814 status = WERR_MORE_DATA;
8816 done:
8817 if ( !W_ERROR_IS_OK(status) )
8819 DEBUG(5, ("error: allocating %d\n", *out_size));
8821 /* reply this param doesn't exist */
8823 if ( *out_size )
8825 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8826 status = WERR_NOMEM;
8827 goto done;
8830 else {
8831 *data = NULL;
8835 if ( printer )
8836 free_a_printer( &printer, 2 );
8838 return status;
8841 /********************************************************************
8842 * spoolss_setprinterdataex
8843 ********************************************************************/
8845 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8847 POLICY_HND *handle = &q_u->handle;
8848 uint32 type = q_u->type;
8849 uint8 *data = q_u->data;
8850 uint32 real_len = q_u->real_len;
8852 NT_PRINTER_INFO_LEVEL *printer = NULL;
8853 int snum = 0;
8854 WERROR status = WERR_OK;
8855 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8856 fstring valuename;
8857 fstring keyname;
8858 char *oid_string;
8860 DEBUG(4,("_spoolss_setprinterdataex\n"));
8862 /* From MSDN documentation of SetPrinterDataEx: pass request to
8863 SetPrinterData if key is "PrinterDriverData" */
8865 if (!Printer) {
8866 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8867 return WERR_BADFID;
8870 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8871 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8872 return WERR_INVALID_PARAM;
8875 if ( !get_printer_snum(p,handle, &snum) )
8876 return WERR_BADFID;
8879 * Access check : NT returns "access denied" if you make a
8880 * SetPrinterData call without the necessary privildge.
8881 * we were originally returning OK if nothing changed
8882 * which made Win2k issue **a lot** of SetPrinterData
8883 * when connecting to a printer --jerry
8886 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8888 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8889 return WERR_ACCESS_DENIED;
8892 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8893 if (!W_ERROR_IS_OK(status))
8894 return status;
8896 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8897 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8899 /* check for OID in valuename */
8901 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8903 *oid_string = '\0';
8904 oid_string++;
8907 /* save the registry data */
8909 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8911 if ( W_ERROR_IS_OK(status) )
8913 /* save the OID if one was specified */
8914 if ( oid_string ) {
8915 fstrcat( keyname, "\\" );
8916 fstrcat( keyname, SPOOL_OID_KEY );
8919 * I'm not checking the status here on purpose. Don't know
8920 * if this is right, but I'm returning the status from the
8921 * previous set_printer_dataex() call. I have no idea if
8922 * this is right. --jerry
8925 set_printer_dataex( printer, keyname, valuename,
8926 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8929 status = mod_a_printer(printer, 2);
8932 free_a_printer(&printer, 2);
8934 return status;
8938 /********************************************************************
8939 * spoolss_deleteprinterdataex
8940 ********************************************************************/
8942 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8944 POLICY_HND *handle = &q_u->handle;
8945 UNISTR2 *value = &q_u->valuename;
8946 UNISTR2 *key = &q_u->keyname;
8948 NT_PRINTER_INFO_LEVEL *printer = NULL;
8949 int snum=0;
8950 WERROR status = WERR_OK;
8951 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8952 pstring valuename, keyname;
8954 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8956 if (!Printer) {
8957 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8958 return WERR_BADFID;
8961 if (!get_printer_snum(p, handle, &snum))
8962 return WERR_BADFID;
8964 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8965 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8966 return WERR_ACCESS_DENIED;
8969 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8970 if (!W_ERROR_IS_OK(status))
8971 return status;
8973 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8974 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8976 status = delete_printer_dataex( printer, keyname, valuename );
8978 if ( W_ERROR_IS_OK(status) )
8979 mod_a_printer( printer, 2 );
8981 free_a_printer(&printer, 2);
8983 return status;
8986 /********************************************************************
8987 * spoolss_enumprinterkey
8988 ********************************************************************/
8991 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8993 fstring key;
8994 fstring *keynames = NULL;
8995 uint16 *enumkeys = NULL;
8996 int num_keys;
8997 int printerkey_len;
8998 POLICY_HND *handle = &q_u->handle;
8999 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9000 NT_PRINTER_DATA *data;
9001 NT_PRINTER_INFO_LEVEL *printer = NULL;
9002 int snum = 0;
9003 WERROR status = WERR_BADFILE;
9006 DEBUG(4,("_spoolss_enumprinterkey\n"));
9008 if (!Printer) {
9009 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9010 return WERR_BADFID;
9013 if ( !get_printer_snum(p,handle, &snum) )
9014 return WERR_BADFID;
9016 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9017 if (!W_ERROR_IS_OK(status))
9018 return status;
9020 /* get the list of subkey names */
9022 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9023 data = &printer->info_2->data;
9025 num_keys = get_printer_subkeys( data, key, &keynames );
9027 if ( num_keys == -1 ) {
9028 status = WERR_BADFILE;
9029 goto done;
9032 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9034 r_u->needed = printerkey_len*2;
9036 if ( q_u->size < r_u->needed ) {
9037 status = WERR_MORE_DATA;
9038 goto done;
9041 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9042 status = WERR_NOMEM;
9043 goto done;
9046 status = WERR_OK;
9048 if ( q_u->size < r_u->needed )
9049 status = WERR_MORE_DATA;
9051 done:
9052 free_a_printer( &printer, 2 );
9053 SAFE_FREE( keynames );
9055 return status;
9058 /********************************************************************
9059 * spoolss_deleteprinterkey
9060 ********************************************************************/
9062 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9064 POLICY_HND *handle = &q_u->handle;
9065 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9066 fstring key;
9067 NT_PRINTER_INFO_LEVEL *printer = NULL;
9068 int snum=0;
9069 WERROR status;
9071 DEBUG(5,("spoolss_deleteprinterkey\n"));
9073 if (!Printer) {
9074 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9075 return WERR_BADFID;
9078 /* if keyname == NULL, return error */
9080 if ( !q_u->keyname.buffer )
9081 return WERR_INVALID_PARAM;
9083 if (!get_printer_snum(p, handle, &snum))
9084 return WERR_BADFID;
9086 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9087 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9088 return WERR_ACCESS_DENIED;
9091 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9092 if (!W_ERROR_IS_OK(status))
9093 return status;
9095 /* delete the key and all subneys */
9097 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9099 status = delete_all_printer_data( printer->info_2, key );
9101 if ( W_ERROR_IS_OK(status) )
9102 status = mod_a_printer(printer, 2);
9104 free_a_printer( &printer, 2 );
9106 return status;
9110 /********************************************************************
9111 * spoolss_enumprinterdataex
9112 ********************************************************************/
9114 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9116 POLICY_HND *handle = &q_u->handle;
9117 uint32 in_size = q_u->size;
9118 uint32 num_entries,
9119 needed;
9120 NT_PRINTER_INFO_LEVEL *printer = NULL;
9121 PRINTER_ENUM_VALUES *enum_values = NULL;
9122 NT_PRINTER_DATA *p_data;
9123 fstring key;
9124 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9125 int snum;
9126 WERROR result;
9127 int key_index;
9128 int i;
9129 REGISTRY_VALUE *val;
9130 char *value_name;
9131 int data_len;
9134 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9136 if (!Printer) {
9137 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9138 return WERR_BADFID;
9142 * first check for a keyname of NULL or "". Win2k seems to send
9143 * this a lot and we should send back WERR_INVALID_PARAM
9144 * no need to spend time looking up the printer in this case.
9145 * --jerry
9148 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9149 if ( !strlen(key) ) {
9150 result = WERR_INVALID_PARAM;
9151 goto done;
9154 /* get the printer off of disk */
9156 if (!get_printer_snum(p,handle, &snum))
9157 return WERR_BADFID;
9159 ZERO_STRUCT(printer);
9160 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9161 if (!W_ERROR_IS_OK(result))
9162 return result;
9164 /* now look for a match on the key name */
9166 p_data = &printer->info_2->data;
9168 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9169 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9171 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9172 result = WERR_INVALID_PARAM;
9173 goto done;
9176 result = WERR_OK;
9177 needed = 0;
9179 /* allocate the memory for the array of pointers -- if necessary */
9181 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9182 if ( num_entries )
9184 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9186 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9187 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9188 result = WERR_NOMEM;
9189 goto done;
9192 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9196 * loop through all params and build the array to pass
9197 * back to the client
9200 for ( i=0; i<num_entries; i++ )
9202 /* lookup the registry value */
9204 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9205 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9207 /* copy the data */
9209 value_name = regval_name( val );
9210 init_unistr( &enum_values[i].valuename, value_name );
9211 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9212 enum_values[i].type = regval_type( val );
9214 data_len = regval_size( val );
9215 if ( data_len ) {
9216 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9218 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9219 data_len ));
9220 result = WERR_NOMEM;
9221 goto done;
9224 enum_values[i].data_len = data_len;
9226 /* keep track of the size of the array in bytes */
9228 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9231 /* housekeeping information in the reply */
9233 r_u->needed = needed;
9234 r_u->returned = num_entries;
9236 if (needed > in_size) {
9237 result = WERR_MORE_DATA;
9238 goto done;
9241 /* copy data into the reply */
9243 r_u->ctr.size = r_u->needed;
9244 r_u->ctr.size_of_array = r_u->returned;
9245 r_u->ctr.values = enum_values;
9249 done:
9250 if ( printer )
9251 free_a_printer(&printer, 2);
9253 return result;
9256 /****************************************************************************
9257 ****************************************************************************/
9259 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9261 init_unistr(&info->name, name);
9264 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9265 UNISTR2 *environment,
9266 NEW_BUFFER *buffer,
9267 uint32 offered,
9268 uint32 *needed)
9270 pstring path;
9271 pstring long_archi;
9272 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9274 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9276 if (!get_short_archi(long_archi))
9277 return WERR_INVALID_ENVIRONMENT;
9279 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9280 return WERR_NOMEM;
9282 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9284 fill_printprocessordirectory_1(info, path);
9286 *needed += spoolss_size_printprocessordirectory_info_1(info);
9288 if (!alloc_buffer_size(buffer, *needed)) {
9289 safe_free(info);
9290 return WERR_INSUFFICIENT_BUFFER;
9293 smb_io_printprocessordirectory_1("", buffer, info, 0);
9295 safe_free(info);
9297 if (*needed > offered)
9298 return WERR_INSUFFICIENT_BUFFER;
9299 else
9300 return WERR_OK;
9303 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9305 uint32 level = q_u->level;
9306 NEW_BUFFER *buffer = NULL;
9307 uint32 offered = q_u->offered;
9308 uint32 *needed = &r_u->needed;
9309 WERROR result;
9311 /* that's an [in out] buffer */
9312 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9313 buffer = r_u->buffer;
9315 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9317 *needed=0;
9319 switch(level) {
9320 case 1:
9321 result = getprintprocessordirectory_level_1
9322 (&q_u->name, &q_u->environment, buffer, offered, needed);
9323 break;
9324 default:
9325 result = WERR_UNKNOWN_LEVEL;
9328 return result;
9331 #if 0
9333 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9334 SPOOL_R_REPLYOPENPRINTER *r_u)
9336 DEBUG(5,("_spoolss_replyopenprinter\n"));
9338 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9340 return WERR_OK;
9343 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9344 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9346 DEBUG(5,("_spoolss_replycloseprinter\n"));
9347 return WERR_OK;
9350 #endif