r1501: One more check for option != 0.
[Samba/gebeck_regimport.git] / source / rpc_server / srv_spoolss_nt.c
blobe3c9ff08d93d18e92a0429ee6c924a4675d36e0b
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 ubi_dlNode Next;
68 ubi_dlNode Prev;
70 int snum;
71 uint32 counter;
72 } counter_printer_0;
74 static ubi_dlList 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_PRINTING );
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->dev.handlename);
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 *printername )
282 Printer_entry *p;
284 DEBUG(10,("find_printer_in_print_hnd_cache: printer [%s]\n", printername));
286 for ( p=printers_list; p; p=p->next )
288 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
289 && p->printer_info
290 && StrCaseCmp(p->dev.handlename, printername) == 0 )
292 DEBUG(10,("Found printer\n"));
293 *info2 = dup_printer_2( ctx, p->printer_info->info_2 );
294 if ( *info2 )
295 return WERR_OK;
299 return WERR_INVALID_PRINTER_NAME;
302 /****************************************************************************
303 destroy any cached printer_info_2 structures on open handles
304 ****************************************************************************/
306 void invalidate_printer_hnd_cache( char *printername )
308 Printer_entry *p;
310 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
312 for ( p=printers_list; p; p=p->next )
314 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
315 && p->printer_info
316 && StrCaseCmp(p->dev.handlename, printername)==0)
318 DEBUG(10,("invalidating printer_info cache for handl:\n"));
319 free_a_printer( &p->printer_info, 2 );
320 p->printer_info = NULL;
324 return;
326 /****************************************************************************
327 Close printer index by handle.
328 ****************************************************************************/
330 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
332 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
334 if (!Printer) {
335 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
336 return False;
339 close_policy_hnd(p, hnd);
341 return True;
344 /****************************************************************************
345 Delete a printer given a handle.
346 ****************************************************************************/
348 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
350 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
352 if (!Printer) {
353 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
354 return WERR_BADFID;
358 * It turns out that Windows allows delete printer on a handle
359 * opened by an admin user, then used on a pipe handle created
360 * by an anonymous user..... but they're working on security.... riiight !
361 * JRA.
364 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
365 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
366 return WERR_ACCESS_DENIED;
369 #if 0
370 /* Check calling user has permission to delete printer. Note that
371 since we set the snum parameter to -1 only administrators can
372 delete the printer. This stops people with the Full Control
373 permission from deleting the printer. */
375 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
376 DEBUG(3, ("printer delete denied by security descriptor\n"));
377 return WERR_ACCESS_DENIED;
379 #endif
381 if (del_a_printer(Printer->dev.handlename) != 0) {
382 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
383 return WERR_BADFID;
386 if (*lp_deleteprinter_cmd()) {
388 char *cmd = lp_deleteprinter_cmd();
389 pstring command;
390 int ret;
392 /* Printer->dev.handlename equals portname equals sharename */
393 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
394 Printer->dev.handlename);
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->dev.handlename ) < 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->dev.handlename));
432 *number = print_queue_snum(Printer->dev.handlename);
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 fstring sname;
479 BOOL found=False;
480 NT_PRINTER_INFO_LEVEL *printer;
481 WERROR result;
483 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
485 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
486 ZERO_STRUCT(Printer->dev.printerservername);
487 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
488 return True;
491 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
492 return False;
494 if (*handlename=='\\') {
495 aprinter=strchr_m(handlename+2, '\\');
496 aprinter++;
498 else {
499 aprinter=handlename;
502 DEBUGADD(5, ("searching for [%s] (len=%lu)\n", aprinter, (unsigned long)strlen(aprinter)));
504 /* have to search on sharename and PRINTER_INFO2->printername */
506 for (snum=0; snum<n_services; snum++) {
508 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
509 continue;
511 /* ------ sharename ------ */
513 fstrcpy(sname, lp_servicename(snum));
515 DEBUGADD(10, ("share: %s\n",sname));
517 if ( strequal(sname, aprinter) ) {
518 found = True;
519 break;
522 /* ------ printername ------ */
524 printer = NULL;
525 result = get_a_printer( NULL, &printer, 2, sname );
526 if ( !W_ERROR_IS_OK(result) ) {
527 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
528 sname, dos_errstr(result)));
529 continue;
532 /* printername is always returned as \\server\printername */
533 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
534 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
535 printer->info_2->printername));
536 free_a_printer( &printer, 2);
537 continue;
540 printername++;
542 if ( strequal(printername, aprinter) ) {
543 found = True;
546 DEBUGADD(10, ("printername: %s\n", printername));
548 free_a_printer( &printer, 2);
550 if ( found )
551 break;
555 if (!found) {
556 DEBUGADD(4,("Printer not found\n"));
557 return False;
560 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
562 ZERO_STRUCT(Printer->dev.handlename);
563 fstrcpy(Printer->dev.handlename, sname);
565 return True;
568 /****************************************************************************
569 Find first available printer slot. creates a printer handle for you.
570 ****************************************************************************/
572 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
574 Printer_entry *new_printer;
576 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
578 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
579 return False;
581 ZERO_STRUCTP(new_printer);
583 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
584 SAFE_FREE(new_printer);
585 return False;
588 /* Add to the internal list. */
589 DLIST_ADD(printers_list, new_printer);
591 new_printer->notify.option=NULL;
593 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
594 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
595 close_printer_handle(p, hnd);
596 return False;
599 if (!set_printer_hnd_printertype(new_printer, name)) {
600 close_printer_handle(p, hnd);
601 return False;
604 if (!set_printer_hnd_name(new_printer, name)) {
605 close_printer_handle(p, hnd);
606 return False;
609 new_printer->access_granted = access_granted;
611 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
613 return True;
616 /****************************************************************************
617 Allocate more memory for a BUFFER.
618 ****************************************************************************/
620 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
622 prs_struct *ps;
623 uint32 extra_space;
624 uint32 old_offset;
626 ps= &buffer->prs;
628 /* damn, I'm doing the reverse operation of prs_grow() :) */
629 if (buffer_size < prs_data_size(ps))
630 extra_space=0;
631 else
632 extra_space = buffer_size - prs_data_size(ps);
635 * save the offset and move to the end of the buffer
636 * prs_grow() checks the extra_space against the offset
638 old_offset=prs_offset(ps);
639 prs_set_offset(ps, prs_data_size(ps));
641 if (!prs_grow(ps, extra_space))
642 return False;
644 prs_set_offset(ps, old_offset);
646 buffer->string_at_end=prs_data_size(ps);
648 return True;
651 /***************************************************************************
652 check to see if the client motify handle is monitoring the notification
653 given by (notify_type, notify_field).
654 **************************************************************************/
656 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
657 uint16 notify_field)
659 return True;
662 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
663 uint16 notify_field)
665 SPOOL_NOTIFY_OPTION *option = p->notify.option;
666 uint32 i, j;
669 * Flags should always be zero when the change notify
670 * is registered by the client's spooler. A user Win32 app
671 * might use the flags though instead of the NOTIFY_OPTION_INFO
672 * --jerry
675 if (!option) {
676 return False;
679 if (p->notify.flags)
680 return is_monitoring_event_flags(
681 p->notify.flags, notify_type, notify_field);
683 for (i = 0; i < option->count; i++) {
685 /* Check match for notify_type */
687 if (option->ctr.type[i].type != notify_type)
688 continue;
690 /* Check match for field */
692 for (j = 0; j < option->ctr.type[i].count; j++) {
693 if (option->ctr.type[i].fields[j] == notify_field) {
694 return True;
699 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
700 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
701 p->dev.handlename : p->dev.printerservername,
702 notify_type, notify_field));
704 return False;
707 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
709 static void notify_one_value(struct spoolss_notify_msg *msg,
710 SPOOL_NOTIFY_INFO_DATA *data,
711 TALLOC_CTX *mem_ctx)
713 data->notify_data.value[0] = msg->notify.value[0];
714 data->notify_data.value[1] = 0;
717 static void notify_string(struct spoolss_notify_msg *msg,
718 SPOOL_NOTIFY_INFO_DATA *data,
719 TALLOC_CTX *mem_ctx)
721 UNISTR2 unistr;
723 /* The length of the message includes the trailing \0 */
725 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
727 data->notify_data.data.length = msg->len * 2;
728 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
730 if (!data->notify_data.data.string) {
731 data->notify_data.data.length = 0;
732 return;
735 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
738 static void notify_system_time(struct spoolss_notify_msg *msg,
739 SPOOL_NOTIFY_INFO_DATA *data,
740 TALLOC_CTX *mem_ctx)
742 SYSTEMTIME systime;
743 prs_struct ps;
745 if (msg->len != sizeof(time_t)) {
746 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
747 msg->len));
748 return;
751 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
752 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
753 return;
756 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
757 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
758 return;
761 if (!spoolss_io_system_time("", &ps, 0, &systime))
762 return;
764 data->notify_data.data.length = prs_offset(&ps);
765 data->notify_data.data.string = talloc(mem_ctx, prs_offset(&ps));
767 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
769 prs_mem_free(&ps);
772 struct notify2_message_table {
773 const char *name;
774 void (*fn)(struct spoolss_notify_msg *msg,
775 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
778 static struct notify2_message_table printer_notify_table[] = {
779 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
780 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
781 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
782 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
783 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
784 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
785 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
786 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
787 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
788 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
789 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
790 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
791 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
792 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
793 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
794 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
795 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
796 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
797 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
800 static struct notify2_message_table job_notify_table[] = {
801 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
802 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
803 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
804 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
805 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
806 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
807 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
808 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
809 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
810 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
811 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
812 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
813 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
814 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
815 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
816 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
817 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
818 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
819 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
820 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
821 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
822 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
823 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
824 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
828 /***********************************************************************
829 Allocate talloc context for container object
830 **********************************************************************/
832 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
834 if ( !ctr )
835 return;
837 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
839 return;
842 /***********************************************************************
843 release all allocated memory and zero out structure
844 **********************************************************************/
846 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
848 if ( !ctr )
849 return;
851 if ( ctr->ctx )
852 talloc_destroy(ctr->ctx);
854 ZERO_STRUCTP(ctr);
856 return;
859 /***********************************************************************
860 **********************************************************************/
862 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
864 if ( !ctr )
865 return NULL;
867 return ctr->ctx;
870 /***********************************************************************
871 **********************************************************************/
873 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
875 if ( !ctr || !ctr->msg_groups )
876 return NULL;
878 if ( idx >= ctr->num_groups )
879 return NULL;
881 return &ctr->msg_groups[idx];
885 /***********************************************************************
886 How many groups of change messages do we have ?
887 **********************************************************************/
889 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
891 if ( !ctr )
892 return 0;
894 return ctr->num_groups;
897 /***********************************************************************
898 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
899 **********************************************************************/
901 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
903 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
904 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
905 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
906 int i, new_slot;
908 if ( !ctr || !msg )
909 return 0;
911 /* loop over all groups looking for a matching printer name */
913 for ( i=0; i<ctr->num_groups; i++ ) {
914 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
915 break;
918 /* add a new group? */
920 if ( i == ctr->num_groups ) {
921 ctr->num_groups++;
923 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
924 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
925 return 0;
927 ctr->msg_groups = groups;
929 /* clear the new entry and set the printer name */
931 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
932 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
935 /* add the change messages; 'i' is the correct index now regardless */
937 msg_grp = &ctr->msg_groups[i];
939 msg_grp->num_msgs++;
941 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
942 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
943 return 0;
945 msg_grp->msgs = msg_list;
947 new_slot = msg_grp->num_msgs-1;
948 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
950 /* need to allocate own copy of data */
952 if ( msg->len != 0 )
953 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
955 return ctr->num_groups;
958 /***********************************************************************
959 Send a change notication message on all handles which have a call
960 back registered
961 **********************************************************************/
963 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
965 Printer_entry *p;
966 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
967 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
968 SPOOLSS_NOTIFY_MSG *messages;
969 int sending_msg_count;
971 if ( !msg_group ) {
972 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
973 return;
976 messages = msg_group->msgs;
978 if ( !messages ) {
979 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
980 return;
983 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
985 /* loop over all printers */
987 for (p = printers_list; p; p = p->next) {
988 SPOOL_NOTIFY_INFO_DATA *data;
989 uint32 data_len = 0;
990 uint32 id;
991 int i;
993 /* Is there notification on this handle? */
995 if ( !p->notify.client_connected )
996 continue;
998 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
1000 /* For this printer? Print servers always receive
1001 notifications. */
1003 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
1004 ( !strequal(msg_group->printername, p->dev.handlename) ) )
1005 continue;
1007 DEBUG(10,("Our printer\n"));
1009 /* allocate the max entries possible */
1011 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
1012 ZERO_STRUCTP(data);
1014 /* build the array of change notifications */
1016 sending_msg_count = 0;
1018 for ( i=0; i<msg_group->num_msgs; i++ ) {
1019 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1021 /* Are we monitoring this event? */
1023 if (!is_monitoring_event(p, msg->type, msg->field))
1024 continue;
1026 sending_msg_count++;
1029 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
1030 msg->type, msg->field, p->dev.handlename));
1033 * if the is a printer notification handle and not a job notification
1034 * type, then set the id to 0. Other wise just use what was specified
1035 * in the message.
1037 * When registering change notification on a print server handle
1038 * we always need to send back the id (snum) matching the printer
1039 * for which the change took place. For change notify registered
1040 * on a printer handle, this does not matter and the id should be 0.
1042 * --jerry
1045 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1046 id = 0;
1047 else
1048 id = msg->id;
1051 /* Convert unix jobid to smb jobid */
1053 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1054 id = sysjob_to_jobid(msg->id);
1056 if (id == -1) {
1057 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1058 goto done;
1062 construct_info_data( &data[data_len], msg->type, msg->field, id );
1064 switch(msg->type) {
1065 case PRINTER_NOTIFY_TYPE:
1066 if ( printer_notify_table[msg->field].fn )
1067 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1068 break;
1070 case JOB_NOTIFY_TYPE:
1071 if ( job_notify_table[msg->field].fn )
1072 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1073 break;
1075 default:
1076 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1077 goto done;
1080 data_len++;
1083 if ( sending_msg_count ) {
1084 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
1085 data_len, data, p->notify.change, 0 );
1089 done:
1090 DEBUG(8,("send_notify2_changes: Exit...\n"));
1091 return;
1094 /***********************************************************************
1095 **********************************************************************/
1097 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1100 uint32 tv_sec, tv_usec;
1101 size_t offset = 0;
1103 /* Unpack message */
1105 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1106 msg->printer);
1108 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1109 &tv_sec, &tv_usec,
1110 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1112 if (msg->len == 0)
1113 tdb_unpack((char *)buf + offset, len - offset, "dd",
1114 &msg->notify.value[0], &msg->notify.value[1]);
1115 else
1116 tdb_unpack((char *)buf + offset, len - offset, "B",
1117 &msg->len, &msg->notify.data);
1119 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1120 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1122 tv->tv_sec = tv_sec;
1123 tv->tv_usec = tv_usec;
1125 if (msg->len == 0)
1126 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1127 msg->notify.value[1]));
1128 else
1129 dump_data(3, msg->notify.data, msg->len);
1131 return True;
1134 /********************************************************************
1135 Receive a notify2 message list
1136 ********************************************************************/
1138 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1140 size_t msg_count, i;
1141 char *buf = (char *)msg;
1142 char *msg_ptr;
1143 size_t msg_len;
1144 SPOOLSS_NOTIFY_MSG notify;
1145 SPOOLSS_NOTIFY_MSG_CTR messages;
1146 int num_groups;
1148 if (len < 4) {
1149 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1150 return;
1153 msg_count = IVAL(buf, 0);
1154 msg_ptr = buf + 4;
1156 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1158 if (msg_count == 0) {
1159 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1160 return;
1163 /* initialize the container */
1165 ZERO_STRUCT( messages );
1166 notify_msg_ctr_init( &messages );
1169 * build message groups for each printer identified
1170 * in a change_notify msg. Remember that a PCN message
1171 * includes the handle returned for the srv_spoolss_replyopenprinter()
1172 * call. Therefore messages are grouped according to printer handle.
1175 for ( i=0; i<msg_count; i++ ) {
1176 struct timeval msg_tv;
1178 if (msg_ptr + 4 - buf > len) {
1179 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1180 return;
1183 msg_len = IVAL(msg_ptr,0);
1184 msg_ptr += 4;
1186 if (msg_ptr + msg_len - buf > len) {
1187 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1188 return;
1191 /* unpack messages */
1193 ZERO_STRUCT( notify );
1194 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1195 msg_ptr += msg_len;
1197 /* we don't know if the change was from us or not so kill
1198 any cached printer objects */
1200 if ( notify.type == PRINTER_NOTIFY_TYPE )
1201 invalidate_printer_hnd_cache( notify.printer );
1203 /* add to correct list in container */
1205 notify_msg_ctr_addmsg( &messages, &notify );
1207 /* free memory that might have been allocated by notify2_unpack_msg() */
1209 if ( notify.len != 0 )
1210 SAFE_FREE( notify.notify.data );
1213 /* process each group of messages */
1215 num_groups = notify_msg_ctr_numgroups( &messages );
1216 for ( i=0; i<num_groups; i++ )
1217 send_notify2_changes( &messages, i );
1220 /* cleanup */
1222 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1224 notify_msg_ctr_destroy( &messages );
1226 return;
1229 /********************************************************************
1230 Send a message to ourself about new driver being installed
1231 so we can upgrade the information for each printer bound to this
1232 driver
1233 ********************************************************************/
1235 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1237 int len = strlen(drivername);
1239 if (!len)
1240 return False;
1242 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1243 drivername));
1245 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1247 return True;
1250 /**********************************************************************
1251 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1252 over all printers, upgrading ones as necessary
1253 **********************************************************************/
1255 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1257 fstring drivername;
1258 int snum;
1259 int n_services = lp_numservices();
1261 len = MIN(len,sizeof(drivername)-1);
1262 strncpy(drivername, buf, len);
1264 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1266 /* Iterate the printer list */
1268 for (snum=0; snum<n_services; snum++)
1270 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1272 WERROR result;
1273 NT_PRINTER_INFO_LEVEL *printer = NULL;
1275 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1276 if (!W_ERROR_IS_OK(result))
1277 continue;
1279 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1281 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1283 /* all we care about currently is the change_id */
1285 result = mod_a_printer(*printer, 2);
1286 if (!W_ERROR_IS_OK(result)) {
1287 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1288 dos_errstr(result)));
1292 free_a_printer(&printer, 2);
1296 /* all done */
1299 /********************************************************************
1300 Update the cache for all printq's with a registered client
1301 connection
1302 ********************************************************************/
1304 void update_monitored_printq_cache( void )
1306 Printer_entry *printer = printers_list;
1307 int snum;
1309 /* loop through all printers and update the cache where
1310 client_connected == True */
1311 while ( printer )
1313 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1314 && printer->notify.client_connected )
1316 snum = print_queue_snum(printer->dev.handlename);
1317 print_queue_status( snum, NULL, NULL );
1320 printer = printer->next;
1323 return;
1325 /********************************************************************
1326 Send a message to ourself about new driver being installed
1327 so we can upgrade the information for each printer bound to this
1328 driver
1329 ********************************************************************/
1331 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1333 int len = strlen(drivername);
1335 if (!len)
1336 return False;
1338 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1339 drivername));
1341 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1343 return True;
1346 /**********************************************************************
1347 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1348 over all printers, resetting printer data as neessary
1349 **********************************************************************/
1351 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1353 fstring drivername;
1354 int snum;
1355 int n_services = lp_numservices();
1357 len = MIN( len, sizeof(drivername)-1 );
1358 strncpy( drivername, buf, len );
1360 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1362 /* Iterate the printer list */
1364 for ( snum=0; snum<n_services; snum++ )
1366 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1368 WERROR result;
1369 NT_PRINTER_INFO_LEVEL *printer = NULL;
1371 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1372 if ( !W_ERROR_IS_OK(result) )
1373 continue;
1376 * if the printer is bound to the driver,
1377 * then reset to the new driver initdata
1380 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1382 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1384 if ( !set_driver_init(printer, 2) ) {
1385 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1386 printer->info_2->printername, printer->info_2->drivername));
1389 result = mod_a_printer( *printer, 2 );
1390 if ( !W_ERROR_IS_OK(result) ) {
1391 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1392 get_dos_error_msg(result)));
1396 free_a_printer( &printer, 2 );
1400 /* all done */
1402 return;
1405 /********************************************************************
1406 Copy routines used by convert_to_openprinterex()
1407 *******************************************************************/
1409 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1411 DEVICEMODE *d;
1412 int len;
1414 if (!devmode)
1415 return NULL;
1417 DEBUG (8,("dup_devmode\n"));
1419 /* bulk copy first */
1421 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1422 if (!d)
1423 return NULL;
1425 /* dup the pointer members separately */
1427 len = unistrlen(devmode->devicename.buffer);
1428 if (len != -1) {
1429 d->devicename.buffer = talloc(ctx, len*2);
1430 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1431 return NULL;
1435 len = unistrlen(devmode->formname.buffer);
1436 if (len != -1) {
1437 d->devicename.buffer = talloc(ctx, len*2);
1438 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1439 return NULL;
1442 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1444 return d;
1447 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1449 if (!new_ctr || !ctr)
1450 return;
1452 DEBUG(8,("copy_devmode_ctr\n"));
1454 new_ctr->size = ctr->size;
1455 new_ctr->devmode_ptr = ctr->devmode_ptr;
1457 if(ctr->devmode_ptr)
1458 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1461 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1463 if (!new_def || !def)
1464 return;
1466 DEBUG(8,("copy_printer_defaults\n"));
1468 new_def->datatype_ptr = def->datatype_ptr;
1470 if (def->datatype_ptr)
1471 copy_unistr2(&new_def->datatype, &def->datatype);
1473 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1475 new_def->access_required = def->access_required;
1478 /********************************************************************
1479 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1480 * SPOOL_Q_OPEN_PRINTER_EX structure
1481 ********************************************************************/
1483 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1485 if (!q_u_ex || !q_u)
1486 return;
1488 DEBUG(8,("convert_to_openprinterex\n"));
1490 q_u_ex->printername_ptr = q_u->printername_ptr;
1492 if (q_u->printername_ptr)
1493 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1495 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1498 /********************************************************************
1499 * spoolss_open_printer
1501 * called from the spoolss dispatcher
1502 ********************************************************************/
1504 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1506 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1507 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1509 if (!q_u || !r_u)
1510 return WERR_NOMEM;
1512 ZERO_STRUCT(q_u_ex);
1513 ZERO_STRUCT(r_u_ex);
1515 /* convert the OpenPrinter() call to OpenPrinterEx() */
1517 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1519 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1521 /* convert back to OpenPrinter() */
1523 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1525 return r_u->status;
1528 /********************************************************************
1529 * spoolss_open_printer
1531 * If the openprinterex rpc call contains a devmode,
1532 * it's a per-user one. This per-user devmode is derivated
1533 * from the global devmode. Openprinterex() contains a per-user
1534 * devmode for when you do EMF printing and spooling.
1535 * In the EMF case, the NT workstation is only doing half the job
1536 * of rendering the page. The other half is done by running the printer
1537 * driver on the server.
1538 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1539 * The EMF file only contains what is to be printed on the page.
1540 * So in order for the server to know how to print, the NT client sends
1541 * a devicemode attached to the openprinterex call.
1542 * But this devicemode is short lived, it's only valid for the current print job.
1544 * If Samba would have supported EMF spooling, this devicemode would
1545 * have been attached to the handle, to sent it to the driver to correctly
1546 * rasterize the EMF file.
1548 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1549 * we just act as a pass-thru between windows and the printer.
1551 * In order to know that Samba supports only RAW spooling, NT has to call
1552 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1553 * and until NT sends a RAW job, we refuse it.
1555 * But to call getprinter() or startdoc(), you first need a valid handle,
1556 * and to get an handle you have to call openprintex(). Hence why you have
1557 * a devicemode in the openprinterex() call.
1560 * Differences between NT4 and NT 2000.
1561 * NT4:
1562 * ---
1563 * On NT4, you only have a global devicemode. This global devicemode can be changed
1564 * by the administrator (or by a user with enough privs). Everytime a user
1565 * wants to print, the devicemode is resetted to the default. In Word, everytime
1566 * you print, the printer's characteristics are always reset to the global devicemode.
1568 * NT 2000:
1569 * -------
1570 * In W2K, there is the notion of per-user devicemode. The first time you use
1571 * a printer, a per-user devicemode is build from the global devicemode.
1572 * If you change your per-user devicemode, it is saved in the registry, under the
1573 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1574 * printer preferences available.
1576 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1577 * on the General Tab of the printer properties windows.
1579 * To change the global devicemode: it's the "Printing Defaults..." button
1580 * on the Advanced Tab of the printer properties window.
1582 * JFM.
1583 ********************************************************************/
1585 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1587 UNISTR2 *printername = NULL;
1588 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1589 POLICY_HND *handle = &r_u->handle;
1591 fstring name;
1592 int snum;
1593 struct current_user user;
1594 Printer_entry *Printer=NULL;
1596 if (q_u->printername_ptr != 0)
1597 printername = &q_u->printername;
1599 if (printername == NULL)
1600 return WERR_INVALID_PRINTER_NAME;
1602 /* some sanity check because you can open a printer or a print server */
1603 /* aka: \\server\printer or \\server */
1604 unistr2_to_ascii(name, printername, sizeof(name)-1);
1606 DEBUGADD(3,("checking name: %s\n",name));
1608 if (!open_printer_hnd(p, handle, name, 0))
1609 return WERR_INVALID_PRINTER_NAME;
1611 Printer=find_printer_index_by_hnd(p, handle);
1612 if (!Printer) {
1613 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1614 Can't find printer handle we created for printer %s\n", name ));
1615 close_printer_handle(p,handle);
1616 return WERR_INVALID_PRINTER_NAME;
1619 get_current_user(&user, p);
1622 * First case: the user is opening the print server:
1624 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1625 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1627 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1628 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1629 * or if the user is listed in the smb.conf printer admin parameter.
1631 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1632 * client view printer folder, but does not show the MSAPW.
1634 * Note: this test needs code to check access rights here too. Jeremy
1635 * could you look at this?
1637 * Second case: the user is opening a printer:
1638 * NT doesn't let us connect to a printer if the connecting user
1639 * doesn't have print permission.
1642 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1644 /* Printserver handles use global struct... */
1646 snum = -1;
1648 /* Map standard access rights to object specific access rights */
1650 se_map_standard(&printer_default->access_required,
1651 &printserver_std_mapping);
1653 /* Deny any object specific bits that don't apply to print
1654 servers (i.e printer and job specific bits) */
1656 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1658 if (printer_default->access_required &
1659 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1660 DEBUG(3, ("access DENIED for non-printserver bits"));
1661 close_printer_handle(p, handle);
1662 return WERR_ACCESS_DENIED;
1665 /* Allow admin access */
1667 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1669 if (!lp_ms_add_printer_wizard()) {
1670 close_printer_handle(p, handle);
1671 return WERR_ACCESS_DENIED;
1674 /* if the user is not root and not a printer admin, then fail */
1676 if ( user.uid != 0
1677 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1679 close_printer_handle(p, handle);
1680 return WERR_ACCESS_DENIED;
1683 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1685 else
1687 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1690 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1691 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1693 /* We fall through to return WERR_OK */
1696 else
1698 /* NT doesn't let us connect to a printer if the connecting user
1699 doesn't have print permission. */
1701 if (!get_printer_snum(p, handle, &snum)) {
1702 close_printer_handle(p, handle);
1703 return WERR_BADFID;
1706 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1708 /* map an empty access mask to the minimum access mask */
1709 if (printer_default->access_required == 0x0)
1710 printer_default->access_required = PRINTER_ACCESS_USE;
1713 * If we are not serving the printer driver for this printer,
1714 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1715 * will keep NT clients happy --jerry
1718 if (lp_use_client_driver(snum)
1719 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1721 printer_default->access_required = PRINTER_ACCESS_USE;
1724 /* check smb.conf parameters and the the sec_desc */
1726 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1727 DEBUG(3, ("access DENIED for printer open\n"));
1728 close_printer_handle(p, handle);
1729 return WERR_ACCESS_DENIED;
1732 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1733 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1734 close_printer_handle(p, handle);
1735 return WERR_ACCESS_DENIED;
1738 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1739 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1740 else
1741 printer_default->access_required = PRINTER_ACCESS_USE;
1743 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1744 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1748 Printer->access_granted = printer_default->access_required;
1751 * If the client sent a devmode in the OpenPrinter() call, then
1752 * save it here in case we get a job submission on this handle
1755 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1756 && q_u->printer_default.devmode_cont.devmode_ptr )
1758 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1759 &Printer->nt_devmode );
1762 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1763 optimization in Windows 2000 clients --jerry */
1765 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1766 && (RA_WIN2K == get_remote_arch()) )
1768 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1769 sys_usleep( 500000 );
1772 return WERR_OK;
1775 /****************************************************************************
1776 ****************************************************************************/
1778 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1779 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1781 BOOL ret = True;
1783 switch (level) {
1784 case 2:
1785 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1786 break;
1787 default:
1788 break;
1791 return ret;
1794 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1795 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1797 BOOL result = True;
1799 switch (level) {
1800 case 3:
1801 printer->info_3=NULL;
1802 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1803 result = False;
1804 break;
1805 case 6:
1806 printer->info_6=NULL;
1807 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1808 result = False;
1809 break;
1810 default:
1811 break;
1814 return result;
1817 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1818 NT_DEVICEMODE **pp_nt_devmode)
1820 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1823 * Ensure nt_devmode is a valid pointer
1824 * as we will be overwriting it.
1827 if (nt_devmode == NULL) {
1828 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1829 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1830 return False;
1833 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1834 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1836 nt_devmode->specversion=devmode->specversion;
1837 nt_devmode->driverversion=devmode->driverversion;
1838 nt_devmode->size=devmode->size;
1839 nt_devmode->fields=devmode->fields;
1840 nt_devmode->orientation=devmode->orientation;
1841 nt_devmode->papersize=devmode->papersize;
1842 nt_devmode->paperlength=devmode->paperlength;
1843 nt_devmode->paperwidth=devmode->paperwidth;
1844 nt_devmode->scale=devmode->scale;
1845 nt_devmode->copies=devmode->copies;
1846 nt_devmode->defaultsource=devmode->defaultsource;
1847 nt_devmode->printquality=devmode->printquality;
1848 nt_devmode->color=devmode->color;
1849 nt_devmode->duplex=devmode->duplex;
1850 nt_devmode->yresolution=devmode->yresolution;
1851 nt_devmode->ttoption=devmode->ttoption;
1852 nt_devmode->collate=devmode->collate;
1854 nt_devmode->logpixels=devmode->logpixels;
1855 nt_devmode->bitsperpel=devmode->bitsperpel;
1856 nt_devmode->pelswidth=devmode->pelswidth;
1857 nt_devmode->pelsheight=devmode->pelsheight;
1858 nt_devmode->displayflags=devmode->displayflags;
1859 nt_devmode->displayfrequency=devmode->displayfrequency;
1860 nt_devmode->icmmethod=devmode->icmmethod;
1861 nt_devmode->icmintent=devmode->icmintent;
1862 nt_devmode->mediatype=devmode->mediatype;
1863 nt_devmode->dithertype=devmode->dithertype;
1864 nt_devmode->reserved1=devmode->reserved1;
1865 nt_devmode->reserved2=devmode->reserved2;
1866 nt_devmode->panningwidth=devmode->panningwidth;
1867 nt_devmode->panningheight=devmode->panningheight;
1870 * Only change private and driverextra if the incoming devmode
1871 * has a new one. JRA.
1874 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1875 SAFE_FREE(nt_devmode->private);
1876 nt_devmode->driverextra=devmode->driverextra;
1877 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1878 return False;
1879 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1882 *pp_nt_devmode = nt_devmode;
1884 return True;
1887 /********************************************************************
1888 * _spoolss_enddocprinter_internal.
1889 ********************************************************************/
1891 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1893 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1894 int snum;
1896 if (!Printer) {
1897 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1898 return WERR_BADFID;
1901 if (!get_printer_snum(p, handle, &snum))
1902 return WERR_BADFID;
1904 Printer->document_started=False;
1905 print_job_end(snum, Printer->jobid,True);
1906 /* error codes unhandled so far ... */
1908 return WERR_OK;
1911 /********************************************************************
1912 * api_spoolss_closeprinter
1913 ********************************************************************/
1915 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1917 POLICY_HND *handle = &q_u->handle;
1919 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1921 if (Printer && Printer->document_started)
1922 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1924 if (!close_printer_handle(p, handle))
1925 return WERR_BADFID;
1927 /* clear the returned printer handle. Observed behavior
1928 from Win2k server. Don't think this really matters.
1929 Previous code just copied the value of the closed
1930 handle. --jerry */
1932 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1934 return WERR_OK;
1937 /********************************************************************
1938 * api_spoolss_deleteprinter
1940 ********************************************************************/
1942 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1944 POLICY_HND *handle = &q_u->handle;
1945 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1946 WERROR result;
1948 if (Printer && Printer->document_started)
1949 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1951 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1953 result = delete_printer_handle(p, handle);
1955 update_c_setprinter(False);
1957 return result;
1960 /*******************************************************************
1961 * static function to lookup the version id corresponding to an
1962 * long architecture string
1963 ******************************************************************/
1965 static int get_version_id (char * arch)
1967 int i;
1968 struct table_node archi_table[]= {
1970 {"Windows 4.0", "WIN40", 0 },
1971 {"Windows NT x86", "W32X86", 2 },
1972 {"Windows NT R4000", "W32MIPS", 2 },
1973 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1974 {"Windows NT PowerPC", "W32PPC", 2 },
1975 {NULL, "", -1 }
1978 for (i=0; archi_table[i].long_archi != NULL; i++)
1980 if (strcmp(arch, archi_table[i].long_archi) == 0)
1981 return (archi_table[i].version);
1984 return -1;
1987 /********************************************************************
1988 * _spoolss_deleteprinterdriver
1989 ********************************************************************/
1991 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1993 fstring driver;
1994 fstring arch;
1995 NT_PRINTER_DRIVER_INFO_LEVEL info;
1996 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1997 int version;
1998 struct current_user user;
1999 WERROR status;
2000 WERROR status_win2k = WERR_ACCESS_DENIED;
2002 get_current_user(&user, p);
2004 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2005 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2007 /* check that we have a valid driver name first */
2009 if ((version=get_version_id(arch)) == -1)
2010 return WERR_INVALID_ENVIRONMENT;
2012 ZERO_STRUCT(info);
2013 ZERO_STRUCT(info_win2k);
2015 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2017 /* try for Win2k driver if "Windows NT x86" */
2019 if ( version == 2 ) {
2020 version = 3;
2021 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2022 status = WERR_UNKNOWN_PRINTER_DRIVER;
2023 goto done;
2026 /* otherwise it was a failure */
2027 else {
2028 status = WERR_UNKNOWN_PRINTER_DRIVER;
2029 goto done;
2034 if (printer_driver_in_use(info.info_3)) {
2035 status = WERR_PRINTER_DRIVER_IN_USE;
2036 goto done;
2039 if ( version == 2 )
2041 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2043 /* if we get to here, we now have 2 driver info structures to remove */
2044 /* remove the Win2k driver first*/
2046 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2047 free_a_printer_driver( info_win2k, 3 );
2049 /* this should not have failed---if it did, report to client */
2050 if ( !W_ERROR_IS_OK(status_win2k) )
2051 goto done;
2055 status = delete_printer_driver(info.info_3, &user, version, False);
2057 /* if at least one of the deletes succeeded return OK */
2059 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2060 status = WERR_OK;
2062 done:
2063 free_a_printer_driver( info, 3 );
2065 return status;
2068 /********************************************************************
2069 * spoolss_deleteprinterdriverex
2070 ********************************************************************/
2072 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2074 fstring driver;
2075 fstring arch;
2076 NT_PRINTER_DRIVER_INFO_LEVEL info;
2077 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2078 int version;
2079 uint32 flags = q_u->delete_flags;
2080 BOOL delete_files;
2081 struct current_user user;
2082 WERROR status;
2083 WERROR status_win2k = WERR_ACCESS_DENIED;
2085 get_current_user(&user, p);
2087 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2088 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2090 /* check that we have a valid driver name first */
2091 if ((version=get_version_id(arch)) == -1) {
2092 /* this is what NT returns */
2093 return WERR_INVALID_ENVIRONMENT;
2096 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2097 version = q_u->version;
2099 ZERO_STRUCT(info);
2100 ZERO_STRUCT(info_win2k);
2102 status = get_a_printer_driver(&info, 3, driver, arch, version);
2104 if ( !W_ERROR_IS_OK(status) )
2107 * if the client asked for a specific version,
2108 * or this is something other than Windows NT x86,
2109 * then we've failed
2112 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2113 goto done;
2115 /* try for Win2k driver if "Windows NT x86" */
2117 version = 3;
2118 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2119 status = WERR_UNKNOWN_PRINTER_DRIVER;
2120 goto done;
2124 if ( printer_driver_in_use(info.info_3) ) {
2125 status = WERR_PRINTER_DRIVER_IN_USE;
2126 goto done;
2130 * we have a couple of cases to consider.
2131 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2132 * then the delete should fail if **any** files overlap with
2133 * other drivers
2134 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2135 * non-overlapping files
2136 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2137 * is set, the do not delete any files
2138 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2141 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2143 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2145 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2146 /* no idea of the correct error here */
2147 status = WERR_ACCESS_DENIED;
2148 goto done;
2152 /* also check for W32X86/3 if necessary; maybe we already have? */
2154 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2155 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2158 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2159 /* no idea of the correct error here */
2160 free_a_printer_driver( info_win2k, 3 );
2161 status = WERR_ACCESS_DENIED;
2162 goto done;
2165 /* if we get to here, we now have 2 driver info structures to remove */
2166 /* remove the Win2k driver first*/
2168 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2169 free_a_printer_driver( info_win2k, 3 );
2171 /* this should not have failed---if it did, report to client */
2173 if ( !W_ERROR_IS_OK(status_win2k) )
2174 goto done;
2178 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2180 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2181 status = WERR_OK;
2182 done:
2183 free_a_printer_driver( info, 3 );
2185 return status;
2189 /****************************************************************************
2190 Internal routine for retreiving printerdata
2191 ***************************************************************************/
2193 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2194 const char *key, const char *value, uint32 *type, uint8 **data,
2195 uint32 *needed, uint32 in_size )
2197 REGISTRY_VALUE *val;
2198 int size, data_len;
2200 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2201 return WERR_BADFILE;
2203 *type = regval_type( val );
2205 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2207 size = regval_size( val );
2209 /* copy the min(in_size, len) */
2211 if ( in_size ) {
2212 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2214 /* special case for 0 length values */
2215 if ( data_len ) {
2216 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2217 return WERR_NOMEM;
2219 else {
2220 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2221 return WERR_NOMEM;
2224 else
2225 *data = NULL;
2227 *needed = size;
2229 DEBUG(5,("get_printer_dataex: copy done\n"));
2231 return WERR_OK;
2234 /****************************************************************************
2235 Internal routine for removing printerdata
2236 ***************************************************************************/
2238 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2240 return delete_printer_data( printer->info_2, key, value );
2243 /****************************************************************************
2244 Internal routine for storing printerdata
2245 ***************************************************************************/
2247 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2248 uint32 type, uint8 *data, int real_len )
2250 delete_printer_data( printer->info_2, key, value );
2252 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2255 /********************************************************************
2256 GetPrinterData on a printer server Handle.
2257 ********************************************************************/
2259 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2261 int i;
2263 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2265 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2266 *type = 0x4;
2267 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2268 return WERR_NOMEM;
2269 *needed = 0x4;
2270 return WERR_OK;
2273 if (!StrCaseCmp(value, "BeepEnabled")) {
2274 *type = 0x4;
2275 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2276 return WERR_NOMEM;
2277 SIVAL(*data, 0, 0x00);
2278 *needed = 0x4;
2279 return WERR_OK;
2282 if (!StrCaseCmp(value, "EventLog")) {
2283 *type = 0x4;
2284 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2285 return WERR_NOMEM;
2286 /* formally was 0x1b */
2287 SIVAL(*data, 0, 0x0);
2288 *needed = 0x4;
2289 return WERR_OK;
2292 if (!StrCaseCmp(value, "NetPopup")) {
2293 *type = 0x4;
2294 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2295 return WERR_NOMEM;
2296 SIVAL(*data, 0, 0x00);
2297 *needed = 0x4;
2298 return WERR_OK;
2301 if (!StrCaseCmp(value, "MajorVersion")) {
2302 *type = 0x4;
2303 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2304 return WERR_NOMEM;
2306 /* Windows NT 4.0 seems to not allow uploading of drivers
2307 to a server that reports 0x3 as the MajorVersion.
2308 need to investigate more how Win2k gets around this .
2309 -- jerry */
2311 if ( RA_WINNT == get_remote_arch() )
2312 SIVAL(*data, 0, 2);
2313 else
2314 SIVAL(*data, 0, 3);
2316 *needed = 0x4;
2317 return WERR_OK;
2320 if (!StrCaseCmp(value, "MinorVersion")) {
2321 *type = 0x4;
2322 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2323 return WERR_NOMEM;
2324 SIVAL(*data, 0, 0);
2325 *needed = 0x4;
2326 return WERR_OK;
2329 /* REG_BINARY
2330 * uint32 size = 0x114
2331 * uint32 major = 5
2332 * uint32 minor = [0|1]
2333 * uint32 build = [2195|2600]
2334 * extra unicode string = e.g. "Service Pack 3"
2336 if (!StrCaseCmp(value, "OSVersion")) {
2337 *type = 0x3;
2338 *needed = 0x114;
2340 if((*data = (uint8 *)talloc(ctx, (*needed)*sizeof(uint8) )) == NULL)
2341 return WERR_NOMEM;
2342 ZERO_STRUCTP( *data );
2344 SIVAL(*data, 0, *needed); /* size */
2345 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2346 SIVAL(*data, 8, 0);
2347 SIVAL(*data, 12, 2195); /* build */
2349 /* leave extra string empty */
2351 return WERR_OK;
2355 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2356 const char *string="C:\\PRINTERS";
2357 *type = 0x1;
2358 *needed = 2*(strlen(string)+1);
2359 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2360 return WERR_NOMEM;
2361 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2363 /* it's done by hand ready to go on the wire */
2364 for (i=0; i<strlen(string); i++) {
2365 (*data)[2*i]=string[i];
2366 (*data)[2*i+1]='\0';
2368 return WERR_OK;
2371 if (!StrCaseCmp(value, "Architecture")) {
2372 const char *string="Windows NT x86";
2373 *type = 0x1;
2374 *needed = 2*(strlen(string)+1);
2375 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2376 return WERR_NOMEM;
2377 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2378 for (i=0; i<strlen(string); i++) {
2379 (*data)[2*i]=string[i];
2380 (*data)[2*i+1]='\0';
2382 return WERR_OK;
2385 if (!StrCaseCmp(value, "DsPresent")) {
2386 *type = 0x4;
2387 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2388 return WERR_NOMEM;
2389 SIVAL(*data, 0, 0x01);
2390 *needed = 0x4;
2391 return WERR_OK;
2394 if (!StrCaseCmp(value, "DNSMachineName")) {
2395 pstring hostname;
2397 if (!get_mydnsfullname(hostname))
2398 return WERR_BADFILE;
2399 *type = 0x1;
2400 *needed = 2*(strlen(hostname)+1);
2401 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2402 return WERR_NOMEM;
2403 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2404 for (i=0; i<strlen(hostname); i++) {
2405 (*data)[2*i]=hostname[i];
2406 (*data)[2*i+1]='\0';
2408 return WERR_OK;
2412 return WERR_BADFILE;
2415 /********************************************************************
2416 * spoolss_getprinterdata
2417 ********************************************************************/
2419 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2421 POLICY_HND *handle = &q_u->handle;
2422 UNISTR2 *valuename = &q_u->valuename;
2423 uint32 in_size = q_u->size;
2424 uint32 *type = &r_u->type;
2425 uint32 *out_size = &r_u->size;
2426 uint8 **data = &r_u->data;
2427 uint32 *needed = &r_u->needed;
2428 WERROR status;
2429 fstring value;
2430 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2431 NT_PRINTER_INFO_LEVEL *printer = NULL;
2432 int snum = 0;
2435 * Reminder: when it's a string, the length is in BYTES
2436 * even if UNICODE is negociated.
2438 * JFM, 4/19/1999
2441 *out_size = in_size;
2443 /* in case of problem, return some default values */
2445 *needed = 0;
2446 *type = 0;
2448 DEBUG(4,("_spoolss_getprinterdata\n"));
2450 if ( !Printer ) {
2451 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2452 status = WERR_BADFID;
2453 goto done;
2456 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2458 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2459 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2460 else
2462 if ( !get_printer_snum(p,handle, &snum) ) {
2463 status = WERR_BADFID;
2464 goto done;
2467 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2468 if ( !W_ERROR_IS_OK(status) )
2469 goto done;
2471 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2473 if ( strequal(value, "ChangeId") ) {
2474 *type = REG_DWORD;
2475 *needed = sizeof(uint32);
2476 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2477 status = WERR_NOMEM;
2478 goto done;
2480 SIVAL( *data, 0, printer->info_2->changeid );
2481 status = WERR_OK;
2483 else
2484 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2487 if (*needed > *out_size)
2488 status = WERR_MORE_DATA;
2490 done:
2491 if ( !W_ERROR_IS_OK(status) )
2493 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2495 /* reply this param doesn't exist */
2497 if ( *out_size ) {
2498 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2499 if ( printer )
2500 free_a_printer( &printer, 2 );
2501 return WERR_NOMEM;
2504 else {
2505 *data = NULL;
2509 /* cleanup & exit */
2511 if ( printer )
2512 free_a_printer( &printer, 2 );
2514 return status;
2517 /*********************************************************
2518 Connect to the client machine.
2519 **********************************************************/
2521 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2522 struct in_addr *client_ip, const char *remote_machine)
2524 ZERO_STRUCTP(the_cli);
2526 if(cli_initialise(the_cli) == NULL) {
2527 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2528 return False;
2531 if ( is_zero_ip(*client_ip) ) {
2532 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2533 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2534 cli_shutdown(the_cli);
2535 return False;
2538 if (ismyip(the_cli->dest_ip)) {
2539 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2540 cli_shutdown(the_cli);
2541 return False;
2544 else {
2545 the_cli->dest_ip.s_addr = client_ip->s_addr;
2546 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2547 inet_ntoa(*client_ip) ));
2550 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2551 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) ));
2552 cli_shutdown(the_cli);
2553 return False;
2556 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2557 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2558 remote_machine));
2559 cli_shutdown(the_cli);
2560 return False;
2563 the_cli->protocol = PROTOCOL_NT1;
2564 cli_setup_signing_state(the_cli, lp_client_signing());
2566 if (!cli_negprot(the_cli)) {
2567 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2568 cli_shutdown(the_cli);
2569 return False;
2572 if (the_cli->protocol != PROTOCOL_NT1) {
2573 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2574 cli_shutdown(the_cli);
2575 return False;
2579 * Do an anonymous session setup.
2582 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2583 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2584 cli_shutdown(the_cli);
2585 return False;
2588 if (!(the_cli->sec_mode & 1)) {
2589 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2590 cli_shutdown(the_cli);
2591 return False;
2594 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2595 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) ));
2596 cli_shutdown(the_cli);
2597 return False;
2601 * Ok - we have an anonymous connection to the IPC$ share.
2602 * Now start the NT Domain stuff :-).
2605 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2606 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)));
2607 cli_nt_session_close(the_cli);
2608 cli_ulogoff(the_cli);
2609 cli_shutdown(the_cli);
2610 return False;
2613 return True;
2616 /***************************************************************************
2617 Connect to the client.
2618 ****************************************************************************/
2620 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2621 uint32 localprinter, uint32 type,
2622 POLICY_HND *handle, struct in_addr *client_ip)
2624 WERROR result;
2627 * If it's the first connection, contact the client
2628 * and connect to the IPC$ share anonymously
2630 if (smb_connections==0) {
2631 fstring unix_printer;
2633 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2635 ZERO_STRUCT(notify_cli);
2637 if(!spoolss_connect_to_client(&notify_cli, client_ip, unix_printer))
2638 return False;
2640 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2641 /* Tell the connections db we're now interested in printer
2642 * notify messages. */
2643 register_message_flags( True, FLAG_MSG_PRINTING );
2647 * Tell the specific printing tdb we want messages for this printer
2648 * by registering our PID.
2651 if (!print_notify_register_pid(snum))
2652 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2654 smb_connections++;
2656 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2657 type, handle);
2659 if (!W_ERROR_IS_OK(result))
2660 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2661 dos_errstr(result)));
2663 return (W_ERROR_IS_OK(result));
2666 /********************************************************************
2667 * _spoolss_rffpcnex
2668 * ReplyFindFirstPrinterChangeNotifyEx
2670 * before replying OK: status=0 a rpc call is made to the workstation
2671 * asking ReplyOpenPrinter
2673 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2674 * called from api_spoolss_rffpcnex
2675 ********************************************************************/
2677 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2679 POLICY_HND *handle = &q_u->handle;
2680 uint32 flags = q_u->flags;
2681 uint32 options = q_u->options;
2682 UNISTR2 *localmachine = &q_u->localmachine;
2683 uint32 printerlocal = q_u->printerlocal;
2684 int snum = -1;
2685 SPOOL_NOTIFY_OPTION *option = q_u->option;
2686 struct in_addr client_ip;
2688 /* store the notify value in the printer struct */
2690 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2692 if (!Printer) {
2693 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2694 return WERR_BADFID;
2697 Printer->notify.flags=flags;
2698 Printer->notify.options=options;
2699 Printer->notify.printerlocal=printerlocal;
2701 if (Printer->notify.option)
2702 free_spool_notify_option(&Printer->notify.option);
2704 Printer->notify.option=dup_spool_notify_option(option);
2706 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2707 sizeof(Printer->notify.localmachine)-1);
2709 /* Connect to the client machine and send a ReplyOpenPrinter */
2711 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2712 snum = -1;
2713 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2714 !get_printer_snum(p, handle, &snum) )
2715 return WERR_BADFID;
2717 client_ip.s_addr = inet_addr(p->conn->client_address);
2719 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2720 Printer->notify.printerlocal, 1,
2721 &Printer->notify.client_hnd, &client_ip))
2722 return WERR_SERVER_UNAVAILABLE;
2724 Printer->notify.client_connected=True;
2726 return WERR_OK;
2729 /*******************************************************************
2730 * fill a notify_info_data with the servername
2731 ********************************************************************/
2733 void spoolss_notify_server_name(int snum,
2734 SPOOL_NOTIFY_INFO_DATA *data,
2735 print_queue_struct *queue,
2736 NT_PRINTER_INFO_LEVEL *printer,
2737 TALLOC_CTX *mem_ctx)
2739 pstring temp_name, temp;
2740 uint32 len;
2742 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2744 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2746 data->notify_data.data.length = len;
2747 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2749 if (!data->notify_data.data.string) {
2750 data->notify_data.data.length = 0;
2751 return;
2754 memcpy(data->notify_data.data.string, temp, len);
2757 /*******************************************************************
2758 * fill a notify_info_data with the printername (not including the servername).
2759 ********************************************************************/
2761 void spoolss_notify_printer_name(int snum,
2762 SPOOL_NOTIFY_INFO_DATA *data,
2763 print_queue_struct *queue,
2764 NT_PRINTER_INFO_LEVEL *printer,
2765 TALLOC_CTX *mem_ctx)
2767 pstring temp;
2768 uint32 len;
2770 /* the notify name should not contain the \\server\ part */
2771 char *p = strrchr(printer->info_2->printername, '\\');
2773 if (!p) {
2774 p = printer->info_2->printername;
2775 } else {
2776 p++;
2779 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2781 data->notify_data.data.length = len;
2782 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2784 if (!data->notify_data.data.string) {
2785 data->notify_data.data.length = 0;
2786 return;
2789 memcpy(data->notify_data.data.string, temp, len);
2792 /*******************************************************************
2793 * fill a notify_info_data with the servicename
2794 ********************************************************************/
2796 void spoolss_notify_share_name(int snum,
2797 SPOOL_NOTIFY_INFO_DATA *data,
2798 print_queue_struct *queue,
2799 NT_PRINTER_INFO_LEVEL *printer,
2800 TALLOC_CTX *mem_ctx)
2802 pstring temp;
2803 uint32 len;
2805 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2807 data->notify_data.data.length = len;
2808 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2810 if (!data->notify_data.data.string) {
2811 data->notify_data.data.length = 0;
2812 return;
2815 memcpy(data->notify_data.data.string, temp, len);
2818 /*******************************************************************
2819 * fill a notify_info_data with the port name
2820 ********************************************************************/
2822 void spoolss_notify_port_name(int snum,
2823 SPOOL_NOTIFY_INFO_DATA *data,
2824 print_queue_struct *queue,
2825 NT_PRINTER_INFO_LEVEL *printer,
2826 TALLOC_CTX *mem_ctx)
2828 pstring temp;
2829 uint32 len;
2831 /* even if it's strange, that's consistant in all the code */
2833 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2835 data->notify_data.data.length = len;
2836 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2838 if (!data->notify_data.data.string) {
2839 data->notify_data.data.length = 0;
2840 return;
2843 memcpy(data->notify_data.data.string, temp, len);
2846 /*******************************************************************
2847 * fill a notify_info_data with the printername
2848 * but it doesn't exist, have to see what to do
2849 ********************************************************************/
2851 void spoolss_notify_driver_name(int snum,
2852 SPOOL_NOTIFY_INFO_DATA *data,
2853 print_queue_struct *queue,
2854 NT_PRINTER_INFO_LEVEL *printer,
2855 TALLOC_CTX *mem_ctx)
2857 pstring temp;
2858 uint32 len;
2860 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2862 data->notify_data.data.length = len;
2863 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2865 if (!data->notify_data.data.string) {
2866 data->notify_data.data.length = 0;
2867 return;
2870 memcpy(data->notify_data.data.string, temp, len);
2873 /*******************************************************************
2874 * fill a notify_info_data with the comment
2875 ********************************************************************/
2877 void spoolss_notify_comment(int snum,
2878 SPOOL_NOTIFY_INFO_DATA *data,
2879 print_queue_struct *queue,
2880 NT_PRINTER_INFO_LEVEL *printer,
2881 TALLOC_CTX *mem_ctx)
2883 pstring temp;
2884 uint32 len;
2886 if (*printer->info_2->comment == '\0')
2887 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2888 else
2889 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2891 data->notify_data.data.length = len;
2892 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2894 if (!data->notify_data.data.string) {
2895 data->notify_data.data.length = 0;
2896 return;
2899 memcpy(data->notify_data.data.string, temp, len);
2902 /*******************************************************************
2903 * fill a notify_info_data with the comment
2904 * location = "Room 1, floor 2, building 3"
2905 ********************************************************************/
2907 void spoolss_notify_location(int snum,
2908 SPOOL_NOTIFY_INFO_DATA *data,
2909 print_queue_struct *queue,
2910 NT_PRINTER_INFO_LEVEL *printer,
2911 TALLOC_CTX *mem_ctx)
2913 pstring temp;
2914 uint32 len;
2916 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2918 data->notify_data.data.length = len;
2919 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2921 if (!data->notify_data.data.string) {
2922 data->notify_data.data.length = 0;
2923 return;
2926 memcpy(data->notify_data.data.string, temp, len);
2929 /*******************************************************************
2930 * fill a notify_info_data with the device mode
2931 * jfm:xxxx don't to it for know but that's a real problem !!!
2932 ********************************************************************/
2934 static void spoolss_notify_devmode(int snum,
2935 SPOOL_NOTIFY_INFO_DATA *data,
2936 print_queue_struct *queue,
2937 NT_PRINTER_INFO_LEVEL *printer,
2938 TALLOC_CTX *mem_ctx)
2942 /*******************************************************************
2943 * fill a notify_info_data with the separator file name
2944 ********************************************************************/
2946 void spoolss_notify_sepfile(int snum,
2947 SPOOL_NOTIFY_INFO_DATA *data,
2948 print_queue_struct *queue,
2949 NT_PRINTER_INFO_LEVEL *printer,
2950 TALLOC_CTX *mem_ctx)
2952 pstring temp;
2953 uint32 len;
2955 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2957 data->notify_data.data.length = len;
2958 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2960 if (!data->notify_data.data.string) {
2961 data->notify_data.data.length = 0;
2962 return;
2965 memcpy(data->notify_data.data.string, temp, len);
2968 /*******************************************************************
2969 * fill a notify_info_data with the print processor
2970 * jfm:xxxx return always winprint to indicate we don't do anything to it
2971 ********************************************************************/
2973 void spoolss_notify_print_processor(int snum,
2974 SPOOL_NOTIFY_INFO_DATA *data,
2975 print_queue_struct *queue,
2976 NT_PRINTER_INFO_LEVEL *printer,
2977 TALLOC_CTX *mem_ctx)
2979 pstring temp;
2980 uint32 len;
2982 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2984 data->notify_data.data.length = len;
2985 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2987 if (!data->notify_data.data.string) {
2988 data->notify_data.data.length = 0;
2989 return;
2992 memcpy(data->notify_data.data.string, temp, len);
2995 /*******************************************************************
2996 * fill a notify_info_data with the print processor options
2997 * jfm:xxxx send an empty string
2998 ********************************************************************/
3000 void spoolss_notify_parameters(int snum,
3001 SPOOL_NOTIFY_INFO_DATA *data,
3002 print_queue_struct *queue,
3003 NT_PRINTER_INFO_LEVEL *printer,
3004 TALLOC_CTX *mem_ctx)
3006 pstring temp;
3007 uint32 len;
3009 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3011 data->notify_data.data.length = len;
3012 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3014 if (!data->notify_data.data.string) {
3015 data->notify_data.data.length = 0;
3016 return;
3019 memcpy(data->notify_data.data.string, temp, len);
3022 /*******************************************************************
3023 * fill a notify_info_data with the data type
3024 * jfm:xxxx always send RAW as data type
3025 ********************************************************************/
3027 void spoolss_notify_datatype(int snum,
3028 SPOOL_NOTIFY_INFO_DATA *data,
3029 print_queue_struct *queue,
3030 NT_PRINTER_INFO_LEVEL *printer,
3031 TALLOC_CTX *mem_ctx)
3033 pstring temp;
3034 uint32 len;
3036 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3038 data->notify_data.data.length = len;
3039 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3041 if (!data->notify_data.data.string) {
3042 data->notify_data.data.length = 0;
3043 return;
3046 memcpy(data->notify_data.data.string, temp, len);
3049 /*******************************************************************
3050 * fill a notify_info_data with the security descriptor
3051 * jfm:xxxx send an null pointer to say no security desc
3052 * have to implement security before !
3053 ********************************************************************/
3055 static void spoolss_notify_security_desc(int snum,
3056 SPOOL_NOTIFY_INFO_DATA *data,
3057 print_queue_struct *queue,
3058 NT_PRINTER_INFO_LEVEL *printer,
3059 TALLOC_CTX *mem_ctx)
3061 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3062 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3065 /*******************************************************************
3066 * fill a notify_info_data with the attributes
3067 * jfm:xxxx a samba printer is always shared
3068 ********************************************************************/
3070 void spoolss_notify_attributes(int snum,
3071 SPOOL_NOTIFY_INFO_DATA *data,
3072 print_queue_struct *queue,
3073 NT_PRINTER_INFO_LEVEL *printer,
3074 TALLOC_CTX *mem_ctx)
3076 data->notify_data.value[0] = printer->info_2->attributes;
3077 data->notify_data.value[1] = 0;
3080 /*******************************************************************
3081 * fill a notify_info_data with the priority
3082 ********************************************************************/
3084 static void spoolss_notify_priority(int snum,
3085 SPOOL_NOTIFY_INFO_DATA *data,
3086 print_queue_struct *queue,
3087 NT_PRINTER_INFO_LEVEL *printer,
3088 TALLOC_CTX *mem_ctx)
3090 data->notify_data.value[0] = printer->info_2->priority;
3091 data->notify_data.value[1] = 0;
3094 /*******************************************************************
3095 * fill a notify_info_data with the default priority
3096 ********************************************************************/
3098 static void spoolss_notify_default_priority(int snum,
3099 SPOOL_NOTIFY_INFO_DATA *data,
3100 print_queue_struct *queue,
3101 NT_PRINTER_INFO_LEVEL *printer,
3102 TALLOC_CTX *mem_ctx)
3104 data->notify_data.value[0] = printer->info_2->default_priority;
3105 data->notify_data.value[1] = 0;
3108 /*******************************************************************
3109 * fill a notify_info_data with the start time
3110 ********************************************************************/
3112 static void spoolss_notify_start_time(int snum,
3113 SPOOL_NOTIFY_INFO_DATA *data,
3114 print_queue_struct *queue,
3115 NT_PRINTER_INFO_LEVEL *printer,
3116 TALLOC_CTX *mem_ctx)
3118 data->notify_data.value[0] = printer->info_2->starttime;
3119 data->notify_data.value[1] = 0;
3122 /*******************************************************************
3123 * fill a notify_info_data with the until time
3124 ********************************************************************/
3126 static void spoolss_notify_until_time(int snum,
3127 SPOOL_NOTIFY_INFO_DATA *data,
3128 print_queue_struct *queue,
3129 NT_PRINTER_INFO_LEVEL *printer,
3130 TALLOC_CTX *mem_ctx)
3132 data->notify_data.value[0] = printer->info_2->untiltime;
3133 data->notify_data.value[1] = 0;
3136 /*******************************************************************
3137 * fill a notify_info_data with the status
3138 ********************************************************************/
3140 static void spoolss_notify_status(int snum,
3141 SPOOL_NOTIFY_INFO_DATA *data,
3142 print_queue_struct *queue,
3143 NT_PRINTER_INFO_LEVEL *printer,
3144 TALLOC_CTX *mem_ctx)
3146 print_status_struct status;
3148 print_queue_length(snum, &status);
3149 data->notify_data.value[0]=(uint32) status.status;
3150 data->notify_data.value[1] = 0;
3153 /*******************************************************************
3154 * fill a notify_info_data with the number of jobs queued
3155 ********************************************************************/
3157 void spoolss_notify_cjobs(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] = print_queue_length(snum, NULL);
3164 data->notify_data.value[1] = 0;
3167 /*******************************************************************
3168 * fill a notify_info_data with the average ppm
3169 ********************************************************************/
3171 static void spoolss_notify_average_ppm(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 /* always respond 8 pages per minutes */
3178 /* a little hard ! */
3179 data->notify_data.value[0] = printer->info_2->averageppm;
3180 data->notify_data.value[1] = 0;
3183 /*******************************************************************
3184 * fill a notify_info_data with username
3185 ********************************************************************/
3187 static void spoolss_notify_username(int snum,
3188 SPOOL_NOTIFY_INFO_DATA *data,
3189 print_queue_struct *queue,
3190 NT_PRINTER_INFO_LEVEL *printer,
3191 TALLOC_CTX *mem_ctx)
3193 pstring temp;
3194 uint32 len;
3196 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3198 data->notify_data.data.length = len;
3199 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3201 if (!data->notify_data.data.string) {
3202 data->notify_data.data.length = 0;
3203 return;
3206 memcpy(data->notify_data.data.string, temp, len);
3209 /*******************************************************************
3210 * fill a notify_info_data with job status
3211 ********************************************************************/
3213 static void spoolss_notify_job_status(int snum,
3214 SPOOL_NOTIFY_INFO_DATA *data,
3215 print_queue_struct *queue,
3216 NT_PRINTER_INFO_LEVEL *printer,
3217 TALLOC_CTX *mem_ctx)
3219 data->notify_data.value[0]=nt_printj_status(queue->status);
3220 data->notify_data.value[1] = 0;
3223 /*******************************************************************
3224 * fill a notify_info_data with job name
3225 ********************************************************************/
3227 static void spoolss_notify_job_name(int snum,
3228 SPOOL_NOTIFY_INFO_DATA *data,
3229 print_queue_struct *queue,
3230 NT_PRINTER_INFO_LEVEL *printer,
3231 TALLOC_CTX *mem_ctx)
3233 pstring temp;
3234 uint32 len;
3236 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3238 data->notify_data.data.length = len;
3239 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3241 if (!data->notify_data.data.string) {
3242 data->notify_data.data.length = 0;
3243 return;
3246 memcpy(data->notify_data.data.string, temp, len);
3249 /*******************************************************************
3250 * fill a notify_info_data with job status
3251 ********************************************************************/
3253 static void spoolss_notify_job_status_string(int snum,
3254 SPOOL_NOTIFY_INFO_DATA *data,
3255 print_queue_struct *queue,
3256 NT_PRINTER_INFO_LEVEL *printer,
3257 TALLOC_CTX *mem_ctx)
3260 * Now we're returning job status codes we just return a "" here. JRA.
3263 const char *p = "";
3264 pstring temp;
3265 uint32 len;
3267 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3268 p = "unknown";
3270 switch (queue->status) {
3271 case LPQ_QUEUED:
3272 p = "Queued";
3273 break;
3274 case LPQ_PAUSED:
3275 p = ""; /* NT provides the paused string */
3276 break;
3277 case LPQ_SPOOLING:
3278 p = "Spooling";
3279 break;
3280 case LPQ_PRINTING:
3281 p = "Printing";
3282 break;
3284 #endif /* NO LONGER NEEDED. */
3286 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3288 data->notify_data.data.length = len;
3289 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3291 if (!data->notify_data.data.string) {
3292 data->notify_data.data.length = 0;
3293 return;
3296 memcpy(data->notify_data.data.string, temp, len);
3299 /*******************************************************************
3300 * fill a notify_info_data with job time
3301 ********************************************************************/
3303 static void spoolss_notify_job_time(int snum,
3304 SPOOL_NOTIFY_INFO_DATA *data,
3305 print_queue_struct *queue,
3306 NT_PRINTER_INFO_LEVEL *printer,
3307 TALLOC_CTX *mem_ctx)
3309 data->notify_data.value[0]=0x0;
3310 data->notify_data.value[1]=0;
3313 /*******************************************************************
3314 * fill a notify_info_data with job size
3315 ********************************************************************/
3317 static void spoolss_notify_job_size(int snum,
3318 SPOOL_NOTIFY_INFO_DATA *data,
3319 print_queue_struct *queue,
3320 NT_PRINTER_INFO_LEVEL *printer,
3321 TALLOC_CTX *mem_ctx)
3323 data->notify_data.value[0]=queue->size;
3324 data->notify_data.value[1]=0;
3327 /*******************************************************************
3328 * fill a notify_info_data with page info
3329 ********************************************************************/
3330 static void spoolss_notify_total_pages(int snum,
3331 SPOOL_NOTIFY_INFO_DATA *data,
3332 print_queue_struct *queue,
3333 NT_PRINTER_INFO_LEVEL *printer,
3334 TALLOC_CTX *mem_ctx)
3336 data->notify_data.value[0]=queue->page_count;
3337 data->notify_data.value[1]=0;
3340 /*******************************************************************
3341 * fill a notify_info_data with pages printed info.
3342 ********************************************************************/
3343 static void spoolss_notify_pages_printed(int snum,
3344 SPOOL_NOTIFY_INFO_DATA *data,
3345 print_queue_struct *queue,
3346 NT_PRINTER_INFO_LEVEL *printer,
3347 TALLOC_CTX *mem_ctx)
3349 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3350 data->notify_data.value[1]=0;
3353 /*******************************************************************
3354 Fill a notify_info_data with job position.
3355 ********************************************************************/
3357 static void spoolss_notify_job_position(int snum,
3358 SPOOL_NOTIFY_INFO_DATA *data,
3359 print_queue_struct *queue,
3360 NT_PRINTER_INFO_LEVEL *printer,
3361 TALLOC_CTX *mem_ctx)
3363 data->notify_data.value[0]=queue->job;
3364 data->notify_data.value[1]=0;
3367 /*******************************************************************
3368 Fill a notify_info_data with submitted time.
3369 ********************************************************************/
3371 static void spoolss_notify_submitted_time(int snum,
3372 SPOOL_NOTIFY_INFO_DATA *data,
3373 print_queue_struct *queue,
3374 NT_PRINTER_INFO_LEVEL *printer,
3375 TALLOC_CTX *mem_ctx)
3377 struct tm *t;
3378 uint32 len;
3379 SYSTEMTIME st;
3380 char *p;
3382 t=gmtime(&queue->time);
3384 len = sizeof(SYSTEMTIME);
3386 data->notify_data.data.length = len;
3387 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3389 if (!data->notify_data.data.string) {
3390 data->notify_data.data.length = 0;
3391 return;
3394 make_systemtime(&st, t);
3397 * Systemtime must be linearized as a set of UINT16's.
3398 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3401 p = (char *)data->notify_data.data.string;
3402 SSVAL(p, 0, st.year);
3403 SSVAL(p, 2, st.month);
3404 SSVAL(p, 4, st.dayofweek);
3405 SSVAL(p, 6, st.day);
3406 SSVAL(p, 8, st.hour);
3407 SSVAL(p, 10, st.minute);
3408 SSVAL(p, 12, st.second);
3409 SSVAL(p, 14, st.milliseconds);
3412 struct s_notify_info_data_table
3414 uint16 type;
3415 uint16 field;
3416 const char *name;
3417 uint32 size;
3418 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3419 print_queue_struct *queue,
3420 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3423 /* A table describing the various print notification constants and
3424 whether the notification data is a pointer to a variable sized
3425 buffer, a one value uint32 or a two value uint32. */
3427 static const struct s_notify_info_data_table notify_info_data_table[] =
3429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3430 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3431 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3432 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3433 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3434 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3435 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3436 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3437 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3455 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3456 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3457 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3458 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3459 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3460 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3461 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3462 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3463 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3464 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3465 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3480 /*******************************************************************
3481 Return the size of info_data structure.
3482 ********************************************************************/
3484 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3486 int i=0;
3488 for (i = 0; i < sizeof(notify_info_data_table); i++)
3490 if ( (notify_info_data_table[i].type == type)
3491 && (notify_info_data_table[i].field == field) )
3493 switch(notify_info_data_table[i].size)
3495 case NOTIFY_ONE_VALUE:
3496 case NOTIFY_TWO_VALUE:
3497 return 1;
3498 case NOTIFY_STRING:
3499 return 2;
3501 /* The only pointer notify data I have seen on
3502 the wire is the submitted time and this has
3503 the notify size set to 4. -tpot */
3505 case NOTIFY_POINTER:
3506 return 4;
3508 case NOTIFY_SECDESC:
3509 return 5;
3514 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3516 return 0;
3519 /*******************************************************************
3520 Return the type of notify_info_data.
3521 ********************************************************************/
3523 static int type_of_notify_info_data(uint16 type, uint16 field)
3525 int i=0;
3527 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3528 if (notify_info_data_table[i].type == type &&
3529 notify_info_data_table[i].field == field)
3530 return notify_info_data_table[i].size;
3533 return False;
3536 /****************************************************************************
3537 ****************************************************************************/
3539 static int search_notify(uint16 type, uint16 field, int *value)
3541 int i;
3543 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3544 if (notify_info_data_table[i].type == type &&
3545 notify_info_data_table[i].field == field &&
3546 notify_info_data_table[i].fn != NULL) {
3547 *value = i;
3548 return True;
3552 return False;
3555 /****************************************************************************
3556 ****************************************************************************/
3558 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3560 info_data->type = type;
3561 info_data->field = field;
3562 info_data->reserved = 0;
3564 info_data->size = size_of_notify_info_data(type, field);
3565 info_data->enc_type = type_of_notify_info_data(type, field);
3567 info_data->id = id;
3572 /*******************************************************************
3574 * fill a notify_info struct with info asked
3576 ********************************************************************/
3578 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3579 snum, SPOOL_NOTIFY_OPTION_TYPE
3580 *option_type, uint32 id,
3581 TALLOC_CTX *mem_ctx)
3583 int field_num,j;
3584 uint16 type;
3585 uint16 field;
3587 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3588 NT_PRINTER_INFO_LEVEL *printer = NULL;
3589 print_queue_struct *queue=NULL;
3591 type=option_type->type;
3593 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3594 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3595 option_type->count, lp_servicename(snum)));
3597 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3598 return False;
3600 for(field_num=0; field_num<option_type->count; field_num++) {
3601 field = option_type->fields[field_num];
3603 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3605 if (!search_notify(type, field, &j) )
3606 continue;
3608 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3609 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3610 return False;
3611 } else
3612 info->data = tid;
3614 current_data = &info->data[info->count];
3616 construct_info_data(current_data, type, field, id);
3618 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3619 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3621 notify_info_data_table[j].fn(snum, current_data, queue,
3622 printer, mem_ctx);
3624 info->count++;
3627 free_a_printer(&printer, 2);
3628 return True;
3631 /*******************************************************************
3633 * fill a notify_info struct with info asked
3635 ********************************************************************/
3637 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3638 SPOOL_NOTIFY_INFO *info,
3639 NT_PRINTER_INFO_LEVEL *printer,
3640 int snum, SPOOL_NOTIFY_OPTION_TYPE
3641 *option_type, uint32 id,
3642 TALLOC_CTX *mem_ctx)
3644 int field_num,j;
3645 uint16 type;
3646 uint16 field;
3648 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3650 DEBUG(4,("construct_notify_jobs_info\n"));
3652 type = option_type->type;
3654 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3655 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3656 option_type->count));
3658 for(field_num=0; field_num<option_type->count; field_num++) {
3659 field = option_type->fields[field_num];
3661 if (!search_notify(type, field, &j) )
3662 continue;
3664 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3665 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3666 return False;
3668 else info->data = tid;
3670 current_data=&(info->data[info->count]);
3672 construct_info_data(current_data, type, field, id);
3673 notify_info_data_table[j].fn(snum, current_data, queue,
3674 printer, mem_ctx);
3675 info->count++;
3678 return True;
3682 * JFM: The enumeration is not that simple, it's even non obvious.
3684 * let's take an example: I want to monitor the PRINTER SERVER for
3685 * the printer's name and the number of jobs currently queued.
3686 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3687 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3689 * I have 3 printers on the back of my server.
3691 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3692 * structures.
3693 * Number Data Id
3694 * 1 printer 1 name 1
3695 * 2 printer 1 cjob 1
3696 * 3 printer 2 name 2
3697 * 4 printer 2 cjob 2
3698 * 5 printer 3 name 3
3699 * 6 printer 3 name 3
3701 * that's the print server case, the printer case is even worse.
3704 /*******************************************************************
3706 * enumerate all printers on the printserver
3707 * fill a notify_info struct with info asked
3709 ********************************************************************/
3711 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3712 SPOOL_NOTIFY_INFO *info,
3713 TALLOC_CTX *mem_ctx)
3715 int snum;
3716 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3717 int n_services=lp_numservices();
3718 int i;
3719 SPOOL_NOTIFY_OPTION *option;
3720 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3722 DEBUG(4,("printserver_notify_info\n"));
3724 if (!Printer)
3725 return WERR_BADFID;
3727 option=Printer->notify.option;
3728 info->version=2;
3729 info->data=NULL;
3730 info->count=0;
3732 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3733 sending a ffpcn() request first */
3735 if ( !option )
3736 return WERR_BADFID;
3738 for (i=0; i<option->count; i++) {
3739 option_type=&(option->ctr.type[i]);
3741 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3742 continue;
3744 for (snum=0; snum<n_services; snum++)
3746 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3747 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3751 #if 0
3753 * Debugging information, don't delete.
3756 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3757 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3758 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3760 for (i=0; i<info->count; i++) {
3761 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3762 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3763 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3765 #endif
3767 return WERR_OK;
3770 /*******************************************************************
3772 * fill a notify_info struct with info asked
3774 ********************************************************************/
3776 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3777 TALLOC_CTX *mem_ctx)
3779 int snum;
3780 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3781 int i;
3782 uint32 id;
3783 SPOOL_NOTIFY_OPTION *option;
3784 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3785 int count,j;
3786 print_queue_struct *queue=NULL;
3787 print_status_struct status;
3789 DEBUG(4,("printer_notify_info\n"));
3791 if (!Printer)
3792 return WERR_BADFID;
3794 option=Printer->notify.option;
3795 id = 0x0;
3796 info->version=2;
3797 info->data=NULL;
3798 info->count=0;
3800 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3801 sending a ffpcn() request first */
3803 if ( !option )
3804 return WERR_BADFID;
3806 get_printer_snum(p, hnd, &snum);
3808 for (i=0; i<option->count; i++) {
3809 option_type=&option->ctr.type[i];
3811 switch ( option_type->type ) {
3812 case PRINTER_NOTIFY_TYPE:
3813 if(construct_notify_printer_info(Printer, info, snum,
3814 option_type, id,
3815 mem_ctx))
3816 id--;
3817 break;
3819 case JOB_NOTIFY_TYPE: {
3820 NT_PRINTER_INFO_LEVEL *printer = NULL;
3822 count = print_queue_status(snum, &queue, &status);
3824 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3825 goto done;
3827 for (j=0; j<count; j++) {
3828 construct_notify_jobs_info(&queue[j], info,
3829 printer, snum,
3830 option_type,
3831 queue[j].job,
3832 mem_ctx);
3835 free_a_printer(&printer, 2);
3837 done:
3838 SAFE_FREE(queue);
3839 break;
3845 * Debugging information, don't delete.
3848 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3849 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3850 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3852 for (i=0; i<info->count; i++) {
3853 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3854 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3855 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3858 return WERR_OK;
3861 /********************************************************************
3862 * spoolss_rfnpcnex
3863 ********************************************************************/
3865 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3867 POLICY_HND *handle = &q_u->handle;
3868 SPOOL_NOTIFY_INFO *info = &r_u->info;
3870 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3871 WERROR result = WERR_BADFID;
3873 /* we always have a NOTIFY_INFO struct */
3874 r_u->info_ptr=0x1;
3876 if (!Printer) {
3877 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3878 OUR_HANDLE(handle)));
3879 goto done;
3882 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3885 * We are now using the change value, and
3886 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3887 * I don't have a global notification system, I'm sending back all the
3888 * informations even when _NOTHING_ has changed.
3891 /* We need to keep track of the change value to send back in
3892 RRPCN replies otherwise our updates are ignored. */
3894 Printer->notify.fnpcn = True;
3896 if (Printer->notify.client_connected) {
3897 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3898 Printer->notify.change = q_u->change;
3901 /* just ignore the SPOOL_NOTIFY_OPTION */
3903 switch (Printer->printer_type) {
3904 case PRINTER_HANDLE_IS_PRINTSERVER:
3905 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3906 break;
3908 case PRINTER_HANDLE_IS_PRINTER:
3909 result = printer_notify_info(p, handle, info, p->mem_ctx);
3910 break;
3913 Printer->notify.fnpcn = False;
3915 done:
3916 return result;
3919 /********************************************************************
3920 * construct_printer_info_0
3921 * fill a printer_info_0 struct
3922 ********************************************************************/
3924 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3926 pstring chaine;
3927 int count;
3928 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3929 counter_printer_0 *session_counter;
3930 uint32 global_counter;
3931 struct tm *t;
3932 time_t setuptime;
3933 print_status_struct status;
3935 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3936 return False;
3938 count = print_queue_length(snum, &status);
3940 /* check if we already have a counter for this printer */
3941 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3943 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3944 if (session_counter->snum == snum)
3945 break;
3948 /* it's the first time, add it to the list */
3949 if (session_counter==NULL) {
3950 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3951 free_a_printer(&ntprinter, 2);
3952 return False;
3954 ZERO_STRUCTP(session_counter);
3955 session_counter->snum=snum;
3956 session_counter->counter=0;
3957 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3960 /* increment it */
3961 session_counter->counter++;
3963 /* JFM:
3964 * the global_counter should be stored in a TDB as it's common to all the clients
3965 * and should be zeroed on samba startup
3967 global_counter=session_counter->counter;
3969 pstrcpy(chaine,ntprinter->info_2->printername);
3971 init_unistr(&printer->printername, chaine);
3973 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3974 init_unistr(&printer->servername, chaine);
3976 printer->cjobs = count;
3977 printer->total_jobs = 0;
3978 printer->total_bytes = 0;
3980 setuptime = (time_t)ntprinter->info_2->setuptime;
3981 t=gmtime(&setuptime);
3983 printer->year = t->tm_year+1900;
3984 printer->month = t->tm_mon+1;
3985 printer->dayofweek = t->tm_wday;
3986 printer->day = t->tm_mday;
3987 printer->hour = t->tm_hour;
3988 printer->minute = t->tm_min;
3989 printer->second = t->tm_sec;
3990 printer->milliseconds = 0;
3992 printer->global_counter = global_counter;
3993 printer->total_pages = 0;
3995 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3996 printer->major_version = 0x0005; /* NT 5 */
3997 printer->build_version = 0x0893; /* build 2195 */
3999 printer->unknown7 = 0x1;
4000 printer->unknown8 = 0x0;
4001 printer->unknown9 = 0x0;
4002 printer->session_counter = session_counter->counter;
4003 printer->unknown11 = 0x0;
4004 printer->printer_errors = 0x0; /* number of print failure */
4005 printer->unknown13 = 0x0;
4006 printer->unknown14 = 0x1;
4007 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4008 printer->unknown16 = 0x0;
4009 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4010 printer->unknown18 = 0x0;
4011 printer->status = nt_printq_status(status.status);
4012 printer->unknown20 = 0x0;
4013 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4014 printer->unknown22 = 0x0;
4015 printer->unknown23 = 0x6; /* 6 ???*/
4016 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4017 printer->unknown25 = 0;
4018 printer->unknown26 = 0;
4019 printer->unknown27 = 0;
4020 printer->unknown28 = 0;
4021 printer->unknown29 = 0;
4023 free_a_printer(&ntprinter,2);
4024 return (True);
4027 /********************************************************************
4028 * construct_printer_info_1
4029 * fill a printer_info_1 struct
4030 ********************************************************************/
4031 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4033 pstring chaine;
4034 pstring chaine2;
4035 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4037 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4038 return False;
4040 printer->flags=flags;
4042 if (*ntprinter->info_2->comment == '\0') {
4043 init_unistr(&printer->comment, lp_comment(snum));
4044 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4045 ntprinter->info_2->drivername, lp_comment(snum));
4047 else {
4048 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4049 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4050 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4053 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4055 init_unistr(&printer->description, chaine);
4056 init_unistr(&printer->name, chaine2);
4058 free_a_printer(&ntprinter,2);
4060 return True;
4063 /****************************************************************************
4064 Free a DEVMODE struct.
4065 ****************************************************************************/
4067 static void free_dev_mode(DEVICEMODE *dev)
4069 if (dev == NULL)
4070 return;
4072 SAFE_FREE(dev->private);
4073 SAFE_FREE(dev);
4077 /****************************************************************************
4078 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4079 should be valid upon entry
4080 ****************************************************************************/
4082 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4084 if ( !devmode || !ntdevmode )
4085 return False;
4087 init_unistr(&devmode->devicename, ntdevmode->devicename);
4089 init_unistr(&devmode->formname, ntdevmode->formname);
4091 devmode->specversion = ntdevmode->specversion;
4092 devmode->driverversion = ntdevmode->driverversion;
4093 devmode->size = ntdevmode->size;
4094 devmode->driverextra = ntdevmode->driverextra;
4095 devmode->fields = ntdevmode->fields;
4097 devmode->orientation = ntdevmode->orientation;
4098 devmode->papersize = ntdevmode->papersize;
4099 devmode->paperlength = ntdevmode->paperlength;
4100 devmode->paperwidth = ntdevmode->paperwidth;
4101 devmode->scale = ntdevmode->scale;
4102 devmode->copies = ntdevmode->copies;
4103 devmode->defaultsource = ntdevmode->defaultsource;
4104 devmode->printquality = ntdevmode->printquality;
4105 devmode->color = ntdevmode->color;
4106 devmode->duplex = ntdevmode->duplex;
4107 devmode->yresolution = ntdevmode->yresolution;
4108 devmode->ttoption = ntdevmode->ttoption;
4109 devmode->collate = ntdevmode->collate;
4110 devmode->icmmethod = ntdevmode->icmmethod;
4111 devmode->icmintent = ntdevmode->icmintent;
4112 devmode->mediatype = ntdevmode->mediatype;
4113 devmode->dithertype = ntdevmode->dithertype;
4115 if (ntdevmode->private != NULL) {
4116 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4117 return False;
4120 return True;
4123 /****************************************************************************
4124 Create a DEVMODE struct. Returns malloced memory.
4125 ****************************************************************************/
4127 DEVICEMODE *construct_dev_mode(int snum)
4129 NT_PRINTER_INFO_LEVEL *printer = NULL;
4130 DEVICEMODE *devmode = NULL;
4132 DEBUG(7,("construct_dev_mode\n"));
4134 DEBUGADD(8,("getting printer characteristics\n"));
4136 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4137 return NULL;
4139 if ( !printer->info_2->devmode ) {
4140 DEBUG(5, ("BONG! There was no device mode!\n"));
4141 goto done;
4144 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4145 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4146 goto done;
4149 ZERO_STRUCTP(devmode);
4151 DEBUGADD(8,("loading DEVICEMODE\n"));
4153 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4154 free_dev_mode( devmode );
4155 devmode = NULL;
4158 done:
4159 free_a_printer(&printer,2);
4161 return devmode;
4164 /********************************************************************
4165 * construct_printer_info_2
4166 * fill a printer_info_2 struct
4167 ********************************************************************/
4169 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4171 int count;
4172 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4174 print_status_struct status;
4176 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4177 return False;
4179 count = print_queue_length(snum, &status);
4181 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4182 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4183 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4184 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4185 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4187 if (*ntprinter->info_2->comment == '\0')
4188 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4189 else
4190 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4192 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4193 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4194 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4195 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4196 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4198 printer->attributes = ntprinter->info_2->attributes;
4200 printer->priority = ntprinter->info_2->priority; /* priority */
4201 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4202 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4203 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4204 printer->status = nt_printq_status(status.status); /* status */
4205 printer->cjobs = count; /* jobs */
4206 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4208 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4209 DEBUG(8, ("Returning NULL Devicemode!\n"));
4212 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4213 /* steal the printer info sec_desc structure. [badly done]. */
4214 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4215 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4216 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4217 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4219 else {
4220 printer->secdesc = NULL;
4223 free_a_printer(&ntprinter, 2);
4224 return True;
4227 /********************************************************************
4228 * construct_printer_info_3
4229 * fill a printer_info_3 struct
4230 ********************************************************************/
4232 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4234 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4235 PRINTER_INFO_3 *printer = NULL;
4237 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4238 return False;
4240 *pp_printer = NULL;
4241 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4242 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4243 return False;
4246 ZERO_STRUCTP(printer);
4248 printer->flags = 4; /* These are the components of the SD we are returning. */
4249 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4250 /* steal the printer info sec_desc structure. [badly done]. */
4251 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4253 #if 0
4255 * Set the flags for the components we are returning.
4258 if (printer->secdesc->owner_sid)
4259 printer->flags |= OWNER_SECURITY_INFORMATION;
4261 if (printer->secdesc->grp_sid)
4262 printer->flags |= GROUP_SECURITY_INFORMATION;
4264 if (printer->secdesc->dacl)
4265 printer->flags |= DACL_SECURITY_INFORMATION;
4267 if (printer->secdesc->sacl)
4268 printer->flags |= SACL_SECURITY_INFORMATION;
4269 #endif
4271 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4272 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4273 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4276 free_a_printer(&ntprinter, 2);
4278 *pp_printer = printer;
4279 return True;
4282 /********************************************************************
4283 * construct_printer_info_4
4284 * fill a printer_info_4 struct
4285 ********************************************************************/
4287 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4289 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4291 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4292 return False;
4294 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4295 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4296 printer->attributes = ntprinter->info_2->attributes;
4298 free_a_printer(&ntprinter, 2);
4299 return True;
4302 /********************************************************************
4303 * construct_printer_info_5
4304 * fill a printer_info_5 struct
4305 ********************************************************************/
4307 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4309 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4311 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4312 return False;
4314 init_unistr(&printer->printername, ntprinter->info_2->printername);
4315 init_unistr(&printer->portname, ntprinter->info_2->portname);
4316 printer->attributes = ntprinter->info_2->attributes;
4318 /* these two are not used by NT+ according to MSDN */
4320 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4321 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4323 free_a_printer(&ntprinter, 2);
4325 return True;
4328 /********************************************************************
4329 * construct_printer_info_7
4330 * fill a printer_info_7 struct
4331 ********************************************************************/
4333 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4335 char *guid_str = NULL;
4336 struct uuid guid;
4338 if (is_printer_published(print_hnd, snum, &guid)) {
4339 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4340 strupper_m(guid_str);
4341 init_unistr(&printer->guid, guid_str);
4342 printer->action = SPOOL_DS_PUBLISH;
4343 } else {
4344 init_unistr(&printer->guid, "");
4345 printer->action = SPOOL_DS_UNPUBLISH;
4348 return True;
4351 /********************************************************************
4352 Spoolss_enumprinters.
4353 ********************************************************************/
4355 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4357 int snum;
4358 int i;
4359 int n_services=lp_numservices();
4360 PRINTER_INFO_1 *tp, *printers=NULL;
4361 PRINTER_INFO_1 current_prt;
4363 DEBUG(4,("enum_all_printers_info_1\n"));
4365 for (snum=0; snum<n_services; snum++) {
4366 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4367 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4369 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4370 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4371 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4372 SAFE_FREE(printers);
4373 *returned=0;
4374 return WERR_NOMEM;
4376 else printers = tp;
4377 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4379 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4380 (*returned)++;
4385 /* check the required size. */
4386 for (i=0; i<*returned; i++)
4387 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4389 if (!alloc_buffer_size(buffer, *needed))
4390 return WERR_INSUFFICIENT_BUFFER;
4392 /* fill the buffer with the structures */
4393 for (i=0; i<*returned; i++)
4394 smb_io_printer_info_1("", buffer, &printers[i], 0);
4396 /* clear memory */
4397 SAFE_FREE(printers);
4399 if (*needed > offered) {
4400 *returned=0;
4401 return WERR_INSUFFICIENT_BUFFER;
4403 else
4404 return WERR_OK;
4407 /********************************************************************
4408 enum_all_printers_info_1_local.
4409 *********************************************************************/
4411 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4413 DEBUG(4,("enum_all_printers_info_1_local\n"));
4415 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4418 /********************************************************************
4419 enum_all_printers_info_1_name.
4420 *********************************************************************/
4422 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4424 char *s = name;
4426 DEBUG(4,("enum_all_printers_info_1_name\n"));
4428 if ((name[0] == '\\') && (name[1] == '\\'))
4429 s = name + 2;
4431 if (is_myname_or_ipaddr(s)) {
4432 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4434 else
4435 return WERR_INVALID_NAME;
4438 /********************************************************************
4439 enum_all_printers_info_1_remote.
4440 *********************************************************************/
4442 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4444 PRINTER_INFO_1 *printer;
4445 fstring printername;
4446 fstring desc;
4447 fstring comment;
4448 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4450 /* JFM: currently it's more a place holder than anything else.
4451 * In the spooler world there is a notion of server registration.
4452 * the print servers are registring (sp ?) on the PDC (in the same domain)
4454 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4457 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4458 return WERR_NOMEM;
4460 *returned=1;
4462 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4463 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4464 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4466 init_unistr(&printer->description, desc);
4467 init_unistr(&printer->name, printername);
4468 init_unistr(&printer->comment, comment);
4469 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4471 /* check the required size. */
4472 *needed += spoolss_size_printer_info_1(printer);
4474 if (!alloc_buffer_size(buffer, *needed)) {
4475 SAFE_FREE(printer);
4476 return WERR_INSUFFICIENT_BUFFER;
4479 /* fill the buffer with the structures */
4480 smb_io_printer_info_1("", buffer, printer, 0);
4482 /* clear memory */
4483 SAFE_FREE(printer);
4485 if (*needed > offered) {
4486 *returned=0;
4487 return WERR_INSUFFICIENT_BUFFER;
4489 else
4490 return WERR_OK;
4493 /********************************************************************
4494 enum_all_printers_info_1_network.
4495 *********************************************************************/
4497 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4499 char *s = name;
4501 DEBUG(4,("enum_all_printers_info_1_network\n"));
4503 /* If we respond to a enum_printers level 1 on our name with flags
4504 set to PRINTER_ENUM_REMOTE with a list of printers then these
4505 printers incorrectly appear in the APW browse list.
4506 Specifically the printers for the server appear at the workgroup
4507 level where all the other servers in the domain are
4508 listed. Windows responds to this call with a
4509 WERR_CAN_NOT_COMPLETE so we should do the same. */
4511 if (name[0] == '\\' && name[1] == '\\')
4512 s = name + 2;
4514 if (is_myname_or_ipaddr(s))
4515 return WERR_CAN_NOT_COMPLETE;
4517 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4520 /********************************************************************
4521 * api_spoolss_enumprinters
4523 * called from api_spoolss_enumprinters (see this to understand)
4524 ********************************************************************/
4526 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4528 int snum;
4529 int i;
4530 int n_services=lp_numservices();
4531 PRINTER_INFO_2 *tp, *printers=NULL;
4532 PRINTER_INFO_2 current_prt;
4534 for (snum=0; snum<n_services; snum++) {
4535 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4536 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4538 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4539 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4540 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4541 SAFE_FREE(printers);
4542 *returned = 0;
4543 return WERR_NOMEM;
4545 else printers = tp;
4546 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4547 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4548 (*returned)++;
4553 /* check the required size. */
4554 for (i=0; i<*returned; i++)
4555 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4557 if (!alloc_buffer_size(buffer, *needed)) {
4558 for (i=0; i<*returned; i++) {
4559 free_devmode(printers[i].devmode);
4561 SAFE_FREE(printers);
4562 return WERR_INSUFFICIENT_BUFFER;
4565 /* fill the buffer with the structures */
4566 for (i=0; i<*returned; i++)
4567 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4569 /* clear memory */
4570 for (i=0; i<*returned; i++) {
4571 free_devmode(printers[i].devmode);
4573 SAFE_FREE(printers);
4575 if (*needed > offered) {
4576 *returned=0;
4577 return WERR_INSUFFICIENT_BUFFER;
4579 else
4580 return WERR_OK;
4583 /********************************************************************
4584 * handle enumeration of printers at level 1
4585 ********************************************************************/
4587 static WERROR enumprinters_level1( uint32 flags, fstring name,
4588 NEW_BUFFER *buffer, uint32 offered,
4589 uint32 *needed, uint32 *returned)
4591 /* Not all the flags are equals */
4593 if (flags & PRINTER_ENUM_LOCAL)
4594 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4596 if (flags & PRINTER_ENUM_NAME)
4597 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4599 if (flags & PRINTER_ENUM_REMOTE)
4600 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4602 if (flags & PRINTER_ENUM_NETWORK)
4603 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4605 return WERR_OK; /* NT4sp5 does that */
4608 /********************************************************************
4609 * handle enumeration of printers at level 2
4610 ********************************************************************/
4612 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4613 NEW_BUFFER *buffer, uint32 offered,
4614 uint32 *needed, uint32 *returned)
4616 char *s = servername;
4618 if (flags & PRINTER_ENUM_LOCAL) {
4619 return enum_all_printers_info_2(buffer, offered, needed, returned);
4622 if (flags & PRINTER_ENUM_NAME) {
4623 if ((servername[0] == '\\') && (servername[1] == '\\'))
4624 s = servername + 2;
4625 if (is_myname_or_ipaddr(s))
4626 return enum_all_printers_info_2(buffer, offered, needed, returned);
4627 else
4628 return WERR_INVALID_NAME;
4631 if (flags & PRINTER_ENUM_REMOTE)
4632 return WERR_UNKNOWN_LEVEL;
4634 return WERR_OK;
4637 /********************************************************************
4638 * handle enumeration of printers at level 5
4639 ********************************************************************/
4641 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4642 NEW_BUFFER *buffer, uint32 offered,
4643 uint32 *needed, uint32 *returned)
4645 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4646 return WERR_OK;
4649 /********************************************************************
4650 * api_spoolss_enumprinters
4652 * called from api_spoolss_enumprinters (see this to understand)
4653 ********************************************************************/
4655 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4657 uint32 flags = q_u->flags;
4658 UNISTR2 *servername = &q_u->servername;
4659 uint32 level = q_u->level;
4660 NEW_BUFFER *buffer = NULL;
4661 uint32 offered = q_u->offered;
4662 uint32 *needed = &r_u->needed;
4663 uint32 *returned = &r_u->returned;
4665 fstring name;
4667 /* that's an [in out] buffer */
4668 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4669 buffer = r_u->buffer;
4671 DEBUG(4,("_spoolss_enumprinters\n"));
4673 *needed=0;
4674 *returned=0;
4677 * Level 1:
4678 * flags==PRINTER_ENUM_NAME
4679 * if name=="" then enumerates all printers
4680 * if name!="" then enumerate the printer
4681 * flags==PRINTER_ENUM_REMOTE
4682 * name is NULL, enumerate printers
4683 * Level 2: name!="" enumerates printers, name can't be NULL
4684 * Level 3: doesn't exist
4685 * Level 4: does a local registry lookup
4686 * Level 5: same as Level 2
4689 unistr2_to_ascii(name, servername, sizeof(name)-1);
4690 strupper_m(name);
4692 switch (level) {
4693 case 1:
4694 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4695 case 2:
4696 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4697 case 5:
4698 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4699 case 3:
4700 case 4:
4701 break;
4703 return WERR_UNKNOWN_LEVEL;
4706 /****************************************************************************
4707 ****************************************************************************/
4709 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4711 PRINTER_INFO_0 *printer=NULL;
4713 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4714 return WERR_NOMEM;
4716 construct_printer_info_0(print_hnd, printer, snum);
4718 /* check the required size. */
4719 *needed += spoolss_size_printer_info_0(printer);
4721 if (!alloc_buffer_size(buffer, *needed)) {
4722 SAFE_FREE(printer);
4723 return WERR_INSUFFICIENT_BUFFER;
4726 /* fill the buffer with the structures */
4727 smb_io_printer_info_0("", buffer, printer, 0);
4729 /* clear memory */
4730 SAFE_FREE(printer);
4732 if (*needed > offered) {
4733 return WERR_INSUFFICIENT_BUFFER;
4736 return WERR_OK;
4739 /****************************************************************************
4740 ****************************************************************************/
4742 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4744 PRINTER_INFO_1 *printer=NULL;
4746 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4747 return WERR_NOMEM;
4749 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4751 /* check the required size. */
4752 *needed += spoolss_size_printer_info_1(printer);
4754 if (!alloc_buffer_size(buffer, *needed)) {
4755 SAFE_FREE(printer);
4756 return WERR_INSUFFICIENT_BUFFER;
4759 /* fill the buffer with the structures */
4760 smb_io_printer_info_1("", buffer, printer, 0);
4762 /* clear memory */
4763 SAFE_FREE(printer);
4765 if (*needed > offered) {
4766 return WERR_INSUFFICIENT_BUFFER;
4769 return WERR_OK;
4772 /****************************************************************************
4773 ****************************************************************************/
4775 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4777 PRINTER_INFO_2 *printer=NULL;
4779 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4780 return WERR_NOMEM;
4782 construct_printer_info_2(print_hnd, printer, snum);
4784 /* check the required size. */
4785 *needed += spoolss_size_printer_info_2(printer);
4787 if (!alloc_buffer_size(buffer, *needed)) {
4788 free_printer_info_2(printer);
4789 return WERR_INSUFFICIENT_BUFFER;
4792 /* fill the buffer with the structures */
4793 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4794 free_printer_info_2(printer);
4795 return WERR_NOMEM;
4798 /* clear memory */
4799 free_printer_info_2(printer);
4801 if (*needed > offered) {
4802 return WERR_INSUFFICIENT_BUFFER;
4805 return WERR_OK;
4808 /****************************************************************************
4809 ****************************************************************************/
4811 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4813 PRINTER_INFO_3 *printer=NULL;
4815 if (!construct_printer_info_3(print_hnd, &printer, snum))
4816 return WERR_NOMEM;
4818 /* check the required size. */
4819 *needed += spoolss_size_printer_info_3(printer);
4821 if (!alloc_buffer_size(buffer, *needed)) {
4822 free_printer_info_3(printer);
4823 return WERR_INSUFFICIENT_BUFFER;
4826 /* fill the buffer with the structures */
4827 smb_io_printer_info_3("", buffer, printer, 0);
4829 /* clear memory */
4830 free_printer_info_3(printer);
4832 if (*needed > offered) {
4833 return WERR_INSUFFICIENT_BUFFER;
4836 return WERR_OK;
4839 /****************************************************************************
4840 ****************************************************************************/
4842 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4844 PRINTER_INFO_4 *printer=NULL;
4846 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4847 return WERR_NOMEM;
4849 if (!construct_printer_info_4(print_hnd, printer, snum))
4850 return WERR_NOMEM;
4852 /* check the required size. */
4853 *needed += spoolss_size_printer_info_4(printer);
4855 if (!alloc_buffer_size(buffer, *needed)) {
4856 free_printer_info_4(printer);
4857 return WERR_INSUFFICIENT_BUFFER;
4860 /* fill the buffer with the structures */
4861 smb_io_printer_info_4("", buffer, printer, 0);
4863 /* clear memory */
4864 free_printer_info_4(printer);
4866 if (*needed > offered) {
4867 return WERR_INSUFFICIENT_BUFFER;
4870 return WERR_OK;
4873 /****************************************************************************
4874 ****************************************************************************/
4876 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4878 PRINTER_INFO_5 *printer=NULL;
4880 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4881 return WERR_NOMEM;
4883 if (!construct_printer_info_5(print_hnd, printer, snum))
4884 return WERR_NOMEM;
4886 /* check the required size. */
4887 *needed += spoolss_size_printer_info_5(printer);
4889 if (!alloc_buffer_size(buffer, *needed)) {
4890 free_printer_info_5(printer);
4891 return WERR_INSUFFICIENT_BUFFER;
4894 /* fill the buffer with the structures */
4895 smb_io_printer_info_5("", buffer, printer, 0);
4897 /* clear memory */
4898 free_printer_info_5(printer);
4900 if (*needed > offered) {
4901 return WERR_INSUFFICIENT_BUFFER;
4904 return WERR_OK;
4907 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4909 PRINTER_INFO_7 *printer=NULL;
4911 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4912 return WERR_NOMEM;
4914 if (!construct_printer_info_7(print_hnd, printer, snum))
4915 return WERR_NOMEM;
4917 /* check the required size. */
4918 *needed += spoolss_size_printer_info_7(printer);
4920 if (!alloc_buffer_size(buffer, *needed)) {
4921 free_printer_info_7(printer);
4922 return WERR_INSUFFICIENT_BUFFER;
4925 /* fill the buffer with the structures */
4926 smb_io_printer_info_7("", buffer, printer, 0);
4928 /* clear memory */
4929 free_printer_info_7(printer);
4931 if (*needed > offered) {
4932 return WERR_INSUFFICIENT_BUFFER;
4935 return WERR_OK;
4938 /****************************************************************************
4939 ****************************************************************************/
4941 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4943 POLICY_HND *handle = &q_u->handle;
4944 uint32 level = q_u->level;
4945 NEW_BUFFER *buffer = NULL;
4946 uint32 offered = q_u->offered;
4947 uint32 *needed = &r_u->needed;
4948 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4950 int snum;
4952 /* that's an [in out] buffer */
4953 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4954 buffer = r_u->buffer;
4956 *needed=0;
4958 if (!get_printer_snum(p, handle, &snum))
4959 return WERR_BADFID;
4961 switch (level) {
4962 case 0:
4963 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4964 case 1:
4965 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4966 case 2:
4967 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4968 case 3:
4969 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4970 case 4:
4971 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4972 case 5:
4973 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4974 case 7:
4975 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4977 return WERR_UNKNOWN_LEVEL;
4980 /********************************************************************
4981 * fill a DRIVER_INFO_1 struct
4982 ********************************************************************/
4984 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4986 init_unistr( &info->name, driver.info_3->name);
4989 /********************************************************************
4990 * construct_printer_driver_info_1
4991 ********************************************************************/
4993 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4995 NT_PRINTER_INFO_LEVEL *printer = NULL;
4996 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4998 ZERO_STRUCT(driver);
5000 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5001 return WERR_INVALID_PRINTER_NAME;
5003 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5004 return WERR_UNKNOWN_PRINTER_DRIVER;
5006 fill_printer_driver_info_1(info, driver, servername, architecture);
5008 free_a_printer(&printer,2);
5010 return WERR_OK;
5013 /********************************************************************
5014 * construct_printer_driver_info_2
5015 * fill a printer_info_2 struct
5016 ********************************************************************/
5018 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5020 pstring temp;
5022 info->version=driver.info_3->cversion;
5024 init_unistr( &info->name, driver.info_3->name );
5025 init_unistr( &info->architecture, driver.info_3->environment );
5028 if (strlen(driver.info_3->driverpath)) {
5029 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5030 init_unistr( &info->driverpath, temp );
5031 } else
5032 init_unistr( &info->driverpath, "" );
5034 if (strlen(driver.info_3->datafile)) {
5035 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5036 init_unistr( &info->datafile, temp );
5037 } else
5038 init_unistr( &info->datafile, "" );
5040 if (strlen(driver.info_3->configfile)) {
5041 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5042 init_unistr( &info->configfile, temp );
5043 } else
5044 init_unistr( &info->configfile, "" );
5047 /********************************************************************
5048 * construct_printer_driver_info_2
5049 * fill a printer_info_2 struct
5050 ********************************************************************/
5052 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5054 NT_PRINTER_INFO_LEVEL *printer = NULL;
5055 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5057 ZERO_STRUCT(printer);
5058 ZERO_STRUCT(driver);
5060 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5061 return WERR_INVALID_PRINTER_NAME;
5063 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5064 return WERR_UNKNOWN_PRINTER_DRIVER;
5066 fill_printer_driver_info_2(info, driver, servername);
5068 free_a_printer(&printer,2);
5070 return WERR_OK;
5073 /********************************************************************
5074 * copy a strings array and convert to UNICODE
5076 * convert an array of ascii string to a UNICODE string
5077 ********************************************************************/
5079 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5081 int i=0;
5082 int j=0;
5083 const char *v;
5084 pstring line;
5085 uint16 *tuary;
5087 DEBUG(6,("init_unistr_array\n"));
5088 *uni_array=NULL;
5090 while (True)
5092 if ( !char_array )
5093 v = "";
5094 else
5096 v = char_array[i];
5097 if (!v)
5098 v = ""; /* hack to handle null lists */
5101 /* hack to allow this to be used in places other than when generating
5102 the list of dependent files */
5104 if ( servername )
5105 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5106 else
5107 pstrcpy( line, v );
5109 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5111 /* add one extra unit16 for the second terminating NULL */
5113 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5114 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5115 return 0;
5116 } else
5117 *uni_array = tuary;
5119 if ( !strlen(v) )
5120 break;
5122 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5123 i++;
5126 if (*uni_array) {
5127 /* special case for ""; we need to add both NULL's here */
5128 if (!j)
5129 (*uni_array)[j++]=0x0000;
5130 (*uni_array)[j]=0x0000;
5133 DEBUGADD(6,("last one:done\n"));
5135 /* return size of array in uint16's */
5137 return j+1;
5140 /********************************************************************
5141 * construct_printer_info_3
5142 * fill a printer_info_3 struct
5143 ********************************************************************/
5145 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5147 pstring temp;
5149 ZERO_STRUCTP(info);
5151 info->version=driver.info_3->cversion;
5153 init_unistr( &info->name, driver.info_3->name );
5154 init_unistr( &info->architecture, driver.info_3->environment );
5156 if (strlen(driver.info_3->driverpath)) {
5157 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5158 init_unistr( &info->driverpath, temp );
5159 } else
5160 init_unistr( &info->driverpath, "" );
5162 if (strlen(driver.info_3->datafile)) {
5163 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5164 init_unistr( &info->datafile, temp );
5165 } else
5166 init_unistr( &info->datafile, "" );
5168 if (strlen(driver.info_3->configfile)) {
5169 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5170 init_unistr( &info->configfile, temp );
5171 } else
5172 init_unistr( &info->configfile, "" );
5174 if (strlen(driver.info_3->helpfile)) {
5175 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5176 init_unistr( &info->helpfile, temp );
5177 } else
5178 init_unistr( &info->helpfile, "" );
5180 init_unistr( &info->monitorname, driver.info_3->monitorname );
5181 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5183 info->dependentfiles=NULL;
5184 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5187 /********************************************************************
5188 * construct_printer_info_3
5189 * fill a printer_info_3 struct
5190 ********************************************************************/
5192 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5194 NT_PRINTER_INFO_LEVEL *printer = NULL;
5195 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5196 WERROR status;
5197 ZERO_STRUCT(driver);
5199 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5200 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5201 if (!W_ERROR_IS_OK(status))
5202 return WERR_INVALID_PRINTER_NAME;
5204 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5205 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5207 #if 0 /* JERRY */
5210 * I put this code in during testing. Helpful when commenting out the
5211 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5212 * as win2k always queries the driver using an infor level of 6.
5213 * I've left it in (but ifdef'd out) because I'll probably
5214 * use it in experimentation again in the future. --jerry 22/01/2002
5217 if (!W_ERROR_IS_OK(status)) {
5219 * Is this a W2k client ?
5221 if (version == 3) {
5222 /* Yes - try again with a WinNT driver. */
5223 version = 2;
5224 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5225 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5227 #endif
5229 if (!W_ERROR_IS_OK(status)) {
5230 free_a_printer(&printer,2);
5231 return WERR_UNKNOWN_PRINTER_DRIVER;
5234 #if 0 /* JERRY */
5236 #endif
5239 fill_printer_driver_info_3(info, driver, servername);
5241 free_a_printer(&printer,2);
5243 return WERR_OK;
5246 /********************************************************************
5247 * construct_printer_info_6
5248 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5249 ********************************************************************/
5251 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5253 pstring temp;
5254 fstring nullstr;
5256 ZERO_STRUCTP(info);
5257 memset(&nullstr, '\0', sizeof(fstring));
5259 info->version=driver.info_3->cversion;
5261 init_unistr( &info->name, driver.info_3->name );
5262 init_unistr( &info->architecture, driver.info_3->environment );
5264 if (strlen(driver.info_3->driverpath)) {
5265 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5266 init_unistr( &info->driverpath, temp );
5267 } else
5268 init_unistr( &info->driverpath, "" );
5270 if (strlen(driver.info_3->datafile)) {
5271 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5272 init_unistr( &info->datafile, temp );
5273 } else
5274 init_unistr( &info->datafile, "" );
5276 if (strlen(driver.info_3->configfile)) {
5277 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5278 init_unistr( &info->configfile, temp );
5279 } else
5280 init_unistr( &info->configfile, "" );
5282 if (strlen(driver.info_3->helpfile)) {
5283 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5284 init_unistr( &info->helpfile, temp );
5285 } else
5286 init_unistr( &info->helpfile, "" );
5288 init_unistr( &info->monitorname, driver.info_3->monitorname );
5289 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5291 info->dependentfiles = NULL;
5292 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5294 info->previousdrivernames=NULL;
5295 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5297 info->driver_date.low=0;
5298 info->driver_date.high=0;
5300 info->padding=0;
5301 info->driver_version_low=0;
5302 info->driver_version_high=0;
5304 init_unistr( &info->mfgname, "");
5305 init_unistr( &info->oem_url, "");
5306 init_unistr( &info->hardware_id, "");
5307 init_unistr( &info->provider, "");
5310 /********************************************************************
5311 * construct_printer_info_6
5312 * fill a printer_info_6 struct
5313 ********************************************************************/
5315 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5316 fstring servername, fstring architecture, uint32 version)
5318 NT_PRINTER_INFO_LEVEL *printer = NULL;
5319 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5320 WERROR status;
5322 ZERO_STRUCT(driver);
5324 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5326 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5328 if (!W_ERROR_IS_OK(status))
5329 return WERR_INVALID_PRINTER_NAME;
5331 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5333 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5335 if (!W_ERROR_IS_OK(status))
5338 * Is this a W2k client ?
5341 if (version < 3) {
5342 free_a_printer(&printer,2);
5343 return WERR_UNKNOWN_PRINTER_DRIVER;
5346 /* Yes - try again with a WinNT driver. */
5347 version = 2;
5348 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5349 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5350 if (!W_ERROR_IS_OK(status)) {
5351 free_a_printer(&printer,2);
5352 return WERR_UNKNOWN_PRINTER_DRIVER;
5356 fill_printer_driver_info_6(info, driver, servername);
5358 free_a_printer(&printer,2);
5359 free_a_printer_driver(driver, 3);
5361 return WERR_OK;
5364 /****************************************************************************
5365 ****************************************************************************/
5367 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5369 SAFE_FREE(info->dependentfiles);
5372 /****************************************************************************
5373 ****************************************************************************/
5375 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5377 SAFE_FREE(info->dependentfiles);
5381 /****************************************************************************
5382 ****************************************************************************/
5384 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5386 DRIVER_INFO_1 *info=NULL;
5387 WERROR status;
5389 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5390 return WERR_NOMEM;
5392 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5393 if (!W_ERROR_IS_OK(status)) {
5394 SAFE_FREE(info);
5395 return status;
5398 /* check the required size. */
5399 *needed += spoolss_size_printer_driver_info_1(info);
5401 if (!alloc_buffer_size(buffer, *needed)) {
5402 SAFE_FREE(info);
5403 return WERR_INSUFFICIENT_BUFFER;
5406 /* fill the buffer with the structures */
5407 smb_io_printer_driver_info_1("", buffer, info, 0);
5409 /* clear memory */
5410 SAFE_FREE(info);
5412 if (*needed > offered)
5413 return WERR_INSUFFICIENT_BUFFER;
5415 return WERR_OK;
5418 /****************************************************************************
5419 ****************************************************************************/
5421 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5423 DRIVER_INFO_2 *info=NULL;
5424 WERROR status;
5426 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5427 return WERR_NOMEM;
5429 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5430 if (!W_ERROR_IS_OK(status)) {
5431 SAFE_FREE(info);
5432 return status;
5435 /* check the required size. */
5436 *needed += spoolss_size_printer_driver_info_2(info);
5438 if (!alloc_buffer_size(buffer, *needed)) {
5439 SAFE_FREE(info);
5440 return WERR_INSUFFICIENT_BUFFER;
5443 /* fill the buffer with the structures */
5444 smb_io_printer_driver_info_2("", buffer, info, 0);
5446 /* clear memory */
5447 SAFE_FREE(info);
5449 if (*needed > offered)
5450 return WERR_INSUFFICIENT_BUFFER;
5452 return WERR_OK;
5455 /****************************************************************************
5456 ****************************************************************************/
5458 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5460 DRIVER_INFO_3 info;
5461 WERROR status;
5463 ZERO_STRUCT(info);
5465 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5466 if (!W_ERROR_IS_OK(status)) {
5467 return status;
5470 /* check the required size. */
5471 *needed += spoolss_size_printer_driver_info_3(&info);
5473 if (!alloc_buffer_size(buffer, *needed)) {
5474 free_printer_driver_info_3(&info);
5475 return WERR_INSUFFICIENT_BUFFER;
5478 /* fill the buffer with the structures */
5479 smb_io_printer_driver_info_3("", buffer, &info, 0);
5481 free_printer_driver_info_3(&info);
5483 if (*needed > offered)
5484 return WERR_INSUFFICIENT_BUFFER;
5486 return WERR_OK;
5489 /****************************************************************************
5490 ****************************************************************************/
5492 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5494 DRIVER_INFO_6 info;
5495 WERROR status;
5497 ZERO_STRUCT(info);
5499 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5500 if (!W_ERROR_IS_OK(status)) {
5501 return status;
5504 /* check the required size. */
5505 *needed += spoolss_size_printer_driver_info_6(&info);
5507 if (!alloc_buffer_size(buffer, *needed)) {
5508 free_printer_driver_info_6(&info);
5509 return WERR_INSUFFICIENT_BUFFER;
5512 /* fill the buffer with the structures */
5513 smb_io_printer_driver_info_6("", buffer, &info, 0);
5515 free_printer_driver_info_6(&info);
5517 if (*needed > offered)
5518 return WERR_INSUFFICIENT_BUFFER;
5520 return WERR_OK;
5523 /****************************************************************************
5524 ****************************************************************************/
5526 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5528 POLICY_HND *handle = &q_u->handle;
5529 UNISTR2 *uni_arch = &q_u->architecture;
5530 uint32 level = q_u->level;
5531 uint32 clientmajorversion = q_u->clientmajorversion;
5532 NEW_BUFFER *buffer = NULL;
5533 uint32 offered = q_u->offered;
5534 uint32 *needed = &r_u->needed;
5535 uint32 *servermajorversion = &r_u->servermajorversion;
5536 uint32 *serverminorversion = &r_u->serverminorversion;
5538 fstring servername;
5539 fstring architecture;
5540 int snum;
5542 /* that's an [in out] buffer */
5543 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5544 buffer = r_u->buffer;
5546 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5548 *needed = 0;
5549 *servermajorversion = 0;
5550 *serverminorversion = 0;
5552 fstrcpy(servername, get_called_name());
5553 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5555 if (!get_printer_snum(p, handle, &snum))
5556 return WERR_BADFID;
5558 switch (level) {
5559 case 1:
5560 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5561 case 2:
5562 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5563 case 3:
5564 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5565 case 6:
5566 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5569 return WERR_UNKNOWN_LEVEL;
5572 /****************************************************************************
5573 ****************************************************************************/
5575 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5577 POLICY_HND *handle = &q_u->handle;
5579 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5581 if (!Printer) {
5582 DEBUG(3,("Error in startpageprinter printer handle\n"));
5583 return WERR_BADFID;
5586 Printer->page_started=True;
5587 return WERR_OK;
5590 /****************************************************************************
5591 ****************************************************************************/
5593 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5595 POLICY_HND *handle = &q_u->handle;
5596 int snum;
5598 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5600 if (!Printer) {
5601 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5602 return WERR_BADFID;
5605 if (!get_printer_snum(p, handle, &snum))
5606 return WERR_BADFID;
5608 Printer->page_started=False;
5609 print_job_endpage(snum, Printer->jobid);
5611 return WERR_OK;
5614 /********************************************************************
5615 * api_spoolss_getprinter
5616 * called from the spoolss dispatcher
5618 ********************************************************************/
5620 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5622 POLICY_HND *handle = &q_u->handle;
5623 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5624 uint32 *jobid = &r_u->jobid;
5626 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5627 int snum;
5628 pstring jobname;
5629 fstring datatype;
5630 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5631 struct current_user user;
5633 if (!Printer) {
5634 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5635 return WERR_BADFID;
5638 get_current_user(&user, p);
5641 * a nice thing with NT is it doesn't listen to what you tell it.
5642 * when asked to send _only_ RAW datas, it tries to send datas
5643 * in EMF format.
5645 * So I add checks like in NT Server ...
5648 if (info_1->p_datatype != 0) {
5649 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5650 if (strcmp(datatype, "RAW") != 0) {
5651 (*jobid)=0;
5652 return WERR_INVALID_DATATYPE;
5656 /* get the share number of the printer */
5657 if (!get_printer_snum(p, handle, &snum)) {
5658 return WERR_BADFID;
5661 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5663 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5665 /* An error occured in print_job_start() so return an appropriate
5666 NT error code. */
5668 if (Printer->jobid == -1) {
5669 return map_werror_from_unix(errno);
5672 Printer->document_started=True;
5673 (*jobid) = Printer->jobid;
5675 return WERR_OK;
5678 /********************************************************************
5679 * api_spoolss_getprinter
5680 * called from the spoolss dispatcher
5682 ********************************************************************/
5684 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5686 POLICY_HND *handle = &q_u->handle;
5688 return _spoolss_enddocprinter_internal(p, handle);
5691 /****************************************************************************
5692 ****************************************************************************/
5694 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5696 POLICY_HND *handle = &q_u->handle;
5697 uint32 buffer_size = q_u->buffer_size;
5698 uint8 *buffer = q_u->buffer;
5699 uint32 *buffer_written = &q_u->buffer_size2;
5700 int snum;
5701 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5703 if (!Printer) {
5704 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5705 r_u->buffer_written = q_u->buffer_size2;
5706 return WERR_BADFID;
5709 if (!get_printer_snum(p, handle, &snum))
5710 return WERR_BADFID;
5712 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5713 if (*buffer_written == -1) {
5714 r_u->buffer_written = 0;
5715 if (errno == ENOSPC)
5716 return WERR_NO_SPOOL_SPACE;
5717 else
5718 return WERR_ACCESS_DENIED;
5721 r_u->buffer_written = q_u->buffer_size2;
5723 return WERR_OK;
5726 /********************************************************************
5727 * api_spoolss_getprinter
5728 * called from the spoolss dispatcher
5730 ********************************************************************/
5732 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5733 pipes_struct *p)
5735 struct current_user user;
5736 int snum;
5737 WERROR errcode = WERR_BADFUNC;
5738 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5740 get_current_user(&user, p);
5742 if (!Printer) {
5743 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5744 return WERR_BADFID;
5747 if (!get_printer_snum(p, handle, &snum))
5748 return WERR_BADFID;
5750 switch (command) {
5751 case PRINTER_CONTROL_PAUSE:
5752 if (print_queue_pause(&user, snum, &errcode)) {
5753 errcode = WERR_OK;
5755 break;
5756 case PRINTER_CONTROL_RESUME:
5757 case PRINTER_CONTROL_UNPAUSE:
5758 if (print_queue_resume(&user, snum, &errcode)) {
5759 errcode = WERR_OK;
5761 break;
5762 case PRINTER_CONTROL_PURGE:
5763 if (print_queue_purge(&user, snum, &errcode)) {
5764 errcode = WERR_OK;
5766 break;
5767 default:
5768 return WERR_UNKNOWN_LEVEL;
5771 return errcode;
5774 /********************************************************************
5775 * api_spoolss_abortprinter
5776 * From MSDN: "Deletes printer's spool file if printer is configured
5777 * for spooling"
5778 ********************************************************************/
5780 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5782 POLICY_HND *handle = &q_u->handle;
5783 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5784 int snum;
5785 struct current_user user;
5786 WERROR errcode = WERR_OK;
5788 if (!Printer) {
5789 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5790 return WERR_BADFID;
5793 if (!get_printer_snum(p, handle, &snum))
5794 return WERR_BADFID;
5796 get_current_user( &user, p );
5798 print_job_delete( &user, snum, Printer->jobid, &errcode );
5800 return errcode;
5803 /********************************************************************
5804 * called by spoolss_api_setprinter
5805 * when updating a printer description
5806 ********************************************************************/
5808 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5809 const SPOOL_PRINTER_INFO_LEVEL *info,
5810 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5812 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5813 struct current_user user;
5814 WERROR result;
5815 int snum;
5817 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5819 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5820 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5821 OUR_HANDLE(handle)));
5823 result = WERR_BADFID;
5824 goto done;
5827 /* NT seems to like setting the security descriptor even though
5828 nothing may have actually changed. This causes annoying
5829 dialog boxes when the user doesn't have permission to change
5830 the security descriptor. */
5832 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5834 if (DEBUGLEVEL >= 10) {
5835 SEC_ACL *the_acl;
5836 int i;
5838 the_acl = old_secdesc_ctr->sec->dacl;
5839 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5840 PRINTERNAME(snum), the_acl->num_aces));
5842 for (i = 0; i < the_acl->num_aces; i++) {
5843 fstring sid_str;
5845 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5847 DEBUG(10, ("%s 0x%08x\n", sid_str,
5848 the_acl->ace[i].info.mask));
5851 the_acl = secdesc_ctr->sec->dacl;
5853 if (the_acl) {
5854 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5855 PRINTERNAME(snum), the_acl->num_aces));
5857 for (i = 0; i < the_acl->num_aces; i++) {
5858 fstring sid_str;
5860 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5862 DEBUG(10, ("%s 0x%08x\n", sid_str,
5863 the_acl->ace[i].info.mask));
5865 } else {
5866 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5870 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5872 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5873 result = WERR_OK;
5874 goto done;
5877 /* Work out which user is performing the operation */
5879 get_current_user(&user, p);
5881 /* Check the user has permissions to change the security
5882 descriptor. By experimentation with two NT machines, the user
5883 requires Full Access to the printer to change security
5884 information. */
5886 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5887 result = WERR_ACCESS_DENIED;
5888 goto done;
5891 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5893 done:
5895 return result;
5898 /********************************************************************
5899 Do Samba sanity checks on a printer info struct.
5900 this has changed purpose: it now "canonicalises" printer
5901 info from a client rather than just checking it is correct
5902 ********************************************************************/
5904 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5906 fstring printername;
5907 const char *p;
5909 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5910 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5912 /* we force some elements to "correct" values */
5913 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5914 fstrcpy(info->sharename, lp_servicename(snum));
5916 /* make sure printername is in \\server\printername format */
5918 fstrcpy( printername, info->printername );
5919 p = printername;
5920 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5921 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5922 p++;
5925 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5926 get_called_name(), p );
5928 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5931 return True;
5934 /****************************************************************************
5935 ****************************************************************************/
5937 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5939 extern userdom_struct current_user_info;
5940 char *cmd = lp_addprinter_cmd();
5941 char **qlines;
5942 pstring command;
5943 int numlines;
5944 int ret;
5945 int fd;
5946 fstring remote_machine = "%m";
5948 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5950 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5951 cmd, printer->info_2->printername, printer->info_2->sharename,
5952 printer->info_2->portname, printer->info_2->drivername,
5953 printer->info_2->location, printer->info_2->comment, remote_machine);
5955 DEBUG(10,("Running [%s]\n", command));
5956 ret = smbrun(command, &fd);
5957 DEBUGADD(10,("returned [%d]\n", ret));
5959 if ( ret != 0 ) {
5960 if (fd != -1)
5961 close(fd);
5962 return False;
5965 numlines = 0;
5966 /* Get lines and convert them back to dos-codepage */
5967 qlines = fd_lines_load(fd, &numlines);
5968 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5969 close(fd);
5971 if(numlines) {
5972 /* Set the portname to what the script says the portname should be. */
5973 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5974 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5976 /* Send SIGHUP to process group... is there a better way? */
5977 kill(0, SIGHUP);
5979 /* reload our services immediately */
5980 reload_services( False );
5983 file_lines_free(qlines);
5984 return True;
5987 /********************************************************************
5988 * Called by spoolss_api_setprinter
5989 * when updating a printer description.
5990 ********************************************************************/
5992 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5993 const SPOOL_PRINTER_INFO_LEVEL *info,
5994 DEVICEMODE *devmode)
5996 int snum;
5997 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5998 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5999 WERROR result;
6000 UNISTR2 buffer;
6001 fstring asc_buffer;
6003 DEBUG(8,("update_printer\n"));
6005 result = WERR_OK;
6007 if (!Printer) {
6008 result = WERR_BADFID;
6009 goto done;
6012 if (!get_printer_snum(p, handle, &snum)) {
6013 result = WERR_BADFID;
6014 goto done;
6017 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6018 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6019 result = WERR_BADFID;
6020 goto done;
6023 DEBUGADD(8,("Converting info_2 struct\n"));
6026 * convert_printer_info converts the incoming
6027 * info from the client and overwrites the info
6028 * just read from the tdb in the pointer 'printer'.
6031 if (!convert_printer_info(info, printer, level)) {
6032 result = WERR_NOMEM;
6033 goto done;
6036 if (devmode) {
6037 /* we have a valid devmode
6038 convert it and link it*/
6040 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6041 if (!convert_devicemode(printer->info_2->printername, devmode,
6042 &printer->info_2->devmode)) {
6043 result = WERR_NOMEM;
6044 goto done;
6048 /* Do sanity check on the requested changes for Samba */
6050 if (!check_printer_ok(printer->info_2, snum)) {
6051 result = WERR_INVALID_PARAM;
6052 goto done;
6055 /* FIXME!!! If the driver has changed we really should verify that
6056 it is installed before doing much else --jerry */
6058 /* Check calling user has permission to update printer description */
6060 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6061 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6062 result = WERR_ACCESS_DENIED;
6063 goto done;
6066 /* Call addprinter hook */
6067 /* Check changes to see if this is really needed */
6069 if ( *lp_addprinter_cmd()
6070 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6071 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6072 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6073 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6075 if ( !add_printer_hook(printer) ) {
6076 result = WERR_ACCESS_DENIED;
6077 goto done;
6081 * make sure we actually reload the services after
6082 * this as smb.conf could have a new section in it
6083 * .... shouldn't .... but could
6085 reload_services(False);
6089 * When a *new* driver is bound to a printer, the drivername is used to
6090 * lookup previously saved driver initialization info, which is then
6091 * bound to the printer, simulating what happens in the Windows arch.
6093 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6095 if (!set_driver_init(printer, 2))
6097 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6098 printer->info_2->drivername));
6101 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6102 printer->info_2->drivername));
6104 notify_printer_driver(snum, printer->info_2->drivername);
6108 * flag which changes actually occured. This is a small subset of
6109 * all the possible changes. We also have to update things in the
6110 * DsSpooler key.
6113 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6114 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6115 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6116 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6118 notify_printer_comment(snum, printer->info_2->comment);
6121 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6122 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6123 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6124 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6126 notify_printer_sharename(snum, printer->info_2->sharename);
6129 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6130 char *pname;
6132 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6133 pname++;
6134 else
6135 pname = printer->info_2->printername;
6138 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6139 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6140 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6142 notify_printer_printername( snum, pname );
6145 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6146 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6147 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6148 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6150 notify_printer_port(snum, printer->info_2->portname);
6153 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6154 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6155 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6156 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6158 notify_printer_location(snum, printer->info_2->location);
6161 /* here we need to update some more DsSpooler keys */
6162 /* uNCName, serverName, shortServerName */
6164 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6165 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6166 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6167 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6168 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6170 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6171 global_myname(), printer->info_2->sharename );
6172 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6173 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6174 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6176 /* Update printer info */
6177 result = mod_a_printer(*printer, 2);
6179 done:
6180 free_a_printer(&printer, 2);
6181 free_a_printer(&old_printer, 2);
6184 return result;
6187 /****************************************************************************
6188 ****************************************************************************/
6189 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6190 const SPOOL_PRINTER_INFO_LEVEL *info)
6192 #ifdef HAVE_ADS
6193 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6194 int snum;
6195 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6197 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6199 if (!Printer)
6200 return WERR_BADFID;
6202 if (!get_printer_snum(p, handle, &snum))
6203 return WERR_BADFID;
6205 nt_printer_publish(Printer, snum, info7->action);
6207 return WERR_OK;
6208 #else
6209 return WERR_UNKNOWN_LEVEL;
6210 #endif
6212 /****************************************************************************
6213 ****************************************************************************/
6215 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6217 POLICY_HND *handle = &q_u->handle;
6218 uint32 level = q_u->level;
6219 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6220 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6221 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6222 uint32 command = q_u->command;
6224 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6226 if (!Printer) {
6227 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6228 return WERR_BADFID;
6231 /* check the level */
6232 switch (level) {
6233 case 0:
6234 return control_printer(handle, command, p);
6235 case 2:
6236 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6237 case 3:
6238 return update_printer_sec(handle, level, info, p,
6239 secdesc_ctr);
6240 case 7:
6241 return publish_or_unpublish_printer(p, handle, info);
6242 default:
6243 return WERR_UNKNOWN_LEVEL;
6247 /****************************************************************************
6248 ****************************************************************************/
6250 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6252 POLICY_HND *handle = &q_u->handle;
6253 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6255 if (!Printer) {
6256 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6257 return WERR_BADFID;
6260 if (Printer->notify.client_connected==True) {
6261 int snum = -1;
6263 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6264 snum = -1;
6265 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6266 !get_printer_snum(p, handle, &snum) )
6267 return WERR_BADFID;
6269 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6272 Printer->notify.flags=0;
6273 Printer->notify.options=0;
6274 Printer->notify.localmachine[0]='\0';
6275 Printer->notify.printerlocal=0;
6276 if (Printer->notify.option)
6277 free_spool_notify_option(&Printer->notify.option);
6278 Printer->notify.client_connected=False;
6280 return WERR_OK;
6283 /****************************************************************************
6284 ****************************************************************************/
6286 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6288 /* that's an [in out] buffer (despite appearences to the contrary) */
6289 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6291 r_u->needed = 0;
6292 return WERR_INVALID_PARAM; /* this is what a NT server
6293 returns for AddJob. AddJob
6294 must fail on non-local
6295 printers */
6298 /****************************************************************************
6299 ****************************************************************************/
6301 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6302 int position, int snum)
6304 pstring temp_name;
6306 struct tm *t;
6308 t=gmtime(&queue->time);
6309 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6311 job_info->jobid=queue->job;
6312 init_unistr(&job_info->printername, lp_servicename(snum));
6313 init_unistr(&job_info->machinename, temp_name);
6314 init_unistr(&job_info->username, queue->fs_user);
6315 init_unistr(&job_info->document, queue->fs_file);
6316 init_unistr(&job_info->datatype, "RAW");
6317 init_unistr(&job_info->text_status, "");
6318 job_info->status=nt_printj_status(queue->status);
6319 job_info->priority=queue->priority;
6320 job_info->position=position;
6321 job_info->totalpages=queue->page_count;
6322 job_info->pagesprinted=0;
6324 make_systemtime(&job_info->submitted, t);
6327 /****************************************************************************
6328 ****************************************************************************/
6330 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6331 int position, int snum,
6332 NT_PRINTER_INFO_LEVEL *ntprinter,
6333 DEVICEMODE *devmode)
6335 pstring temp_name;
6336 struct tm *t;
6338 t=gmtime(&queue->time);
6339 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6341 job_info->jobid=queue->job;
6343 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6345 init_unistr(&job_info->machinename, temp_name);
6346 init_unistr(&job_info->username, queue->fs_user);
6347 init_unistr(&job_info->document, queue->fs_file);
6348 init_unistr(&job_info->notifyname, queue->fs_user);
6349 init_unistr(&job_info->datatype, "RAW");
6350 init_unistr(&job_info->printprocessor, "winprint");
6351 init_unistr(&job_info->parameters, "");
6352 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6353 init_unistr(&job_info->text_status, "");
6355 /* and here the security descriptor */
6357 job_info->status=nt_printj_status(queue->status);
6358 job_info->priority=queue->priority;
6359 job_info->position=position;
6360 job_info->starttime=0;
6361 job_info->untiltime=0;
6362 job_info->totalpages=queue->page_count;
6363 job_info->size=queue->size;
6364 make_systemtime(&(job_info->submitted), t);
6365 job_info->timeelapsed=0;
6366 job_info->pagesprinted=0;
6368 job_info->devmode = devmode;
6370 return (True);
6373 /****************************************************************************
6374 Enumjobs at level 1.
6375 ****************************************************************************/
6377 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6378 NEW_BUFFER *buffer, uint32 offered,
6379 uint32 *needed, uint32 *returned)
6381 JOB_INFO_1 *info;
6382 int i;
6384 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6385 if (info==NULL) {
6386 SAFE_FREE(queue);
6387 *returned=0;
6388 return WERR_NOMEM;
6391 for (i=0; i<*returned; i++)
6392 fill_job_info_1(&info[i], &queue[i], i, snum);
6394 SAFE_FREE(queue);
6396 /* check the required size. */
6397 for (i=0; i<*returned; i++)
6398 (*needed) += spoolss_size_job_info_1(&info[i]);
6400 if (!alloc_buffer_size(buffer, *needed)) {
6401 SAFE_FREE(info);
6402 return WERR_INSUFFICIENT_BUFFER;
6405 /* fill the buffer with the structures */
6406 for (i=0; i<*returned; i++)
6407 smb_io_job_info_1("", buffer, &info[i], 0);
6409 /* clear memory */
6410 SAFE_FREE(info);
6412 if (*needed > offered) {
6413 *returned=0;
6414 return WERR_INSUFFICIENT_BUFFER;
6417 return WERR_OK;
6420 /****************************************************************************
6421 Enumjobs at level 2.
6422 ****************************************************************************/
6424 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6425 NEW_BUFFER *buffer, uint32 offered,
6426 uint32 *needed, uint32 *returned)
6428 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6429 JOB_INFO_2 *info = NULL;
6430 int i;
6431 WERROR result;
6432 DEVICEMODE *devmode = NULL;
6434 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6435 if (info==NULL) {
6436 *returned=0;
6437 result = WERR_NOMEM;
6438 goto done;
6441 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6442 if (!W_ERROR_IS_OK(result)) {
6443 *returned = 0;
6444 goto done;
6447 /* this should not be a failure condition if the devmode is NULL */
6449 devmode = construct_dev_mode(snum);
6451 for (i=0; i<*returned; i++)
6452 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6453 devmode);
6455 free_a_printer(&ntprinter, 2);
6456 SAFE_FREE(queue);
6458 /* check the required size. */
6459 for (i=0; i<*returned; i++)
6460 (*needed) += spoolss_size_job_info_2(&info[i]);
6462 if (*needed > offered) {
6463 *returned=0;
6464 result = WERR_INSUFFICIENT_BUFFER;
6465 goto done;
6468 if (!alloc_buffer_size(buffer, *needed)) {
6469 SAFE_FREE(info);
6470 result = WERR_INSUFFICIENT_BUFFER;
6471 goto done;
6474 /* fill the buffer with the structures */
6475 for (i=0; i<*returned; i++)
6476 smb_io_job_info_2("", buffer, &info[i], 0);
6478 result = WERR_OK;
6480 done:
6481 free_a_printer(&ntprinter, 2);
6482 free_devmode(devmode);
6483 SAFE_FREE(queue);
6484 SAFE_FREE(info);
6486 return result;
6490 /****************************************************************************
6491 Enumjobs.
6492 ****************************************************************************/
6494 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6496 POLICY_HND *handle = &q_u->handle;
6497 uint32 level = q_u->level;
6498 NEW_BUFFER *buffer = NULL;
6499 uint32 offered = q_u->offered;
6500 uint32 *needed = &r_u->needed;
6501 uint32 *returned = &r_u->returned;
6502 WERROR wret;
6504 int snum;
6505 print_status_struct prt_status;
6506 print_queue_struct *queue=NULL;
6508 /* that's an [in out] buffer */
6509 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6510 buffer = r_u->buffer;
6512 DEBUG(4,("_spoolss_enumjobs\n"));
6514 *needed=0;
6515 *returned=0;
6517 if (!get_printer_snum(p, handle, &snum))
6518 return WERR_BADFID;
6520 *returned = print_queue_status(snum, &queue, &prt_status);
6521 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6523 if (*returned == 0) {
6524 SAFE_FREE(queue);
6525 return WERR_OK;
6528 switch (level) {
6529 case 1:
6530 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6531 return wret;
6532 case 2:
6533 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6534 return wret;
6535 default:
6536 SAFE_FREE(queue);
6537 *returned=0;
6538 return WERR_UNKNOWN_LEVEL;
6542 /****************************************************************************
6543 ****************************************************************************/
6545 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6547 return WERR_OK;
6550 /****************************************************************************
6551 ****************************************************************************/
6553 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6555 POLICY_HND *handle = &q_u->handle;
6556 uint32 jobid = q_u->jobid;
6557 uint32 command = q_u->command;
6559 struct current_user user;
6560 int snum;
6561 WERROR errcode = WERR_BADFUNC;
6563 if (!get_printer_snum(p, handle, &snum)) {
6564 return WERR_BADFID;
6567 if (!print_job_exists(snum, jobid)) {
6568 return WERR_INVALID_PRINTER_NAME;
6571 get_current_user(&user, p);
6573 switch (command) {
6574 case JOB_CONTROL_CANCEL:
6575 case JOB_CONTROL_DELETE:
6576 if (print_job_delete(&user, snum, jobid, &errcode)) {
6577 errcode = WERR_OK;
6579 break;
6580 case JOB_CONTROL_PAUSE:
6581 if (print_job_pause(&user, snum, jobid, &errcode)) {
6582 errcode = WERR_OK;
6584 break;
6585 case JOB_CONTROL_RESTART:
6586 case JOB_CONTROL_RESUME:
6587 if (print_job_resume(&user, snum, jobid, &errcode)) {
6588 errcode = WERR_OK;
6590 break;
6591 default:
6592 return WERR_UNKNOWN_LEVEL;
6595 return errcode;
6598 /****************************************************************************
6599 Enumerates all printer drivers at level 1.
6600 ****************************************************************************/
6602 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6604 int i;
6605 int ndrivers;
6606 uint32 version;
6607 fstring *list = NULL;
6609 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6610 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6612 *returned=0;
6614 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6615 list=NULL;
6616 ndrivers=get_ntdrivers(&list, architecture, version);
6617 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6619 if(ndrivers == -1)
6620 return WERR_NOMEM;
6622 if(ndrivers != 0) {
6623 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6624 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6625 SAFE_FREE(driver_info_1);
6626 SAFE_FREE(list);
6627 return WERR_NOMEM;
6629 else driver_info_1 = tdi1;
6632 for (i=0; i<ndrivers; i++) {
6633 WERROR status;
6634 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6635 ZERO_STRUCT(driver);
6636 status = get_a_printer_driver(&driver, 3, list[i],
6637 architecture, version);
6638 if (!W_ERROR_IS_OK(status)) {
6639 SAFE_FREE(list);
6640 return status;
6642 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6643 free_a_printer_driver(driver, 3);
6646 *returned+=ndrivers;
6647 SAFE_FREE(list);
6650 /* check the required size. */
6651 for (i=0; i<*returned; i++) {
6652 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6653 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6656 if (!alloc_buffer_size(buffer, *needed)) {
6657 SAFE_FREE(driver_info_1);
6658 return WERR_INSUFFICIENT_BUFFER;
6661 /* fill the buffer with the driver structures */
6662 for (i=0; i<*returned; i++) {
6663 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6664 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6667 SAFE_FREE(driver_info_1);
6669 if (*needed > offered) {
6670 *returned=0;
6671 return WERR_INSUFFICIENT_BUFFER;
6674 return WERR_OK;
6677 /****************************************************************************
6678 Enumerates all printer drivers at level 2.
6679 ****************************************************************************/
6681 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6683 int i;
6684 int ndrivers;
6685 uint32 version;
6686 fstring *list = NULL;
6688 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6689 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6691 *returned=0;
6693 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6694 list=NULL;
6695 ndrivers=get_ntdrivers(&list, architecture, version);
6696 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6698 if(ndrivers == -1)
6699 return WERR_NOMEM;
6701 if(ndrivers != 0) {
6702 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6703 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6704 SAFE_FREE(driver_info_2);
6705 SAFE_FREE(list);
6706 return WERR_NOMEM;
6708 else driver_info_2 = tdi2;
6711 for (i=0; i<ndrivers; i++) {
6712 WERROR status;
6714 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6715 ZERO_STRUCT(driver);
6716 status = get_a_printer_driver(&driver, 3, list[i],
6717 architecture, version);
6718 if (!W_ERROR_IS_OK(status)) {
6719 SAFE_FREE(list);
6720 return status;
6722 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6723 free_a_printer_driver(driver, 3);
6726 *returned+=ndrivers;
6727 SAFE_FREE(list);
6730 /* check the required size. */
6731 for (i=0; i<*returned; i++) {
6732 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6733 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6736 if (!alloc_buffer_size(buffer, *needed)) {
6737 SAFE_FREE(driver_info_2);
6738 return WERR_INSUFFICIENT_BUFFER;
6741 /* fill the buffer with the form structures */
6742 for (i=0; i<*returned; i++) {
6743 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6744 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6747 SAFE_FREE(driver_info_2);
6749 if (*needed > offered) {
6750 *returned=0;
6751 return WERR_INSUFFICIENT_BUFFER;
6754 return WERR_OK;
6757 /****************************************************************************
6758 Enumerates all printer drivers at level 3.
6759 ****************************************************************************/
6761 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6763 int i;
6764 int ndrivers;
6765 uint32 version;
6766 fstring *list = NULL;
6768 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6769 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6771 *returned=0;
6773 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6774 list=NULL;
6775 ndrivers=get_ntdrivers(&list, architecture, version);
6776 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6778 if(ndrivers == -1)
6779 return WERR_NOMEM;
6781 if(ndrivers != 0) {
6782 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6783 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6784 SAFE_FREE(driver_info_3);
6785 SAFE_FREE(list);
6786 return WERR_NOMEM;
6788 else driver_info_3 = tdi3;
6791 for (i=0; i<ndrivers; i++) {
6792 WERROR status;
6794 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6795 ZERO_STRUCT(driver);
6796 status = get_a_printer_driver(&driver, 3, list[i],
6797 architecture, version);
6798 if (!W_ERROR_IS_OK(status)) {
6799 SAFE_FREE(list);
6800 return status;
6802 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6803 free_a_printer_driver(driver, 3);
6806 *returned+=ndrivers;
6807 SAFE_FREE(list);
6810 /* check the required size. */
6811 for (i=0; i<*returned; i++) {
6812 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6813 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6816 if (!alloc_buffer_size(buffer, *needed)) {
6817 SAFE_FREE(driver_info_3);
6818 return WERR_INSUFFICIENT_BUFFER;
6821 /* fill the buffer with the driver structures */
6822 for (i=0; i<*returned; i++) {
6823 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6824 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6827 for (i=0; i<*returned; i++)
6828 SAFE_FREE(driver_info_3[i].dependentfiles);
6830 SAFE_FREE(driver_info_3);
6832 if (*needed > offered) {
6833 *returned=0;
6834 return WERR_INSUFFICIENT_BUFFER;
6837 return WERR_OK;
6840 /****************************************************************************
6841 Enumerates all printer drivers.
6842 ****************************************************************************/
6844 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6846 UNISTR2 *environment = &q_u->environment;
6847 uint32 level = q_u->level;
6848 NEW_BUFFER *buffer = NULL;
6849 uint32 offered = q_u->offered;
6850 uint32 *needed = &r_u->needed;
6851 uint32 *returned = &r_u->returned;
6853 fstring *list = NULL;
6854 fstring servername;
6855 fstring architecture;
6857 /* that's an [in out] buffer */
6858 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6859 buffer = r_u->buffer;
6861 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6862 fstrcpy(servername, get_called_name());
6863 *needed=0;
6864 *returned=0;
6866 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6868 switch (level) {
6869 case 1:
6870 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6871 case 2:
6872 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6873 case 3:
6874 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6875 default:
6876 *returned=0;
6877 SAFE_FREE(list);
6878 return WERR_UNKNOWN_LEVEL;
6882 /****************************************************************************
6883 ****************************************************************************/
6885 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6887 form->flag=list->flag;
6888 init_unistr(&form->name, list->name);
6889 form->width=list->width;
6890 form->length=list->length;
6891 form->left=list->left;
6892 form->top=list->top;
6893 form->right=list->right;
6894 form->bottom=list->bottom;
6897 /****************************************************************************
6898 ****************************************************************************/
6900 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6902 uint32 level = q_u->level;
6903 NEW_BUFFER *buffer = NULL;
6904 uint32 offered = q_u->offered;
6905 uint32 *needed = &r_u->needed;
6906 uint32 *numofforms = &r_u->numofforms;
6907 uint32 numbuiltinforms;
6909 nt_forms_struct *list=NULL;
6910 nt_forms_struct *builtinlist=NULL;
6911 FORM_1 *forms_1;
6912 int buffer_size=0;
6913 int i;
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_enumforms\n"));
6920 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6921 DEBUGADD(5,("Info level [%d]\n", level));
6923 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6924 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6925 *numofforms = get_ntforms(&list);
6926 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6927 *numofforms += numbuiltinforms;
6929 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6931 switch (level) {
6932 case 1:
6933 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6934 *numofforms=0;
6935 return WERR_NOMEM;
6938 /* construct the list of form structures */
6939 for (i=0; i<numbuiltinforms; i++) {
6940 DEBUGADD(6,("Filling form number [%d]\n",i));
6941 fill_form_1(&forms_1[i], &builtinlist[i]);
6944 SAFE_FREE(builtinlist);
6946 for (; i<*numofforms; i++) {
6947 DEBUGADD(6,("Filling form number [%d]\n",i));
6948 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6951 SAFE_FREE(list);
6953 /* check the required size. */
6954 for (i=0; i<numbuiltinforms; i++) {
6955 DEBUGADD(6,("adding form [%d]'s size\n",i));
6956 buffer_size += spoolss_size_form_1(&forms_1[i]);
6958 for (; i<*numofforms; i++) {
6959 DEBUGADD(6,("adding form [%d]'s size\n",i));
6960 buffer_size += spoolss_size_form_1(&forms_1[i]);
6963 *needed=buffer_size;
6965 if (!alloc_buffer_size(buffer, buffer_size)){
6966 SAFE_FREE(forms_1);
6967 return WERR_INSUFFICIENT_BUFFER;
6970 /* fill the buffer with the form structures */
6971 for (i=0; i<numbuiltinforms; i++) {
6972 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6973 smb_io_form_1("", buffer, &forms_1[i], 0);
6975 for (; i<*numofforms; i++) {
6976 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6977 smb_io_form_1("", buffer, &forms_1[i], 0);
6980 SAFE_FREE(forms_1);
6982 if (*needed > offered) {
6983 *numofforms=0;
6984 return WERR_INSUFFICIENT_BUFFER;
6986 else
6987 return WERR_OK;
6989 default:
6990 SAFE_FREE(list);
6991 SAFE_FREE(builtinlist);
6992 return WERR_UNKNOWN_LEVEL;
6997 /****************************************************************************
6998 ****************************************************************************/
7000 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7002 uint32 level = q_u->level;
7003 UNISTR2 *uni_formname = &q_u->formname;
7004 NEW_BUFFER *buffer = NULL;
7005 uint32 offered = q_u->offered;
7006 uint32 *needed = &r_u->needed;
7008 nt_forms_struct *list=NULL;
7009 nt_forms_struct builtin_form;
7010 BOOL foundBuiltin;
7011 FORM_1 form_1;
7012 fstring form_name;
7013 int buffer_size=0;
7014 int numofforms=0, i=0;
7016 /* that's an [in out] buffer */
7017 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7018 buffer = r_u->buffer;
7020 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7022 DEBUG(4,("_spoolss_getform\n"));
7023 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7024 DEBUGADD(5,("Info level [%d]\n", level));
7026 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7027 if (!foundBuiltin) {
7028 numofforms = get_ntforms(&list);
7029 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7031 if (numofforms == 0)
7032 return WERR_BADFID;
7035 switch (level) {
7036 case 1:
7037 if (foundBuiltin) {
7038 fill_form_1(&form_1, &builtin_form);
7039 } else {
7041 /* Check if the requested name is in the list of form structures */
7042 for (i=0; i<numofforms; i++) {
7044 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7046 if (strequal(form_name, list[i].name)) {
7047 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7048 fill_form_1(&form_1, &list[i]);
7049 break;
7053 SAFE_FREE(list);
7054 if (i == numofforms) {
7055 return WERR_BADFID;
7058 /* check the required size. */
7060 *needed=spoolss_size_form_1(&form_1);
7062 if (!alloc_buffer_size(buffer, buffer_size)){
7063 return WERR_INSUFFICIENT_BUFFER;
7066 if (*needed > offered) {
7067 return WERR_INSUFFICIENT_BUFFER;
7070 /* fill the buffer with the form structures */
7071 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7072 smb_io_form_1("", buffer, &form_1, 0);
7074 return WERR_OK;
7076 default:
7077 SAFE_FREE(list);
7078 return WERR_UNKNOWN_LEVEL;
7082 /****************************************************************************
7083 ****************************************************************************/
7085 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7087 init_unistr(&port->port_name, name);
7090 /****************************************************************************
7091 ****************************************************************************/
7093 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7095 init_unistr(&port->port_name, name);
7096 init_unistr(&port->monitor_name, "Local Monitor");
7097 init_unistr(&port->description, "Local Port");
7098 port->port_type=PORT_TYPE_WRITE;
7099 port->reserved=0x0;
7102 /****************************************************************************
7103 enumports level 1.
7104 ****************************************************************************/
7106 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7108 PORT_INFO_1 *ports=NULL;
7109 int i=0;
7111 if (*lp_enumports_cmd()) {
7112 char *cmd = lp_enumports_cmd();
7113 char **qlines;
7114 pstring command;
7115 int numlines;
7116 int ret;
7117 int fd;
7119 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7121 DEBUG(10,("Running [%s]\n", command));
7122 ret = smbrun(command, &fd);
7123 DEBUG(10,("Returned [%d]\n", ret));
7124 if (ret != 0) {
7125 if (fd != -1)
7126 close(fd);
7127 /* Is this the best error to return here? */
7128 return WERR_ACCESS_DENIED;
7131 numlines = 0;
7132 qlines = fd_lines_load(fd, &numlines);
7133 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7134 close(fd);
7136 if(numlines) {
7137 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7138 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7139 dos_errstr(WERR_NOMEM)));
7140 file_lines_free(qlines);
7141 return WERR_NOMEM;
7144 for (i=0; i<numlines; i++) {
7145 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7146 fill_port_1(&ports[i], qlines[i]);
7149 file_lines_free(qlines);
7152 *returned = numlines;
7154 } else {
7155 *returned = 1; /* Sole Samba port returned. */
7157 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7158 return WERR_NOMEM;
7160 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7162 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7165 /* check the required size. */
7166 for (i=0; i<*returned; i++) {
7167 DEBUGADD(6,("adding port [%d]'s size\n", i));
7168 *needed += spoolss_size_port_info_1(&ports[i]);
7171 if (!alloc_buffer_size(buffer, *needed)) {
7172 SAFE_FREE(ports);
7173 return WERR_INSUFFICIENT_BUFFER;
7176 /* fill the buffer with the ports structures */
7177 for (i=0; i<*returned; i++) {
7178 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7179 smb_io_port_1("", buffer, &ports[i], 0);
7182 SAFE_FREE(ports);
7184 if (*needed > offered) {
7185 *returned=0;
7186 return WERR_INSUFFICIENT_BUFFER;
7189 return WERR_OK;
7192 /****************************************************************************
7193 enumports level 2.
7194 ****************************************************************************/
7196 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7198 PORT_INFO_2 *ports=NULL;
7199 int i=0;
7201 if (*lp_enumports_cmd()) {
7202 char *cmd = lp_enumports_cmd();
7203 char *path;
7204 char **qlines;
7205 pstring tmp_file;
7206 pstring command;
7207 int numlines;
7208 int ret;
7209 int fd;
7211 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7212 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7213 else
7214 path = lp_lockdir();
7216 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7217 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7219 unlink(tmp_file);
7220 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7221 ret = smbrun(command, &fd);
7222 DEBUGADD(10,("returned [%d]\n", ret));
7223 if (ret != 0) {
7224 if (fd != -1)
7225 close(fd);
7226 /* Is this the best error to return here? */
7227 return WERR_ACCESS_DENIED;
7230 numlines = 0;
7231 qlines = fd_lines_load(fd, &numlines);
7232 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7233 close(fd);
7235 if(numlines) {
7236 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7237 file_lines_free(qlines);
7238 return WERR_NOMEM;
7241 for (i=0; i<numlines; i++) {
7242 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7243 fill_port_2(&(ports[i]), qlines[i]);
7246 file_lines_free(qlines);
7249 *returned = numlines;
7251 } else {
7253 *returned = 1;
7255 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7256 return WERR_NOMEM;
7258 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7260 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7263 /* check the required size. */
7264 for (i=0; i<*returned; i++) {
7265 DEBUGADD(6,("adding port [%d]'s size\n", i));
7266 *needed += spoolss_size_port_info_2(&ports[i]);
7269 if (!alloc_buffer_size(buffer, *needed)) {
7270 SAFE_FREE(ports);
7271 return WERR_INSUFFICIENT_BUFFER;
7274 /* fill the buffer with the ports structures */
7275 for (i=0; i<*returned; i++) {
7276 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7277 smb_io_port_2("", buffer, &ports[i], 0);
7280 SAFE_FREE(ports);
7282 if (*needed > offered) {
7283 *returned=0;
7284 return WERR_INSUFFICIENT_BUFFER;
7287 return WERR_OK;
7290 /****************************************************************************
7291 enumports.
7292 ****************************************************************************/
7294 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7296 uint32 level = q_u->level;
7297 NEW_BUFFER *buffer = NULL;
7298 uint32 offered = q_u->offered;
7299 uint32 *needed = &r_u->needed;
7300 uint32 *returned = &r_u->returned;
7302 /* that's an [in out] buffer */
7303 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7304 buffer = r_u->buffer;
7306 DEBUG(4,("_spoolss_enumports\n"));
7308 *returned=0;
7309 *needed=0;
7311 switch (level) {
7312 case 1:
7313 return enumports_level_1(buffer, offered, needed, returned);
7314 case 2:
7315 return enumports_level_2(buffer, offered, needed, returned);
7316 default:
7317 return WERR_UNKNOWN_LEVEL;
7321 /****************************************************************************
7322 ****************************************************************************/
7324 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7325 const SPOOL_PRINTER_INFO_LEVEL *info,
7326 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7327 uint32 user_switch, const SPOOL_USER_CTR *user,
7328 POLICY_HND *handle)
7330 NT_PRINTER_INFO_LEVEL *printer = NULL;
7331 fstring name;
7332 int snum;
7333 WERROR err = WERR_OK;
7335 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7336 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7337 return WERR_NOMEM;
7340 ZERO_STRUCTP(printer);
7342 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7343 if (!convert_printer_info(info, printer, 2)) {
7344 free_a_printer(&printer, 2);
7345 return WERR_NOMEM;
7348 /* check to see if the printer already exists */
7350 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7351 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7352 printer->info_2->sharename));
7353 free_a_printer(&printer, 2);
7354 return WERR_PRINTER_ALREADY_EXISTS;
7357 /* FIXME!!! smbd should check to see if the driver is installed before
7358 trying to add a printer like this --jerry */
7360 if (*lp_addprinter_cmd() ) {
7361 if ( !add_printer_hook(printer) ) {
7362 free_a_printer(&printer,2);
7363 return WERR_ACCESS_DENIED;
7367 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7368 printer->info_2->sharename);
7371 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7372 free_a_printer(&printer,2);
7373 return WERR_ACCESS_DENIED;
7376 /* you must be a printer admin to add a new printer */
7377 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7378 free_a_printer(&printer,2);
7379 return WERR_ACCESS_DENIED;
7383 * Do sanity check on the requested changes for Samba.
7386 if (!check_printer_ok(printer->info_2, snum)) {
7387 free_a_printer(&printer,2);
7388 return WERR_INVALID_PARAM;
7392 * When a printer is created, the drivername bound to the printer is used
7393 * to lookup previously saved driver initialization info, which is then
7394 * bound to the new printer, simulating what happens in the Windows arch.
7397 if (!devmode)
7399 set_driver_init(printer, 2);
7401 else
7403 /* A valid devmode was included, convert and link it
7405 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7407 if (!convert_devicemode(printer->info_2->printername, devmode,
7408 &printer->info_2->devmode))
7409 return WERR_NOMEM;
7412 /* write the ASCII on disk */
7413 err = mod_a_printer(*printer, 2);
7414 if (!W_ERROR_IS_OK(err)) {
7415 free_a_printer(&printer,2);
7416 return err;
7419 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7420 /* Handle open failed - remove addition. */
7421 del_a_printer(printer->info_2->sharename);
7422 free_a_printer(&printer,2);
7423 return WERR_ACCESS_DENIED;
7426 update_c_setprinter(False);
7427 free_a_printer(&printer,2);
7429 return WERR_OK;
7432 /****************************************************************************
7433 ****************************************************************************/
7435 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7437 UNISTR2 *uni_srv_name = &q_u->server_name;
7438 uint32 level = q_u->level;
7439 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7440 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7441 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7442 uint32 user_switch = q_u->user_switch;
7443 SPOOL_USER_CTR *user = &q_u->user_ctr;
7444 POLICY_HND *handle = &r_u->handle;
7446 switch (level) {
7447 case 1:
7448 /* we don't handle yet */
7449 /* but I know what to do ... */
7450 return WERR_UNKNOWN_LEVEL;
7451 case 2:
7452 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7453 devmode, sdb,
7454 user_switch, user, handle);
7455 default:
7456 return WERR_UNKNOWN_LEVEL;
7460 /****************************************************************************
7461 ****************************************************************************/
7463 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7465 uint32 level = q_u->level;
7466 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7467 WERROR err = WERR_OK;
7468 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7469 struct current_user user;
7470 fstring driver_name;
7471 uint32 version;
7473 ZERO_STRUCT(driver);
7475 get_current_user(&user, p);
7477 if (!convert_printer_driver_info(info, &driver, level)) {
7478 err = WERR_NOMEM;
7479 goto done;
7482 DEBUG(5,("Cleaning driver's information\n"));
7483 err = clean_up_driver_struct(driver, level, &user);
7484 if (!W_ERROR_IS_OK(err))
7485 goto done;
7487 DEBUG(5,("Moving driver to final destination\n"));
7488 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7489 if (W_ERROR_IS_OK(err))
7490 err = WERR_ACCESS_DENIED;
7491 goto done;
7494 if (add_a_printer_driver(driver, level)!=0) {
7495 err = WERR_ACCESS_DENIED;
7496 goto done;
7499 /* BEGIN_ADMIN_LOG */
7500 switch(level) {
7501 case 3:
7502 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7503 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7504 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7505 break;
7506 case 6:
7507 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7508 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7509 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7510 break;
7512 /* END_ADMIN_LOG */
7515 * I think this is where he DrvUpgradePrinter() hook would be
7516 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7517 * server. Right now, we just need to send ourselves a message
7518 * to update each printer bound to this driver. --jerry
7521 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7522 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7523 driver_name));
7527 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7528 * decide if the driver init data should be deleted. The rules are:
7529 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7530 * 2) delete init data only if there is no 2k/Xp driver
7531 * 3) always delete init data
7532 * The generalized rule is always use init data from the highest order driver.
7533 * It is necessary to follow the driver install by an initialization step to
7534 * finish off this process.
7536 if (level == 3)
7537 version = driver.info_3->cversion;
7538 else if (level == 6)
7539 version = driver.info_6->version;
7540 else
7541 version = -1;
7542 switch (version) {
7544 * 9x printer driver - never delete init data
7546 case 0:
7547 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7548 driver_name));
7549 break;
7552 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7553 * there is no 2k/Xp driver init data for this driver name.
7555 case 2:
7557 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7559 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7561 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7563 if (!del_driver_init(driver_name))
7564 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7565 } else {
7567 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7569 free_a_printer_driver(driver1,3);
7570 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7571 driver_name));
7574 break;
7577 * 2k or Xp printer driver - always delete init data
7579 case 3:
7580 if (!del_driver_init(driver_name))
7581 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7582 break;
7584 default:
7585 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7586 break;
7590 done:
7591 free_a_printer_driver(driver, level);
7592 return err;
7595 /********************************************************************
7596 * spoolss_addprinterdriverex
7597 ********************************************************************/
7599 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7601 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7602 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7605 * we only support the semantics of AddPrinterDriver()
7606 * i.e. only copy files that are newer than existing ones
7609 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7610 return WERR_ACCESS_DENIED;
7612 ZERO_STRUCT(q_u_local);
7613 ZERO_STRUCT(r_u_local);
7615 /* just pass the information off to _spoolss_addprinterdriver() */
7616 q_u_local.server_name_ptr = q_u->server_name_ptr;
7617 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7618 q_u_local.level = q_u->level;
7619 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7621 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7624 /****************************************************************************
7625 ****************************************************************************/
7627 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7629 init_unistr(&info->name, name);
7632 /****************************************************************************
7633 ****************************************************************************/
7635 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7637 pstring path;
7638 pstring long_archi;
7639 const char *short_archi;
7640 DRIVER_DIRECTORY_1 *info=NULL;
7642 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7644 if (!(short_archi = get_short_archi(long_archi)))
7645 return WERR_INVALID_ENVIRONMENT;
7647 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7648 return WERR_NOMEM;
7650 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7652 DEBUG(4,("printer driver directory: [%s]\n", path));
7654 fill_driverdir_1(info, path);
7656 *needed += spoolss_size_driverdir_info_1(info);
7658 if (!alloc_buffer_size(buffer, *needed)) {
7659 SAFE_FREE(info);
7660 return WERR_INSUFFICIENT_BUFFER;
7663 smb_io_driverdir_1("", buffer, info, 0);
7665 SAFE_FREE(info);
7667 if (*needed > offered)
7668 return WERR_INSUFFICIENT_BUFFER;
7670 return WERR_OK;
7673 /****************************************************************************
7674 ****************************************************************************/
7676 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7678 UNISTR2 *name = &q_u->name;
7679 UNISTR2 *uni_environment = &q_u->environment;
7680 uint32 level = q_u->level;
7681 NEW_BUFFER *buffer = NULL;
7682 uint32 offered = q_u->offered;
7683 uint32 *needed = &r_u->needed;
7685 /* that's an [in out] buffer */
7686 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7687 buffer = r_u->buffer;
7689 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7691 *needed=0;
7693 switch(level) {
7694 case 1:
7695 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7696 default:
7697 return WERR_UNKNOWN_LEVEL;
7701 /****************************************************************************
7702 ****************************************************************************/
7704 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7706 POLICY_HND *handle = &q_u->handle;
7707 uint32 idx = q_u->index;
7708 uint32 in_value_len = q_u->valuesize;
7709 uint32 in_data_len = q_u->datasize;
7710 uint32 *out_max_value_len = &r_u->valuesize;
7711 uint16 **out_value = &r_u->value;
7712 uint32 *out_value_len = &r_u->realvaluesize;
7713 uint32 *out_type = &r_u->type;
7714 uint32 *out_max_data_len = &r_u->datasize;
7715 uint8 **data_out = &r_u->data;
7716 uint32 *out_data_len = &r_u->realdatasize;
7718 NT_PRINTER_INFO_LEVEL *printer = NULL;
7720 uint32 biggest_valuesize;
7721 uint32 biggest_datasize;
7722 uint32 data_len;
7723 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7724 int snum;
7725 WERROR result;
7726 REGISTRY_VALUE *val = NULL;
7727 NT_PRINTER_DATA *p_data;
7728 int i, key_index, num_values;
7729 int name_length;
7731 ZERO_STRUCT( printer );
7733 *out_type = 0;
7735 *out_max_data_len = 0;
7736 *data_out = NULL;
7737 *out_data_len = 0;
7739 DEBUG(5,("spoolss_enumprinterdata\n"));
7741 if (!Printer) {
7742 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7743 return WERR_BADFID;
7746 if (!get_printer_snum(p,handle, &snum))
7747 return WERR_BADFID;
7749 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7750 if (!W_ERROR_IS_OK(result))
7751 return result;
7753 p_data = &printer->info_2->data;
7754 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7756 result = WERR_OK;
7759 * The NT machine wants to know the biggest size of value and data
7761 * cf: MSDN EnumPrinterData remark section
7764 if ( !in_value_len && !in_data_len && (key_index != -1) )
7766 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7768 biggest_valuesize = 0;
7769 biggest_datasize = 0;
7771 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7773 for ( i=0; i<num_values; i++ )
7775 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7777 name_length = strlen(val->valuename);
7778 if ( strlen(val->valuename) > biggest_valuesize )
7779 biggest_valuesize = name_length;
7781 if ( val->size > biggest_datasize )
7782 biggest_datasize = val->size;
7784 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7785 biggest_datasize));
7788 /* the value is an UNICODE string but real_value_size is the length
7789 in bytes including the trailing 0 */
7791 *out_value_len = 2 * (1+biggest_valuesize);
7792 *out_data_len = biggest_datasize;
7794 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7796 goto done;
7800 * the value len is wrong in NT sp3
7801 * that's the number of bytes not the number of unicode chars
7804 if ( key_index != -1 )
7805 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7807 if ( !val )
7810 /* out_value should default to "" or else NT4 has
7811 problems unmarshalling the response */
7813 *out_max_value_len=(in_value_len/sizeof(uint16));
7815 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7817 result = WERR_NOMEM;
7818 goto done;
7821 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7823 /* the data is counted in bytes */
7825 *out_max_data_len = in_data_len;
7826 *out_data_len = in_data_len;
7828 /* only allocate when given a non-zero data_len */
7830 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7832 result = WERR_NOMEM;
7833 goto done;
7836 result = WERR_NO_MORE_ITEMS;
7838 else
7841 * the value is:
7842 * - counted in bytes in the request
7843 * - counted in UNICODE chars in the max reply
7844 * - counted in bytes in the real size
7846 * take a pause *before* coding not *during* coding
7849 /* name */
7850 *out_max_value_len=(in_value_len/sizeof(uint16));
7851 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7853 result = WERR_NOMEM;
7854 goto done;
7857 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7859 /* type */
7861 *out_type = regval_type( val );
7863 /* data - counted in bytes */
7865 *out_max_data_len = in_data_len;
7866 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7868 result = WERR_NOMEM;
7869 goto done;
7871 data_len = (size_t)regval_size(val);
7872 memcpy( *data_out, regval_data_p(val), data_len );
7873 *out_data_len = data_len;
7876 done:
7877 free_a_printer(&printer, 2);
7878 return result;
7881 /****************************************************************************
7882 ****************************************************************************/
7884 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7886 POLICY_HND *handle = &q_u->handle;
7887 UNISTR2 *value = &q_u->value;
7888 uint32 type = q_u->type;
7889 uint8 *data = q_u->data;
7890 uint32 real_len = q_u->real_len;
7892 NT_PRINTER_INFO_LEVEL *printer = NULL;
7893 int snum=0;
7894 WERROR status = WERR_OK;
7895 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7896 fstring valuename;
7898 DEBUG(5,("spoolss_setprinterdata\n"));
7900 if (!Printer) {
7901 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7902 return WERR_BADFID;
7905 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7906 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7907 return WERR_INVALID_PARAM;
7910 if (!get_printer_snum(p,handle, &snum))
7911 return WERR_BADFID;
7914 * Access check : NT returns "access denied" if you make a
7915 * SetPrinterData call without the necessary privildge.
7916 * we were originally returning OK if nothing changed
7917 * which made Win2k issue **a lot** of SetPrinterData
7918 * when connecting to a printer --jerry
7921 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7923 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7924 status = WERR_ACCESS_DENIED;
7925 goto done;
7928 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7929 if (!W_ERROR_IS_OK(status))
7930 return status;
7932 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7935 * When client side code sets a magic printer data key, detect it and save
7936 * the current printer data and the magic key's data (its the DEVMODE) for
7937 * future printer/driver initializations.
7939 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7941 /* Set devmode and printer initialization info */
7942 status = save_driver_init( printer, 2, data, real_len );
7944 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7946 else
7948 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7949 type, data, real_len );
7950 if ( W_ERROR_IS_OK(status) )
7951 status = mod_a_printer(*printer, 2);
7954 done:
7955 free_a_printer(&printer, 2);
7957 return status;
7960 /****************************************************************************
7961 ****************************************************************************/
7963 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7965 POLICY_HND *handle = &q_u->handle;
7966 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7967 int snum;
7969 DEBUG(5,("_spoolss_resetprinter\n"));
7972 * All we do is to check to see if the handle and queue is valid.
7973 * This call really doesn't mean anything to us because we only
7974 * support RAW printing. --jerry
7977 if (!Printer) {
7978 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7979 return WERR_BADFID;
7982 if (!get_printer_snum(p,handle, &snum))
7983 return WERR_BADFID;
7986 /* blindly return success */
7987 return WERR_OK;
7991 /****************************************************************************
7992 ****************************************************************************/
7994 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7996 POLICY_HND *handle = &q_u->handle;
7997 UNISTR2 *value = &q_u->valuename;
7999 NT_PRINTER_INFO_LEVEL *printer = NULL;
8000 int snum=0;
8001 WERROR status = WERR_OK;
8002 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8003 pstring valuename;
8005 DEBUG(5,("spoolss_deleteprinterdata\n"));
8007 if (!Printer) {
8008 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8009 return WERR_BADFID;
8012 if (!get_printer_snum(p, handle, &snum))
8013 return WERR_BADFID;
8015 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8016 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8017 return WERR_ACCESS_DENIED;
8020 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8021 if (!W_ERROR_IS_OK(status))
8022 return status;
8024 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8026 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8028 if ( W_ERROR_IS_OK(status) )
8029 mod_a_printer( *printer, 2 );
8031 free_a_printer(&printer, 2);
8033 return status;
8036 /****************************************************************************
8037 ****************************************************************************/
8039 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8041 POLICY_HND *handle = &q_u->handle;
8042 FORM *form = &q_u->form;
8043 nt_forms_struct tmpForm;
8044 int snum;
8045 WERROR status = WERR_OK;
8046 NT_PRINTER_INFO_LEVEL *printer = NULL;
8048 int count=0;
8049 nt_forms_struct *list=NULL;
8050 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8052 DEBUG(5,("spoolss_addform\n"));
8054 if (!Printer) {
8055 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8056 return WERR_BADFID;
8060 /* forms can be added on printer of on the print server handle */
8062 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8064 if (!get_printer_snum(p,handle, &snum))
8065 return WERR_BADFID;
8067 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8068 if (!W_ERROR_IS_OK(status))
8069 goto done;
8072 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8073 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8074 status = WERR_ACCESS_DENIED;
8075 goto done;
8078 /* can't add if builtin */
8080 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8081 status = WERR_ALREADY_EXISTS;
8082 goto done;
8085 count = get_ntforms(&list);
8087 if(!add_a_form(&list, form, &count)) {
8088 status = WERR_NOMEM;
8089 goto done;
8092 write_ntforms(&list, count);
8095 * ChangeID must always be set if this is a printer
8098 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8099 status = mod_a_printer(*printer, 2);
8101 done:
8102 if ( printer )
8103 free_a_printer(&printer, 2);
8104 SAFE_FREE(list);
8106 return status;
8109 /****************************************************************************
8110 ****************************************************************************/
8112 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8114 POLICY_HND *handle = &q_u->handle;
8115 UNISTR2 *form_name = &q_u->name;
8116 nt_forms_struct tmpForm;
8117 int count=0;
8118 nt_forms_struct *list=NULL;
8119 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8120 int snum;
8121 WERROR status = WERR_OK;
8122 NT_PRINTER_INFO_LEVEL *printer = NULL;
8124 DEBUG(5,("spoolss_deleteform\n"));
8126 if (!Printer) {
8127 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8128 return WERR_BADFID;
8131 /* forms can be deleted on printer of on the print server handle */
8133 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8135 if (!get_printer_snum(p,handle, &snum))
8136 return WERR_BADFID;
8138 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8139 if (!W_ERROR_IS_OK(status))
8140 goto done;
8143 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8144 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8145 status = WERR_ACCESS_DENIED;
8146 goto done;
8149 /* can't delete if builtin */
8151 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8152 status = WERR_INVALID_PARAM;
8153 goto done;
8156 count = get_ntforms(&list);
8158 if ( !delete_a_form(&list, form_name, &count, &status ))
8159 goto done;
8162 * ChangeID must always be set if this is a printer
8165 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8166 status = mod_a_printer(*printer, 2);
8168 done:
8169 if ( printer )
8170 free_a_printer(&printer, 2);
8171 SAFE_FREE(list);
8173 return status;
8176 /****************************************************************************
8177 ****************************************************************************/
8179 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8181 POLICY_HND *handle = &q_u->handle;
8182 FORM *form = &q_u->form;
8183 nt_forms_struct tmpForm;
8184 int snum;
8185 WERROR status = WERR_OK;
8186 NT_PRINTER_INFO_LEVEL *printer = NULL;
8188 int count=0;
8189 nt_forms_struct *list=NULL;
8190 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8192 DEBUG(5,("spoolss_setform\n"));
8194 if (!Printer) {
8195 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8196 return WERR_BADFID;
8199 /* forms can be modified on printer of on the print server handle */
8201 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8203 if (!get_printer_snum(p,handle, &snum))
8204 return WERR_BADFID;
8206 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8207 if (!W_ERROR_IS_OK(status))
8208 goto done;
8211 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8212 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8213 status = WERR_ACCESS_DENIED;
8214 goto done;
8217 /* can't set if builtin */
8218 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8219 status = WERR_INVALID_PARAM;
8220 goto done;
8223 count = get_ntforms(&list);
8224 update_a_form(&list, form, count);
8225 write_ntforms(&list, count);
8228 * ChangeID must always be set if this is a printer
8231 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8232 status = mod_a_printer(*printer, 2);
8235 done:
8236 if ( printer )
8237 free_a_printer(&printer, 2);
8238 SAFE_FREE(list);
8240 return status;
8243 /****************************************************************************
8244 enumprintprocessors level 1.
8245 ****************************************************************************/
8247 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8249 PRINTPROCESSOR_1 *info_1=NULL;
8251 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8252 return WERR_NOMEM;
8254 (*returned) = 0x1;
8256 init_unistr(&info_1->name, "winprint");
8258 *needed += spoolss_size_printprocessor_info_1(info_1);
8260 if (!alloc_buffer_size(buffer, *needed))
8261 return WERR_INSUFFICIENT_BUFFER;
8263 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8265 SAFE_FREE(info_1);
8267 if (*needed > offered) {
8268 *returned=0;
8269 return WERR_INSUFFICIENT_BUFFER;
8272 return WERR_OK;
8275 /****************************************************************************
8276 ****************************************************************************/
8278 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8280 uint32 level = q_u->level;
8281 NEW_BUFFER *buffer = NULL;
8282 uint32 offered = q_u->offered;
8283 uint32 *needed = &r_u->needed;
8284 uint32 *returned = &r_u->returned;
8286 /* that's an [in out] buffer */
8287 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8288 buffer = r_u->buffer;
8290 DEBUG(5,("spoolss_enumprintprocessors\n"));
8293 * Enumerate the print processors ...
8295 * Just reply with "winprint", to keep NT happy
8296 * and I can use my nice printer checker.
8299 *returned=0;
8300 *needed=0;
8302 switch (level) {
8303 case 1:
8304 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8305 default:
8306 return WERR_UNKNOWN_LEVEL;
8310 /****************************************************************************
8311 enumprintprocdatatypes level 1.
8312 ****************************************************************************/
8314 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8316 PRINTPROCDATATYPE_1 *info_1=NULL;
8318 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8319 return WERR_NOMEM;
8321 (*returned) = 0x1;
8323 init_unistr(&info_1->name, "RAW");
8325 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8327 if (!alloc_buffer_size(buffer, *needed))
8328 return WERR_INSUFFICIENT_BUFFER;
8330 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8332 SAFE_FREE(info_1);
8334 if (*needed > offered) {
8335 *returned=0;
8336 return WERR_INSUFFICIENT_BUFFER;
8339 return WERR_OK;
8342 /****************************************************************************
8343 ****************************************************************************/
8345 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8347 uint32 level = q_u->level;
8348 NEW_BUFFER *buffer = NULL;
8349 uint32 offered = q_u->offered;
8350 uint32 *needed = &r_u->needed;
8351 uint32 *returned = &r_u->returned;
8353 /* that's an [in out] buffer */
8354 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8355 buffer = r_u->buffer;
8357 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8359 *returned=0;
8360 *needed=0;
8362 switch (level) {
8363 case 1:
8364 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8365 default:
8366 return WERR_UNKNOWN_LEVEL;
8370 /****************************************************************************
8371 enumprintmonitors level 1.
8372 ****************************************************************************/
8374 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8376 PRINTMONITOR_1 *info_1=NULL;
8378 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8379 return WERR_NOMEM;
8381 (*returned) = 0x1;
8383 init_unistr(&info_1->name, "Local Port");
8385 *needed += spoolss_size_printmonitor_info_1(info_1);
8387 if (!alloc_buffer_size(buffer, *needed))
8388 return WERR_INSUFFICIENT_BUFFER;
8390 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8392 SAFE_FREE(info_1);
8394 if (*needed > offered) {
8395 *returned=0;
8396 return WERR_INSUFFICIENT_BUFFER;
8399 return WERR_OK;
8402 /****************************************************************************
8403 enumprintmonitors level 2.
8404 ****************************************************************************/
8406 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8408 PRINTMONITOR_2 *info_2=NULL;
8410 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8411 return WERR_NOMEM;
8413 (*returned) = 0x1;
8415 init_unistr(&info_2->name, "Local Port");
8416 init_unistr(&info_2->environment, "Windows NT X86");
8417 init_unistr(&info_2->dll_name, "localmon.dll");
8419 *needed += spoolss_size_printmonitor_info_2(info_2);
8421 if (!alloc_buffer_size(buffer, *needed))
8422 return WERR_INSUFFICIENT_BUFFER;
8424 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8426 SAFE_FREE(info_2);
8428 if (*needed > offered) {
8429 *returned=0;
8430 return WERR_INSUFFICIENT_BUFFER;
8433 return WERR_OK;
8436 /****************************************************************************
8437 ****************************************************************************/
8439 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8441 uint32 level = q_u->level;
8442 NEW_BUFFER *buffer = NULL;
8443 uint32 offered = q_u->offered;
8444 uint32 *needed = &r_u->needed;
8445 uint32 *returned = &r_u->returned;
8447 /* that's an [in out] buffer */
8448 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8449 buffer = r_u->buffer;
8451 DEBUG(5,("spoolss_enumprintmonitors\n"));
8454 * Enumerate the print monitors ...
8456 * Just reply with "Local Port", to keep NT happy
8457 * and I can use my nice printer checker.
8460 *returned=0;
8461 *needed=0;
8463 switch (level) {
8464 case 1:
8465 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8466 case 2:
8467 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8468 default:
8469 return WERR_UNKNOWN_LEVEL;
8473 /****************************************************************************
8474 ****************************************************************************/
8476 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8478 int i=0;
8479 BOOL found=False;
8480 JOB_INFO_1 *info_1=NULL;
8482 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8484 if (info_1 == NULL) {
8485 return WERR_NOMEM;
8488 for (i=0; i<count && found==False; i++) {
8489 if ((*queue)[i].job==(int)jobid)
8490 found=True;
8493 if (found==False) {
8494 SAFE_FREE(info_1);
8495 /* NT treats not found as bad param... yet another bad choice */
8496 return WERR_INVALID_PARAM;
8499 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8501 *needed += spoolss_size_job_info_1(info_1);
8503 if (!alloc_buffer_size(buffer, *needed)) {
8504 SAFE_FREE(info_1);
8505 return WERR_INSUFFICIENT_BUFFER;
8508 smb_io_job_info_1("", buffer, info_1, 0);
8510 SAFE_FREE(info_1);
8512 if (*needed > offered)
8513 return WERR_INSUFFICIENT_BUFFER;
8515 return WERR_OK;
8518 /****************************************************************************
8519 ****************************************************************************/
8521 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8523 int i = 0;
8524 BOOL found = False;
8525 JOB_INFO_2 *info_2;
8526 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8527 WERROR ret;
8528 DEVICEMODE *devmode = NULL;
8529 NT_DEVICEMODE *nt_devmode = NULL;
8531 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8533 ZERO_STRUCTP(info_2);
8535 if (info_2 == NULL) {
8536 ret = WERR_NOMEM;
8537 goto done;
8540 for ( i=0; i<count && found==False; i++ )
8542 if ((*queue)[i].job == (int)jobid)
8543 found = True;
8546 if ( !found )
8548 /* NT treats not found as bad param... yet another bad
8549 choice */
8550 ret = WERR_INVALID_PARAM;
8551 goto done;
8554 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8555 if (!W_ERROR_IS_OK(ret))
8556 goto done;
8559 * if the print job does not have a DEVMODE associated with it,
8560 * just use the one for the printer. A NULL devicemode is not
8561 * a failure condition
8564 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8565 devmode = construct_dev_mode(snum);
8566 else {
8567 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8568 ZERO_STRUCTP( devmode );
8569 convert_nt_devicemode( devmode, nt_devmode );
8573 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8575 *needed += spoolss_size_job_info_2(info_2);
8577 if (!alloc_buffer_size(buffer, *needed)) {
8578 ret = WERR_INSUFFICIENT_BUFFER;
8579 goto done;
8582 smb_io_job_info_2("", buffer, info_2, 0);
8584 if (*needed > offered) {
8585 ret = WERR_INSUFFICIENT_BUFFER;
8586 goto done;
8589 ret = WERR_OK;
8591 done:
8592 /* Cleanup allocated memory */
8594 free_job_info_2(info_2); /* Also frees devmode */
8595 SAFE_FREE(info_2);
8596 free_a_printer(&ntprinter, 2);
8598 return ret;
8601 /****************************************************************************
8602 ****************************************************************************/
8604 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8606 POLICY_HND *handle = &q_u->handle;
8607 uint32 jobid = q_u->jobid;
8608 uint32 level = q_u->level;
8609 NEW_BUFFER *buffer = NULL;
8610 uint32 offered = q_u->offered;
8611 uint32 *needed = &r_u->needed;
8612 WERROR wstatus = WERR_OK;
8614 int snum;
8615 int count;
8616 print_queue_struct *queue = NULL;
8617 print_status_struct prt_status;
8619 /* that's an [in out] buffer */
8620 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8621 buffer = r_u->buffer;
8623 DEBUG(5,("spoolss_getjob\n"));
8625 *needed = 0;
8627 if (!get_printer_snum(p, handle, &snum))
8628 return WERR_BADFID;
8630 count = print_queue_status(snum, &queue, &prt_status);
8632 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8633 count, prt_status.status, prt_status.message));
8635 switch ( level ) {
8636 case 1:
8637 wstatus = getjob_level_1(&queue, count, snum, jobid,
8638 buffer, offered, needed);
8639 break;
8640 case 2:
8641 wstatus = getjob_level_2(&queue, count, snum, jobid,
8642 buffer, offered, needed);
8643 break;
8644 default:
8645 wstatus = WERR_UNKNOWN_LEVEL;
8646 break;
8649 SAFE_FREE(queue);
8650 return wstatus;
8653 /********************************************************************
8654 spoolss_getprinterdataex
8656 From MSDN documentation of GetPrinterDataEx: pass request
8657 to GetPrinterData if key is "PrinterDriverData".
8658 ********************************************************************/
8660 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8662 POLICY_HND *handle = &q_u->handle;
8663 uint32 in_size = q_u->size;
8664 uint32 *type = &r_u->type;
8665 uint32 *out_size = &r_u->size;
8666 uint8 **data = &r_u->data;
8667 uint32 *needed = &r_u->needed;
8668 fstring keyname, valuename;
8670 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8672 NT_PRINTER_INFO_LEVEL *printer = NULL;
8673 int snum = 0;
8674 WERROR status = WERR_OK;
8676 DEBUG(4,("_spoolss_getprinterdataex\n"));
8678 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8679 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8681 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8682 keyname, valuename));
8684 /* in case of problem, return some default values */
8686 *needed = 0;
8687 *type = 0;
8688 *out_size = in_size;
8690 if (!Printer) {
8691 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8692 status = WERR_BADFID;
8693 goto done;
8696 /* Is the handle to a printer or to the server? */
8698 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8699 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8700 status = WERR_INVALID_PARAM;
8701 goto done;
8704 if ( !get_printer_snum(p,handle, &snum) )
8705 return WERR_BADFID;
8707 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8708 if ( !W_ERROR_IS_OK(status) )
8709 goto done;
8711 /* check to see if the keyname is valid */
8712 if ( !strlen(keyname) ) {
8713 status = WERR_INVALID_PARAM;
8714 goto done;
8717 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8718 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8719 free_a_printer( &printer, 2 );
8720 status = WERR_BADFILE;
8721 goto done;
8724 /* When given a new keyname, we should just create it */
8726 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8728 if (*needed > *out_size)
8729 status = WERR_MORE_DATA;
8731 done:
8732 if ( !W_ERROR_IS_OK(status) )
8734 DEBUG(5, ("error: allocating %d\n", *out_size));
8736 /* reply this param doesn't exist */
8738 if ( *out_size )
8740 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8741 status = WERR_NOMEM;
8742 goto done;
8745 else {
8746 *data = NULL;
8750 if ( printer )
8751 free_a_printer( &printer, 2 );
8753 return status;
8756 /********************************************************************
8757 * spoolss_setprinterdataex
8758 ********************************************************************/
8760 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8762 POLICY_HND *handle = &q_u->handle;
8763 uint32 type = q_u->type;
8764 uint8 *data = q_u->data;
8765 uint32 real_len = q_u->real_len;
8767 NT_PRINTER_INFO_LEVEL *printer = NULL;
8768 int snum = 0;
8769 WERROR status = WERR_OK;
8770 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8771 fstring valuename;
8772 fstring keyname;
8773 char *oid_string;
8775 DEBUG(4,("_spoolss_setprinterdataex\n"));
8777 /* From MSDN documentation of SetPrinterDataEx: pass request to
8778 SetPrinterData if key is "PrinterDriverData" */
8780 if (!Printer) {
8781 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8782 return WERR_BADFID;
8785 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8786 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8787 return WERR_INVALID_PARAM;
8790 if ( !get_printer_snum(p,handle, &snum) )
8791 return WERR_BADFID;
8794 * Access check : NT returns "access denied" if you make a
8795 * SetPrinterData call without the necessary privildge.
8796 * we were originally returning OK if nothing changed
8797 * which made Win2k issue **a lot** of SetPrinterData
8798 * when connecting to a printer --jerry
8801 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8803 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8804 return WERR_ACCESS_DENIED;
8807 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8808 if (!W_ERROR_IS_OK(status))
8809 return status;
8811 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8812 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8814 /* check for OID in valuename */
8816 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8818 *oid_string = '\0';
8819 oid_string++;
8822 /* save the registry data */
8824 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8826 if ( W_ERROR_IS_OK(status) )
8828 /* save the OID if one was specified */
8829 if ( oid_string ) {
8830 fstrcat( keyname, "\\" );
8831 fstrcat( keyname, SPOOL_OID_KEY );
8834 * I'm not checking the status here on purpose. Don't know
8835 * if this is right, but I'm returning the status from the
8836 * previous set_printer_dataex() call. I have no idea if
8837 * this is right. --jerry
8840 set_printer_dataex( printer, keyname, valuename,
8841 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8844 status = mod_a_printer(*printer, 2);
8847 free_a_printer(&printer, 2);
8849 return status;
8853 /********************************************************************
8854 * spoolss_deleteprinterdataex
8855 ********************************************************************/
8857 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8859 POLICY_HND *handle = &q_u->handle;
8860 UNISTR2 *value = &q_u->valuename;
8861 UNISTR2 *key = &q_u->keyname;
8863 NT_PRINTER_INFO_LEVEL *printer = NULL;
8864 int snum=0;
8865 WERROR status = WERR_OK;
8866 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8867 pstring valuename, keyname;
8869 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8871 if (!Printer) {
8872 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8873 return WERR_BADFID;
8876 if (!get_printer_snum(p, handle, &snum))
8877 return WERR_BADFID;
8879 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8880 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8881 return WERR_ACCESS_DENIED;
8884 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8885 if (!W_ERROR_IS_OK(status))
8886 return status;
8888 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8889 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8891 status = delete_printer_dataex( printer, keyname, valuename );
8893 if ( W_ERROR_IS_OK(status) )
8894 mod_a_printer( *printer, 2 );
8896 free_a_printer(&printer, 2);
8898 return status;
8901 /********************************************************************
8902 * spoolss_enumprinterkey
8903 ********************************************************************/
8906 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8908 fstring key;
8909 fstring *keynames = NULL;
8910 uint16 *enumkeys = NULL;
8911 int num_keys;
8912 int printerkey_len;
8913 POLICY_HND *handle = &q_u->handle;
8914 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8915 NT_PRINTER_DATA *data;
8916 NT_PRINTER_INFO_LEVEL *printer = NULL;
8917 int snum = 0;
8918 WERROR status = WERR_BADFILE;
8921 DEBUG(4,("_spoolss_enumprinterkey\n"));
8923 if (!Printer) {
8924 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8925 return WERR_BADFID;
8928 if ( !get_printer_snum(p,handle, &snum) )
8929 return WERR_BADFID;
8931 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8932 if (!W_ERROR_IS_OK(status))
8933 return status;
8935 /* get the list of subkey names */
8937 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8938 data = &printer->info_2->data;
8940 num_keys = get_printer_subkeys( data, key, &keynames );
8942 if ( num_keys == -1 ) {
8943 status = WERR_BADFILE;
8944 goto done;
8947 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8949 r_u->needed = printerkey_len*2;
8951 if ( q_u->size < r_u->needed ) {
8952 status = WERR_MORE_DATA;
8953 goto done;
8956 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8957 status = WERR_NOMEM;
8958 goto done;
8961 status = WERR_OK;
8963 if ( q_u->size < r_u->needed )
8964 status = WERR_MORE_DATA;
8966 done:
8967 free_a_printer( &printer, 2 );
8968 SAFE_FREE( keynames );
8970 return status;
8973 /********************************************************************
8974 * spoolss_deleteprinterkey
8975 ********************************************************************/
8977 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8979 POLICY_HND *handle = &q_u->handle;
8980 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8981 fstring key;
8982 NT_PRINTER_INFO_LEVEL *printer = NULL;
8983 int snum=0;
8984 WERROR status;
8986 DEBUG(5,("spoolss_deleteprinterkey\n"));
8988 if (!Printer) {
8989 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8990 return WERR_BADFID;
8993 /* if keyname == NULL, return error */
8995 if ( !q_u->keyname.buffer )
8996 return WERR_INVALID_PARAM;
8998 if (!get_printer_snum(p, handle, &snum))
8999 return WERR_BADFID;
9001 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9002 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9003 return WERR_ACCESS_DENIED;
9006 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9007 if (!W_ERROR_IS_OK(status))
9008 return status;
9010 /* delete the key and all subneys */
9012 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9014 status = delete_all_printer_data( printer->info_2, key );
9016 if ( W_ERROR_IS_OK(status) )
9017 status = mod_a_printer(*printer, 2);
9019 free_a_printer( &printer, 2 );
9021 return status;
9025 /********************************************************************
9026 * spoolss_enumprinterdataex
9027 ********************************************************************/
9029 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9031 POLICY_HND *handle = &q_u->handle;
9032 uint32 in_size = q_u->size;
9033 uint32 num_entries,
9034 needed;
9035 NT_PRINTER_INFO_LEVEL *printer = NULL;
9036 PRINTER_ENUM_VALUES *enum_values = NULL;
9037 NT_PRINTER_DATA *p_data;
9038 fstring key;
9039 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9040 int snum;
9041 WERROR result;
9042 int key_index;
9043 int i;
9044 REGISTRY_VALUE *val;
9045 char *value_name;
9046 int data_len;
9049 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9051 if (!Printer) {
9052 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9053 return WERR_BADFID;
9057 * first check for a keyname of NULL or "". Win2k seems to send
9058 * this a lot and we should send back WERR_INVALID_PARAM
9059 * no need to spend time looking up the printer in this case.
9060 * --jerry
9063 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9064 if ( !strlen(key) ) {
9065 result = WERR_INVALID_PARAM;
9066 goto done;
9069 /* get the printer off of disk */
9071 if (!get_printer_snum(p,handle, &snum))
9072 return WERR_BADFID;
9074 ZERO_STRUCT(printer);
9075 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9076 if (!W_ERROR_IS_OK(result))
9077 return result;
9079 /* now look for a match on the key name */
9081 p_data = &printer->info_2->data;
9083 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9084 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9086 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9087 result = WERR_INVALID_PARAM;
9088 goto done;
9091 result = WERR_OK;
9092 needed = 0;
9094 /* allocate the memory for the array of pointers -- if necessary */
9096 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9097 if ( num_entries )
9099 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9101 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9102 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9103 result = WERR_NOMEM;
9104 goto done;
9107 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9111 * loop through all params and build the array to pass
9112 * back to the client
9115 for ( i=0; i<num_entries; i++ )
9117 /* lookup the registry value */
9119 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9120 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9122 /* copy the data */
9124 value_name = regval_name( val );
9125 init_unistr( &enum_values[i].valuename, value_name );
9126 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9127 enum_values[i].type = regval_type( val );
9129 data_len = regval_size( val );
9130 if ( data_len ) {
9131 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9133 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9134 data_len ));
9135 result = WERR_NOMEM;
9136 goto done;
9139 enum_values[i].data_len = data_len;
9141 /* keep track of the size of the array in bytes */
9143 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9146 /* housekeeping information in the reply */
9148 r_u->needed = needed;
9149 r_u->returned = num_entries;
9151 if (needed > in_size) {
9152 result = WERR_MORE_DATA;
9153 goto done;
9156 /* copy data into the reply */
9158 r_u->ctr.size = r_u->needed;
9159 r_u->ctr.size_of_array = r_u->returned;
9160 r_u->ctr.values = enum_values;
9164 done:
9165 if ( printer )
9166 free_a_printer(&printer, 2);
9168 return result;
9171 /****************************************************************************
9172 ****************************************************************************/
9174 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9176 init_unistr(&info->name, name);
9179 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9180 UNISTR2 *environment,
9181 NEW_BUFFER *buffer,
9182 uint32 offered,
9183 uint32 *needed)
9185 pstring path;
9186 pstring long_archi;
9187 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9189 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9191 if (!get_short_archi(long_archi))
9192 return WERR_INVALID_ENVIRONMENT;
9194 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9195 return WERR_NOMEM;
9197 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9199 fill_printprocessordirectory_1(info, path);
9201 *needed += spoolss_size_printprocessordirectory_info_1(info);
9203 if (!alloc_buffer_size(buffer, *needed)) {
9204 safe_free(info);
9205 return WERR_INSUFFICIENT_BUFFER;
9208 smb_io_printprocessordirectory_1("", buffer, info, 0);
9210 safe_free(info);
9212 if (*needed > offered)
9213 return WERR_INSUFFICIENT_BUFFER;
9214 else
9215 return WERR_OK;
9218 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9220 uint32 level = q_u->level;
9221 NEW_BUFFER *buffer = NULL;
9222 uint32 offered = q_u->offered;
9223 uint32 *needed = &r_u->needed;
9224 WERROR result;
9226 /* that's an [in out] buffer */
9227 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9228 buffer = r_u->buffer;
9230 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9232 *needed=0;
9234 switch(level) {
9235 case 1:
9236 result = getprintprocessordirectory_level_1
9237 (&q_u->name, &q_u->environment, buffer, offered, needed);
9238 break;
9239 default:
9240 result = WERR_UNKNOWN_LEVEL;
9243 return result;
9246 #if 0
9248 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9249 SPOOL_R_REPLYOPENPRINTER *r_u)
9251 DEBUG(5,("_spoolss_replyopenprinter\n"));
9253 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9255 return WERR_OK;
9258 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9259 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9261 DEBUG(5,("_spoolss_replycloseprinter\n"));
9262 return WERR_OK;
9265 #endif