r2176: syncing necessary changes for 3.0.7
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blob812939ddf50ce97e76a3d637554b7b6d5c504b59
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_PRINT_NOTIFY );
186 smb_connections--;
189 /****************************************************************************
190 Functions to free a printer entry datastruct.
191 ****************************************************************************/
193 static void free_printer_entry(void *ptr)
195 Printer_entry *Printer = (Printer_entry *)ptr;
197 if (Printer->notify.client_connected==True) {
198 int snum = -1;
200 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
201 snum = -1;
202 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
204 snum = print_queue_snum(Printer->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 [0x%x] field [0x%2x] 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 /* add to correct list in container */
1199 notify_msg_ctr_addmsg( &messages, &notify );
1201 /* free memory that might have been allocated by notify2_unpack_msg() */
1203 if ( notify.len != 0 )
1204 SAFE_FREE( notify.notify.data );
1207 /* process each group of messages */
1209 num_groups = notify_msg_ctr_numgroups( &messages );
1210 for ( i=0; i<num_groups; i++ )
1211 send_notify2_changes( &messages, i );
1214 /* cleanup */
1216 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1218 notify_msg_ctr_destroy( &messages );
1220 return;
1223 /********************************************************************
1224 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1225 one smbd, all of processes must clear their printer cache immediately.
1226 ********************************************************************/
1228 void receive_printer_mod_msg(int msg_type, pid_t src, void *buf, size_t len)
1230 fstring printername;
1232 fstrcpy( printername, buf );
1234 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername ));
1236 invalidate_printer_hnd_cache( printername );
1239 /********************************************************************
1240 Send a message to ourself about new driver being installed
1241 so we can upgrade the information for each printer bound to this
1242 driver
1243 ********************************************************************/
1245 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1247 int len = strlen(drivername);
1249 if (!len)
1250 return False;
1252 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1253 drivername));
1255 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1257 return True;
1260 /**********************************************************************
1261 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1262 over all printers, upgrading ones as necessary
1263 **********************************************************************/
1265 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1267 fstring drivername;
1268 int snum;
1269 int n_services = lp_numservices();
1271 len = MIN(len,sizeof(drivername)-1);
1272 strncpy(drivername, buf, len);
1274 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1276 /* Iterate the printer list */
1278 for (snum=0; snum<n_services; snum++)
1280 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1282 WERROR result;
1283 NT_PRINTER_INFO_LEVEL *printer = NULL;
1285 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1286 if (!W_ERROR_IS_OK(result))
1287 continue;
1289 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1291 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1293 /* all we care about currently is the change_id */
1295 result = mod_a_printer(*printer, 2);
1296 if (!W_ERROR_IS_OK(result)) {
1297 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1298 dos_errstr(result)));
1302 free_a_printer(&printer, 2);
1306 /* all done */
1309 /********************************************************************
1310 Update the cache for all printq's with a registered client
1311 connection
1312 ********************************************************************/
1314 void update_monitored_printq_cache( void )
1316 Printer_entry *printer = printers_list;
1317 int snum;
1319 /* loop through all printers and update the cache where
1320 client_connected == True */
1321 while ( printer )
1323 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1324 && printer->notify.client_connected )
1326 snum = print_queue_snum(printer->dev.handlename);
1327 print_queue_status( snum, NULL, NULL );
1330 printer = printer->next;
1333 return;
1335 /********************************************************************
1336 Send a message to ourself about new driver being installed
1337 so we can upgrade the information for each printer bound to this
1338 driver
1339 ********************************************************************/
1341 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1343 int len = strlen(drivername);
1345 if (!len)
1346 return False;
1348 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1349 drivername));
1351 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1353 return True;
1356 /**********************************************************************
1357 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1358 over all printers, resetting printer data as neessary
1359 **********************************************************************/
1361 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1363 fstring drivername;
1364 int snum;
1365 int n_services = lp_numservices();
1367 len = MIN( len, sizeof(drivername)-1 );
1368 strncpy( drivername, buf, len );
1370 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1372 /* Iterate the printer list */
1374 for ( snum=0; snum<n_services; snum++ )
1376 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1378 WERROR result;
1379 NT_PRINTER_INFO_LEVEL *printer = NULL;
1381 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1382 if ( !W_ERROR_IS_OK(result) )
1383 continue;
1386 * if the printer is bound to the driver,
1387 * then reset to the new driver initdata
1390 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1392 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1394 if ( !set_driver_init(printer, 2) ) {
1395 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1396 printer->info_2->printername, printer->info_2->drivername));
1399 result = mod_a_printer( *printer, 2 );
1400 if ( !W_ERROR_IS_OK(result) ) {
1401 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1402 get_dos_error_msg(result)));
1406 free_a_printer( &printer, 2 );
1410 /* all done */
1412 return;
1415 /********************************************************************
1416 Copy routines used by convert_to_openprinterex()
1417 *******************************************************************/
1419 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1421 DEVICEMODE *d;
1422 int len;
1424 if (!devmode)
1425 return NULL;
1427 DEBUG (8,("dup_devmode\n"));
1429 /* bulk copy first */
1431 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1432 if (!d)
1433 return NULL;
1435 /* dup the pointer members separately */
1437 len = unistrlen(devmode->devicename.buffer);
1438 if (len != -1) {
1439 d->devicename.buffer = talloc(ctx, len*2);
1440 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1441 return NULL;
1445 len = unistrlen(devmode->formname.buffer);
1446 if (len != -1) {
1447 d->devicename.buffer = talloc(ctx, len*2);
1448 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1449 return NULL;
1452 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1454 return d;
1457 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1459 if (!new_ctr || !ctr)
1460 return;
1462 DEBUG(8,("copy_devmode_ctr\n"));
1464 new_ctr->size = ctr->size;
1465 new_ctr->devmode_ptr = ctr->devmode_ptr;
1467 if(ctr->devmode_ptr)
1468 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1471 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1473 if (!new_def || !def)
1474 return;
1476 DEBUG(8,("copy_printer_defaults\n"));
1478 new_def->datatype_ptr = def->datatype_ptr;
1480 if (def->datatype_ptr)
1481 copy_unistr2(&new_def->datatype, &def->datatype);
1483 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1485 new_def->access_required = def->access_required;
1488 /********************************************************************
1489 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1490 * SPOOL_Q_OPEN_PRINTER_EX structure
1491 ********************************************************************/
1493 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1495 if (!q_u_ex || !q_u)
1496 return;
1498 DEBUG(8,("convert_to_openprinterex\n"));
1500 q_u_ex->printername_ptr = q_u->printername_ptr;
1502 if (q_u->printername_ptr)
1503 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1505 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1508 /********************************************************************
1509 * spoolss_open_printer
1511 * called from the spoolss dispatcher
1512 ********************************************************************/
1514 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1516 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1517 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1519 if (!q_u || !r_u)
1520 return WERR_NOMEM;
1522 ZERO_STRUCT(q_u_ex);
1523 ZERO_STRUCT(r_u_ex);
1525 /* convert the OpenPrinter() call to OpenPrinterEx() */
1527 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1529 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1531 /* convert back to OpenPrinter() */
1533 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1535 return r_u->status;
1538 /********************************************************************
1539 * spoolss_open_printer
1541 * If the openprinterex rpc call contains a devmode,
1542 * it's a per-user one. This per-user devmode is derivated
1543 * from the global devmode. Openprinterex() contains a per-user
1544 * devmode for when you do EMF printing and spooling.
1545 * In the EMF case, the NT workstation is only doing half the job
1546 * of rendering the page. The other half is done by running the printer
1547 * driver on the server.
1548 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1549 * The EMF file only contains what is to be printed on the page.
1550 * So in order for the server to know how to print, the NT client sends
1551 * a devicemode attached to the openprinterex call.
1552 * But this devicemode is short lived, it's only valid for the current print job.
1554 * If Samba would have supported EMF spooling, this devicemode would
1555 * have been attached to the handle, to sent it to the driver to correctly
1556 * rasterize the EMF file.
1558 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1559 * we just act as a pass-thru between windows and the printer.
1561 * In order to know that Samba supports only RAW spooling, NT has to call
1562 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1563 * and until NT sends a RAW job, we refuse it.
1565 * But to call getprinter() or startdoc(), you first need a valid handle,
1566 * and to get an handle you have to call openprintex(). Hence why you have
1567 * a devicemode in the openprinterex() call.
1570 * Differences between NT4 and NT 2000.
1571 * NT4:
1572 * ---
1573 * On NT4, you only have a global devicemode. This global devicemode can be changed
1574 * by the administrator (or by a user with enough privs). Everytime a user
1575 * wants to print, the devicemode is resetted to the default. In Word, everytime
1576 * you print, the printer's characteristics are always reset to the global devicemode.
1578 * NT 2000:
1579 * -------
1580 * In W2K, there is the notion of per-user devicemode. The first time you use
1581 * a printer, a per-user devicemode is build from the global devicemode.
1582 * If you change your per-user devicemode, it is saved in the registry, under the
1583 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1584 * printer preferences available.
1586 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1587 * on the General Tab of the printer properties windows.
1589 * To change the global devicemode: it's the "Printing Defaults..." button
1590 * on the Advanced Tab of the printer properties window.
1592 * JFM.
1593 ********************************************************************/
1595 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1597 UNISTR2 *printername = NULL;
1598 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1599 POLICY_HND *handle = &r_u->handle;
1601 fstring name;
1602 int snum;
1603 struct current_user user;
1604 Printer_entry *Printer=NULL;
1606 if (q_u->printername_ptr != 0)
1607 printername = &q_u->printername;
1609 if (printername == NULL)
1610 return WERR_INVALID_PRINTER_NAME;
1612 /* some sanity check because you can open a printer or a print server */
1613 /* aka: \\server\printer or \\server */
1614 unistr2_to_ascii(name, printername, sizeof(name)-1);
1616 DEBUGADD(3,("checking name: %s\n",name));
1618 if (!open_printer_hnd(p, handle, name, 0))
1619 return WERR_INVALID_PRINTER_NAME;
1621 Printer=find_printer_index_by_hnd(p, handle);
1622 if (!Printer) {
1623 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1624 Can't find printer handle we created for printer %s\n", name ));
1625 close_printer_handle(p,handle);
1626 return WERR_INVALID_PRINTER_NAME;
1629 get_current_user(&user, p);
1632 * First case: the user is opening the print server:
1634 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1635 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1637 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1638 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1639 * or if the user is listed in the smb.conf printer admin parameter.
1641 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1642 * client view printer folder, but does not show the MSAPW.
1644 * Note: this test needs code to check access rights here too. Jeremy
1645 * could you look at this?
1647 * Second case: the user is opening a printer:
1648 * NT doesn't let us connect to a printer if the connecting user
1649 * doesn't have print permission.
1652 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1654 /* Printserver handles use global struct... */
1656 snum = -1;
1658 /* Map standard access rights to object specific access rights */
1660 se_map_standard(&printer_default->access_required,
1661 &printserver_std_mapping);
1663 /* Deny any object specific bits that don't apply to print
1664 servers (i.e printer and job specific bits) */
1666 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1668 if (printer_default->access_required &
1669 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1670 DEBUG(3, ("access DENIED for non-printserver bits"));
1671 close_printer_handle(p, handle);
1672 return WERR_ACCESS_DENIED;
1675 /* Allow admin access */
1677 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1679 if (!lp_ms_add_printer_wizard()) {
1680 close_printer_handle(p, handle);
1681 return WERR_ACCESS_DENIED;
1684 /* if the user is not root and not a printer admin, then fail */
1686 if ( user.uid != 0
1687 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1689 close_printer_handle(p, handle);
1690 return WERR_ACCESS_DENIED;
1693 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1695 else
1697 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1700 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1701 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1703 /* We fall through to return WERR_OK */
1706 else
1708 /* NT doesn't let us connect to a printer if the connecting user
1709 doesn't have print permission. */
1711 if (!get_printer_snum(p, handle, &snum)) {
1712 close_printer_handle(p, handle);
1713 return WERR_BADFID;
1716 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1718 /* map an empty access mask to the minimum access mask */
1719 if (printer_default->access_required == 0x0)
1720 printer_default->access_required = PRINTER_ACCESS_USE;
1723 * If we are not serving the printer driver for this printer,
1724 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1725 * will keep NT clients happy --jerry
1728 if (lp_use_client_driver(snum)
1729 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1731 printer_default->access_required = PRINTER_ACCESS_USE;
1734 /* check smb.conf parameters and the the sec_desc */
1736 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1737 DEBUG(3, ("access DENIED for printer open\n"));
1738 close_printer_handle(p, handle);
1739 return WERR_ACCESS_DENIED;
1742 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1743 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1744 close_printer_handle(p, handle);
1745 return WERR_ACCESS_DENIED;
1748 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1749 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1750 else
1751 printer_default->access_required = PRINTER_ACCESS_USE;
1753 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1754 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1758 Printer->access_granted = printer_default->access_required;
1761 * If the client sent a devmode in the OpenPrinter() call, then
1762 * save it here in case we get a job submission on this handle
1765 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1766 && q_u->printer_default.devmode_cont.devmode_ptr )
1768 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1769 &Printer->nt_devmode );
1772 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1773 optimization in Windows 2000 clients --jerry */
1775 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1776 && (RA_WIN2K == get_remote_arch()) )
1778 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1779 sys_usleep( 500000 );
1782 return WERR_OK;
1785 /****************************************************************************
1786 ****************************************************************************/
1788 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1789 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1791 BOOL ret = True;
1793 switch (level) {
1794 case 2:
1795 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1796 break;
1797 default:
1798 break;
1801 return ret;
1804 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1805 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1807 BOOL result = True;
1809 switch (level) {
1810 case 3:
1811 printer->info_3=NULL;
1812 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1813 result = False;
1814 break;
1815 case 6:
1816 printer->info_6=NULL;
1817 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1818 result = False;
1819 break;
1820 default:
1821 break;
1824 return result;
1827 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1828 NT_DEVICEMODE **pp_nt_devmode)
1830 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1833 * Ensure nt_devmode is a valid pointer
1834 * as we will be overwriting it.
1837 if (nt_devmode == NULL) {
1838 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1839 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1840 return False;
1843 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1844 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1846 nt_devmode->specversion=devmode->specversion;
1847 nt_devmode->driverversion=devmode->driverversion;
1848 nt_devmode->size=devmode->size;
1849 nt_devmode->fields=devmode->fields;
1850 nt_devmode->orientation=devmode->orientation;
1851 nt_devmode->papersize=devmode->papersize;
1852 nt_devmode->paperlength=devmode->paperlength;
1853 nt_devmode->paperwidth=devmode->paperwidth;
1854 nt_devmode->scale=devmode->scale;
1855 nt_devmode->copies=devmode->copies;
1856 nt_devmode->defaultsource=devmode->defaultsource;
1857 nt_devmode->printquality=devmode->printquality;
1858 nt_devmode->color=devmode->color;
1859 nt_devmode->duplex=devmode->duplex;
1860 nt_devmode->yresolution=devmode->yresolution;
1861 nt_devmode->ttoption=devmode->ttoption;
1862 nt_devmode->collate=devmode->collate;
1864 nt_devmode->logpixels=devmode->logpixels;
1865 nt_devmode->bitsperpel=devmode->bitsperpel;
1866 nt_devmode->pelswidth=devmode->pelswidth;
1867 nt_devmode->pelsheight=devmode->pelsheight;
1868 nt_devmode->displayflags=devmode->displayflags;
1869 nt_devmode->displayfrequency=devmode->displayfrequency;
1870 nt_devmode->icmmethod=devmode->icmmethod;
1871 nt_devmode->icmintent=devmode->icmintent;
1872 nt_devmode->mediatype=devmode->mediatype;
1873 nt_devmode->dithertype=devmode->dithertype;
1874 nt_devmode->reserved1=devmode->reserved1;
1875 nt_devmode->reserved2=devmode->reserved2;
1876 nt_devmode->panningwidth=devmode->panningwidth;
1877 nt_devmode->panningheight=devmode->panningheight;
1880 * Only change private and driverextra if the incoming devmode
1881 * has a new one. JRA.
1884 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1885 SAFE_FREE(nt_devmode->private);
1886 nt_devmode->driverextra=devmode->driverextra;
1887 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1888 return False;
1889 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1892 *pp_nt_devmode = nt_devmode;
1894 return True;
1897 /********************************************************************
1898 * _spoolss_enddocprinter_internal.
1899 ********************************************************************/
1901 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1903 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1904 int snum;
1906 if (!Printer) {
1907 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1908 return WERR_BADFID;
1911 if (!get_printer_snum(p, handle, &snum))
1912 return WERR_BADFID;
1914 Printer->document_started=False;
1915 print_job_end(snum, Printer->jobid,True);
1916 /* error codes unhandled so far ... */
1918 return WERR_OK;
1921 /********************************************************************
1922 * api_spoolss_closeprinter
1923 ********************************************************************/
1925 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1927 POLICY_HND *handle = &q_u->handle;
1929 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1931 if (Printer && Printer->document_started)
1932 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1934 if (!close_printer_handle(p, handle))
1935 return WERR_BADFID;
1937 /* clear the returned printer handle. Observed behavior
1938 from Win2k server. Don't think this really matters.
1939 Previous code just copied the value of the closed
1940 handle. --jerry */
1942 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1944 return WERR_OK;
1947 /********************************************************************
1948 * api_spoolss_deleteprinter
1950 ********************************************************************/
1952 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1954 POLICY_HND *handle = &q_u->handle;
1955 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1956 WERROR result;
1958 if (Printer && Printer->document_started)
1959 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1961 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1963 result = delete_printer_handle(p, handle);
1965 update_c_setprinter(False);
1967 return result;
1970 /*******************************************************************
1971 * static function to lookup the version id corresponding to an
1972 * long architecture string
1973 ******************************************************************/
1975 static int get_version_id (char * arch)
1977 int i;
1978 struct table_node archi_table[]= {
1980 {"Windows 4.0", "WIN40", 0 },
1981 {"Windows NT x86", "W32X86", 2 },
1982 {"Windows NT R4000", "W32MIPS", 2 },
1983 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1984 {"Windows NT PowerPC", "W32PPC", 2 },
1985 {NULL, "", -1 }
1988 for (i=0; archi_table[i].long_archi != NULL; i++)
1990 if (strcmp(arch, archi_table[i].long_archi) == 0)
1991 return (archi_table[i].version);
1994 return -1;
1997 /********************************************************************
1998 * _spoolss_deleteprinterdriver
1999 ********************************************************************/
2001 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2003 fstring driver;
2004 fstring arch;
2005 NT_PRINTER_DRIVER_INFO_LEVEL info;
2006 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2007 int version;
2008 struct current_user user;
2009 WERROR status;
2010 WERROR status_win2k = WERR_ACCESS_DENIED;
2012 get_current_user(&user, p);
2014 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2015 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2017 /* check that we have a valid driver name first */
2019 if ((version=get_version_id(arch)) == -1)
2020 return WERR_INVALID_ENVIRONMENT;
2022 ZERO_STRUCT(info);
2023 ZERO_STRUCT(info_win2k);
2025 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2027 /* try for Win2k driver if "Windows NT x86" */
2029 if ( version == 2 ) {
2030 version = 3;
2031 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2032 status = WERR_UNKNOWN_PRINTER_DRIVER;
2033 goto done;
2036 /* otherwise it was a failure */
2037 else {
2038 status = WERR_UNKNOWN_PRINTER_DRIVER;
2039 goto done;
2044 if (printer_driver_in_use(info.info_3)) {
2045 status = WERR_PRINTER_DRIVER_IN_USE;
2046 goto done;
2049 if ( version == 2 )
2051 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2053 /* if we get to here, we now have 2 driver info structures to remove */
2054 /* remove the Win2k driver first*/
2056 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2057 free_a_printer_driver( info_win2k, 3 );
2059 /* this should not have failed---if it did, report to client */
2060 if ( !W_ERROR_IS_OK(status_win2k) )
2061 goto done;
2065 status = delete_printer_driver(info.info_3, &user, version, False);
2067 /* if at least one of the deletes succeeded return OK */
2069 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2070 status = WERR_OK;
2072 done:
2073 free_a_printer_driver( info, 3 );
2075 return status;
2078 /********************************************************************
2079 * spoolss_deleteprinterdriverex
2080 ********************************************************************/
2082 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2084 fstring driver;
2085 fstring arch;
2086 NT_PRINTER_DRIVER_INFO_LEVEL info;
2087 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2088 int version;
2089 uint32 flags = q_u->delete_flags;
2090 BOOL delete_files;
2091 struct current_user user;
2092 WERROR status;
2093 WERROR status_win2k = WERR_ACCESS_DENIED;
2095 get_current_user(&user, p);
2097 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2098 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2100 /* check that we have a valid driver name first */
2101 if ((version=get_version_id(arch)) == -1) {
2102 /* this is what NT returns */
2103 return WERR_INVALID_ENVIRONMENT;
2106 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2107 version = q_u->version;
2109 ZERO_STRUCT(info);
2110 ZERO_STRUCT(info_win2k);
2112 status = get_a_printer_driver(&info, 3, driver, arch, version);
2114 if ( !W_ERROR_IS_OK(status) )
2117 * if the client asked for a specific version,
2118 * or this is something other than Windows NT x86,
2119 * then we've failed
2122 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2123 goto done;
2125 /* try for Win2k driver if "Windows NT x86" */
2127 version = 3;
2128 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2129 status = WERR_UNKNOWN_PRINTER_DRIVER;
2130 goto done;
2134 if ( printer_driver_in_use(info.info_3) ) {
2135 status = WERR_PRINTER_DRIVER_IN_USE;
2136 goto done;
2140 * we have a couple of cases to consider.
2141 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2142 * then the delete should fail if **any** files overlap with
2143 * other drivers
2144 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2145 * non-overlapping files
2146 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2147 * is set, the do not delete any files
2148 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2151 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2153 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2155 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2156 /* no idea of the correct error here */
2157 status = WERR_ACCESS_DENIED;
2158 goto done;
2162 /* also check for W32X86/3 if necessary; maybe we already have? */
2164 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2165 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2168 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2169 /* no idea of the correct error here */
2170 free_a_printer_driver( info_win2k, 3 );
2171 status = WERR_ACCESS_DENIED;
2172 goto done;
2175 /* if we get to here, we now have 2 driver info structures to remove */
2176 /* remove the Win2k driver first*/
2178 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2179 free_a_printer_driver( info_win2k, 3 );
2181 /* this should not have failed---if it did, report to client */
2183 if ( !W_ERROR_IS_OK(status_win2k) )
2184 goto done;
2188 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2190 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2191 status = WERR_OK;
2192 done:
2193 free_a_printer_driver( info, 3 );
2195 return status;
2199 /****************************************************************************
2200 Internal routine for retreiving printerdata
2201 ***************************************************************************/
2203 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2204 const char *key, const char *value, uint32 *type, uint8 **data,
2205 uint32 *needed, uint32 in_size )
2207 REGISTRY_VALUE *val;
2208 int size, data_len;
2210 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2211 return WERR_BADFILE;
2213 *type = regval_type( val );
2215 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2217 size = regval_size( val );
2219 /* copy the min(in_size, len) */
2221 if ( in_size ) {
2222 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2224 /* special case for 0 length values */
2225 if ( data_len ) {
2226 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2227 return WERR_NOMEM;
2229 else {
2230 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2231 return WERR_NOMEM;
2234 else
2235 *data = NULL;
2237 *needed = size;
2239 DEBUG(5,("get_printer_dataex: copy done\n"));
2241 return WERR_OK;
2244 /****************************************************************************
2245 Internal routine for removing printerdata
2246 ***************************************************************************/
2248 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2250 return delete_printer_data( printer->info_2, key, value );
2253 /****************************************************************************
2254 Internal routine for storing printerdata
2255 ***************************************************************************/
2257 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2258 uint32 type, uint8 *data, int real_len )
2260 delete_printer_data( printer->info_2, key, value );
2262 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2265 /********************************************************************
2266 GetPrinterData on a printer server Handle.
2267 ********************************************************************/
2269 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2271 int i;
2273 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2275 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2276 *type = 0x4;
2277 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2278 return WERR_NOMEM;
2279 *needed = 0x4;
2280 return WERR_OK;
2283 if (!StrCaseCmp(value, "BeepEnabled")) {
2284 *type = 0x4;
2285 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2286 return WERR_NOMEM;
2287 SIVAL(*data, 0, 0x00);
2288 *needed = 0x4;
2289 return WERR_OK;
2292 if (!StrCaseCmp(value, "EventLog")) {
2293 *type = 0x4;
2294 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2295 return WERR_NOMEM;
2296 /* formally was 0x1b */
2297 SIVAL(*data, 0, 0x0);
2298 *needed = 0x4;
2299 return WERR_OK;
2302 if (!StrCaseCmp(value, "NetPopup")) {
2303 *type = 0x4;
2304 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2305 return WERR_NOMEM;
2306 SIVAL(*data, 0, 0x00);
2307 *needed = 0x4;
2308 return WERR_OK;
2311 if (!StrCaseCmp(value, "MajorVersion")) {
2312 *type = 0x4;
2313 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2314 return WERR_NOMEM;
2316 /* Windows NT 4.0 seems to not allow uploading of drivers
2317 to a server that reports 0x3 as the MajorVersion.
2318 need to investigate more how Win2k gets around this .
2319 -- jerry */
2321 if ( RA_WINNT == get_remote_arch() )
2322 SIVAL(*data, 0, 2);
2323 else
2324 SIVAL(*data, 0, 3);
2326 *needed = 0x4;
2327 return WERR_OK;
2330 if (!StrCaseCmp(value, "MinorVersion")) {
2331 *type = 0x4;
2332 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2333 return WERR_NOMEM;
2334 SIVAL(*data, 0, 0);
2335 *needed = 0x4;
2336 return WERR_OK;
2339 /* REG_BINARY
2340 * uint32 size = 0x114
2341 * uint32 major = 5
2342 * uint32 minor = [0|1]
2343 * uint32 build = [2195|2600]
2344 * extra unicode string = e.g. "Service Pack 3"
2346 if (!StrCaseCmp(value, "OSVersion")) {
2347 *type = 0x3;
2348 *needed = 0x114;
2350 if((*data = (uint8 *)talloc(ctx, (*needed)*sizeof(uint8) )) == NULL)
2351 return WERR_NOMEM;
2352 ZERO_STRUCTP( *data );
2354 SIVAL(*data, 0, *needed); /* size */
2355 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2356 SIVAL(*data, 8, 0);
2357 SIVAL(*data, 12, 2195); /* build */
2359 /* leave extra string empty */
2361 return WERR_OK;
2365 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2366 const char *string="C:\\PRINTERS";
2367 *type = 0x1;
2368 *needed = 2*(strlen(string)+1);
2369 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2370 return WERR_NOMEM;
2371 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2373 /* it's done by hand ready to go on the wire */
2374 for (i=0; i<strlen(string); i++) {
2375 (*data)[2*i]=string[i];
2376 (*data)[2*i+1]='\0';
2378 return WERR_OK;
2381 if (!StrCaseCmp(value, "Architecture")) {
2382 const char *string="Windows NT x86";
2383 *type = 0x1;
2384 *needed = 2*(strlen(string)+1);
2385 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2386 return WERR_NOMEM;
2387 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2388 for (i=0; i<strlen(string); i++) {
2389 (*data)[2*i]=string[i];
2390 (*data)[2*i+1]='\0';
2392 return WERR_OK;
2395 if (!StrCaseCmp(value, "DsPresent")) {
2396 *type = 0x4;
2397 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2398 return WERR_NOMEM;
2399 SIVAL(*data, 0, 0x01);
2400 *needed = 0x4;
2401 return WERR_OK;
2404 if (!StrCaseCmp(value, "DNSMachineName")) {
2405 pstring hostname;
2407 if (!get_mydnsfullname(hostname))
2408 return WERR_BADFILE;
2409 *type = 0x1;
2410 *needed = 2*(strlen(hostname)+1);
2411 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2412 return WERR_NOMEM;
2413 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2414 for (i=0; i<strlen(hostname); i++) {
2415 (*data)[2*i]=hostname[i];
2416 (*data)[2*i+1]='\0';
2418 return WERR_OK;
2422 return WERR_BADFILE;
2425 /********************************************************************
2426 * spoolss_getprinterdata
2427 ********************************************************************/
2429 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2431 POLICY_HND *handle = &q_u->handle;
2432 UNISTR2 *valuename = &q_u->valuename;
2433 uint32 in_size = q_u->size;
2434 uint32 *type = &r_u->type;
2435 uint32 *out_size = &r_u->size;
2436 uint8 **data = &r_u->data;
2437 uint32 *needed = &r_u->needed;
2438 WERROR status;
2439 fstring value;
2440 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2441 NT_PRINTER_INFO_LEVEL *printer = NULL;
2442 int snum = 0;
2445 * Reminder: when it's a string, the length is in BYTES
2446 * even if UNICODE is negociated.
2448 * JFM, 4/19/1999
2451 *out_size = in_size;
2453 /* in case of problem, return some default values */
2455 *needed = 0;
2456 *type = 0;
2458 DEBUG(4,("_spoolss_getprinterdata\n"));
2460 if ( !Printer ) {
2461 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2462 status = WERR_BADFID;
2463 goto done;
2466 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2468 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2469 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2470 else
2472 if ( !get_printer_snum(p,handle, &snum) ) {
2473 status = WERR_BADFID;
2474 goto done;
2477 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2478 if ( !W_ERROR_IS_OK(status) )
2479 goto done;
2481 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2483 if ( strequal(value, "ChangeId") ) {
2484 *type = REG_DWORD;
2485 *needed = sizeof(uint32);
2486 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2487 status = WERR_NOMEM;
2488 goto done;
2490 SIVAL( *data, 0, printer->info_2->changeid );
2491 status = WERR_OK;
2493 else
2494 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2497 if (*needed > *out_size)
2498 status = WERR_MORE_DATA;
2500 done:
2501 if ( !W_ERROR_IS_OK(status) )
2503 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2505 /* reply this param doesn't exist */
2507 if ( *out_size ) {
2508 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2509 if ( printer )
2510 free_a_printer( &printer, 2 );
2511 return WERR_NOMEM;
2514 else {
2515 *data = NULL;
2519 /* cleanup & exit */
2521 if ( printer )
2522 free_a_printer( &printer, 2 );
2524 return status;
2527 /*********************************************************
2528 Connect to the client machine.
2529 **********************************************************/
2531 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2532 struct in_addr *client_ip, const char *remote_machine)
2534 ZERO_STRUCTP(the_cli);
2536 if(cli_initialise(the_cli) == NULL) {
2537 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2538 return False;
2541 if ( is_zero_ip(*client_ip) ) {
2542 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2543 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2544 cli_shutdown(the_cli);
2545 return False;
2548 if (ismyip(the_cli->dest_ip)) {
2549 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2550 cli_shutdown(the_cli);
2551 return False;
2554 else {
2555 the_cli->dest_ip.s_addr = client_ip->s_addr;
2556 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2557 inet_ntoa(*client_ip) ));
2560 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2561 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) ));
2562 cli_shutdown(the_cli);
2563 return False;
2566 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2567 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2568 remote_machine));
2569 cli_shutdown(the_cli);
2570 return False;
2573 the_cli->protocol = PROTOCOL_NT1;
2574 cli_setup_signing_state(the_cli, lp_client_signing());
2576 if (!cli_negprot(the_cli)) {
2577 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2578 cli_shutdown(the_cli);
2579 return False;
2582 if (the_cli->protocol != PROTOCOL_NT1) {
2583 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2584 cli_shutdown(the_cli);
2585 return False;
2589 * Do an anonymous session setup.
2592 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2593 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2594 cli_shutdown(the_cli);
2595 return False;
2598 if (!(the_cli->sec_mode & 1)) {
2599 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2600 cli_shutdown(the_cli);
2601 return False;
2604 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2605 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) ));
2606 cli_shutdown(the_cli);
2607 return False;
2611 * Ok - we have an anonymous connection to the IPC$ share.
2612 * Now start the NT Domain stuff :-).
2615 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2616 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)));
2617 cli_nt_session_close(the_cli);
2618 cli_ulogoff(the_cli);
2619 cli_shutdown(the_cli);
2620 return False;
2623 return True;
2626 /***************************************************************************
2627 Connect to the client.
2628 ****************************************************************************/
2630 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2631 uint32 localprinter, uint32 type,
2632 POLICY_HND *handle, struct in_addr *client_ip)
2634 WERROR result;
2637 * If it's the first connection, contact the client
2638 * and connect to the IPC$ share anonymously
2640 if (smb_connections==0) {
2641 fstring unix_printer;
2643 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2645 ZERO_STRUCT(notify_cli);
2647 if(!spoolss_connect_to_client(&notify_cli, client_ip, unix_printer))
2648 return False;
2650 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2651 /* Tell the connections db we're now interested in printer
2652 * notify messages. */
2653 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2657 * Tell the specific printing tdb we want messages for this printer
2658 * by registering our PID.
2661 if (!print_notify_register_pid(snum))
2662 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2664 smb_connections++;
2666 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2667 type, handle);
2669 if (!W_ERROR_IS_OK(result))
2670 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2671 dos_errstr(result)));
2673 return (W_ERROR_IS_OK(result));
2676 /********************************************************************
2677 * _spoolss_rffpcnex
2678 * ReplyFindFirstPrinterChangeNotifyEx
2680 * before replying OK: status=0 a rpc call is made to the workstation
2681 * asking ReplyOpenPrinter
2683 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2684 * called from api_spoolss_rffpcnex
2685 ********************************************************************/
2687 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2689 POLICY_HND *handle = &q_u->handle;
2690 uint32 flags = q_u->flags;
2691 uint32 options = q_u->options;
2692 UNISTR2 *localmachine = &q_u->localmachine;
2693 uint32 printerlocal = q_u->printerlocal;
2694 int snum = -1;
2695 SPOOL_NOTIFY_OPTION *option = q_u->option;
2696 struct in_addr client_ip;
2698 /* store the notify value in the printer struct */
2700 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2702 if (!Printer) {
2703 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2704 return WERR_BADFID;
2707 Printer->notify.flags=flags;
2708 Printer->notify.options=options;
2709 Printer->notify.printerlocal=printerlocal;
2711 if (Printer->notify.option)
2712 free_spool_notify_option(&Printer->notify.option);
2714 Printer->notify.option=dup_spool_notify_option(option);
2716 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2717 sizeof(Printer->notify.localmachine)-1);
2719 /* Connect to the client machine and send a ReplyOpenPrinter */
2721 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2722 snum = -1;
2723 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2724 !get_printer_snum(p, handle, &snum) )
2725 return WERR_BADFID;
2727 client_ip.s_addr = inet_addr(p->conn->client_address);
2729 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2730 Printer->notify.printerlocal, 1,
2731 &Printer->notify.client_hnd, &client_ip))
2732 return WERR_SERVER_UNAVAILABLE;
2734 Printer->notify.client_connected=True;
2736 return WERR_OK;
2739 /*******************************************************************
2740 * fill a notify_info_data with the servername
2741 ********************************************************************/
2743 void spoolss_notify_server_name(int snum,
2744 SPOOL_NOTIFY_INFO_DATA *data,
2745 print_queue_struct *queue,
2746 NT_PRINTER_INFO_LEVEL *printer,
2747 TALLOC_CTX *mem_ctx)
2749 pstring temp_name, temp;
2750 uint32 len;
2752 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2754 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2756 data->notify_data.data.length = len;
2757 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2759 if (!data->notify_data.data.string) {
2760 data->notify_data.data.length = 0;
2761 return;
2764 memcpy(data->notify_data.data.string, temp, len);
2767 /*******************************************************************
2768 * fill a notify_info_data with the printername (not including the servername).
2769 ********************************************************************/
2771 void spoolss_notify_printer_name(int snum,
2772 SPOOL_NOTIFY_INFO_DATA *data,
2773 print_queue_struct *queue,
2774 NT_PRINTER_INFO_LEVEL *printer,
2775 TALLOC_CTX *mem_ctx)
2777 pstring temp;
2778 uint32 len;
2780 /* the notify name should not contain the \\server\ part */
2781 char *p = strrchr(printer->info_2->printername, '\\');
2783 if (!p) {
2784 p = printer->info_2->printername;
2785 } else {
2786 p++;
2789 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2791 data->notify_data.data.length = len;
2792 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2794 if (!data->notify_data.data.string) {
2795 data->notify_data.data.length = 0;
2796 return;
2799 memcpy(data->notify_data.data.string, temp, len);
2802 /*******************************************************************
2803 * fill a notify_info_data with the servicename
2804 ********************************************************************/
2806 void spoolss_notify_share_name(int snum,
2807 SPOOL_NOTIFY_INFO_DATA *data,
2808 print_queue_struct *queue,
2809 NT_PRINTER_INFO_LEVEL *printer,
2810 TALLOC_CTX *mem_ctx)
2812 pstring temp;
2813 uint32 len;
2815 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2817 data->notify_data.data.length = len;
2818 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2820 if (!data->notify_data.data.string) {
2821 data->notify_data.data.length = 0;
2822 return;
2825 memcpy(data->notify_data.data.string, temp, len);
2828 /*******************************************************************
2829 * fill a notify_info_data with the port name
2830 ********************************************************************/
2832 void spoolss_notify_port_name(int snum,
2833 SPOOL_NOTIFY_INFO_DATA *data,
2834 print_queue_struct *queue,
2835 NT_PRINTER_INFO_LEVEL *printer,
2836 TALLOC_CTX *mem_ctx)
2838 pstring temp;
2839 uint32 len;
2841 /* even if it's strange, that's consistant in all the code */
2843 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2845 data->notify_data.data.length = len;
2846 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2848 if (!data->notify_data.data.string) {
2849 data->notify_data.data.length = 0;
2850 return;
2853 memcpy(data->notify_data.data.string, temp, len);
2856 /*******************************************************************
2857 * fill a notify_info_data with the printername
2858 * but it doesn't exist, have to see what to do
2859 ********************************************************************/
2861 void spoolss_notify_driver_name(int snum,
2862 SPOOL_NOTIFY_INFO_DATA *data,
2863 print_queue_struct *queue,
2864 NT_PRINTER_INFO_LEVEL *printer,
2865 TALLOC_CTX *mem_ctx)
2867 pstring temp;
2868 uint32 len;
2870 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2872 data->notify_data.data.length = len;
2873 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2875 if (!data->notify_data.data.string) {
2876 data->notify_data.data.length = 0;
2877 return;
2880 memcpy(data->notify_data.data.string, temp, len);
2883 /*******************************************************************
2884 * fill a notify_info_data with the comment
2885 ********************************************************************/
2887 void spoolss_notify_comment(int snum,
2888 SPOOL_NOTIFY_INFO_DATA *data,
2889 print_queue_struct *queue,
2890 NT_PRINTER_INFO_LEVEL *printer,
2891 TALLOC_CTX *mem_ctx)
2893 pstring temp;
2894 uint32 len;
2896 if (*printer->info_2->comment == '\0')
2897 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2898 else
2899 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2901 data->notify_data.data.length = len;
2902 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2904 if (!data->notify_data.data.string) {
2905 data->notify_data.data.length = 0;
2906 return;
2909 memcpy(data->notify_data.data.string, temp, len);
2912 /*******************************************************************
2913 * fill a notify_info_data with the comment
2914 * location = "Room 1, floor 2, building 3"
2915 ********************************************************************/
2917 void spoolss_notify_location(int snum,
2918 SPOOL_NOTIFY_INFO_DATA *data,
2919 print_queue_struct *queue,
2920 NT_PRINTER_INFO_LEVEL *printer,
2921 TALLOC_CTX *mem_ctx)
2923 pstring temp;
2924 uint32 len;
2926 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2928 data->notify_data.data.length = len;
2929 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2931 if (!data->notify_data.data.string) {
2932 data->notify_data.data.length = 0;
2933 return;
2936 memcpy(data->notify_data.data.string, temp, len);
2939 /*******************************************************************
2940 * fill a notify_info_data with the device mode
2941 * jfm:xxxx don't to it for know but that's a real problem !!!
2942 ********************************************************************/
2944 static void spoolss_notify_devmode(int snum,
2945 SPOOL_NOTIFY_INFO_DATA *data,
2946 print_queue_struct *queue,
2947 NT_PRINTER_INFO_LEVEL *printer,
2948 TALLOC_CTX *mem_ctx)
2952 /*******************************************************************
2953 * fill a notify_info_data with the separator file name
2954 ********************************************************************/
2956 void spoolss_notify_sepfile(int snum,
2957 SPOOL_NOTIFY_INFO_DATA *data,
2958 print_queue_struct *queue,
2959 NT_PRINTER_INFO_LEVEL *printer,
2960 TALLOC_CTX *mem_ctx)
2962 pstring temp;
2963 uint32 len;
2965 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2967 data->notify_data.data.length = len;
2968 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2970 if (!data->notify_data.data.string) {
2971 data->notify_data.data.length = 0;
2972 return;
2975 memcpy(data->notify_data.data.string, temp, len);
2978 /*******************************************************************
2979 * fill a notify_info_data with the print processor
2980 * jfm:xxxx return always winprint to indicate we don't do anything to it
2981 ********************************************************************/
2983 void spoolss_notify_print_processor(int snum,
2984 SPOOL_NOTIFY_INFO_DATA *data,
2985 print_queue_struct *queue,
2986 NT_PRINTER_INFO_LEVEL *printer,
2987 TALLOC_CTX *mem_ctx)
2989 pstring temp;
2990 uint32 len;
2992 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2994 data->notify_data.data.length = len;
2995 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2997 if (!data->notify_data.data.string) {
2998 data->notify_data.data.length = 0;
2999 return;
3002 memcpy(data->notify_data.data.string, temp, len);
3005 /*******************************************************************
3006 * fill a notify_info_data with the print processor options
3007 * jfm:xxxx send an empty string
3008 ********************************************************************/
3010 void spoolss_notify_parameters(int snum,
3011 SPOOL_NOTIFY_INFO_DATA *data,
3012 print_queue_struct *queue,
3013 NT_PRINTER_INFO_LEVEL *printer,
3014 TALLOC_CTX *mem_ctx)
3016 pstring temp;
3017 uint32 len;
3019 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3021 data->notify_data.data.length = len;
3022 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3024 if (!data->notify_data.data.string) {
3025 data->notify_data.data.length = 0;
3026 return;
3029 memcpy(data->notify_data.data.string, temp, len);
3032 /*******************************************************************
3033 * fill a notify_info_data with the data type
3034 * jfm:xxxx always send RAW as data type
3035 ********************************************************************/
3037 void spoolss_notify_datatype(int snum,
3038 SPOOL_NOTIFY_INFO_DATA *data,
3039 print_queue_struct *queue,
3040 NT_PRINTER_INFO_LEVEL *printer,
3041 TALLOC_CTX *mem_ctx)
3043 pstring temp;
3044 uint32 len;
3046 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3048 data->notify_data.data.length = len;
3049 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3051 if (!data->notify_data.data.string) {
3052 data->notify_data.data.length = 0;
3053 return;
3056 memcpy(data->notify_data.data.string, temp, len);
3059 /*******************************************************************
3060 * fill a notify_info_data with the security descriptor
3061 * jfm:xxxx send an null pointer to say no security desc
3062 * have to implement security before !
3063 ********************************************************************/
3065 static void spoolss_notify_security_desc(int snum,
3066 SPOOL_NOTIFY_INFO_DATA *data,
3067 print_queue_struct *queue,
3068 NT_PRINTER_INFO_LEVEL *printer,
3069 TALLOC_CTX *mem_ctx)
3071 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3072 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3075 /*******************************************************************
3076 * fill a notify_info_data with the attributes
3077 * jfm:xxxx a samba printer is always shared
3078 ********************************************************************/
3080 void spoolss_notify_attributes(int snum,
3081 SPOOL_NOTIFY_INFO_DATA *data,
3082 print_queue_struct *queue,
3083 NT_PRINTER_INFO_LEVEL *printer,
3084 TALLOC_CTX *mem_ctx)
3086 data->notify_data.value[0] = printer->info_2->attributes;
3087 data->notify_data.value[1] = 0;
3090 /*******************************************************************
3091 * fill a notify_info_data with the priority
3092 ********************************************************************/
3094 static void spoolss_notify_priority(int snum,
3095 SPOOL_NOTIFY_INFO_DATA *data,
3096 print_queue_struct *queue,
3097 NT_PRINTER_INFO_LEVEL *printer,
3098 TALLOC_CTX *mem_ctx)
3100 data->notify_data.value[0] = printer->info_2->priority;
3101 data->notify_data.value[1] = 0;
3104 /*******************************************************************
3105 * fill a notify_info_data with the default priority
3106 ********************************************************************/
3108 static void spoolss_notify_default_priority(int snum,
3109 SPOOL_NOTIFY_INFO_DATA *data,
3110 print_queue_struct *queue,
3111 NT_PRINTER_INFO_LEVEL *printer,
3112 TALLOC_CTX *mem_ctx)
3114 data->notify_data.value[0] = printer->info_2->default_priority;
3115 data->notify_data.value[1] = 0;
3118 /*******************************************************************
3119 * fill a notify_info_data with the start time
3120 ********************************************************************/
3122 static void spoolss_notify_start_time(int snum,
3123 SPOOL_NOTIFY_INFO_DATA *data,
3124 print_queue_struct *queue,
3125 NT_PRINTER_INFO_LEVEL *printer,
3126 TALLOC_CTX *mem_ctx)
3128 data->notify_data.value[0] = printer->info_2->starttime;
3129 data->notify_data.value[1] = 0;
3132 /*******************************************************************
3133 * fill a notify_info_data with the until time
3134 ********************************************************************/
3136 static void spoolss_notify_until_time(int snum,
3137 SPOOL_NOTIFY_INFO_DATA *data,
3138 print_queue_struct *queue,
3139 NT_PRINTER_INFO_LEVEL *printer,
3140 TALLOC_CTX *mem_ctx)
3142 data->notify_data.value[0] = printer->info_2->untiltime;
3143 data->notify_data.value[1] = 0;
3146 /*******************************************************************
3147 * fill a notify_info_data with the status
3148 ********************************************************************/
3150 static void spoolss_notify_status(int snum,
3151 SPOOL_NOTIFY_INFO_DATA *data,
3152 print_queue_struct *queue,
3153 NT_PRINTER_INFO_LEVEL *printer,
3154 TALLOC_CTX *mem_ctx)
3156 print_status_struct status;
3158 print_queue_length(snum, &status);
3159 data->notify_data.value[0]=(uint32) status.status;
3160 data->notify_data.value[1] = 0;
3163 /*******************************************************************
3164 * fill a notify_info_data with the number of jobs queued
3165 ********************************************************************/
3167 void spoolss_notify_cjobs(int snum,
3168 SPOOL_NOTIFY_INFO_DATA *data,
3169 print_queue_struct *queue,
3170 NT_PRINTER_INFO_LEVEL *printer,
3171 TALLOC_CTX *mem_ctx)
3173 data->notify_data.value[0] = print_queue_length(snum, NULL);
3174 data->notify_data.value[1] = 0;
3177 /*******************************************************************
3178 * fill a notify_info_data with the average ppm
3179 ********************************************************************/
3181 static void spoolss_notify_average_ppm(int snum,
3182 SPOOL_NOTIFY_INFO_DATA *data,
3183 print_queue_struct *queue,
3184 NT_PRINTER_INFO_LEVEL *printer,
3185 TALLOC_CTX *mem_ctx)
3187 /* always respond 8 pages per minutes */
3188 /* a little hard ! */
3189 data->notify_data.value[0] = printer->info_2->averageppm;
3190 data->notify_data.value[1] = 0;
3193 /*******************************************************************
3194 * fill a notify_info_data with username
3195 ********************************************************************/
3197 static void spoolss_notify_username(int snum,
3198 SPOOL_NOTIFY_INFO_DATA *data,
3199 print_queue_struct *queue,
3200 NT_PRINTER_INFO_LEVEL *printer,
3201 TALLOC_CTX *mem_ctx)
3203 pstring temp;
3204 uint32 len;
3206 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3208 data->notify_data.data.length = len;
3209 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3211 if (!data->notify_data.data.string) {
3212 data->notify_data.data.length = 0;
3213 return;
3216 memcpy(data->notify_data.data.string, temp, len);
3219 /*******************************************************************
3220 * fill a notify_info_data with job status
3221 ********************************************************************/
3223 static void spoolss_notify_job_status(int snum,
3224 SPOOL_NOTIFY_INFO_DATA *data,
3225 print_queue_struct *queue,
3226 NT_PRINTER_INFO_LEVEL *printer,
3227 TALLOC_CTX *mem_ctx)
3229 data->notify_data.value[0]=nt_printj_status(queue->status);
3230 data->notify_data.value[1] = 0;
3233 /*******************************************************************
3234 * fill a notify_info_data with job name
3235 ********************************************************************/
3237 static void spoolss_notify_job_name(int snum,
3238 SPOOL_NOTIFY_INFO_DATA *data,
3239 print_queue_struct *queue,
3240 NT_PRINTER_INFO_LEVEL *printer,
3241 TALLOC_CTX *mem_ctx)
3243 pstring temp;
3244 uint32 len;
3246 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3248 data->notify_data.data.length = len;
3249 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3251 if (!data->notify_data.data.string) {
3252 data->notify_data.data.length = 0;
3253 return;
3256 memcpy(data->notify_data.data.string, temp, len);
3259 /*******************************************************************
3260 * fill a notify_info_data with job status
3261 ********************************************************************/
3263 static void spoolss_notify_job_status_string(int snum,
3264 SPOOL_NOTIFY_INFO_DATA *data,
3265 print_queue_struct *queue,
3266 NT_PRINTER_INFO_LEVEL *printer,
3267 TALLOC_CTX *mem_ctx)
3270 * Now we're returning job status codes we just return a "" here. JRA.
3273 const char *p = "";
3274 pstring temp;
3275 uint32 len;
3277 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3278 p = "unknown";
3280 switch (queue->status) {
3281 case LPQ_QUEUED:
3282 p = "Queued";
3283 break;
3284 case LPQ_PAUSED:
3285 p = ""; /* NT provides the paused string */
3286 break;
3287 case LPQ_SPOOLING:
3288 p = "Spooling";
3289 break;
3290 case LPQ_PRINTING:
3291 p = "Printing";
3292 break;
3294 #endif /* NO LONGER NEEDED. */
3296 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3298 data->notify_data.data.length = len;
3299 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3301 if (!data->notify_data.data.string) {
3302 data->notify_data.data.length = 0;
3303 return;
3306 memcpy(data->notify_data.data.string, temp, len);
3309 /*******************************************************************
3310 * fill a notify_info_data with job time
3311 ********************************************************************/
3313 static void spoolss_notify_job_time(int snum,
3314 SPOOL_NOTIFY_INFO_DATA *data,
3315 print_queue_struct *queue,
3316 NT_PRINTER_INFO_LEVEL *printer,
3317 TALLOC_CTX *mem_ctx)
3319 data->notify_data.value[0]=0x0;
3320 data->notify_data.value[1]=0;
3323 /*******************************************************************
3324 * fill a notify_info_data with job size
3325 ********************************************************************/
3327 static void spoolss_notify_job_size(int snum,
3328 SPOOL_NOTIFY_INFO_DATA *data,
3329 print_queue_struct *queue,
3330 NT_PRINTER_INFO_LEVEL *printer,
3331 TALLOC_CTX *mem_ctx)
3333 data->notify_data.value[0]=queue->size;
3334 data->notify_data.value[1]=0;
3337 /*******************************************************************
3338 * fill a notify_info_data with page info
3339 ********************************************************************/
3340 static void spoolss_notify_total_pages(int snum,
3341 SPOOL_NOTIFY_INFO_DATA *data,
3342 print_queue_struct *queue,
3343 NT_PRINTER_INFO_LEVEL *printer,
3344 TALLOC_CTX *mem_ctx)
3346 data->notify_data.value[0]=queue->page_count;
3347 data->notify_data.value[1]=0;
3350 /*******************************************************************
3351 * fill a notify_info_data with pages printed info.
3352 ********************************************************************/
3353 static void spoolss_notify_pages_printed(int snum,
3354 SPOOL_NOTIFY_INFO_DATA *data,
3355 print_queue_struct *queue,
3356 NT_PRINTER_INFO_LEVEL *printer,
3357 TALLOC_CTX *mem_ctx)
3359 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3360 data->notify_data.value[1]=0;
3363 /*******************************************************************
3364 Fill a notify_info_data with job position.
3365 ********************************************************************/
3367 static void spoolss_notify_job_position(int snum,
3368 SPOOL_NOTIFY_INFO_DATA *data,
3369 print_queue_struct *queue,
3370 NT_PRINTER_INFO_LEVEL *printer,
3371 TALLOC_CTX *mem_ctx)
3373 data->notify_data.value[0]=queue->job;
3374 data->notify_data.value[1]=0;
3377 /*******************************************************************
3378 Fill a notify_info_data with submitted time.
3379 ********************************************************************/
3381 static void spoolss_notify_submitted_time(int snum,
3382 SPOOL_NOTIFY_INFO_DATA *data,
3383 print_queue_struct *queue,
3384 NT_PRINTER_INFO_LEVEL *printer,
3385 TALLOC_CTX *mem_ctx)
3387 struct tm *t;
3388 uint32 len;
3389 SYSTEMTIME st;
3390 char *p;
3392 t=gmtime(&queue->time);
3394 len = sizeof(SYSTEMTIME);
3396 data->notify_data.data.length = len;
3397 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3399 if (!data->notify_data.data.string) {
3400 data->notify_data.data.length = 0;
3401 return;
3404 make_systemtime(&st, t);
3407 * Systemtime must be linearized as a set of UINT16's.
3408 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3411 p = (char *)data->notify_data.data.string;
3412 SSVAL(p, 0, st.year);
3413 SSVAL(p, 2, st.month);
3414 SSVAL(p, 4, st.dayofweek);
3415 SSVAL(p, 6, st.day);
3416 SSVAL(p, 8, st.hour);
3417 SSVAL(p, 10, st.minute);
3418 SSVAL(p, 12, st.second);
3419 SSVAL(p, 14, st.milliseconds);
3422 struct s_notify_info_data_table
3424 uint16 type;
3425 uint16 field;
3426 const char *name;
3427 uint32 size;
3428 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3429 print_queue_struct *queue,
3430 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3433 /* A table describing the various print notification constants and
3434 whether the notification data is a pointer to a variable sized
3435 buffer, a one value uint32 or a two value uint32. */
3437 static const struct s_notify_info_data_table notify_info_data_table[] =
3439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3465 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3490 /*******************************************************************
3491 Return the size of info_data structure.
3492 ********************************************************************/
3494 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3496 int i=0;
3498 for (i = 0; i < sizeof(notify_info_data_table); i++)
3500 if ( (notify_info_data_table[i].type == type)
3501 && (notify_info_data_table[i].field == field) )
3503 switch(notify_info_data_table[i].size)
3505 case NOTIFY_ONE_VALUE:
3506 case NOTIFY_TWO_VALUE:
3507 return 1;
3508 case NOTIFY_STRING:
3509 return 2;
3511 /* The only pointer notify data I have seen on
3512 the wire is the submitted time and this has
3513 the notify size set to 4. -tpot */
3515 case NOTIFY_POINTER:
3516 return 4;
3518 case NOTIFY_SECDESC:
3519 return 5;
3524 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3526 return 0;
3529 /*******************************************************************
3530 Return the type of notify_info_data.
3531 ********************************************************************/
3533 static int type_of_notify_info_data(uint16 type, uint16 field)
3535 int i=0;
3537 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3538 if (notify_info_data_table[i].type == type &&
3539 notify_info_data_table[i].field == field)
3540 return notify_info_data_table[i].size;
3543 return False;
3546 /****************************************************************************
3547 ****************************************************************************/
3549 static int search_notify(uint16 type, uint16 field, int *value)
3551 int i;
3553 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3554 if (notify_info_data_table[i].type == type &&
3555 notify_info_data_table[i].field == field &&
3556 notify_info_data_table[i].fn != NULL) {
3557 *value = i;
3558 return True;
3562 return False;
3565 /****************************************************************************
3566 ****************************************************************************/
3568 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3570 info_data->type = type;
3571 info_data->field = field;
3572 info_data->reserved = 0;
3574 info_data->size = size_of_notify_info_data(type, field);
3575 info_data->enc_type = type_of_notify_info_data(type, field);
3577 info_data->id = id;
3582 /*******************************************************************
3584 * fill a notify_info struct with info asked
3586 ********************************************************************/
3588 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3589 snum, SPOOL_NOTIFY_OPTION_TYPE
3590 *option_type, uint32 id,
3591 TALLOC_CTX *mem_ctx)
3593 int field_num,j;
3594 uint16 type;
3595 uint16 field;
3597 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3598 NT_PRINTER_INFO_LEVEL *printer = NULL;
3599 print_queue_struct *queue=NULL;
3601 type=option_type->type;
3603 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3604 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3605 option_type->count, lp_servicename(snum)));
3607 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3608 return False;
3610 for(field_num=0; field_num<option_type->count; field_num++) {
3611 field = option_type->fields[field_num];
3613 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3615 if (!search_notify(type, field, &j) )
3616 continue;
3618 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3619 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3620 return False;
3621 } else
3622 info->data = tid;
3624 current_data = &info->data[info->count];
3626 construct_info_data(current_data, type, field, id);
3628 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3629 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3631 notify_info_data_table[j].fn(snum, current_data, queue,
3632 printer, mem_ctx);
3634 info->count++;
3637 free_a_printer(&printer, 2);
3638 return True;
3641 /*******************************************************************
3643 * fill a notify_info struct with info asked
3645 ********************************************************************/
3647 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3648 SPOOL_NOTIFY_INFO *info,
3649 NT_PRINTER_INFO_LEVEL *printer,
3650 int snum, SPOOL_NOTIFY_OPTION_TYPE
3651 *option_type, uint32 id,
3652 TALLOC_CTX *mem_ctx)
3654 int field_num,j;
3655 uint16 type;
3656 uint16 field;
3658 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3660 DEBUG(4,("construct_notify_jobs_info\n"));
3662 type = option_type->type;
3664 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3665 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3666 option_type->count));
3668 for(field_num=0; field_num<option_type->count; field_num++) {
3669 field = option_type->fields[field_num];
3671 if (!search_notify(type, field, &j) )
3672 continue;
3674 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3675 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3676 return False;
3678 else info->data = tid;
3680 current_data=&(info->data[info->count]);
3682 construct_info_data(current_data, type, field, id);
3683 notify_info_data_table[j].fn(snum, current_data, queue,
3684 printer, mem_ctx);
3685 info->count++;
3688 return True;
3692 * JFM: The enumeration is not that simple, it's even non obvious.
3694 * let's take an example: I want to monitor the PRINTER SERVER for
3695 * the printer's name and the number of jobs currently queued.
3696 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3697 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3699 * I have 3 printers on the back of my server.
3701 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3702 * structures.
3703 * Number Data Id
3704 * 1 printer 1 name 1
3705 * 2 printer 1 cjob 1
3706 * 3 printer 2 name 2
3707 * 4 printer 2 cjob 2
3708 * 5 printer 3 name 3
3709 * 6 printer 3 name 3
3711 * that's the print server case, the printer case is even worse.
3714 /*******************************************************************
3716 * enumerate all printers on the printserver
3717 * fill a notify_info struct with info asked
3719 ********************************************************************/
3721 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3722 SPOOL_NOTIFY_INFO *info,
3723 TALLOC_CTX *mem_ctx)
3725 int snum;
3726 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3727 int n_services=lp_numservices();
3728 int i;
3729 SPOOL_NOTIFY_OPTION *option;
3730 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3732 DEBUG(4,("printserver_notify_info\n"));
3734 if (!Printer)
3735 return WERR_BADFID;
3737 option=Printer->notify.option;
3738 info->version=2;
3739 info->data=NULL;
3740 info->count=0;
3742 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3743 sending a ffpcn() request first */
3745 if ( !option )
3746 return WERR_BADFID;
3748 for (i=0; i<option->count; i++) {
3749 option_type=&(option->ctr.type[i]);
3751 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3752 continue;
3754 for (snum=0; snum<n_services; snum++)
3756 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3757 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3761 #if 0
3763 * Debugging information, don't delete.
3766 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3767 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3768 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3770 for (i=0; i<info->count; i++) {
3771 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3772 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3773 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3775 #endif
3777 return WERR_OK;
3780 /*******************************************************************
3782 * fill a notify_info struct with info asked
3784 ********************************************************************/
3786 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3787 TALLOC_CTX *mem_ctx)
3789 int snum;
3790 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3791 int i;
3792 uint32 id;
3793 SPOOL_NOTIFY_OPTION *option;
3794 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3795 int count,j;
3796 print_queue_struct *queue=NULL;
3797 print_status_struct status;
3799 DEBUG(4,("printer_notify_info\n"));
3801 if (!Printer)
3802 return WERR_BADFID;
3804 option=Printer->notify.option;
3805 id = 0x0;
3806 info->version=2;
3807 info->data=NULL;
3808 info->count=0;
3810 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3811 sending a ffpcn() request first */
3813 if ( !option )
3814 return WERR_BADFID;
3816 get_printer_snum(p, hnd, &snum);
3818 for (i=0; i<option->count; i++) {
3819 option_type=&option->ctr.type[i];
3821 switch ( option_type->type ) {
3822 case PRINTER_NOTIFY_TYPE:
3823 if(construct_notify_printer_info(Printer, info, snum,
3824 option_type, id,
3825 mem_ctx))
3826 id--;
3827 break;
3829 case JOB_NOTIFY_TYPE: {
3830 NT_PRINTER_INFO_LEVEL *printer = NULL;
3832 count = print_queue_status(snum, &queue, &status);
3834 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3835 goto done;
3837 for (j=0; j<count; j++) {
3838 construct_notify_jobs_info(&queue[j], info,
3839 printer, snum,
3840 option_type,
3841 queue[j].job,
3842 mem_ctx);
3845 free_a_printer(&printer, 2);
3847 done:
3848 SAFE_FREE(queue);
3849 break;
3855 * Debugging information, don't delete.
3858 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3859 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3860 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3862 for (i=0; i<info->count; i++) {
3863 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3864 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3865 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3868 return WERR_OK;
3871 /********************************************************************
3872 * spoolss_rfnpcnex
3873 ********************************************************************/
3875 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3877 POLICY_HND *handle = &q_u->handle;
3878 SPOOL_NOTIFY_INFO *info = &r_u->info;
3880 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3881 WERROR result = WERR_BADFID;
3883 /* we always have a NOTIFY_INFO struct */
3884 r_u->info_ptr=0x1;
3886 if (!Printer) {
3887 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3888 OUR_HANDLE(handle)));
3889 goto done;
3892 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3895 * We are now using the change value, and
3896 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3897 * I don't have a global notification system, I'm sending back all the
3898 * informations even when _NOTHING_ has changed.
3901 /* We need to keep track of the change value to send back in
3902 RRPCN replies otherwise our updates are ignored. */
3904 Printer->notify.fnpcn = True;
3906 if (Printer->notify.client_connected) {
3907 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3908 Printer->notify.change = q_u->change;
3911 /* just ignore the SPOOL_NOTIFY_OPTION */
3913 switch (Printer->printer_type) {
3914 case PRINTER_HANDLE_IS_PRINTSERVER:
3915 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3916 break;
3918 case PRINTER_HANDLE_IS_PRINTER:
3919 result = printer_notify_info(p, handle, info, p->mem_ctx);
3920 break;
3923 Printer->notify.fnpcn = False;
3925 done:
3926 return result;
3929 /********************************************************************
3930 * construct_printer_info_0
3931 * fill a printer_info_0 struct
3932 ********************************************************************/
3934 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3936 pstring chaine;
3937 int count;
3938 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3939 counter_printer_0 *session_counter;
3940 uint32 global_counter;
3941 struct tm *t;
3942 time_t setuptime;
3943 print_status_struct status;
3945 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3946 return False;
3948 count = print_queue_length(snum, &status);
3950 /* check if we already have a counter for this printer */
3951 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3953 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3954 if (session_counter->snum == snum)
3955 break;
3958 /* it's the first time, add it to the list */
3959 if (session_counter==NULL) {
3960 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3961 free_a_printer(&ntprinter, 2);
3962 return False;
3964 ZERO_STRUCTP(session_counter);
3965 session_counter->snum=snum;
3966 session_counter->counter=0;
3967 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3970 /* increment it */
3971 session_counter->counter++;
3973 /* JFM:
3974 * the global_counter should be stored in a TDB as it's common to all the clients
3975 * and should be zeroed on samba startup
3977 global_counter=session_counter->counter;
3979 pstrcpy(chaine,ntprinter->info_2->printername);
3981 init_unistr(&printer->printername, chaine);
3983 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3984 init_unistr(&printer->servername, chaine);
3986 printer->cjobs = count;
3987 printer->total_jobs = 0;
3988 printer->total_bytes = 0;
3990 setuptime = (time_t)ntprinter->info_2->setuptime;
3991 t=gmtime(&setuptime);
3993 printer->year = t->tm_year+1900;
3994 printer->month = t->tm_mon+1;
3995 printer->dayofweek = t->tm_wday;
3996 printer->day = t->tm_mday;
3997 printer->hour = t->tm_hour;
3998 printer->minute = t->tm_min;
3999 printer->second = t->tm_sec;
4000 printer->milliseconds = 0;
4002 printer->global_counter = global_counter;
4003 printer->total_pages = 0;
4005 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4006 printer->major_version = 0x0005; /* NT 5 */
4007 printer->build_version = 0x0893; /* build 2195 */
4009 printer->unknown7 = 0x1;
4010 printer->unknown8 = 0x0;
4011 printer->unknown9 = 0x0;
4012 printer->session_counter = session_counter->counter;
4013 printer->unknown11 = 0x0;
4014 printer->printer_errors = 0x0; /* number of print failure */
4015 printer->unknown13 = 0x0;
4016 printer->unknown14 = 0x1;
4017 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4018 printer->unknown16 = 0x0;
4019 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4020 printer->unknown18 = 0x0;
4021 printer->status = nt_printq_status(status.status);
4022 printer->unknown20 = 0x0;
4023 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4024 printer->unknown22 = 0x0;
4025 printer->unknown23 = 0x6; /* 6 ???*/
4026 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4027 printer->unknown25 = 0;
4028 printer->unknown26 = 0;
4029 printer->unknown27 = 0;
4030 printer->unknown28 = 0;
4031 printer->unknown29 = 0;
4033 free_a_printer(&ntprinter,2);
4034 return (True);
4037 /********************************************************************
4038 * construct_printer_info_1
4039 * fill a printer_info_1 struct
4040 ********************************************************************/
4041 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4043 pstring chaine;
4044 pstring chaine2;
4045 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4047 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4048 return False;
4050 printer->flags=flags;
4052 if (*ntprinter->info_2->comment == '\0') {
4053 init_unistr(&printer->comment, lp_comment(snum));
4054 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4055 ntprinter->info_2->drivername, lp_comment(snum));
4057 else {
4058 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4059 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4060 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4063 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4065 init_unistr(&printer->description, chaine);
4066 init_unistr(&printer->name, chaine2);
4068 free_a_printer(&ntprinter,2);
4070 return True;
4073 /****************************************************************************
4074 Free a DEVMODE struct.
4075 ****************************************************************************/
4077 static void free_dev_mode(DEVICEMODE *dev)
4079 if (dev == NULL)
4080 return;
4082 SAFE_FREE(dev->private);
4083 SAFE_FREE(dev);
4087 /****************************************************************************
4088 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4089 should be valid upon entry
4090 ****************************************************************************/
4092 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4094 if ( !devmode || !ntdevmode )
4095 return False;
4097 init_unistr(&devmode->devicename, ntdevmode->devicename);
4099 init_unistr(&devmode->formname, ntdevmode->formname);
4101 devmode->specversion = ntdevmode->specversion;
4102 devmode->driverversion = ntdevmode->driverversion;
4103 devmode->size = ntdevmode->size;
4104 devmode->driverextra = ntdevmode->driverextra;
4105 devmode->fields = ntdevmode->fields;
4107 devmode->orientation = ntdevmode->orientation;
4108 devmode->papersize = ntdevmode->papersize;
4109 devmode->paperlength = ntdevmode->paperlength;
4110 devmode->paperwidth = ntdevmode->paperwidth;
4111 devmode->scale = ntdevmode->scale;
4112 devmode->copies = ntdevmode->copies;
4113 devmode->defaultsource = ntdevmode->defaultsource;
4114 devmode->printquality = ntdevmode->printquality;
4115 devmode->color = ntdevmode->color;
4116 devmode->duplex = ntdevmode->duplex;
4117 devmode->yresolution = ntdevmode->yresolution;
4118 devmode->ttoption = ntdevmode->ttoption;
4119 devmode->collate = ntdevmode->collate;
4120 devmode->icmmethod = ntdevmode->icmmethod;
4121 devmode->icmintent = ntdevmode->icmintent;
4122 devmode->mediatype = ntdevmode->mediatype;
4123 devmode->dithertype = ntdevmode->dithertype;
4125 if (ntdevmode->private != NULL) {
4126 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4127 return False;
4130 return True;
4133 /****************************************************************************
4134 Create a DEVMODE struct. Returns malloced memory.
4135 ****************************************************************************/
4137 DEVICEMODE *construct_dev_mode(int snum)
4139 NT_PRINTER_INFO_LEVEL *printer = NULL;
4140 DEVICEMODE *devmode = NULL;
4142 DEBUG(7,("construct_dev_mode\n"));
4144 DEBUGADD(8,("getting printer characteristics\n"));
4146 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4147 return NULL;
4149 if ( !printer->info_2->devmode ) {
4150 DEBUG(5, ("BONG! There was no device mode!\n"));
4151 goto done;
4154 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4155 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4156 goto done;
4159 ZERO_STRUCTP(devmode);
4161 DEBUGADD(8,("loading DEVICEMODE\n"));
4163 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4164 free_dev_mode( devmode );
4165 devmode = NULL;
4168 done:
4169 free_a_printer(&printer,2);
4171 return devmode;
4174 /********************************************************************
4175 * construct_printer_info_2
4176 * fill a printer_info_2 struct
4177 ********************************************************************/
4179 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4181 int count;
4182 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4184 print_status_struct status;
4186 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4187 return False;
4189 count = print_queue_length(snum, &status);
4191 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4192 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4193 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4194 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4195 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4197 if (*ntprinter->info_2->comment == '\0')
4198 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4199 else
4200 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4202 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4203 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4204 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4205 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4206 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4208 printer->attributes = ntprinter->info_2->attributes;
4210 printer->priority = ntprinter->info_2->priority; /* priority */
4211 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4212 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4213 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4214 printer->status = nt_printq_status(status.status); /* status */
4215 printer->cjobs = count; /* jobs */
4216 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4218 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4219 DEBUG(8, ("Returning NULL Devicemode!\n"));
4222 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4223 /* steal the printer info sec_desc structure. [badly done]. */
4224 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4225 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4226 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4227 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4229 else {
4230 printer->secdesc = NULL;
4233 free_a_printer(&ntprinter, 2);
4234 return True;
4237 /********************************************************************
4238 * construct_printer_info_3
4239 * fill a printer_info_3 struct
4240 ********************************************************************/
4242 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4244 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4245 PRINTER_INFO_3 *printer = NULL;
4247 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4248 return False;
4250 *pp_printer = NULL;
4251 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4252 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4253 return False;
4256 ZERO_STRUCTP(printer);
4258 printer->flags = 4; /* These are the components of the SD we are returning. */
4259 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4260 /* steal the printer info sec_desc structure. [badly done]. */
4261 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4263 #if 0
4265 * Set the flags for the components we are returning.
4268 if (printer->secdesc->owner_sid)
4269 printer->flags |= OWNER_SECURITY_INFORMATION;
4271 if (printer->secdesc->grp_sid)
4272 printer->flags |= GROUP_SECURITY_INFORMATION;
4274 if (printer->secdesc->dacl)
4275 printer->flags |= DACL_SECURITY_INFORMATION;
4277 if (printer->secdesc->sacl)
4278 printer->flags |= SACL_SECURITY_INFORMATION;
4279 #endif
4281 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4282 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4283 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4286 free_a_printer(&ntprinter, 2);
4288 *pp_printer = printer;
4289 return True;
4292 /********************************************************************
4293 * construct_printer_info_4
4294 * fill a printer_info_4 struct
4295 ********************************************************************/
4297 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4299 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4301 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4302 return False;
4304 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4305 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4306 printer->attributes = ntprinter->info_2->attributes;
4308 free_a_printer(&ntprinter, 2);
4309 return True;
4312 /********************************************************************
4313 * construct_printer_info_5
4314 * fill a printer_info_5 struct
4315 ********************************************************************/
4317 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4319 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4321 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4322 return False;
4324 init_unistr(&printer->printername, ntprinter->info_2->printername);
4325 init_unistr(&printer->portname, ntprinter->info_2->portname);
4326 printer->attributes = ntprinter->info_2->attributes;
4328 /* these two are not used by NT+ according to MSDN */
4330 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4331 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4333 free_a_printer(&ntprinter, 2);
4335 return True;
4338 /********************************************************************
4339 * construct_printer_info_7
4340 * fill a printer_info_7 struct
4341 ********************************************************************/
4343 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4345 char *guid_str = NULL;
4346 struct uuid guid;
4348 if (is_printer_published(print_hnd, snum, &guid)) {
4349 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4350 strupper_m(guid_str);
4351 init_unistr(&printer->guid, guid_str);
4352 printer->action = SPOOL_DS_PUBLISH;
4353 } else {
4354 init_unistr(&printer->guid, "");
4355 printer->action = SPOOL_DS_UNPUBLISH;
4358 return True;
4361 /********************************************************************
4362 Spoolss_enumprinters.
4363 ********************************************************************/
4365 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4367 int snum;
4368 int i;
4369 int n_services=lp_numservices();
4370 PRINTER_INFO_1 *tp, *printers=NULL;
4371 PRINTER_INFO_1 current_prt;
4373 DEBUG(4,("enum_all_printers_info_1\n"));
4375 for (snum=0; snum<n_services; snum++) {
4376 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4377 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4379 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4380 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4381 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4382 SAFE_FREE(printers);
4383 *returned=0;
4384 return WERR_NOMEM;
4386 else printers = tp;
4387 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4389 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4390 (*returned)++;
4395 /* check the required size. */
4396 for (i=0; i<*returned; i++)
4397 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4399 if (!alloc_buffer_size(buffer, *needed))
4400 return WERR_INSUFFICIENT_BUFFER;
4402 /* fill the buffer with the structures */
4403 for (i=0; i<*returned; i++)
4404 smb_io_printer_info_1("", buffer, &printers[i], 0);
4406 /* clear memory */
4407 SAFE_FREE(printers);
4409 if (*needed > offered) {
4410 *returned=0;
4411 return WERR_INSUFFICIENT_BUFFER;
4413 else
4414 return WERR_OK;
4417 /********************************************************************
4418 enum_all_printers_info_1_local.
4419 *********************************************************************/
4421 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4423 DEBUG(4,("enum_all_printers_info_1_local\n"));
4425 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4428 /********************************************************************
4429 enum_all_printers_info_1_name.
4430 *********************************************************************/
4432 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4434 char *s = name;
4436 DEBUG(4,("enum_all_printers_info_1_name\n"));
4438 if ((name[0] == '\\') && (name[1] == '\\'))
4439 s = name + 2;
4441 if (is_myname_or_ipaddr(s)) {
4442 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4444 else
4445 return WERR_INVALID_NAME;
4448 /********************************************************************
4449 enum_all_printers_info_1_remote.
4450 *********************************************************************/
4452 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4454 PRINTER_INFO_1 *printer;
4455 fstring printername;
4456 fstring desc;
4457 fstring comment;
4458 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4460 /* JFM: currently it's more a place holder than anything else.
4461 * In the spooler world there is a notion of server registration.
4462 * the print servers are registring (sp ?) on the PDC (in the same domain)
4464 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4467 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4468 return WERR_NOMEM;
4470 *returned=1;
4472 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4473 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4474 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4476 init_unistr(&printer->description, desc);
4477 init_unistr(&printer->name, printername);
4478 init_unistr(&printer->comment, comment);
4479 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4481 /* check the required size. */
4482 *needed += spoolss_size_printer_info_1(printer);
4484 if (!alloc_buffer_size(buffer, *needed)) {
4485 SAFE_FREE(printer);
4486 return WERR_INSUFFICIENT_BUFFER;
4489 /* fill the buffer with the structures */
4490 smb_io_printer_info_1("", buffer, printer, 0);
4492 /* clear memory */
4493 SAFE_FREE(printer);
4495 if (*needed > offered) {
4496 *returned=0;
4497 return WERR_INSUFFICIENT_BUFFER;
4499 else
4500 return WERR_OK;
4503 /********************************************************************
4504 enum_all_printers_info_1_network.
4505 *********************************************************************/
4507 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4509 char *s = name;
4511 DEBUG(4,("enum_all_printers_info_1_network\n"));
4513 /* If we respond to a enum_printers level 1 on our name with flags
4514 set to PRINTER_ENUM_REMOTE with a list of printers then these
4515 printers incorrectly appear in the APW browse list.
4516 Specifically the printers for the server appear at the workgroup
4517 level where all the other servers in the domain are
4518 listed. Windows responds to this call with a
4519 WERR_CAN_NOT_COMPLETE so we should do the same. */
4521 if (name[0] == '\\' && name[1] == '\\')
4522 s = name + 2;
4524 if (is_myname_or_ipaddr(s))
4525 return WERR_CAN_NOT_COMPLETE;
4527 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4530 /********************************************************************
4531 * api_spoolss_enumprinters
4533 * called from api_spoolss_enumprinters (see this to understand)
4534 ********************************************************************/
4536 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4538 int snum;
4539 int i;
4540 int n_services=lp_numservices();
4541 PRINTER_INFO_2 *tp, *printers=NULL;
4542 PRINTER_INFO_2 current_prt;
4544 for (snum=0; snum<n_services; snum++) {
4545 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4546 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4548 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4549 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4550 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4551 SAFE_FREE(printers);
4552 *returned = 0;
4553 return WERR_NOMEM;
4555 else printers = tp;
4556 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4557 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4558 (*returned)++;
4563 /* check the required size. */
4564 for (i=0; i<*returned; i++)
4565 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4567 if (!alloc_buffer_size(buffer, *needed)) {
4568 for (i=0; i<*returned; i++) {
4569 free_devmode(printers[i].devmode);
4571 SAFE_FREE(printers);
4572 return WERR_INSUFFICIENT_BUFFER;
4575 /* fill the buffer with the structures */
4576 for (i=0; i<*returned; i++)
4577 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4579 /* clear memory */
4580 for (i=0; i<*returned; i++) {
4581 free_devmode(printers[i].devmode);
4583 SAFE_FREE(printers);
4585 if (*needed > offered) {
4586 *returned=0;
4587 return WERR_INSUFFICIENT_BUFFER;
4589 else
4590 return WERR_OK;
4593 /********************************************************************
4594 * handle enumeration of printers at level 1
4595 ********************************************************************/
4597 static WERROR enumprinters_level1( uint32 flags, fstring name,
4598 NEW_BUFFER *buffer, uint32 offered,
4599 uint32 *needed, uint32 *returned)
4601 /* Not all the flags are equals */
4603 if (flags & PRINTER_ENUM_LOCAL)
4604 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4606 if (flags & PRINTER_ENUM_NAME)
4607 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4609 if (flags & PRINTER_ENUM_REMOTE)
4610 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4612 if (flags & PRINTER_ENUM_NETWORK)
4613 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4615 return WERR_OK; /* NT4sp5 does that */
4618 /********************************************************************
4619 * handle enumeration of printers at level 2
4620 ********************************************************************/
4622 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4623 NEW_BUFFER *buffer, uint32 offered,
4624 uint32 *needed, uint32 *returned)
4626 char *s = servername;
4628 if (flags & PRINTER_ENUM_LOCAL) {
4629 return enum_all_printers_info_2(buffer, offered, needed, returned);
4632 if (flags & PRINTER_ENUM_NAME) {
4633 if ((servername[0] == '\\') && (servername[1] == '\\'))
4634 s = servername + 2;
4635 if (is_myname_or_ipaddr(s))
4636 return enum_all_printers_info_2(buffer, offered, needed, returned);
4637 else
4638 return WERR_INVALID_NAME;
4641 if (flags & PRINTER_ENUM_REMOTE)
4642 return WERR_UNKNOWN_LEVEL;
4644 return WERR_OK;
4647 /********************************************************************
4648 * handle enumeration of printers at level 5
4649 ********************************************************************/
4651 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4652 NEW_BUFFER *buffer, uint32 offered,
4653 uint32 *needed, uint32 *returned)
4655 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4656 return WERR_OK;
4659 /********************************************************************
4660 * api_spoolss_enumprinters
4662 * called from api_spoolss_enumprinters (see this to understand)
4663 ********************************************************************/
4665 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4667 uint32 flags = q_u->flags;
4668 UNISTR2 *servername = &q_u->servername;
4669 uint32 level = q_u->level;
4670 NEW_BUFFER *buffer = NULL;
4671 uint32 offered = q_u->offered;
4672 uint32 *needed = &r_u->needed;
4673 uint32 *returned = &r_u->returned;
4675 fstring name;
4677 /* that's an [in out] buffer */
4678 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4679 buffer = r_u->buffer;
4681 DEBUG(4,("_spoolss_enumprinters\n"));
4683 *needed=0;
4684 *returned=0;
4687 * Level 1:
4688 * flags==PRINTER_ENUM_NAME
4689 * if name=="" then enumerates all printers
4690 * if name!="" then enumerate the printer
4691 * flags==PRINTER_ENUM_REMOTE
4692 * name is NULL, enumerate printers
4693 * Level 2: name!="" enumerates printers, name can't be NULL
4694 * Level 3: doesn't exist
4695 * Level 4: does a local registry lookup
4696 * Level 5: same as Level 2
4699 unistr2_to_ascii(name, servername, sizeof(name)-1);
4700 strupper_m(name);
4702 switch (level) {
4703 case 1:
4704 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4705 case 2:
4706 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4707 case 5:
4708 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4709 case 3:
4710 case 4:
4711 break;
4713 return WERR_UNKNOWN_LEVEL;
4716 /****************************************************************************
4717 ****************************************************************************/
4719 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4721 PRINTER_INFO_0 *printer=NULL;
4723 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4724 return WERR_NOMEM;
4726 construct_printer_info_0(print_hnd, printer, snum);
4728 /* check the required size. */
4729 *needed += spoolss_size_printer_info_0(printer);
4731 if (!alloc_buffer_size(buffer, *needed)) {
4732 SAFE_FREE(printer);
4733 return WERR_INSUFFICIENT_BUFFER;
4736 /* fill the buffer with the structures */
4737 smb_io_printer_info_0("", buffer, printer, 0);
4739 /* clear memory */
4740 SAFE_FREE(printer);
4742 if (*needed > offered) {
4743 return WERR_INSUFFICIENT_BUFFER;
4746 return WERR_OK;
4749 /****************************************************************************
4750 ****************************************************************************/
4752 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4754 PRINTER_INFO_1 *printer=NULL;
4756 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4757 return WERR_NOMEM;
4759 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4761 /* check the required size. */
4762 *needed += spoolss_size_printer_info_1(printer);
4764 if (!alloc_buffer_size(buffer, *needed)) {
4765 SAFE_FREE(printer);
4766 return WERR_INSUFFICIENT_BUFFER;
4769 /* fill the buffer with the structures */
4770 smb_io_printer_info_1("", buffer, printer, 0);
4772 /* clear memory */
4773 SAFE_FREE(printer);
4775 if (*needed > offered) {
4776 return WERR_INSUFFICIENT_BUFFER;
4779 return WERR_OK;
4782 /****************************************************************************
4783 ****************************************************************************/
4785 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4787 PRINTER_INFO_2 *printer=NULL;
4789 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4790 return WERR_NOMEM;
4792 construct_printer_info_2(print_hnd, printer, snum);
4794 /* check the required size. */
4795 *needed += spoolss_size_printer_info_2(printer);
4797 if (!alloc_buffer_size(buffer, *needed)) {
4798 free_printer_info_2(printer);
4799 return WERR_INSUFFICIENT_BUFFER;
4802 /* fill the buffer with the structures */
4803 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4804 free_printer_info_2(printer);
4805 return WERR_NOMEM;
4808 /* clear memory */
4809 free_printer_info_2(printer);
4811 if (*needed > offered) {
4812 return WERR_INSUFFICIENT_BUFFER;
4815 return WERR_OK;
4818 /****************************************************************************
4819 ****************************************************************************/
4821 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4823 PRINTER_INFO_3 *printer=NULL;
4825 if (!construct_printer_info_3(print_hnd, &printer, snum))
4826 return WERR_NOMEM;
4828 /* check the required size. */
4829 *needed += spoolss_size_printer_info_3(printer);
4831 if (!alloc_buffer_size(buffer, *needed)) {
4832 free_printer_info_3(printer);
4833 return WERR_INSUFFICIENT_BUFFER;
4836 /* fill the buffer with the structures */
4837 smb_io_printer_info_3("", buffer, printer, 0);
4839 /* clear memory */
4840 free_printer_info_3(printer);
4842 if (*needed > offered) {
4843 return WERR_INSUFFICIENT_BUFFER;
4846 return WERR_OK;
4849 /****************************************************************************
4850 ****************************************************************************/
4852 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4854 PRINTER_INFO_4 *printer=NULL;
4856 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4857 return WERR_NOMEM;
4859 if (!construct_printer_info_4(print_hnd, printer, snum))
4860 return WERR_NOMEM;
4862 /* check the required size. */
4863 *needed += spoolss_size_printer_info_4(printer);
4865 if (!alloc_buffer_size(buffer, *needed)) {
4866 free_printer_info_4(printer);
4867 return WERR_INSUFFICIENT_BUFFER;
4870 /* fill the buffer with the structures */
4871 smb_io_printer_info_4("", buffer, printer, 0);
4873 /* clear memory */
4874 free_printer_info_4(printer);
4876 if (*needed > offered) {
4877 return WERR_INSUFFICIENT_BUFFER;
4880 return WERR_OK;
4883 /****************************************************************************
4884 ****************************************************************************/
4886 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4888 PRINTER_INFO_5 *printer=NULL;
4890 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4891 return WERR_NOMEM;
4893 if (!construct_printer_info_5(print_hnd, printer, snum))
4894 return WERR_NOMEM;
4896 /* check the required size. */
4897 *needed += spoolss_size_printer_info_5(printer);
4899 if (!alloc_buffer_size(buffer, *needed)) {
4900 free_printer_info_5(printer);
4901 return WERR_INSUFFICIENT_BUFFER;
4904 /* fill the buffer with the structures */
4905 smb_io_printer_info_5("", buffer, printer, 0);
4907 /* clear memory */
4908 free_printer_info_5(printer);
4910 if (*needed > offered) {
4911 return WERR_INSUFFICIENT_BUFFER;
4914 return WERR_OK;
4917 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4919 PRINTER_INFO_7 *printer=NULL;
4921 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4922 return WERR_NOMEM;
4924 if (!construct_printer_info_7(print_hnd, printer, snum))
4925 return WERR_NOMEM;
4927 /* check the required size. */
4928 *needed += spoolss_size_printer_info_7(printer);
4930 if (!alloc_buffer_size(buffer, *needed)) {
4931 free_printer_info_7(printer);
4932 return WERR_INSUFFICIENT_BUFFER;
4935 /* fill the buffer with the structures */
4936 smb_io_printer_info_7("", buffer, printer, 0);
4938 /* clear memory */
4939 free_printer_info_7(printer);
4941 if (*needed > offered) {
4942 return WERR_INSUFFICIENT_BUFFER;
4945 return WERR_OK;
4948 /****************************************************************************
4949 ****************************************************************************/
4951 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4953 POLICY_HND *handle = &q_u->handle;
4954 uint32 level = q_u->level;
4955 NEW_BUFFER *buffer = NULL;
4956 uint32 offered = q_u->offered;
4957 uint32 *needed = &r_u->needed;
4958 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4960 int snum;
4962 /* that's an [in out] buffer */
4963 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4964 buffer = r_u->buffer;
4966 *needed=0;
4968 if (!get_printer_snum(p, handle, &snum))
4969 return WERR_BADFID;
4971 switch (level) {
4972 case 0:
4973 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4974 case 1:
4975 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4976 case 2:
4977 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4978 case 3:
4979 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4980 case 4:
4981 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4982 case 5:
4983 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4984 case 7:
4985 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4987 return WERR_UNKNOWN_LEVEL;
4990 /********************************************************************
4991 * fill a DRIVER_INFO_1 struct
4992 ********************************************************************/
4994 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4996 init_unistr( &info->name, driver.info_3->name);
4999 /********************************************************************
5000 * construct_printer_driver_info_1
5001 ********************************************************************/
5003 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5005 NT_PRINTER_INFO_LEVEL *printer = NULL;
5006 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5008 ZERO_STRUCT(driver);
5010 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5011 return WERR_INVALID_PRINTER_NAME;
5013 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5014 return WERR_UNKNOWN_PRINTER_DRIVER;
5016 fill_printer_driver_info_1(info, driver, servername, architecture);
5018 free_a_printer(&printer,2);
5020 return WERR_OK;
5023 /********************************************************************
5024 * construct_printer_driver_info_2
5025 * fill a printer_info_2 struct
5026 ********************************************************************/
5028 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5030 pstring temp;
5032 info->version=driver.info_3->cversion;
5034 init_unistr( &info->name, driver.info_3->name );
5035 init_unistr( &info->architecture, driver.info_3->environment );
5038 if (strlen(driver.info_3->driverpath)) {
5039 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5040 init_unistr( &info->driverpath, temp );
5041 } else
5042 init_unistr( &info->driverpath, "" );
5044 if (strlen(driver.info_3->datafile)) {
5045 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5046 init_unistr( &info->datafile, temp );
5047 } else
5048 init_unistr( &info->datafile, "" );
5050 if (strlen(driver.info_3->configfile)) {
5051 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5052 init_unistr( &info->configfile, temp );
5053 } else
5054 init_unistr( &info->configfile, "" );
5057 /********************************************************************
5058 * construct_printer_driver_info_2
5059 * fill a printer_info_2 struct
5060 ********************************************************************/
5062 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5064 NT_PRINTER_INFO_LEVEL *printer = NULL;
5065 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5067 ZERO_STRUCT(printer);
5068 ZERO_STRUCT(driver);
5070 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5071 return WERR_INVALID_PRINTER_NAME;
5073 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5074 return WERR_UNKNOWN_PRINTER_DRIVER;
5076 fill_printer_driver_info_2(info, driver, servername);
5078 free_a_printer(&printer,2);
5080 return WERR_OK;
5083 /********************************************************************
5084 * copy a strings array and convert to UNICODE
5086 * convert an array of ascii string to a UNICODE string
5087 ********************************************************************/
5089 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5091 int i=0;
5092 int j=0;
5093 const char *v;
5094 pstring line;
5095 uint16 *tuary;
5097 DEBUG(6,("init_unistr_array\n"));
5098 *uni_array=NULL;
5100 while (True)
5102 if ( !char_array )
5103 v = "";
5104 else
5106 v = char_array[i];
5107 if (!v)
5108 v = ""; /* hack to handle null lists */
5111 /* hack to allow this to be used in places other than when generating
5112 the list of dependent files */
5114 if ( servername )
5115 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5116 else
5117 pstrcpy( line, v );
5119 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5121 /* add one extra unit16 for the second terminating NULL */
5123 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5124 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5125 return 0;
5126 } else
5127 *uni_array = tuary;
5129 if ( !strlen(v) )
5130 break;
5132 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5133 i++;
5136 if (*uni_array) {
5137 /* special case for ""; we need to add both NULL's here */
5138 if (!j)
5139 (*uni_array)[j++]=0x0000;
5140 (*uni_array)[j]=0x0000;
5143 DEBUGADD(6,("last one:done\n"));
5145 /* return size of array in uint16's */
5147 return j+1;
5150 /********************************************************************
5151 * construct_printer_info_3
5152 * fill a printer_info_3 struct
5153 ********************************************************************/
5155 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5157 pstring temp;
5159 ZERO_STRUCTP(info);
5161 info->version=driver.info_3->cversion;
5163 init_unistr( &info->name, driver.info_3->name );
5164 init_unistr( &info->architecture, driver.info_3->environment );
5166 if (strlen(driver.info_3->driverpath)) {
5167 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5168 init_unistr( &info->driverpath, temp );
5169 } else
5170 init_unistr( &info->driverpath, "" );
5172 if (strlen(driver.info_3->datafile)) {
5173 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5174 init_unistr( &info->datafile, temp );
5175 } else
5176 init_unistr( &info->datafile, "" );
5178 if (strlen(driver.info_3->configfile)) {
5179 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5180 init_unistr( &info->configfile, temp );
5181 } else
5182 init_unistr( &info->configfile, "" );
5184 if (strlen(driver.info_3->helpfile)) {
5185 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5186 init_unistr( &info->helpfile, temp );
5187 } else
5188 init_unistr( &info->helpfile, "" );
5190 init_unistr( &info->monitorname, driver.info_3->monitorname );
5191 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5193 info->dependentfiles=NULL;
5194 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5197 /********************************************************************
5198 * construct_printer_info_3
5199 * fill a printer_info_3 struct
5200 ********************************************************************/
5202 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5204 NT_PRINTER_INFO_LEVEL *printer = NULL;
5205 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5206 WERROR status;
5207 ZERO_STRUCT(driver);
5209 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5210 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5211 if (!W_ERROR_IS_OK(status))
5212 return WERR_INVALID_PRINTER_NAME;
5214 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5215 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5217 #if 0 /* JERRY */
5220 * I put this code in during testing. Helpful when commenting out the
5221 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5222 * as win2k always queries the driver using an infor level of 6.
5223 * I've left it in (but ifdef'd out) because I'll probably
5224 * use it in experimentation again in the future. --jerry 22/01/2002
5227 if (!W_ERROR_IS_OK(status)) {
5229 * Is this a W2k client ?
5231 if (version == 3) {
5232 /* Yes - try again with a WinNT driver. */
5233 version = 2;
5234 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5235 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5237 #endif
5239 if (!W_ERROR_IS_OK(status)) {
5240 free_a_printer(&printer,2);
5241 return WERR_UNKNOWN_PRINTER_DRIVER;
5244 #if 0 /* JERRY */
5246 #endif
5249 fill_printer_driver_info_3(info, driver, servername);
5251 free_a_printer(&printer,2);
5253 return WERR_OK;
5256 /********************************************************************
5257 * construct_printer_info_6
5258 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5259 ********************************************************************/
5261 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5263 pstring temp;
5264 fstring nullstr;
5266 ZERO_STRUCTP(info);
5267 memset(&nullstr, '\0', sizeof(fstring));
5269 info->version=driver.info_3->cversion;
5271 init_unistr( &info->name, driver.info_3->name );
5272 init_unistr( &info->architecture, driver.info_3->environment );
5274 if (strlen(driver.info_3->driverpath)) {
5275 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5276 init_unistr( &info->driverpath, temp );
5277 } else
5278 init_unistr( &info->driverpath, "" );
5280 if (strlen(driver.info_3->datafile)) {
5281 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5282 init_unistr( &info->datafile, temp );
5283 } else
5284 init_unistr( &info->datafile, "" );
5286 if (strlen(driver.info_3->configfile)) {
5287 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5288 init_unistr( &info->configfile, temp );
5289 } else
5290 init_unistr( &info->configfile, "" );
5292 if (strlen(driver.info_3->helpfile)) {
5293 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5294 init_unistr( &info->helpfile, temp );
5295 } else
5296 init_unistr( &info->helpfile, "" );
5298 init_unistr( &info->monitorname, driver.info_3->monitorname );
5299 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5301 info->dependentfiles = NULL;
5302 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5304 info->previousdrivernames=NULL;
5305 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5307 info->driver_date.low=0;
5308 info->driver_date.high=0;
5310 info->padding=0;
5311 info->driver_version_low=0;
5312 info->driver_version_high=0;
5314 init_unistr( &info->mfgname, "");
5315 init_unistr( &info->oem_url, "");
5316 init_unistr( &info->hardware_id, "");
5317 init_unistr( &info->provider, "");
5320 /********************************************************************
5321 * construct_printer_info_6
5322 * fill a printer_info_6 struct
5323 ********************************************************************/
5325 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5326 fstring servername, fstring architecture, uint32 version)
5328 NT_PRINTER_INFO_LEVEL *printer = NULL;
5329 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5330 WERROR status;
5332 ZERO_STRUCT(driver);
5334 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5336 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5338 if (!W_ERROR_IS_OK(status))
5339 return WERR_INVALID_PRINTER_NAME;
5341 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5343 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5345 if (!W_ERROR_IS_OK(status))
5348 * Is this a W2k client ?
5351 if (version < 3) {
5352 free_a_printer(&printer,2);
5353 return WERR_UNKNOWN_PRINTER_DRIVER;
5356 /* Yes - try again with a WinNT driver. */
5357 version = 2;
5358 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5359 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5360 if (!W_ERROR_IS_OK(status)) {
5361 free_a_printer(&printer,2);
5362 return WERR_UNKNOWN_PRINTER_DRIVER;
5366 fill_printer_driver_info_6(info, driver, servername);
5368 free_a_printer(&printer,2);
5369 free_a_printer_driver(driver, 3);
5371 return WERR_OK;
5374 /****************************************************************************
5375 ****************************************************************************/
5377 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5379 SAFE_FREE(info->dependentfiles);
5382 /****************************************************************************
5383 ****************************************************************************/
5385 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5387 SAFE_FREE(info->dependentfiles);
5391 /****************************************************************************
5392 ****************************************************************************/
5394 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5396 DRIVER_INFO_1 *info=NULL;
5397 WERROR status;
5399 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5400 return WERR_NOMEM;
5402 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5403 if (!W_ERROR_IS_OK(status)) {
5404 SAFE_FREE(info);
5405 return status;
5408 /* check the required size. */
5409 *needed += spoolss_size_printer_driver_info_1(info);
5411 if (!alloc_buffer_size(buffer, *needed)) {
5412 SAFE_FREE(info);
5413 return WERR_INSUFFICIENT_BUFFER;
5416 /* fill the buffer with the structures */
5417 smb_io_printer_driver_info_1("", buffer, info, 0);
5419 /* clear memory */
5420 SAFE_FREE(info);
5422 if (*needed > offered)
5423 return WERR_INSUFFICIENT_BUFFER;
5425 return WERR_OK;
5428 /****************************************************************************
5429 ****************************************************************************/
5431 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5433 DRIVER_INFO_2 *info=NULL;
5434 WERROR status;
5436 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5437 return WERR_NOMEM;
5439 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5440 if (!W_ERROR_IS_OK(status)) {
5441 SAFE_FREE(info);
5442 return status;
5445 /* check the required size. */
5446 *needed += spoolss_size_printer_driver_info_2(info);
5448 if (!alloc_buffer_size(buffer, *needed)) {
5449 SAFE_FREE(info);
5450 return WERR_INSUFFICIENT_BUFFER;
5453 /* fill the buffer with the structures */
5454 smb_io_printer_driver_info_2("", buffer, info, 0);
5456 /* clear memory */
5457 SAFE_FREE(info);
5459 if (*needed > offered)
5460 return WERR_INSUFFICIENT_BUFFER;
5462 return WERR_OK;
5465 /****************************************************************************
5466 ****************************************************************************/
5468 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5470 DRIVER_INFO_3 info;
5471 WERROR status;
5473 ZERO_STRUCT(info);
5475 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5476 if (!W_ERROR_IS_OK(status)) {
5477 return status;
5480 /* check the required size. */
5481 *needed += spoolss_size_printer_driver_info_3(&info);
5483 if (!alloc_buffer_size(buffer, *needed)) {
5484 free_printer_driver_info_3(&info);
5485 return WERR_INSUFFICIENT_BUFFER;
5488 /* fill the buffer with the structures */
5489 smb_io_printer_driver_info_3("", buffer, &info, 0);
5491 free_printer_driver_info_3(&info);
5493 if (*needed > offered)
5494 return WERR_INSUFFICIENT_BUFFER;
5496 return WERR_OK;
5499 /****************************************************************************
5500 ****************************************************************************/
5502 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5504 DRIVER_INFO_6 info;
5505 WERROR status;
5507 ZERO_STRUCT(info);
5509 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5510 if (!W_ERROR_IS_OK(status)) {
5511 return status;
5514 /* check the required size. */
5515 *needed += spoolss_size_printer_driver_info_6(&info);
5517 if (!alloc_buffer_size(buffer, *needed)) {
5518 free_printer_driver_info_6(&info);
5519 return WERR_INSUFFICIENT_BUFFER;
5522 /* fill the buffer with the structures */
5523 smb_io_printer_driver_info_6("", buffer, &info, 0);
5525 free_printer_driver_info_6(&info);
5527 if (*needed > offered)
5528 return WERR_INSUFFICIENT_BUFFER;
5530 return WERR_OK;
5533 /****************************************************************************
5534 ****************************************************************************/
5536 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5538 POLICY_HND *handle = &q_u->handle;
5539 UNISTR2 *uni_arch = &q_u->architecture;
5540 uint32 level = q_u->level;
5541 uint32 clientmajorversion = q_u->clientmajorversion;
5542 NEW_BUFFER *buffer = NULL;
5543 uint32 offered = q_u->offered;
5544 uint32 *needed = &r_u->needed;
5545 uint32 *servermajorversion = &r_u->servermajorversion;
5546 uint32 *serverminorversion = &r_u->serverminorversion;
5548 fstring servername;
5549 fstring architecture;
5550 int snum;
5552 /* that's an [in out] buffer */
5553 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5554 buffer = r_u->buffer;
5556 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5558 *needed = 0;
5559 *servermajorversion = 0;
5560 *serverminorversion = 0;
5562 fstrcpy(servername, get_called_name());
5563 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5565 if (!get_printer_snum(p, handle, &snum))
5566 return WERR_BADFID;
5568 switch (level) {
5569 case 1:
5570 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5571 case 2:
5572 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5573 case 3:
5574 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5575 case 6:
5576 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5577 #if 0 /* JERRY */
5578 case 101:
5579 /* apparently this call is the equivalent of
5580 EnumPrinterDataEx() for the DsDriver key */
5581 break;
5582 #endif
5585 return WERR_UNKNOWN_LEVEL;
5588 /****************************************************************************
5589 ****************************************************************************/
5591 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5593 POLICY_HND *handle = &q_u->handle;
5595 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5597 if (!Printer) {
5598 DEBUG(3,("Error in startpageprinter printer handle\n"));
5599 return WERR_BADFID;
5602 Printer->page_started=True;
5603 return WERR_OK;
5606 /****************************************************************************
5607 ****************************************************************************/
5609 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5611 POLICY_HND *handle = &q_u->handle;
5612 int snum;
5614 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5616 if (!Printer) {
5617 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5618 return WERR_BADFID;
5621 if (!get_printer_snum(p, handle, &snum))
5622 return WERR_BADFID;
5624 Printer->page_started=False;
5625 print_job_endpage(snum, Printer->jobid);
5627 return WERR_OK;
5630 /********************************************************************
5631 * api_spoolss_getprinter
5632 * called from the spoolss dispatcher
5634 ********************************************************************/
5636 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5638 POLICY_HND *handle = &q_u->handle;
5639 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5640 uint32 *jobid = &r_u->jobid;
5642 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5643 int snum;
5644 pstring jobname;
5645 fstring datatype;
5646 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5647 struct current_user user;
5649 if (!Printer) {
5650 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5651 return WERR_BADFID;
5654 get_current_user(&user, p);
5657 * a nice thing with NT is it doesn't listen to what you tell it.
5658 * when asked to send _only_ RAW datas, it tries to send datas
5659 * in EMF format.
5661 * So I add checks like in NT Server ...
5664 if (info_1->p_datatype != 0) {
5665 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5666 if (strcmp(datatype, "RAW") != 0) {
5667 (*jobid)=0;
5668 return WERR_INVALID_DATATYPE;
5672 /* get the share number of the printer */
5673 if (!get_printer_snum(p, handle, &snum)) {
5674 return WERR_BADFID;
5677 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5679 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5681 /* An error occured in print_job_start() so return an appropriate
5682 NT error code. */
5684 if (Printer->jobid == -1) {
5685 return map_werror_from_unix(errno);
5688 Printer->document_started=True;
5689 (*jobid) = Printer->jobid;
5691 return WERR_OK;
5694 /********************************************************************
5695 * api_spoolss_getprinter
5696 * called from the spoolss dispatcher
5698 ********************************************************************/
5700 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5702 POLICY_HND *handle = &q_u->handle;
5704 return _spoolss_enddocprinter_internal(p, handle);
5707 /****************************************************************************
5708 ****************************************************************************/
5710 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5712 POLICY_HND *handle = &q_u->handle;
5713 uint32 buffer_size = q_u->buffer_size;
5714 uint8 *buffer = q_u->buffer;
5715 uint32 *buffer_written = &q_u->buffer_size2;
5716 int snum;
5717 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5719 if (!Printer) {
5720 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5721 r_u->buffer_written = q_u->buffer_size2;
5722 return WERR_BADFID;
5725 if (!get_printer_snum(p, handle, &snum))
5726 return WERR_BADFID;
5728 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5729 if (*buffer_written == -1) {
5730 r_u->buffer_written = 0;
5731 if (errno == ENOSPC)
5732 return WERR_NO_SPOOL_SPACE;
5733 else
5734 return WERR_ACCESS_DENIED;
5737 r_u->buffer_written = q_u->buffer_size2;
5739 return WERR_OK;
5742 /********************************************************************
5743 * api_spoolss_getprinter
5744 * called from the spoolss dispatcher
5746 ********************************************************************/
5748 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5749 pipes_struct *p)
5751 struct current_user user;
5752 int snum;
5753 WERROR errcode = WERR_BADFUNC;
5754 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5756 get_current_user(&user, p);
5758 if (!Printer) {
5759 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5760 return WERR_BADFID;
5763 if (!get_printer_snum(p, handle, &snum))
5764 return WERR_BADFID;
5766 switch (command) {
5767 case PRINTER_CONTROL_PAUSE:
5768 if (print_queue_pause(&user, snum, &errcode)) {
5769 errcode = WERR_OK;
5771 break;
5772 case PRINTER_CONTROL_RESUME:
5773 case PRINTER_CONTROL_UNPAUSE:
5774 if (print_queue_resume(&user, snum, &errcode)) {
5775 errcode = WERR_OK;
5777 break;
5778 case PRINTER_CONTROL_PURGE:
5779 if (print_queue_purge(&user, snum, &errcode)) {
5780 errcode = WERR_OK;
5782 break;
5783 default:
5784 return WERR_UNKNOWN_LEVEL;
5787 return errcode;
5790 /********************************************************************
5791 * api_spoolss_abortprinter
5792 * From MSDN: "Deletes printer's spool file if printer is configured
5793 * for spooling"
5794 ********************************************************************/
5796 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5798 POLICY_HND *handle = &q_u->handle;
5799 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5800 int snum;
5801 struct current_user user;
5802 WERROR errcode = WERR_OK;
5804 if (!Printer) {
5805 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5806 return WERR_BADFID;
5809 if (!get_printer_snum(p, handle, &snum))
5810 return WERR_BADFID;
5812 get_current_user( &user, p );
5814 print_job_delete( &user, snum, Printer->jobid, &errcode );
5816 return errcode;
5819 /********************************************************************
5820 * called by spoolss_api_setprinter
5821 * when updating a printer description
5822 ********************************************************************/
5824 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5825 const SPOOL_PRINTER_INFO_LEVEL *info,
5826 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5828 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5829 struct current_user user;
5830 WERROR result;
5831 int snum;
5833 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5835 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5836 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5837 OUR_HANDLE(handle)));
5839 result = WERR_BADFID;
5840 goto done;
5843 /* NT seems to like setting the security descriptor even though
5844 nothing may have actually changed. This causes annoying
5845 dialog boxes when the user doesn't have permission to change
5846 the security descriptor. */
5848 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5850 if (DEBUGLEVEL >= 10) {
5851 SEC_ACL *the_acl;
5852 int i;
5854 the_acl = old_secdesc_ctr->sec->dacl;
5855 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5856 PRINTERNAME(snum), the_acl->num_aces));
5858 for (i = 0; i < the_acl->num_aces; i++) {
5859 fstring sid_str;
5861 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5863 DEBUG(10, ("%s 0x%08x\n", sid_str,
5864 the_acl->ace[i].info.mask));
5867 the_acl = secdesc_ctr->sec->dacl;
5869 if (the_acl) {
5870 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5871 PRINTERNAME(snum), the_acl->num_aces));
5873 for (i = 0; i < the_acl->num_aces; i++) {
5874 fstring sid_str;
5876 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5878 DEBUG(10, ("%s 0x%08x\n", sid_str,
5879 the_acl->ace[i].info.mask));
5881 } else {
5882 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5886 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5888 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5889 result = WERR_OK;
5890 goto done;
5893 /* Work out which user is performing the operation */
5895 get_current_user(&user, p);
5897 /* Check the user has permissions to change the security
5898 descriptor. By experimentation with two NT machines, the user
5899 requires Full Access to the printer to change security
5900 information. */
5902 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5903 result = WERR_ACCESS_DENIED;
5904 goto done;
5907 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5909 done:
5911 return result;
5914 /********************************************************************
5915 Do Samba sanity checks on a printer info struct.
5916 this has changed purpose: it now "canonicalises" printer
5917 info from a client rather than just checking it is correct
5918 ********************************************************************/
5920 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5922 fstring printername;
5923 const char *p;
5925 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5926 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5928 /* we force some elements to "correct" values */
5929 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5930 fstrcpy(info->sharename, lp_servicename(snum));
5932 /* make sure printername is in \\server\printername format */
5934 fstrcpy( printername, info->printername );
5935 p = printername;
5936 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5937 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5938 p++;
5941 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5942 get_called_name(), p );
5944 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5945 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5949 return True;
5952 /****************************************************************************
5953 ****************************************************************************/
5955 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5957 extern userdom_struct current_user_info;
5958 char *cmd = lp_addprinter_cmd();
5959 char **qlines;
5960 pstring command;
5961 int numlines;
5962 int ret;
5963 int fd;
5964 fstring remote_machine = "%m";
5966 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5968 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5969 cmd, printer->info_2->printername, printer->info_2->sharename,
5970 printer->info_2->portname, printer->info_2->drivername,
5971 printer->info_2->location, printer->info_2->comment, remote_machine);
5973 DEBUG(10,("Running [%s]\n", command));
5974 ret = smbrun(command, &fd);
5975 DEBUGADD(10,("returned [%d]\n", ret));
5977 if ( ret != 0 ) {
5978 if (fd != -1)
5979 close(fd);
5980 return False;
5983 numlines = 0;
5984 /* Get lines and convert them back to dos-codepage */
5985 qlines = fd_lines_load(fd, &numlines);
5986 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5987 close(fd);
5989 if(numlines) {
5990 /* Set the portname to what the script says the portname should be. */
5991 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5992 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5994 /* Send SIGHUP to process group... is there a better way? */
5995 kill(0, SIGHUP);
5997 /* reload our services immediately */
5998 reload_services( False );
6001 file_lines_free(qlines);
6002 return True;
6005 /********************************************************************
6006 * Called by spoolss_api_setprinter
6007 * when updating a printer description.
6008 ********************************************************************/
6010 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6011 const SPOOL_PRINTER_INFO_LEVEL *info,
6012 DEVICEMODE *devmode)
6014 int snum;
6015 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6016 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6017 WERROR result;
6018 UNISTR2 buffer;
6019 fstring asc_buffer;
6021 DEBUG(8,("update_printer\n"));
6023 result = WERR_OK;
6025 if (!Printer) {
6026 result = WERR_BADFID;
6027 goto done;
6030 if (!get_printer_snum(p, handle, &snum)) {
6031 result = WERR_BADFID;
6032 goto done;
6035 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6036 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6037 result = WERR_BADFID;
6038 goto done;
6041 DEBUGADD(8,("Converting info_2 struct\n"));
6044 * convert_printer_info converts the incoming
6045 * info from the client and overwrites the info
6046 * just read from the tdb in the pointer 'printer'.
6049 if (!convert_printer_info(info, printer, level)) {
6050 result = WERR_NOMEM;
6051 goto done;
6054 if (devmode) {
6055 /* we have a valid devmode
6056 convert it and link it*/
6058 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6059 if (!convert_devicemode(printer->info_2->printername, devmode,
6060 &printer->info_2->devmode)) {
6061 result = WERR_NOMEM;
6062 goto done;
6066 /* Do sanity check on the requested changes for Samba */
6068 if (!check_printer_ok(printer->info_2, snum)) {
6069 result = WERR_INVALID_PARAM;
6070 goto done;
6073 /* FIXME!!! If the driver has changed we really should verify that
6074 it is installed before doing much else --jerry */
6076 /* Check calling user has permission to update printer description */
6078 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6079 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6080 result = WERR_ACCESS_DENIED;
6081 goto done;
6084 /* Call addprinter hook */
6085 /* Check changes to see if this is really needed */
6087 if ( *lp_addprinter_cmd()
6088 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6089 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6090 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6091 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6093 if ( !add_printer_hook(printer) ) {
6094 result = WERR_ACCESS_DENIED;
6095 goto done;
6099 * make sure we actually reload the services after
6100 * this as smb.conf could have a new section in it
6101 * .... shouldn't .... but could
6103 reload_services(False);
6107 * When a *new* driver is bound to a printer, the drivername is used to
6108 * lookup previously saved driver initialization info, which is then
6109 * bound to the printer, simulating what happens in the Windows arch.
6111 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6113 if (!set_driver_init(printer, 2))
6115 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6116 printer->info_2->drivername));
6119 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6120 printer->info_2->drivername));
6122 notify_printer_driver(snum, printer->info_2->drivername);
6126 * flag which changes actually occured. This is a small subset of
6127 * all the possible changes. We also have to update things in the
6128 * DsSpooler key.
6131 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6132 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6133 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6134 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6136 notify_printer_comment(snum, printer->info_2->comment);
6139 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6140 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6141 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6142 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6144 notify_printer_sharename(snum, printer->info_2->sharename);
6147 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6148 char *pname;
6150 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6151 pname++;
6152 else
6153 pname = printer->info_2->printername;
6156 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6157 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6158 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6160 notify_printer_printername( snum, pname );
6163 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6164 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6165 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6166 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6168 notify_printer_port(snum, printer->info_2->portname);
6171 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6172 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6173 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6174 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6176 notify_printer_location(snum, printer->info_2->location);
6179 /* here we need to update some more DsSpooler keys */
6180 /* uNCName, serverName, shortServerName */
6182 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6183 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6184 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6185 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6186 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6188 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6189 global_myname(), printer->info_2->sharename );
6190 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6191 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6192 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6194 /* Update printer info */
6195 result = mod_a_printer(*printer, 2);
6197 done:
6198 free_a_printer(&printer, 2);
6199 free_a_printer(&old_printer, 2);
6202 return result;
6205 /****************************************************************************
6206 ****************************************************************************/
6207 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6208 const SPOOL_PRINTER_INFO_LEVEL *info)
6210 #ifdef HAVE_ADS
6211 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6212 int snum;
6213 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6215 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6217 if (!Printer)
6218 return WERR_BADFID;
6220 if (!get_printer_snum(p, handle, &snum))
6221 return WERR_BADFID;
6223 nt_printer_publish(Printer, snum, info7->action);
6225 return WERR_OK;
6226 #else
6227 return WERR_UNKNOWN_LEVEL;
6228 #endif
6230 /****************************************************************************
6231 ****************************************************************************/
6233 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6235 POLICY_HND *handle = &q_u->handle;
6236 uint32 level = q_u->level;
6237 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6238 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6239 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6240 uint32 command = q_u->command;
6242 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6244 if (!Printer) {
6245 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6246 return WERR_BADFID;
6249 /* check the level */
6250 switch (level) {
6251 case 0:
6252 return control_printer(handle, command, p);
6253 case 2:
6254 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6255 case 3:
6256 return update_printer_sec(handle, level, info, p,
6257 secdesc_ctr);
6258 case 7:
6259 return publish_or_unpublish_printer(p, handle, info);
6260 default:
6261 return WERR_UNKNOWN_LEVEL;
6265 /****************************************************************************
6266 ****************************************************************************/
6268 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6270 POLICY_HND *handle = &q_u->handle;
6271 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6273 if (!Printer) {
6274 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6275 return WERR_BADFID;
6278 if (Printer->notify.client_connected==True) {
6279 int snum = -1;
6281 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6282 snum = -1;
6283 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6284 !get_printer_snum(p, handle, &snum) )
6285 return WERR_BADFID;
6287 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6290 Printer->notify.flags=0;
6291 Printer->notify.options=0;
6292 Printer->notify.localmachine[0]='\0';
6293 Printer->notify.printerlocal=0;
6294 if (Printer->notify.option)
6295 free_spool_notify_option(&Printer->notify.option);
6296 Printer->notify.client_connected=False;
6298 return WERR_OK;
6301 /****************************************************************************
6302 ****************************************************************************/
6304 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6306 /* that's an [in out] buffer (despite appearences to the contrary) */
6307 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6309 r_u->needed = 0;
6310 return WERR_INVALID_PARAM; /* this is what a NT server
6311 returns for AddJob. AddJob
6312 must fail on non-local
6313 printers */
6316 /****************************************************************************
6317 ****************************************************************************/
6319 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6320 int position, int snum)
6322 pstring temp_name;
6324 struct tm *t;
6326 t=gmtime(&queue->time);
6327 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6329 job_info->jobid=queue->job;
6330 init_unistr(&job_info->printername, lp_servicename(snum));
6331 init_unistr(&job_info->machinename, temp_name);
6332 init_unistr(&job_info->username, queue->fs_user);
6333 init_unistr(&job_info->document, queue->fs_file);
6334 init_unistr(&job_info->datatype, "RAW");
6335 init_unistr(&job_info->text_status, "");
6336 job_info->status=nt_printj_status(queue->status);
6337 job_info->priority=queue->priority;
6338 job_info->position=position;
6339 job_info->totalpages=queue->page_count;
6340 job_info->pagesprinted=0;
6342 make_systemtime(&job_info->submitted, t);
6345 /****************************************************************************
6346 ****************************************************************************/
6348 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6349 int position, int snum,
6350 NT_PRINTER_INFO_LEVEL *ntprinter,
6351 DEVICEMODE *devmode)
6353 pstring temp_name;
6354 struct tm *t;
6356 t=gmtime(&queue->time);
6357 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6359 job_info->jobid=queue->job;
6361 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6363 init_unistr(&job_info->machinename, temp_name);
6364 init_unistr(&job_info->username, queue->fs_user);
6365 init_unistr(&job_info->document, queue->fs_file);
6366 init_unistr(&job_info->notifyname, queue->fs_user);
6367 init_unistr(&job_info->datatype, "RAW");
6368 init_unistr(&job_info->printprocessor, "winprint");
6369 init_unistr(&job_info->parameters, "");
6370 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6371 init_unistr(&job_info->text_status, "");
6373 /* and here the security descriptor */
6375 job_info->status=nt_printj_status(queue->status);
6376 job_info->priority=queue->priority;
6377 job_info->position=position;
6378 job_info->starttime=0;
6379 job_info->untiltime=0;
6380 job_info->totalpages=queue->page_count;
6381 job_info->size=queue->size;
6382 make_systemtime(&(job_info->submitted), t);
6383 job_info->timeelapsed=0;
6384 job_info->pagesprinted=0;
6386 job_info->devmode = devmode;
6388 return (True);
6391 /****************************************************************************
6392 Enumjobs at level 1.
6393 ****************************************************************************/
6395 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6396 NEW_BUFFER *buffer, uint32 offered,
6397 uint32 *needed, uint32 *returned)
6399 JOB_INFO_1 *info;
6400 int i;
6402 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6403 if (info==NULL) {
6404 SAFE_FREE(queue);
6405 *returned=0;
6406 return WERR_NOMEM;
6409 for (i=0; i<*returned; i++)
6410 fill_job_info_1(&info[i], &queue[i], i, snum);
6412 SAFE_FREE(queue);
6414 /* check the required size. */
6415 for (i=0; i<*returned; i++)
6416 (*needed) += spoolss_size_job_info_1(&info[i]);
6418 if (!alloc_buffer_size(buffer, *needed)) {
6419 SAFE_FREE(info);
6420 return WERR_INSUFFICIENT_BUFFER;
6423 /* fill the buffer with the structures */
6424 for (i=0; i<*returned; i++)
6425 smb_io_job_info_1("", buffer, &info[i], 0);
6427 /* clear memory */
6428 SAFE_FREE(info);
6430 if (*needed > offered) {
6431 *returned=0;
6432 return WERR_INSUFFICIENT_BUFFER;
6435 return WERR_OK;
6438 /****************************************************************************
6439 Enumjobs at level 2.
6440 ****************************************************************************/
6442 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6443 NEW_BUFFER *buffer, uint32 offered,
6444 uint32 *needed, uint32 *returned)
6446 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6447 JOB_INFO_2 *info = NULL;
6448 int i;
6449 WERROR result;
6450 DEVICEMODE *devmode = NULL;
6452 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6453 if (info==NULL) {
6454 *returned=0;
6455 result = WERR_NOMEM;
6456 goto done;
6459 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6460 if (!W_ERROR_IS_OK(result)) {
6461 *returned = 0;
6462 goto done;
6465 /* this should not be a failure condition if the devmode is NULL */
6467 devmode = construct_dev_mode(snum);
6469 for (i=0; i<*returned; i++)
6470 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6471 devmode);
6473 free_a_printer(&ntprinter, 2);
6474 SAFE_FREE(queue);
6476 /* check the required size. */
6477 for (i=0; i<*returned; i++)
6478 (*needed) += spoolss_size_job_info_2(&info[i]);
6480 if (*needed > offered) {
6481 *returned=0;
6482 result = WERR_INSUFFICIENT_BUFFER;
6483 goto done;
6486 if (!alloc_buffer_size(buffer, *needed)) {
6487 SAFE_FREE(info);
6488 result = WERR_INSUFFICIENT_BUFFER;
6489 goto done;
6492 /* fill the buffer with the structures */
6493 for (i=0; i<*returned; i++)
6494 smb_io_job_info_2("", buffer, &info[i], 0);
6496 result = WERR_OK;
6498 done:
6499 free_a_printer(&ntprinter, 2);
6500 free_devmode(devmode);
6501 SAFE_FREE(queue);
6502 SAFE_FREE(info);
6504 return result;
6508 /****************************************************************************
6509 Enumjobs.
6510 ****************************************************************************/
6512 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6514 POLICY_HND *handle = &q_u->handle;
6515 uint32 level = q_u->level;
6516 NEW_BUFFER *buffer = NULL;
6517 uint32 offered = q_u->offered;
6518 uint32 *needed = &r_u->needed;
6519 uint32 *returned = &r_u->returned;
6520 WERROR wret;
6522 int snum;
6523 print_status_struct prt_status;
6524 print_queue_struct *queue=NULL;
6526 /* that's an [in out] buffer */
6527 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6528 buffer = r_u->buffer;
6530 DEBUG(4,("_spoolss_enumjobs\n"));
6532 *needed=0;
6533 *returned=0;
6535 if (!get_printer_snum(p, handle, &snum))
6536 return WERR_BADFID;
6538 *returned = print_queue_status(snum, &queue, &prt_status);
6539 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6541 if (*returned == 0) {
6542 SAFE_FREE(queue);
6543 return WERR_OK;
6546 switch (level) {
6547 case 1:
6548 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6549 return wret;
6550 case 2:
6551 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6552 return wret;
6553 default:
6554 SAFE_FREE(queue);
6555 *returned=0;
6556 return WERR_UNKNOWN_LEVEL;
6560 /****************************************************************************
6561 ****************************************************************************/
6563 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6565 return WERR_OK;
6568 /****************************************************************************
6569 ****************************************************************************/
6571 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6573 POLICY_HND *handle = &q_u->handle;
6574 uint32 jobid = q_u->jobid;
6575 uint32 command = q_u->command;
6577 struct current_user user;
6578 int snum;
6579 WERROR errcode = WERR_BADFUNC;
6581 if (!get_printer_snum(p, handle, &snum)) {
6582 return WERR_BADFID;
6585 if (!print_job_exists(snum, jobid)) {
6586 return WERR_INVALID_PRINTER_NAME;
6589 get_current_user(&user, p);
6591 switch (command) {
6592 case JOB_CONTROL_CANCEL:
6593 case JOB_CONTROL_DELETE:
6594 if (print_job_delete(&user, snum, jobid, &errcode)) {
6595 errcode = WERR_OK;
6597 break;
6598 case JOB_CONTROL_PAUSE:
6599 if (print_job_pause(&user, snum, jobid, &errcode)) {
6600 errcode = WERR_OK;
6602 break;
6603 case JOB_CONTROL_RESTART:
6604 case JOB_CONTROL_RESUME:
6605 if (print_job_resume(&user, snum, jobid, &errcode)) {
6606 errcode = WERR_OK;
6608 break;
6609 default:
6610 return WERR_UNKNOWN_LEVEL;
6613 return errcode;
6616 /****************************************************************************
6617 Enumerates all printer drivers at level 1.
6618 ****************************************************************************/
6620 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6622 int i;
6623 int ndrivers;
6624 uint32 version;
6625 fstring *list = NULL;
6627 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6628 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6630 *returned=0;
6632 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6633 list=NULL;
6634 ndrivers=get_ntdrivers(&list, architecture, version);
6635 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6637 if(ndrivers == -1)
6638 return WERR_NOMEM;
6640 if(ndrivers != 0) {
6641 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6642 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6643 SAFE_FREE(driver_info_1);
6644 SAFE_FREE(list);
6645 return WERR_NOMEM;
6647 else driver_info_1 = tdi1;
6650 for (i=0; i<ndrivers; i++) {
6651 WERROR status;
6652 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6653 ZERO_STRUCT(driver);
6654 status = get_a_printer_driver(&driver, 3, list[i],
6655 architecture, version);
6656 if (!W_ERROR_IS_OK(status)) {
6657 SAFE_FREE(list);
6658 return status;
6660 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6661 free_a_printer_driver(driver, 3);
6664 *returned+=ndrivers;
6665 SAFE_FREE(list);
6668 /* check the required size. */
6669 for (i=0; i<*returned; i++) {
6670 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6671 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6674 if (!alloc_buffer_size(buffer, *needed)) {
6675 SAFE_FREE(driver_info_1);
6676 return WERR_INSUFFICIENT_BUFFER;
6679 /* fill the buffer with the driver structures */
6680 for (i=0; i<*returned; i++) {
6681 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6682 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6685 SAFE_FREE(driver_info_1);
6687 if (*needed > offered) {
6688 *returned=0;
6689 return WERR_INSUFFICIENT_BUFFER;
6692 return WERR_OK;
6695 /****************************************************************************
6696 Enumerates all printer drivers at level 2.
6697 ****************************************************************************/
6699 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6701 int i;
6702 int ndrivers;
6703 uint32 version;
6704 fstring *list = NULL;
6706 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6707 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6709 *returned=0;
6711 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6712 list=NULL;
6713 ndrivers=get_ntdrivers(&list, architecture, version);
6714 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6716 if(ndrivers == -1)
6717 return WERR_NOMEM;
6719 if(ndrivers != 0) {
6720 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6721 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6722 SAFE_FREE(driver_info_2);
6723 SAFE_FREE(list);
6724 return WERR_NOMEM;
6726 else driver_info_2 = tdi2;
6729 for (i=0; i<ndrivers; i++) {
6730 WERROR status;
6732 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6733 ZERO_STRUCT(driver);
6734 status = get_a_printer_driver(&driver, 3, list[i],
6735 architecture, version);
6736 if (!W_ERROR_IS_OK(status)) {
6737 SAFE_FREE(list);
6738 return status;
6740 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6741 free_a_printer_driver(driver, 3);
6744 *returned+=ndrivers;
6745 SAFE_FREE(list);
6748 /* check the required size. */
6749 for (i=0; i<*returned; i++) {
6750 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6751 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6754 if (!alloc_buffer_size(buffer, *needed)) {
6755 SAFE_FREE(driver_info_2);
6756 return WERR_INSUFFICIENT_BUFFER;
6759 /* fill the buffer with the form structures */
6760 for (i=0; i<*returned; i++) {
6761 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6762 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6765 SAFE_FREE(driver_info_2);
6767 if (*needed > offered) {
6768 *returned=0;
6769 return WERR_INSUFFICIENT_BUFFER;
6772 return WERR_OK;
6775 /****************************************************************************
6776 Enumerates all printer drivers at level 3.
6777 ****************************************************************************/
6779 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6781 int i;
6782 int ndrivers;
6783 uint32 version;
6784 fstring *list = NULL;
6786 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6787 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6789 *returned=0;
6791 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6792 list=NULL;
6793 ndrivers=get_ntdrivers(&list, architecture, version);
6794 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6796 if(ndrivers == -1)
6797 return WERR_NOMEM;
6799 if(ndrivers != 0) {
6800 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6801 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6802 SAFE_FREE(driver_info_3);
6803 SAFE_FREE(list);
6804 return WERR_NOMEM;
6806 else driver_info_3 = tdi3;
6809 for (i=0; i<ndrivers; i++) {
6810 WERROR status;
6812 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6813 ZERO_STRUCT(driver);
6814 status = get_a_printer_driver(&driver, 3, list[i],
6815 architecture, version);
6816 if (!W_ERROR_IS_OK(status)) {
6817 SAFE_FREE(list);
6818 return status;
6820 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6821 free_a_printer_driver(driver, 3);
6824 *returned+=ndrivers;
6825 SAFE_FREE(list);
6828 /* check the required size. */
6829 for (i=0; i<*returned; i++) {
6830 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6831 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6834 if (!alloc_buffer_size(buffer, *needed)) {
6835 SAFE_FREE(driver_info_3);
6836 return WERR_INSUFFICIENT_BUFFER;
6839 /* fill the buffer with the driver structures */
6840 for (i=0; i<*returned; i++) {
6841 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6842 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6845 for (i=0; i<*returned; i++)
6846 SAFE_FREE(driver_info_3[i].dependentfiles);
6848 SAFE_FREE(driver_info_3);
6850 if (*needed > offered) {
6851 *returned=0;
6852 return WERR_INSUFFICIENT_BUFFER;
6855 return WERR_OK;
6858 /****************************************************************************
6859 Enumerates all printer drivers.
6860 ****************************************************************************/
6862 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6864 UNISTR2 *environment = &q_u->environment;
6865 uint32 level = q_u->level;
6866 NEW_BUFFER *buffer = NULL;
6867 uint32 offered = q_u->offered;
6868 uint32 *needed = &r_u->needed;
6869 uint32 *returned = &r_u->returned;
6871 fstring *list = NULL;
6872 fstring servername;
6873 fstring architecture;
6875 /* that's an [in out] buffer */
6876 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6877 buffer = r_u->buffer;
6879 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6880 fstrcpy(servername, get_called_name());
6881 *needed=0;
6882 *returned=0;
6884 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6886 switch (level) {
6887 case 1:
6888 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6889 case 2:
6890 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6891 case 3:
6892 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6893 default:
6894 *returned=0;
6895 SAFE_FREE(list);
6896 return WERR_UNKNOWN_LEVEL;
6900 /****************************************************************************
6901 ****************************************************************************/
6903 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6905 form->flag=list->flag;
6906 init_unistr(&form->name, list->name);
6907 form->width=list->width;
6908 form->length=list->length;
6909 form->left=list->left;
6910 form->top=list->top;
6911 form->right=list->right;
6912 form->bottom=list->bottom;
6915 /****************************************************************************
6916 ****************************************************************************/
6918 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6920 uint32 level = q_u->level;
6921 NEW_BUFFER *buffer = NULL;
6922 uint32 offered = q_u->offered;
6923 uint32 *needed = &r_u->needed;
6924 uint32 *numofforms = &r_u->numofforms;
6925 uint32 numbuiltinforms;
6927 nt_forms_struct *list=NULL;
6928 nt_forms_struct *builtinlist=NULL;
6929 FORM_1 *forms_1;
6930 int buffer_size=0;
6931 int i;
6933 /* that's an [in out] buffer */
6934 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6935 buffer = r_u->buffer;
6937 DEBUG(4,("_spoolss_enumforms\n"));
6938 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6939 DEBUGADD(5,("Info level [%d]\n", level));
6941 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6942 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6943 *numofforms = get_ntforms(&list);
6944 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6945 *numofforms += numbuiltinforms;
6947 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6949 switch (level) {
6950 case 1:
6951 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6952 *numofforms=0;
6953 return WERR_NOMEM;
6956 /* construct the list of form structures */
6957 for (i=0; i<numbuiltinforms; i++) {
6958 DEBUGADD(6,("Filling form number [%d]\n",i));
6959 fill_form_1(&forms_1[i], &builtinlist[i]);
6962 SAFE_FREE(builtinlist);
6964 for (; i<*numofforms; i++) {
6965 DEBUGADD(6,("Filling form number [%d]\n",i));
6966 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6969 SAFE_FREE(list);
6971 /* check the required size. */
6972 for (i=0; i<numbuiltinforms; i++) {
6973 DEBUGADD(6,("adding form [%d]'s size\n",i));
6974 buffer_size += spoolss_size_form_1(&forms_1[i]);
6976 for (; i<*numofforms; i++) {
6977 DEBUGADD(6,("adding form [%d]'s size\n",i));
6978 buffer_size += spoolss_size_form_1(&forms_1[i]);
6981 *needed=buffer_size;
6983 if (!alloc_buffer_size(buffer, buffer_size)){
6984 SAFE_FREE(forms_1);
6985 return WERR_INSUFFICIENT_BUFFER;
6988 /* fill the buffer with the form structures */
6989 for (i=0; i<numbuiltinforms; i++) {
6990 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6991 smb_io_form_1("", buffer, &forms_1[i], 0);
6993 for (; i<*numofforms; i++) {
6994 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6995 smb_io_form_1("", buffer, &forms_1[i], 0);
6998 SAFE_FREE(forms_1);
7000 if (*needed > offered) {
7001 *numofforms=0;
7002 return WERR_INSUFFICIENT_BUFFER;
7004 else
7005 return WERR_OK;
7007 default:
7008 SAFE_FREE(list);
7009 SAFE_FREE(builtinlist);
7010 return WERR_UNKNOWN_LEVEL;
7015 /****************************************************************************
7016 ****************************************************************************/
7018 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7020 uint32 level = q_u->level;
7021 UNISTR2 *uni_formname = &q_u->formname;
7022 NEW_BUFFER *buffer = NULL;
7023 uint32 offered = q_u->offered;
7024 uint32 *needed = &r_u->needed;
7026 nt_forms_struct *list=NULL;
7027 nt_forms_struct builtin_form;
7028 BOOL foundBuiltin;
7029 FORM_1 form_1;
7030 fstring form_name;
7031 int buffer_size=0;
7032 int numofforms=0, i=0;
7034 /* that's an [in out] buffer */
7035 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7036 buffer = r_u->buffer;
7038 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7040 DEBUG(4,("_spoolss_getform\n"));
7041 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7042 DEBUGADD(5,("Info level [%d]\n", level));
7044 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7045 if (!foundBuiltin) {
7046 numofforms = get_ntforms(&list);
7047 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7049 if (numofforms == 0)
7050 return WERR_BADFID;
7053 switch (level) {
7054 case 1:
7055 if (foundBuiltin) {
7056 fill_form_1(&form_1, &builtin_form);
7057 } else {
7059 /* Check if the requested name is in the list of form structures */
7060 for (i=0; i<numofforms; i++) {
7062 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7064 if (strequal(form_name, list[i].name)) {
7065 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7066 fill_form_1(&form_1, &list[i]);
7067 break;
7071 SAFE_FREE(list);
7072 if (i == numofforms) {
7073 return WERR_BADFID;
7076 /* check the required size. */
7078 *needed=spoolss_size_form_1(&form_1);
7080 if (!alloc_buffer_size(buffer, buffer_size)){
7081 return WERR_INSUFFICIENT_BUFFER;
7084 if (*needed > offered) {
7085 return WERR_INSUFFICIENT_BUFFER;
7088 /* fill the buffer with the form structures */
7089 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7090 smb_io_form_1("", buffer, &form_1, 0);
7092 return WERR_OK;
7094 default:
7095 SAFE_FREE(list);
7096 return WERR_UNKNOWN_LEVEL;
7100 /****************************************************************************
7101 ****************************************************************************/
7103 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7105 init_unistr(&port->port_name, name);
7108 /****************************************************************************
7109 ****************************************************************************/
7111 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7113 init_unistr(&port->port_name, name);
7114 init_unistr(&port->monitor_name, "Local Monitor");
7115 init_unistr(&port->description, "Local Port");
7116 port->port_type=PORT_TYPE_WRITE;
7117 port->reserved=0x0;
7120 /****************************************************************************
7121 enumports level 1.
7122 ****************************************************************************/
7124 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7126 PORT_INFO_1 *ports=NULL;
7127 int i=0;
7129 if (*lp_enumports_cmd()) {
7130 char *cmd = lp_enumports_cmd();
7131 char **qlines;
7132 pstring command;
7133 int numlines;
7134 int ret;
7135 int fd;
7137 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7139 DEBUG(10,("Running [%s]\n", command));
7140 ret = smbrun(command, &fd);
7141 DEBUG(10,("Returned [%d]\n", ret));
7142 if (ret != 0) {
7143 if (fd != -1)
7144 close(fd);
7145 /* Is this the best error to return here? */
7146 return WERR_ACCESS_DENIED;
7149 numlines = 0;
7150 qlines = fd_lines_load(fd, &numlines);
7151 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7152 close(fd);
7154 if(numlines) {
7155 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7156 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7157 dos_errstr(WERR_NOMEM)));
7158 file_lines_free(qlines);
7159 return WERR_NOMEM;
7162 for (i=0; i<numlines; i++) {
7163 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7164 fill_port_1(&ports[i], qlines[i]);
7167 file_lines_free(qlines);
7170 *returned = numlines;
7172 } else {
7173 *returned = 1; /* Sole Samba port returned. */
7175 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7176 return WERR_NOMEM;
7178 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7180 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7183 /* check the required size. */
7184 for (i=0; i<*returned; i++) {
7185 DEBUGADD(6,("adding port [%d]'s size\n", i));
7186 *needed += spoolss_size_port_info_1(&ports[i]);
7189 if (!alloc_buffer_size(buffer, *needed)) {
7190 SAFE_FREE(ports);
7191 return WERR_INSUFFICIENT_BUFFER;
7194 /* fill the buffer with the ports structures */
7195 for (i=0; i<*returned; i++) {
7196 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7197 smb_io_port_1("", buffer, &ports[i], 0);
7200 SAFE_FREE(ports);
7202 if (*needed > offered) {
7203 *returned=0;
7204 return WERR_INSUFFICIENT_BUFFER;
7207 return WERR_OK;
7210 /****************************************************************************
7211 enumports level 2.
7212 ****************************************************************************/
7214 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7216 PORT_INFO_2 *ports=NULL;
7217 int i=0;
7219 if (*lp_enumports_cmd()) {
7220 char *cmd = lp_enumports_cmd();
7221 char *path;
7222 char **qlines;
7223 pstring tmp_file;
7224 pstring command;
7225 int numlines;
7226 int ret;
7227 int fd;
7229 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7230 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7231 else
7232 path = lp_lockdir();
7234 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7235 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7237 unlink(tmp_file);
7238 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7239 ret = smbrun(command, &fd);
7240 DEBUGADD(10,("returned [%d]\n", ret));
7241 if (ret != 0) {
7242 if (fd != -1)
7243 close(fd);
7244 /* Is this the best error to return here? */
7245 return WERR_ACCESS_DENIED;
7248 numlines = 0;
7249 qlines = fd_lines_load(fd, &numlines);
7250 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7251 close(fd);
7253 if(numlines) {
7254 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7255 file_lines_free(qlines);
7256 return WERR_NOMEM;
7259 for (i=0; i<numlines; i++) {
7260 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7261 fill_port_2(&(ports[i]), qlines[i]);
7264 file_lines_free(qlines);
7267 *returned = numlines;
7269 } else {
7271 *returned = 1;
7273 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7274 return WERR_NOMEM;
7276 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7278 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7281 /* check the required size. */
7282 for (i=0; i<*returned; i++) {
7283 DEBUGADD(6,("adding port [%d]'s size\n", i));
7284 *needed += spoolss_size_port_info_2(&ports[i]);
7287 if (!alloc_buffer_size(buffer, *needed)) {
7288 SAFE_FREE(ports);
7289 return WERR_INSUFFICIENT_BUFFER;
7292 /* fill the buffer with the ports structures */
7293 for (i=0; i<*returned; i++) {
7294 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7295 smb_io_port_2("", buffer, &ports[i], 0);
7298 SAFE_FREE(ports);
7300 if (*needed > offered) {
7301 *returned=0;
7302 return WERR_INSUFFICIENT_BUFFER;
7305 return WERR_OK;
7308 /****************************************************************************
7309 enumports.
7310 ****************************************************************************/
7312 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7314 uint32 level = q_u->level;
7315 NEW_BUFFER *buffer = NULL;
7316 uint32 offered = q_u->offered;
7317 uint32 *needed = &r_u->needed;
7318 uint32 *returned = &r_u->returned;
7320 /* that's an [in out] buffer */
7321 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7322 buffer = r_u->buffer;
7324 DEBUG(4,("_spoolss_enumports\n"));
7326 *returned=0;
7327 *needed=0;
7329 switch (level) {
7330 case 1:
7331 return enumports_level_1(buffer, offered, needed, returned);
7332 case 2:
7333 return enumports_level_2(buffer, offered, needed, returned);
7334 default:
7335 return WERR_UNKNOWN_LEVEL;
7339 /****************************************************************************
7340 ****************************************************************************/
7342 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7343 const SPOOL_PRINTER_INFO_LEVEL *info,
7344 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7345 uint32 user_switch, const SPOOL_USER_CTR *user,
7346 POLICY_HND *handle)
7348 NT_PRINTER_INFO_LEVEL *printer = NULL;
7349 fstring name;
7350 int snum;
7351 WERROR err = WERR_OK;
7353 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7354 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7355 return WERR_NOMEM;
7358 ZERO_STRUCTP(printer);
7360 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7361 if (!convert_printer_info(info, printer, 2)) {
7362 free_a_printer(&printer, 2);
7363 return WERR_NOMEM;
7366 /* check to see if the printer already exists */
7368 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7369 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7370 printer->info_2->sharename));
7371 free_a_printer(&printer, 2);
7372 return WERR_PRINTER_ALREADY_EXISTS;
7375 /* FIXME!!! smbd should check to see if the driver is installed before
7376 trying to add a printer like this --jerry */
7378 if (*lp_addprinter_cmd() ) {
7379 if ( !add_printer_hook(printer) ) {
7380 free_a_printer(&printer,2);
7381 return WERR_ACCESS_DENIED;
7385 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7386 printer->info_2->sharename);
7389 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7390 free_a_printer(&printer,2);
7391 return WERR_ACCESS_DENIED;
7394 /* you must be a printer admin to add a new printer */
7395 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7396 free_a_printer(&printer,2);
7397 return WERR_ACCESS_DENIED;
7401 * Do sanity check on the requested changes for Samba.
7404 if (!check_printer_ok(printer->info_2, snum)) {
7405 free_a_printer(&printer,2);
7406 return WERR_INVALID_PARAM;
7410 * When a printer is created, the drivername bound to the printer is used
7411 * to lookup previously saved driver initialization info, which is then
7412 * bound to the new printer, simulating what happens in the Windows arch.
7415 if (!devmode)
7417 set_driver_init(printer, 2);
7419 else
7421 /* A valid devmode was included, convert and link it
7423 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7425 if (!convert_devicemode(printer->info_2->printername, devmode,
7426 &printer->info_2->devmode))
7427 return WERR_NOMEM;
7430 /* write the ASCII on disk */
7431 err = mod_a_printer(*printer, 2);
7432 if (!W_ERROR_IS_OK(err)) {
7433 free_a_printer(&printer,2);
7434 return err;
7437 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7438 /* Handle open failed - remove addition. */
7439 del_a_printer(printer->info_2->sharename);
7440 free_a_printer(&printer,2);
7441 return WERR_ACCESS_DENIED;
7444 update_c_setprinter(False);
7445 free_a_printer(&printer,2);
7447 return WERR_OK;
7450 /****************************************************************************
7451 ****************************************************************************/
7453 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7455 UNISTR2 *uni_srv_name = &q_u->server_name;
7456 uint32 level = q_u->level;
7457 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7458 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7459 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7460 uint32 user_switch = q_u->user_switch;
7461 SPOOL_USER_CTR *user = &q_u->user_ctr;
7462 POLICY_HND *handle = &r_u->handle;
7464 switch (level) {
7465 case 1:
7466 /* we don't handle yet */
7467 /* but I know what to do ... */
7468 return WERR_UNKNOWN_LEVEL;
7469 case 2:
7470 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7471 devmode, sdb,
7472 user_switch, user, handle);
7473 default:
7474 return WERR_UNKNOWN_LEVEL;
7478 /****************************************************************************
7479 ****************************************************************************/
7481 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7483 uint32 level = q_u->level;
7484 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7485 WERROR err = WERR_OK;
7486 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7487 struct current_user user;
7488 fstring driver_name;
7489 uint32 version;
7491 ZERO_STRUCT(driver);
7493 get_current_user(&user, p);
7495 if (!convert_printer_driver_info(info, &driver, level)) {
7496 err = WERR_NOMEM;
7497 goto done;
7500 DEBUG(5,("Cleaning driver's information\n"));
7501 err = clean_up_driver_struct(driver, level, &user);
7502 if (!W_ERROR_IS_OK(err))
7503 goto done;
7505 DEBUG(5,("Moving driver to final destination\n"));
7506 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7507 if (W_ERROR_IS_OK(err))
7508 err = WERR_ACCESS_DENIED;
7509 goto done;
7512 if (add_a_printer_driver(driver, level)!=0) {
7513 err = WERR_ACCESS_DENIED;
7514 goto done;
7517 /* BEGIN_ADMIN_LOG */
7518 switch(level) {
7519 case 3:
7520 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7521 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7522 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7523 break;
7524 case 6:
7525 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7526 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7527 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7528 break;
7530 /* END_ADMIN_LOG */
7533 * I think this is where he DrvUpgradePrinter() hook would be
7534 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7535 * server. Right now, we just need to send ourselves a message
7536 * to update each printer bound to this driver. --jerry
7539 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7540 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7541 driver_name));
7545 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7546 * decide if the driver init data should be deleted. The rules are:
7547 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7548 * 2) delete init data only if there is no 2k/Xp driver
7549 * 3) always delete init data
7550 * The generalized rule is always use init data from the highest order driver.
7551 * It is necessary to follow the driver install by an initialization step to
7552 * finish off this process.
7554 if (level == 3)
7555 version = driver.info_3->cversion;
7556 else if (level == 6)
7557 version = driver.info_6->version;
7558 else
7559 version = -1;
7560 switch (version) {
7562 * 9x printer driver - never delete init data
7564 case 0:
7565 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7566 driver_name));
7567 break;
7570 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7571 * there is no 2k/Xp driver init data for this driver name.
7573 case 2:
7575 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7577 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7579 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7581 if (!del_driver_init(driver_name))
7582 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7583 } else {
7585 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7587 free_a_printer_driver(driver1,3);
7588 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7589 driver_name));
7592 break;
7595 * 2k or Xp printer driver - always delete init data
7597 case 3:
7598 if (!del_driver_init(driver_name))
7599 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7600 break;
7602 default:
7603 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7604 break;
7608 done:
7609 free_a_printer_driver(driver, level);
7610 return err;
7613 /********************************************************************
7614 * spoolss_addprinterdriverex
7615 ********************************************************************/
7617 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7619 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7620 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7623 * we only support the semantics of AddPrinterDriver()
7624 * i.e. only copy files that are newer than existing ones
7627 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7628 return WERR_ACCESS_DENIED;
7630 ZERO_STRUCT(q_u_local);
7631 ZERO_STRUCT(r_u_local);
7633 /* just pass the information off to _spoolss_addprinterdriver() */
7634 q_u_local.server_name_ptr = q_u->server_name_ptr;
7635 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7636 q_u_local.level = q_u->level;
7637 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7639 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7642 /****************************************************************************
7643 ****************************************************************************/
7645 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7647 init_unistr(&info->name, name);
7650 /****************************************************************************
7651 ****************************************************************************/
7653 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7655 pstring path;
7656 pstring long_archi;
7657 const char *short_archi;
7658 DRIVER_DIRECTORY_1 *info=NULL;
7660 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7662 if (!(short_archi = get_short_archi(long_archi)))
7663 return WERR_INVALID_ENVIRONMENT;
7665 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7666 return WERR_NOMEM;
7668 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7670 DEBUG(4,("printer driver directory: [%s]\n", path));
7672 fill_driverdir_1(info, path);
7674 *needed += spoolss_size_driverdir_info_1(info);
7676 if (!alloc_buffer_size(buffer, *needed)) {
7677 SAFE_FREE(info);
7678 return WERR_INSUFFICIENT_BUFFER;
7681 smb_io_driverdir_1("", buffer, info, 0);
7683 SAFE_FREE(info);
7685 if (*needed > offered)
7686 return WERR_INSUFFICIENT_BUFFER;
7688 return WERR_OK;
7691 /****************************************************************************
7692 ****************************************************************************/
7694 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7696 UNISTR2 *name = &q_u->name;
7697 UNISTR2 *uni_environment = &q_u->environment;
7698 uint32 level = q_u->level;
7699 NEW_BUFFER *buffer = NULL;
7700 uint32 offered = q_u->offered;
7701 uint32 *needed = &r_u->needed;
7703 /* that's an [in out] buffer */
7704 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7705 buffer = r_u->buffer;
7707 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7709 *needed=0;
7711 switch(level) {
7712 case 1:
7713 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7714 default:
7715 return WERR_UNKNOWN_LEVEL;
7719 /****************************************************************************
7720 ****************************************************************************/
7722 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7724 POLICY_HND *handle = &q_u->handle;
7725 uint32 idx = q_u->index;
7726 uint32 in_value_len = q_u->valuesize;
7727 uint32 in_data_len = q_u->datasize;
7728 uint32 *out_max_value_len = &r_u->valuesize;
7729 uint16 **out_value = &r_u->value;
7730 uint32 *out_value_len = &r_u->realvaluesize;
7731 uint32 *out_type = &r_u->type;
7732 uint32 *out_max_data_len = &r_u->datasize;
7733 uint8 **data_out = &r_u->data;
7734 uint32 *out_data_len = &r_u->realdatasize;
7736 NT_PRINTER_INFO_LEVEL *printer = NULL;
7738 uint32 biggest_valuesize;
7739 uint32 biggest_datasize;
7740 uint32 data_len;
7741 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7742 int snum;
7743 WERROR result;
7744 REGISTRY_VALUE *val = NULL;
7745 NT_PRINTER_DATA *p_data;
7746 int i, key_index, num_values;
7747 int name_length;
7749 ZERO_STRUCT( printer );
7751 *out_type = 0;
7753 *out_max_data_len = 0;
7754 *data_out = NULL;
7755 *out_data_len = 0;
7757 DEBUG(5,("spoolss_enumprinterdata\n"));
7759 if (!Printer) {
7760 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7761 return WERR_BADFID;
7764 if (!get_printer_snum(p,handle, &snum))
7765 return WERR_BADFID;
7767 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7768 if (!W_ERROR_IS_OK(result))
7769 return result;
7771 p_data = &printer->info_2->data;
7772 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7774 result = WERR_OK;
7777 * The NT machine wants to know the biggest size of value and data
7779 * cf: MSDN EnumPrinterData remark section
7782 if ( !in_value_len && !in_data_len && (key_index != -1) )
7784 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7786 biggest_valuesize = 0;
7787 biggest_datasize = 0;
7789 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7791 for ( i=0; i<num_values; i++ )
7793 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7795 name_length = strlen(val->valuename);
7796 if ( strlen(val->valuename) > biggest_valuesize )
7797 biggest_valuesize = name_length;
7799 if ( val->size > biggest_datasize )
7800 biggest_datasize = val->size;
7802 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7803 biggest_datasize));
7806 /* the value is an UNICODE string but real_value_size is the length
7807 in bytes including the trailing 0 */
7809 *out_value_len = 2 * (1+biggest_valuesize);
7810 *out_data_len = biggest_datasize;
7812 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7814 goto done;
7818 * the value len is wrong in NT sp3
7819 * that's the number of bytes not the number of unicode chars
7822 if ( key_index != -1 )
7823 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7825 if ( !val )
7828 /* out_value should default to "" or else NT4 has
7829 problems unmarshalling the response */
7831 *out_max_value_len=(in_value_len/sizeof(uint16));
7833 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7835 result = WERR_NOMEM;
7836 goto done;
7839 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7841 /* the data is counted in bytes */
7843 *out_max_data_len = in_data_len;
7844 *out_data_len = in_data_len;
7846 /* only allocate when given a non-zero data_len */
7848 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7850 result = WERR_NOMEM;
7851 goto done;
7854 result = WERR_NO_MORE_ITEMS;
7856 else
7859 * the value is:
7860 * - counted in bytes in the request
7861 * - counted in UNICODE chars in the max reply
7862 * - counted in bytes in the real size
7864 * take a pause *before* coding not *during* coding
7867 /* name */
7868 *out_max_value_len=(in_value_len/sizeof(uint16));
7869 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7871 result = WERR_NOMEM;
7872 goto done;
7875 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7877 /* type */
7879 *out_type = regval_type( val );
7881 /* data - counted in bytes */
7883 *out_max_data_len = in_data_len;
7884 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7886 result = WERR_NOMEM;
7887 goto done;
7889 data_len = (size_t)regval_size(val);
7890 memcpy( *data_out, regval_data_p(val), data_len );
7891 *out_data_len = data_len;
7894 done:
7895 free_a_printer(&printer, 2);
7896 return result;
7899 /****************************************************************************
7900 ****************************************************************************/
7902 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7904 POLICY_HND *handle = &q_u->handle;
7905 UNISTR2 *value = &q_u->value;
7906 uint32 type = q_u->type;
7907 uint8 *data = q_u->data;
7908 uint32 real_len = q_u->real_len;
7910 NT_PRINTER_INFO_LEVEL *printer = NULL;
7911 int snum=0;
7912 WERROR status = WERR_OK;
7913 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7914 fstring valuename;
7916 DEBUG(5,("spoolss_setprinterdata\n"));
7918 if (!Printer) {
7919 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7920 return WERR_BADFID;
7923 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7924 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7925 return WERR_INVALID_PARAM;
7928 if (!get_printer_snum(p,handle, &snum))
7929 return WERR_BADFID;
7932 * Access check : NT returns "access denied" if you make a
7933 * SetPrinterData call without the necessary privildge.
7934 * we were originally returning OK if nothing changed
7935 * which made Win2k issue **a lot** of SetPrinterData
7936 * when connecting to a printer --jerry
7939 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7941 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7942 status = WERR_ACCESS_DENIED;
7943 goto done;
7946 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7947 if (!W_ERROR_IS_OK(status))
7948 return status;
7950 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7953 * When client side code sets a magic printer data key, detect it and save
7954 * the current printer data and the magic key's data (its the DEVMODE) for
7955 * future printer/driver initializations.
7957 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7959 /* Set devmode and printer initialization info */
7960 status = save_driver_init( printer, 2, data, real_len );
7962 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7964 else
7966 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7967 type, data, real_len );
7968 if ( W_ERROR_IS_OK(status) )
7969 status = mod_a_printer(*printer, 2);
7972 done:
7973 free_a_printer(&printer, 2);
7975 return status;
7978 /****************************************************************************
7979 ****************************************************************************/
7981 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7983 POLICY_HND *handle = &q_u->handle;
7984 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7985 int snum;
7987 DEBUG(5,("_spoolss_resetprinter\n"));
7990 * All we do is to check to see if the handle and queue is valid.
7991 * This call really doesn't mean anything to us because we only
7992 * support RAW printing. --jerry
7995 if (!Printer) {
7996 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7997 return WERR_BADFID;
8000 if (!get_printer_snum(p,handle, &snum))
8001 return WERR_BADFID;
8004 /* blindly return success */
8005 return WERR_OK;
8009 /****************************************************************************
8010 ****************************************************************************/
8012 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8014 POLICY_HND *handle = &q_u->handle;
8015 UNISTR2 *value = &q_u->valuename;
8017 NT_PRINTER_INFO_LEVEL *printer = NULL;
8018 int snum=0;
8019 WERROR status = WERR_OK;
8020 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8021 pstring valuename;
8023 DEBUG(5,("spoolss_deleteprinterdata\n"));
8025 if (!Printer) {
8026 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8027 return WERR_BADFID;
8030 if (!get_printer_snum(p, handle, &snum))
8031 return WERR_BADFID;
8033 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8034 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8035 return WERR_ACCESS_DENIED;
8038 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8039 if (!W_ERROR_IS_OK(status))
8040 return status;
8042 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8044 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8046 if ( W_ERROR_IS_OK(status) )
8047 mod_a_printer( *printer, 2 );
8049 free_a_printer(&printer, 2);
8051 return status;
8054 /****************************************************************************
8055 ****************************************************************************/
8057 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8059 POLICY_HND *handle = &q_u->handle;
8060 FORM *form = &q_u->form;
8061 nt_forms_struct tmpForm;
8062 int snum;
8063 WERROR status = WERR_OK;
8064 NT_PRINTER_INFO_LEVEL *printer = NULL;
8066 int count=0;
8067 nt_forms_struct *list=NULL;
8068 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8070 DEBUG(5,("spoolss_addform\n"));
8072 if (!Printer) {
8073 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8074 return WERR_BADFID;
8078 /* forms can be added on printer of on the print server handle */
8080 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8082 if (!get_printer_snum(p,handle, &snum))
8083 return WERR_BADFID;
8085 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8086 if (!W_ERROR_IS_OK(status))
8087 goto done;
8090 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8091 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8092 status = WERR_ACCESS_DENIED;
8093 goto done;
8096 /* can't add if builtin */
8098 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8099 status = WERR_ALREADY_EXISTS;
8100 goto done;
8103 count = get_ntforms(&list);
8105 if(!add_a_form(&list, form, &count)) {
8106 status = WERR_NOMEM;
8107 goto done;
8110 write_ntforms(&list, count);
8113 * ChangeID must always be set if this is a printer
8116 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8117 status = mod_a_printer(*printer, 2);
8119 done:
8120 if ( printer )
8121 free_a_printer(&printer, 2);
8122 SAFE_FREE(list);
8124 return status;
8127 /****************************************************************************
8128 ****************************************************************************/
8130 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8132 POLICY_HND *handle = &q_u->handle;
8133 UNISTR2 *form_name = &q_u->name;
8134 nt_forms_struct tmpForm;
8135 int count=0;
8136 nt_forms_struct *list=NULL;
8137 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8138 int snum;
8139 WERROR status = WERR_OK;
8140 NT_PRINTER_INFO_LEVEL *printer = NULL;
8142 DEBUG(5,("spoolss_deleteform\n"));
8144 if (!Printer) {
8145 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8146 return WERR_BADFID;
8149 /* forms can be deleted on printer of on the print server handle */
8151 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8153 if (!get_printer_snum(p,handle, &snum))
8154 return WERR_BADFID;
8156 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8157 if (!W_ERROR_IS_OK(status))
8158 goto done;
8161 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8162 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8163 status = WERR_ACCESS_DENIED;
8164 goto done;
8167 /* can't delete if builtin */
8169 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8170 status = WERR_INVALID_PARAM;
8171 goto done;
8174 count = get_ntforms(&list);
8176 if ( !delete_a_form(&list, form_name, &count, &status ))
8177 goto done;
8180 * ChangeID must always be set if this is a printer
8183 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8184 status = mod_a_printer(*printer, 2);
8186 done:
8187 if ( printer )
8188 free_a_printer(&printer, 2);
8189 SAFE_FREE(list);
8191 return status;
8194 /****************************************************************************
8195 ****************************************************************************/
8197 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8199 POLICY_HND *handle = &q_u->handle;
8200 FORM *form = &q_u->form;
8201 nt_forms_struct tmpForm;
8202 int snum;
8203 WERROR status = WERR_OK;
8204 NT_PRINTER_INFO_LEVEL *printer = NULL;
8206 int count=0;
8207 nt_forms_struct *list=NULL;
8208 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8210 DEBUG(5,("spoolss_setform\n"));
8212 if (!Printer) {
8213 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8214 return WERR_BADFID;
8217 /* forms can be modified on printer of on the print server handle */
8219 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8221 if (!get_printer_snum(p,handle, &snum))
8222 return WERR_BADFID;
8224 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8225 if (!W_ERROR_IS_OK(status))
8226 goto done;
8229 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8230 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8231 status = WERR_ACCESS_DENIED;
8232 goto done;
8235 /* can't set if builtin */
8236 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8237 status = WERR_INVALID_PARAM;
8238 goto done;
8241 count = get_ntforms(&list);
8242 update_a_form(&list, form, count);
8243 write_ntforms(&list, count);
8246 * ChangeID must always be set if this is a printer
8249 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8250 status = mod_a_printer(*printer, 2);
8253 done:
8254 if ( printer )
8255 free_a_printer(&printer, 2);
8256 SAFE_FREE(list);
8258 return status;
8261 /****************************************************************************
8262 enumprintprocessors level 1.
8263 ****************************************************************************/
8265 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8267 PRINTPROCESSOR_1 *info_1=NULL;
8269 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8270 return WERR_NOMEM;
8272 (*returned) = 0x1;
8274 init_unistr(&info_1->name, "winprint");
8276 *needed += spoolss_size_printprocessor_info_1(info_1);
8278 if (!alloc_buffer_size(buffer, *needed))
8279 return WERR_INSUFFICIENT_BUFFER;
8281 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8283 SAFE_FREE(info_1);
8285 if (*needed > offered) {
8286 *returned=0;
8287 return WERR_INSUFFICIENT_BUFFER;
8290 return WERR_OK;
8293 /****************************************************************************
8294 ****************************************************************************/
8296 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8298 uint32 level = q_u->level;
8299 NEW_BUFFER *buffer = NULL;
8300 uint32 offered = q_u->offered;
8301 uint32 *needed = &r_u->needed;
8302 uint32 *returned = &r_u->returned;
8304 /* that's an [in out] buffer */
8305 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8306 buffer = r_u->buffer;
8308 DEBUG(5,("spoolss_enumprintprocessors\n"));
8311 * Enumerate the print processors ...
8313 * Just reply with "winprint", to keep NT happy
8314 * and I can use my nice printer checker.
8317 *returned=0;
8318 *needed=0;
8320 switch (level) {
8321 case 1:
8322 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8323 default:
8324 return WERR_UNKNOWN_LEVEL;
8328 /****************************************************************************
8329 enumprintprocdatatypes level 1.
8330 ****************************************************************************/
8332 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8334 PRINTPROCDATATYPE_1 *info_1=NULL;
8336 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8337 return WERR_NOMEM;
8339 (*returned) = 0x1;
8341 init_unistr(&info_1->name, "RAW");
8343 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8345 if (!alloc_buffer_size(buffer, *needed))
8346 return WERR_INSUFFICIENT_BUFFER;
8348 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8350 SAFE_FREE(info_1);
8352 if (*needed > offered) {
8353 *returned=0;
8354 return WERR_INSUFFICIENT_BUFFER;
8357 return WERR_OK;
8360 /****************************************************************************
8361 ****************************************************************************/
8363 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8365 uint32 level = q_u->level;
8366 NEW_BUFFER *buffer = NULL;
8367 uint32 offered = q_u->offered;
8368 uint32 *needed = &r_u->needed;
8369 uint32 *returned = &r_u->returned;
8371 /* that's an [in out] buffer */
8372 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8373 buffer = r_u->buffer;
8375 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8377 *returned=0;
8378 *needed=0;
8380 switch (level) {
8381 case 1:
8382 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8383 default:
8384 return WERR_UNKNOWN_LEVEL;
8388 /****************************************************************************
8389 enumprintmonitors level 1.
8390 ****************************************************************************/
8392 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8394 PRINTMONITOR_1 *info_1=NULL;
8396 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8397 return WERR_NOMEM;
8399 (*returned) = 0x1;
8401 init_unistr(&info_1->name, "Local Port");
8403 *needed += spoolss_size_printmonitor_info_1(info_1);
8405 if (!alloc_buffer_size(buffer, *needed))
8406 return WERR_INSUFFICIENT_BUFFER;
8408 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8410 SAFE_FREE(info_1);
8412 if (*needed > offered) {
8413 *returned=0;
8414 return WERR_INSUFFICIENT_BUFFER;
8417 return WERR_OK;
8420 /****************************************************************************
8421 enumprintmonitors level 2.
8422 ****************************************************************************/
8424 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8426 PRINTMONITOR_2 *info_2=NULL;
8428 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8429 return WERR_NOMEM;
8431 (*returned) = 0x1;
8433 init_unistr(&info_2->name, "Local Port");
8434 init_unistr(&info_2->environment, "Windows NT X86");
8435 init_unistr(&info_2->dll_name, "localmon.dll");
8437 *needed += spoolss_size_printmonitor_info_2(info_2);
8439 if (!alloc_buffer_size(buffer, *needed))
8440 return WERR_INSUFFICIENT_BUFFER;
8442 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8444 SAFE_FREE(info_2);
8446 if (*needed > offered) {
8447 *returned=0;
8448 return WERR_INSUFFICIENT_BUFFER;
8451 return WERR_OK;
8454 /****************************************************************************
8455 ****************************************************************************/
8457 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8459 uint32 level = q_u->level;
8460 NEW_BUFFER *buffer = NULL;
8461 uint32 offered = q_u->offered;
8462 uint32 *needed = &r_u->needed;
8463 uint32 *returned = &r_u->returned;
8465 /* that's an [in out] buffer */
8466 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8467 buffer = r_u->buffer;
8469 DEBUG(5,("spoolss_enumprintmonitors\n"));
8472 * Enumerate the print monitors ...
8474 * Just reply with "Local Port", to keep NT happy
8475 * and I can use my nice printer checker.
8478 *returned=0;
8479 *needed=0;
8481 switch (level) {
8482 case 1:
8483 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8484 case 2:
8485 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8486 default:
8487 return WERR_UNKNOWN_LEVEL;
8491 /****************************************************************************
8492 ****************************************************************************/
8494 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8496 int i=0;
8497 BOOL found=False;
8498 JOB_INFO_1 *info_1=NULL;
8500 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8502 if (info_1 == NULL) {
8503 return WERR_NOMEM;
8506 for (i=0; i<count && found==False; i++) {
8507 if ((*queue)[i].job==(int)jobid)
8508 found=True;
8511 if (found==False) {
8512 SAFE_FREE(info_1);
8513 /* NT treats not found as bad param... yet another bad choice */
8514 return WERR_INVALID_PARAM;
8517 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8519 *needed += spoolss_size_job_info_1(info_1);
8521 if (!alloc_buffer_size(buffer, *needed)) {
8522 SAFE_FREE(info_1);
8523 return WERR_INSUFFICIENT_BUFFER;
8526 smb_io_job_info_1("", buffer, info_1, 0);
8528 SAFE_FREE(info_1);
8530 if (*needed > offered)
8531 return WERR_INSUFFICIENT_BUFFER;
8533 return WERR_OK;
8536 /****************************************************************************
8537 ****************************************************************************/
8539 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8541 int i = 0;
8542 BOOL found = False;
8543 JOB_INFO_2 *info_2;
8544 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8545 WERROR ret;
8546 DEVICEMODE *devmode = NULL;
8547 NT_DEVICEMODE *nt_devmode = NULL;
8549 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8551 ZERO_STRUCTP(info_2);
8553 if (info_2 == NULL) {
8554 ret = WERR_NOMEM;
8555 goto done;
8558 for ( i=0; i<count && found==False; i++ )
8560 if ((*queue)[i].job == (int)jobid)
8561 found = True;
8564 if ( !found )
8566 /* NT treats not found as bad param... yet another bad
8567 choice */
8568 ret = WERR_INVALID_PARAM;
8569 goto done;
8572 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8573 if (!W_ERROR_IS_OK(ret))
8574 goto done;
8577 * if the print job does not have a DEVMODE associated with it,
8578 * just use the one for the printer. A NULL devicemode is not
8579 * a failure condition
8582 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8583 devmode = construct_dev_mode(snum);
8584 else {
8585 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8586 ZERO_STRUCTP( devmode );
8587 convert_nt_devicemode( devmode, nt_devmode );
8591 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8593 *needed += spoolss_size_job_info_2(info_2);
8595 if (!alloc_buffer_size(buffer, *needed)) {
8596 ret = WERR_INSUFFICIENT_BUFFER;
8597 goto done;
8600 smb_io_job_info_2("", buffer, info_2, 0);
8602 if (*needed > offered) {
8603 ret = WERR_INSUFFICIENT_BUFFER;
8604 goto done;
8607 ret = WERR_OK;
8609 done:
8610 /* Cleanup allocated memory */
8612 free_job_info_2(info_2); /* Also frees devmode */
8613 SAFE_FREE(info_2);
8614 free_a_printer(&ntprinter, 2);
8616 return ret;
8619 /****************************************************************************
8620 ****************************************************************************/
8622 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8624 POLICY_HND *handle = &q_u->handle;
8625 uint32 jobid = q_u->jobid;
8626 uint32 level = q_u->level;
8627 NEW_BUFFER *buffer = NULL;
8628 uint32 offered = q_u->offered;
8629 uint32 *needed = &r_u->needed;
8630 WERROR wstatus = WERR_OK;
8632 int snum;
8633 int count;
8634 print_queue_struct *queue = NULL;
8635 print_status_struct prt_status;
8637 /* that's an [in out] buffer */
8638 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8639 buffer = r_u->buffer;
8641 DEBUG(5,("spoolss_getjob\n"));
8643 *needed = 0;
8645 if (!get_printer_snum(p, handle, &snum))
8646 return WERR_BADFID;
8648 count = print_queue_status(snum, &queue, &prt_status);
8650 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8651 count, prt_status.status, prt_status.message));
8653 switch ( level ) {
8654 case 1:
8655 wstatus = getjob_level_1(&queue, count, snum, jobid,
8656 buffer, offered, needed);
8657 break;
8658 case 2:
8659 wstatus = getjob_level_2(&queue, count, snum, jobid,
8660 buffer, offered, needed);
8661 break;
8662 default:
8663 wstatus = WERR_UNKNOWN_LEVEL;
8664 break;
8667 SAFE_FREE(queue);
8668 return wstatus;
8671 /********************************************************************
8672 spoolss_getprinterdataex
8674 From MSDN documentation of GetPrinterDataEx: pass request
8675 to GetPrinterData if key is "PrinterDriverData".
8676 ********************************************************************/
8678 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8680 POLICY_HND *handle = &q_u->handle;
8681 uint32 in_size = q_u->size;
8682 uint32 *type = &r_u->type;
8683 uint32 *out_size = &r_u->size;
8684 uint8 **data = &r_u->data;
8685 uint32 *needed = &r_u->needed;
8686 fstring keyname, valuename;
8688 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8690 NT_PRINTER_INFO_LEVEL *printer = NULL;
8691 int snum = 0;
8692 WERROR status = WERR_OK;
8694 DEBUG(4,("_spoolss_getprinterdataex\n"));
8696 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8697 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8699 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8700 keyname, valuename));
8702 /* in case of problem, return some default values */
8704 *needed = 0;
8705 *type = 0;
8706 *out_size = in_size;
8708 if (!Printer) {
8709 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8710 status = WERR_BADFID;
8711 goto done;
8714 /* Is the handle to a printer or to the server? */
8716 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8717 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8718 status = WERR_INVALID_PARAM;
8719 goto done;
8722 if ( !get_printer_snum(p,handle, &snum) )
8723 return WERR_BADFID;
8725 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8726 if ( !W_ERROR_IS_OK(status) )
8727 goto done;
8729 /* check to see if the keyname is valid */
8730 if ( !strlen(keyname) ) {
8731 status = WERR_INVALID_PARAM;
8732 goto done;
8735 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8736 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8737 free_a_printer( &printer, 2 );
8738 status = WERR_BADFILE;
8739 goto done;
8742 /* When given a new keyname, we should just create it */
8744 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8746 if (*needed > *out_size)
8747 status = WERR_MORE_DATA;
8749 done:
8750 if ( !W_ERROR_IS_OK(status) )
8752 DEBUG(5, ("error: allocating %d\n", *out_size));
8754 /* reply this param doesn't exist */
8756 if ( *out_size )
8758 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8759 status = WERR_NOMEM;
8760 goto done;
8763 else {
8764 *data = NULL;
8768 if ( printer )
8769 free_a_printer( &printer, 2 );
8771 return status;
8774 /********************************************************************
8775 * spoolss_setprinterdataex
8776 ********************************************************************/
8778 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8780 POLICY_HND *handle = &q_u->handle;
8781 uint32 type = q_u->type;
8782 uint8 *data = q_u->data;
8783 uint32 real_len = q_u->real_len;
8785 NT_PRINTER_INFO_LEVEL *printer = NULL;
8786 int snum = 0;
8787 WERROR status = WERR_OK;
8788 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8789 fstring valuename;
8790 fstring keyname;
8791 char *oid_string;
8793 DEBUG(4,("_spoolss_setprinterdataex\n"));
8795 /* From MSDN documentation of SetPrinterDataEx: pass request to
8796 SetPrinterData if key is "PrinterDriverData" */
8798 if (!Printer) {
8799 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8800 return WERR_BADFID;
8803 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8804 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8805 return WERR_INVALID_PARAM;
8808 if ( !get_printer_snum(p,handle, &snum) )
8809 return WERR_BADFID;
8812 * Access check : NT returns "access denied" if you make a
8813 * SetPrinterData call without the necessary privildge.
8814 * we were originally returning OK if nothing changed
8815 * which made Win2k issue **a lot** of SetPrinterData
8816 * when connecting to a printer --jerry
8819 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8821 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8822 return WERR_ACCESS_DENIED;
8825 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8826 if (!W_ERROR_IS_OK(status))
8827 return status;
8829 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8830 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8832 /* check for OID in valuename */
8834 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8836 *oid_string = '\0';
8837 oid_string++;
8840 /* save the registry data */
8842 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8844 if ( W_ERROR_IS_OK(status) )
8846 /* save the OID if one was specified */
8847 if ( oid_string ) {
8848 fstrcat( keyname, "\\" );
8849 fstrcat( keyname, SPOOL_OID_KEY );
8852 * I'm not checking the status here on purpose. Don't know
8853 * if this is right, but I'm returning the status from the
8854 * previous set_printer_dataex() call. I have no idea if
8855 * this is right. --jerry
8858 set_printer_dataex( printer, keyname, valuename,
8859 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8862 status = mod_a_printer(*printer, 2);
8865 free_a_printer(&printer, 2);
8867 return status;
8871 /********************************************************************
8872 * spoolss_deleteprinterdataex
8873 ********************************************************************/
8875 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8877 POLICY_HND *handle = &q_u->handle;
8878 UNISTR2 *value = &q_u->valuename;
8879 UNISTR2 *key = &q_u->keyname;
8881 NT_PRINTER_INFO_LEVEL *printer = NULL;
8882 int snum=0;
8883 WERROR status = WERR_OK;
8884 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8885 pstring valuename, keyname;
8887 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8889 if (!Printer) {
8890 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8891 return WERR_BADFID;
8894 if (!get_printer_snum(p, handle, &snum))
8895 return WERR_BADFID;
8897 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8898 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8899 return WERR_ACCESS_DENIED;
8902 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8903 if (!W_ERROR_IS_OK(status))
8904 return status;
8906 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8907 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8909 status = delete_printer_dataex( printer, keyname, valuename );
8911 if ( W_ERROR_IS_OK(status) )
8912 mod_a_printer( *printer, 2 );
8914 free_a_printer(&printer, 2);
8916 return status;
8919 /********************************************************************
8920 * spoolss_enumprinterkey
8921 ********************************************************************/
8924 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8926 fstring key;
8927 fstring *keynames = NULL;
8928 uint16 *enumkeys = NULL;
8929 int num_keys;
8930 int printerkey_len;
8931 POLICY_HND *handle = &q_u->handle;
8932 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8933 NT_PRINTER_DATA *data;
8934 NT_PRINTER_INFO_LEVEL *printer = NULL;
8935 int snum = 0;
8936 WERROR status = WERR_BADFILE;
8939 DEBUG(4,("_spoolss_enumprinterkey\n"));
8941 if (!Printer) {
8942 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8943 return WERR_BADFID;
8946 if ( !get_printer_snum(p,handle, &snum) )
8947 return WERR_BADFID;
8949 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8950 if (!W_ERROR_IS_OK(status))
8951 return status;
8953 /* get the list of subkey names */
8955 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8956 data = &printer->info_2->data;
8958 num_keys = get_printer_subkeys( data, key, &keynames );
8960 if ( num_keys == -1 ) {
8961 status = WERR_BADFILE;
8962 goto done;
8965 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8967 r_u->needed = printerkey_len*2;
8969 if ( q_u->size < r_u->needed ) {
8970 status = WERR_MORE_DATA;
8971 goto done;
8974 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8975 status = WERR_NOMEM;
8976 goto done;
8979 status = WERR_OK;
8981 if ( q_u->size < r_u->needed )
8982 status = WERR_MORE_DATA;
8984 done:
8985 free_a_printer( &printer, 2 );
8986 SAFE_FREE( keynames );
8988 return status;
8991 /********************************************************************
8992 * spoolss_deleteprinterkey
8993 ********************************************************************/
8995 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8997 POLICY_HND *handle = &q_u->handle;
8998 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8999 fstring key;
9000 NT_PRINTER_INFO_LEVEL *printer = NULL;
9001 int snum=0;
9002 WERROR status;
9004 DEBUG(5,("spoolss_deleteprinterkey\n"));
9006 if (!Printer) {
9007 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9008 return WERR_BADFID;
9011 /* if keyname == NULL, return error */
9013 if ( !q_u->keyname.buffer )
9014 return WERR_INVALID_PARAM;
9016 if (!get_printer_snum(p, handle, &snum))
9017 return WERR_BADFID;
9019 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9020 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9021 return WERR_ACCESS_DENIED;
9024 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9025 if (!W_ERROR_IS_OK(status))
9026 return status;
9028 /* delete the key and all subneys */
9030 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9032 status = delete_all_printer_data( printer->info_2, key );
9034 if ( W_ERROR_IS_OK(status) )
9035 status = mod_a_printer(*printer, 2);
9037 free_a_printer( &printer, 2 );
9039 return status;
9043 /********************************************************************
9044 * spoolss_enumprinterdataex
9045 ********************************************************************/
9047 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9049 POLICY_HND *handle = &q_u->handle;
9050 uint32 in_size = q_u->size;
9051 uint32 num_entries,
9052 needed;
9053 NT_PRINTER_INFO_LEVEL *printer = NULL;
9054 PRINTER_ENUM_VALUES *enum_values = NULL;
9055 NT_PRINTER_DATA *p_data;
9056 fstring key;
9057 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9058 int snum;
9059 WERROR result;
9060 int key_index;
9061 int i;
9062 REGISTRY_VALUE *val;
9063 char *value_name;
9064 int data_len;
9067 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9069 if (!Printer) {
9070 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9071 return WERR_BADFID;
9075 * first check for a keyname of NULL or "". Win2k seems to send
9076 * this a lot and we should send back WERR_INVALID_PARAM
9077 * no need to spend time looking up the printer in this case.
9078 * --jerry
9081 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9082 if ( !strlen(key) ) {
9083 result = WERR_INVALID_PARAM;
9084 goto done;
9087 /* get the printer off of disk */
9089 if (!get_printer_snum(p,handle, &snum))
9090 return WERR_BADFID;
9092 ZERO_STRUCT(printer);
9093 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9094 if (!W_ERROR_IS_OK(result))
9095 return result;
9097 /* now look for a match on the key name */
9099 p_data = &printer->info_2->data;
9101 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9102 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9104 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9105 result = WERR_INVALID_PARAM;
9106 goto done;
9109 result = WERR_OK;
9110 needed = 0;
9112 /* allocate the memory for the array of pointers -- if necessary */
9114 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9115 if ( num_entries )
9117 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9119 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9120 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9121 result = WERR_NOMEM;
9122 goto done;
9125 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9129 * loop through all params and build the array to pass
9130 * back to the client
9133 for ( i=0; i<num_entries; i++ )
9135 /* lookup the registry value */
9137 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9138 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9140 /* copy the data */
9142 value_name = regval_name( val );
9143 init_unistr( &enum_values[i].valuename, value_name );
9144 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9145 enum_values[i].type = regval_type( val );
9147 data_len = regval_size( val );
9148 if ( data_len ) {
9149 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9151 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9152 data_len ));
9153 result = WERR_NOMEM;
9154 goto done;
9157 enum_values[i].data_len = data_len;
9159 /* keep track of the size of the array in bytes */
9161 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9164 /* housekeeping information in the reply */
9166 r_u->needed = needed;
9167 r_u->returned = num_entries;
9169 if (needed > in_size) {
9170 result = WERR_MORE_DATA;
9171 goto done;
9174 /* copy data into the reply */
9176 r_u->ctr.size = r_u->needed;
9177 r_u->ctr.size_of_array = r_u->returned;
9178 r_u->ctr.values = enum_values;
9182 done:
9183 if ( printer )
9184 free_a_printer(&printer, 2);
9186 return result;
9189 /****************************************************************************
9190 ****************************************************************************/
9192 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9194 init_unistr(&info->name, name);
9197 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9198 UNISTR2 *environment,
9199 NEW_BUFFER *buffer,
9200 uint32 offered,
9201 uint32 *needed)
9203 pstring path;
9204 pstring long_archi;
9205 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9207 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9209 if (!get_short_archi(long_archi))
9210 return WERR_INVALID_ENVIRONMENT;
9212 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9213 return WERR_NOMEM;
9215 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9217 fill_printprocessordirectory_1(info, path);
9219 *needed += spoolss_size_printprocessordirectory_info_1(info);
9221 if (!alloc_buffer_size(buffer, *needed)) {
9222 safe_free(info);
9223 return WERR_INSUFFICIENT_BUFFER;
9226 smb_io_printprocessordirectory_1("", buffer, info, 0);
9228 safe_free(info);
9230 if (*needed > offered)
9231 return WERR_INSUFFICIENT_BUFFER;
9232 else
9233 return WERR_OK;
9236 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9238 uint32 level = q_u->level;
9239 NEW_BUFFER *buffer = NULL;
9240 uint32 offered = q_u->offered;
9241 uint32 *needed = &r_u->needed;
9242 WERROR result;
9244 /* that's an [in out] buffer */
9245 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9246 buffer = r_u->buffer;
9248 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9250 *needed=0;
9252 switch(level) {
9253 case 1:
9254 result = getprintprocessordirectory_level_1
9255 (&q_u->name, &q_u->environment, buffer, offered, needed);
9256 break;
9257 default:
9258 result = WERR_UNKNOWN_LEVEL;
9261 return result;
9264 #if 0
9266 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9267 SPOOL_R_REPLYOPENPRINTER *r_u)
9269 DEBUG(5,("_spoolss_replyopenprinter\n"));
9271 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9273 return WERR_OK;
9276 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9277 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9279 DEBUG(5,("_spoolss_replycloseprinter\n"));
9280 return WERR_OK;
9283 #endif