r1899: this is 3.0.6 -- will release tomorrow
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blobdb60855ba0977fd532adb95a7d85a19f48ea7849
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 [%x] field [%x] for printer [%s]\n",
1030 msg->type, msg->field, p->dev.handlename));
1033 * if the is a printer notification handle and not a job notification
1034 * type, then set the id to 0. Other wise just use what was specified
1035 * in the message.
1037 * When registering change notification on a print server handle
1038 * we always need to send back the id (snum) matching the printer
1039 * for which the change took place. For change notify registered
1040 * on a printer handle, this does not matter and the id should be 0.
1042 * --jerry
1045 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1046 id = 0;
1047 else
1048 id = msg->id;
1051 /* Convert unix jobid to smb jobid */
1053 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1054 id = sysjob_to_jobid(msg->id);
1056 if (id == -1) {
1057 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1058 goto done;
1062 construct_info_data( &data[data_len], msg->type, msg->field, id );
1064 switch(msg->type) {
1065 case PRINTER_NOTIFY_TYPE:
1066 if ( printer_notify_table[msg->field].fn )
1067 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1068 break;
1070 case JOB_NOTIFY_TYPE:
1071 if ( job_notify_table[msg->field].fn )
1072 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1073 break;
1075 default:
1076 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1077 goto done;
1080 data_len++;
1083 if ( sending_msg_count ) {
1084 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
1085 data_len, data, p->notify.change, 0 );
1089 done:
1090 DEBUG(8,("send_notify2_changes: Exit...\n"));
1091 return;
1094 /***********************************************************************
1095 **********************************************************************/
1097 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1100 uint32 tv_sec, tv_usec;
1101 size_t offset = 0;
1103 /* Unpack message */
1105 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1106 msg->printer);
1108 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1109 &tv_sec, &tv_usec,
1110 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1112 if (msg->len == 0)
1113 tdb_unpack((char *)buf + offset, len - offset, "dd",
1114 &msg->notify.value[0], &msg->notify.value[1]);
1115 else
1116 tdb_unpack((char *)buf + offset, len - offset, "B",
1117 &msg->len, &msg->notify.data);
1119 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1120 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1122 tv->tv_sec = tv_sec;
1123 tv->tv_usec = tv_usec;
1125 if (msg->len == 0)
1126 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1127 msg->notify.value[1]));
1128 else
1129 dump_data(3, msg->notify.data, msg->len);
1131 return True;
1134 /********************************************************************
1135 Receive a notify2 message list
1136 ********************************************************************/
1138 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1140 size_t msg_count, i;
1141 char *buf = (char *)msg;
1142 char *msg_ptr;
1143 size_t msg_len;
1144 SPOOLSS_NOTIFY_MSG notify;
1145 SPOOLSS_NOTIFY_MSG_CTR messages;
1146 int num_groups;
1148 if (len < 4) {
1149 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1150 return;
1153 msg_count = IVAL(buf, 0);
1154 msg_ptr = buf + 4;
1156 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1158 if (msg_count == 0) {
1159 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1160 return;
1163 /* initialize the container */
1165 ZERO_STRUCT( messages );
1166 notify_msg_ctr_init( &messages );
1169 * build message groups for each printer identified
1170 * in a change_notify msg. Remember that a PCN message
1171 * includes the handle returned for the srv_spoolss_replyopenprinter()
1172 * call. Therefore messages are grouped according to printer handle.
1175 for ( i=0; i<msg_count; i++ ) {
1176 struct timeval msg_tv;
1178 if (msg_ptr + 4 - buf > len) {
1179 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1180 return;
1183 msg_len = IVAL(msg_ptr,0);
1184 msg_ptr += 4;
1186 if (msg_ptr + msg_len - buf > len) {
1187 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1188 return;
1191 /* unpack messages */
1193 ZERO_STRUCT( notify );
1194 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1195 msg_ptr += msg_len;
1197 /* 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);
5579 return WERR_UNKNOWN_LEVEL;
5582 /****************************************************************************
5583 ****************************************************************************/
5585 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5587 POLICY_HND *handle = &q_u->handle;
5589 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5591 if (!Printer) {
5592 DEBUG(3,("Error in startpageprinter printer handle\n"));
5593 return WERR_BADFID;
5596 Printer->page_started=True;
5597 return WERR_OK;
5600 /****************************************************************************
5601 ****************************************************************************/
5603 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5605 POLICY_HND *handle = &q_u->handle;
5606 int snum;
5608 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5610 if (!Printer) {
5611 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5612 return WERR_BADFID;
5615 if (!get_printer_snum(p, handle, &snum))
5616 return WERR_BADFID;
5618 Printer->page_started=False;
5619 print_job_endpage(snum, Printer->jobid);
5621 return WERR_OK;
5624 /********************************************************************
5625 * api_spoolss_getprinter
5626 * called from the spoolss dispatcher
5628 ********************************************************************/
5630 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5632 POLICY_HND *handle = &q_u->handle;
5633 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5634 uint32 *jobid = &r_u->jobid;
5636 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5637 int snum;
5638 pstring jobname;
5639 fstring datatype;
5640 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5641 struct current_user user;
5643 if (!Printer) {
5644 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5645 return WERR_BADFID;
5648 get_current_user(&user, p);
5651 * a nice thing with NT is it doesn't listen to what you tell it.
5652 * when asked to send _only_ RAW datas, it tries to send datas
5653 * in EMF format.
5655 * So I add checks like in NT Server ...
5658 if (info_1->p_datatype != 0) {
5659 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5660 if (strcmp(datatype, "RAW") != 0) {
5661 (*jobid)=0;
5662 return WERR_INVALID_DATATYPE;
5666 /* get the share number of the printer */
5667 if (!get_printer_snum(p, handle, &snum)) {
5668 return WERR_BADFID;
5671 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5673 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5675 /* An error occured in print_job_start() so return an appropriate
5676 NT error code. */
5678 if (Printer->jobid == -1) {
5679 return map_werror_from_unix(errno);
5682 Printer->document_started=True;
5683 (*jobid) = Printer->jobid;
5685 return WERR_OK;
5688 /********************************************************************
5689 * api_spoolss_getprinter
5690 * called from the spoolss dispatcher
5692 ********************************************************************/
5694 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5696 POLICY_HND *handle = &q_u->handle;
5698 return _spoolss_enddocprinter_internal(p, handle);
5701 /****************************************************************************
5702 ****************************************************************************/
5704 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5706 POLICY_HND *handle = &q_u->handle;
5707 uint32 buffer_size = q_u->buffer_size;
5708 uint8 *buffer = q_u->buffer;
5709 uint32 *buffer_written = &q_u->buffer_size2;
5710 int snum;
5711 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5713 if (!Printer) {
5714 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5715 r_u->buffer_written = q_u->buffer_size2;
5716 return WERR_BADFID;
5719 if (!get_printer_snum(p, handle, &snum))
5720 return WERR_BADFID;
5722 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5723 if (*buffer_written == -1) {
5724 r_u->buffer_written = 0;
5725 if (errno == ENOSPC)
5726 return WERR_NO_SPOOL_SPACE;
5727 else
5728 return WERR_ACCESS_DENIED;
5731 r_u->buffer_written = q_u->buffer_size2;
5733 return WERR_OK;
5736 /********************************************************************
5737 * api_spoolss_getprinter
5738 * called from the spoolss dispatcher
5740 ********************************************************************/
5742 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5743 pipes_struct *p)
5745 struct current_user user;
5746 int snum;
5747 WERROR errcode = WERR_BADFUNC;
5748 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5750 get_current_user(&user, p);
5752 if (!Printer) {
5753 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5754 return WERR_BADFID;
5757 if (!get_printer_snum(p, handle, &snum))
5758 return WERR_BADFID;
5760 switch (command) {
5761 case PRINTER_CONTROL_PAUSE:
5762 if (print_queue_pause(&user, snum, &errcode)) {
5763 errcode = WERR_OK;
5765 break;
5766 case PRINTER_CONTROL_RESUME:
5767 case PRINTER_CONTROL_UNPAUSE:
5768 if (print_queue_resume(&user, snum, &errcode)) {
5769 errcode = WERR_OK;
5771 break;
5772 case PRINTER_CONTROL_PURGE:
5773 if (print_queue_purge(&user, snum, &errcode)) {
5774 errcode = WERR_OK;
5776 break;
5777 default:
5778 return WERR_UNKNOWN_LEVEL;
5781 return errcode;
5784 /********************************************************************
5785 * api_spoolss_abortprinter
5786 * From MSDN: "Deletes printer's spool file if printer is configured
5787 * for spooling"
5788 ********************************************************************/
5790 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5792 POLICY_HND *handle = &q_u->handle;
5793 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5794 int snum;
5795 struct current_user user;
5796 WERROR errcode = WERR_OK;
5798 if (!Printer) {
5799 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5800 return WERR_BADFID;
5803 if (!get_printer_snum(p, handle, &snum))
5804 return WERR_BADFID;
5806 get_current_user( &user, p );
5808 print_job_delete( &user, snum, Printer->jobid, &errcode );
5810 return errcode;
5813 /********************************************************************
5814 * called by spoolss_api_setprinter
5815 * when updating a printer description
5816 ********************************************************************/
5818 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5819 const SPOOL_PRINTER_INFO_LEVEL *info,
5820 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5822 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5823 struct current_user user;
5824 WERROR result;
5825 int snum;
5827 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5829 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5830 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5831 OUR_HANDLE(handle)));
5833 result = WERR_BADFID;
5834 goto done;
5837 /* NT seems to like setting the security descriptor even though
5838 nothing may have actually changed. This causes annoying
5839 dialog boxes when the user doesn't have permission to change
5840 the security descriptor. */
5842 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5844 if (DEBUGLEVEL >= 10) {
5845 SEC_ACL *the_acl;
5846 int i;
5848 the_acl = old_secdesc_ctr->sec->dacl;
5849 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5850 PRINTERNAME(snum), the_acl->num_aces));
5852 for (i = 0; i < the_acl->num_aces; i++) {
5853 fstring sid_str;
5855 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5857 DEBUG(10, ("%s 0x%08x\n", sid_str,
5858 the_acl->ace[i].info.mask));
5861 the_acl = secdesc_ctr->sec->dacl;
5863 if (the_acl) {
5864 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5865 PRINTERNAME(snum), the_acl->num_aces));
5867 for (i = 0; i < the_acl->num_aces; i++) {
5868 fstring sid_str;
5870 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5872 DEBUG(10, ("%s 0x%08x\n", sid_str,
5873 the_acl->ace[i].info.mask));
5875 } else {
5876 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5880 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5882 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5883 result = WERR_OK;
5884 goto done;
5887 /* Work out which user is performing the operation */
5889 get_current_user(&user, p);
5891 /* Check the user has permissions to change the security
5892 descriptor. By experimentation with two NT machines, the user
5893 requires Full Access to the printer to change security
5894 information. */
5896 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5897 result = WERR_ACCESS_DENIED;
5898 goto done;
5901 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5903 done:
5905 return result;
5908 /********************************************************************
5909 Do Samba sanity checks on a printer info struct.
5910 this has changed purpose: it now "canonicalises" printer
5911 info from a client rather than just checking it is correct
5912 ********************************************************************/
5914 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5916 fstring printername;
5917 const char *p;
5919 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5920 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5922 /* we force some elements to "correct" values */
5923 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5924 fstrcpy(info->sharename, lp_servicename(snum));
5926 /* make sure printername is in \\server\printername format */
5928 fstrcpy( printername, info->printername );
5929 p = printername;
5930 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5931 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5932 p++;
5935 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5936 get_called_name(), p );
5938 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5941 return True;
5944 /****************************************************************************
5945 ****************************************************************************/
5947 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5949 extern userdom_struct current_user_info;
5950 char *cmd = lp_addprinter_cmd();
5951 char **qlines;
5952 pstring command;
5953 int numlines;
5954 int ret;
5955 int fd;
5956 fstring remote_machine = "%m";
5958 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5960 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5961 cmd, printer->info_2->printername, printer->info_2->sharename,
5962 printer->info_2->portname, printer->info_2->drivername,
5963 printer->info_2->location, printer->info_2->comment, remote_machine);
5965 DEBUG(10,("Running [%s]\n", command));
5966 ret = smbrun(command, &fd);
5967 DEBUGADD(10,("returned [%d]\n", ret));
5969 if ( ret != 0 ) {
5970 if (fd != -1)
5971 close(fd);
5972 return False;
5975 numlines = 0;
5976 /* Get lines and convert them back to dos-codepage */
5977 qlines = fd_lines_load(fd, &numlines);
5978 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5979 close(fd);
5981 if(numlines) {
5982 /* Set the portname to what the script says the portname should be. */
5983 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5984 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5986 /* Send SIGHUP to process group... is there a better way? */
5987 kill(0, SIGHUP);
5989 /* reload our services immediately */
5990 reload_services( False );
5993 file_lines_free(qlines);
5994 return True;
5997 /********************************************************************
5998 * Called by spoolss_api_setprinter
5999 * when updating a printer description.
6000 ********************************************************************/
6002 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6003 const SPOOL_PRINTER_INFO_LEVEL *info,
6004 DEVICEMODE *devmode)
6006 int snum;
6007 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6008 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6009 WERROR result;
6010 UNISTR2 buffer;
6011 fstring asc_buffer;
6013 DEBUG(8,("update_printer\n"));
6015 result = WERR_OK;
6017 if (!Printer) {
6018 result = WERR_BADFID;
6019 goto done;
6022 if (!get_printer_snum(p, handle, &snum)) {
6023 result = WERR_BADFID;
6024 goto done;
6027 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6028 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6029 result = WERR_BADFID;
6030 goto done;
6033 DEBUGADD(8,("Converting info_2 struct\n"));
6036 * convert_printer_info converts the incoming
6037 * info from the client and overwrites the info
6038 * just read from the tdb in the pointer 'printer'.
6041 if (!convert_printer_info(info, printer, level)) {
6042 result = WERR_NOMEM;
6043 goto done;
6046 if (devmode) {
6047 /* we have a valid devmode
6048 convert it and link it*/
6050 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6051 if (!convert_devicemode(printer->info_2->printername, devmode,
6052 &printer->info_2->devmode)) {
6053 result = WERR_NOMEM;
6054 goto done;
6058 /* Do sanity check on the requested changes for Samba */
6060 if (!check_printer_ok(printer->info_2, snum)) {
6061 result = WERR_INVALID_PARAM;
6062 goto done;
6065 /* FIXME!!! If the driver has changed we really should verify that
6066 it is installed before doing much else --jerry */
6068 /* Check calling user has permission to update printer description */
6070 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6071 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6072 result = WERR_ACCESS_DENIED;
6073 goto done;
6076 /* Call addprinter hook */
6077 /* Check changes to see if this is really needed */
6079 if ( *lp_addprinter_cmd()
6080 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6081 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6082 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6083 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6085 if ( !add_printer_hook(printer) ) {
6086 result = WERR_ACCESS_DENIED;
6087 goto done;
6091 * make sure we actually reload the services after
6092 * this as smb.conf could have a new section in it
6093 * .... shouldn't .... but could
6095 reload_services(False);
6099 * When a *new* driver is bound to a printer, the drivername is used to
6100 * lookup previously saved driver initialization info, which is then
6101 * bound to the printer, simulating what happens in the Windows arch.
6103 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6105 if (!set_driver_init(printer, 2))
6107 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6108 printer->info_2->drivername));
6111 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6112 printer->info_2->drivername));
6114 notify_printer_driver(snum, printer->info_2->drivername);
6118 * flag which changes actually occured. This is a small subset of
6119 * all the possible changes. We also have to update things in the
6120 * DsSpooler key.
6123 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6124 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6125 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6126 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6128 notify_printer_comment(snum, printer->info_2->comment);
6131 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6132 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6133 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6134 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6136 notify_printer_sharename(snum, printer->info_2->sharename);
6139 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6140 char *pname;
6142 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6143 pname++;
6144 else
6145 pname = printer->info_2->printername;
6148 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6149 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6150 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6152 notify_printer_printername( snum, pname );
6155 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6156 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6157 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6158 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6160 notify_printer_port(snum, printer->info_2->portname);
6163 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6164 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6165 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6166 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6168 notify_printer_location(snum, printer->info_2->location);
6171 /* here we need to update some more DsSpooler keys */
6172 /* uNCName, serverName, shortServerName */
6174 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6175 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6176 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6177 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6178 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6180 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6181 global_myname(), printer->info_2->sharename );
6182 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6183 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6184 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6186 /* Update printer info */
6187 result = mod_a_printer(*printer, 2);
6189 done:
6190 free_a_printer(&printer, 2);
6191 free_a_printer(&old_printer, 2);
6194 return result;
6197 /****************************************************************************
6198 ****************************************************************************/
6199 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6200 const SPOOL_PRINTER_INFO_LEVEL *info)
6202 #ifdef HAVE_ADS
6203 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6204 int snum;
6205 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6207 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6209 if (!Printer)
6210 return WERR_BADFID;
6212 if (!get_printer_snum(p, handle, &snum))
6213 return WERR_BADFID;
6215 nt_printer_publish(Printer, snum, info7->action);
6217 return WERR_OK;
6218 #else
6219 return WERR_UNKNOWN_LEVEL;
6220 #endif
6222 /****************************************************************************
6223 ****************************************************************************/
6225 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6227 POLICY_HND *handle = &q_u->handle;
6228 uint32 level = q_u->level;
6229 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6230 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6231 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6232 uint32 command = q_u->command;
6234 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6236 if (!Printer) {
6237 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6238 return WERR_BADFID;
6241 /* check the level */
6242 switch (level) {
6243 case 0:
6244 return control_printer(handle, command, p);
6245 case 2:
6246 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6247 case 3:
6248 return update_printer_sec(handle, level, info, p,
6249 secdesc_ctr);
6250 case 7:
6251 return publish_or_unpublish_printer(p, handle, info);
6252 default:
6253 return WERR_UNKNOWN_LEVEL;
6257 /****************************************************************************
6258 ****************************************************************************/
6260 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6262 POLICY_HND *handle = &q_u->handle;
6263 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6265 if (!Printer) {
6266 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6267 return WERR_BADFID;
6270 if (Printer->notify.client_connected==True) {
6271 int snum = -1;
6273 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6274 snum = -1;
6275 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6276 !get_printer_snum(p, handle, &snum) )
6277 return WERR_BADFID;
6279 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6282 Printer->notify.flags=0;
6283 Printer->notify.options=0;
6284 Printer->notify.localmachine[0]='\0';
6285 Printer->notify.printerlocal=0;
6286 if (Printer->notify.option)
6287 free_spool_notify_option(&Printer->notify.option);
6288 Printer->notify.client_connected=False;
6290 return WERR_OK;
6293 /****************************************************************************
6294 ****************************************************************************/
6296 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6298 /* that's an [in out] buffer (despite appearences to the contrary) */
6299 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6301 r_u->needed = 0;
6302 return WERR_INVALID_PARAM; /* this is what a NT server
6303 returns for AddJob. AddJob
6304 must fail on non-local
6305 printers */
6308 /****************************************************************************
6309 ****************************************************************************/
6311 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6312 int position, int snum)
6314 pstring temp_name;
6316 struct tm *t;
6318 t=gmtime(&queue->time);
6319 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6321 job_info->jobid=queue->job;
6322 init_unistr(&job_info->printername, lp_servicename(snum));
6323 init_unistr(&job_info->machinename, temp_name);
6324 init_unistr(&job_info->username, queue->fs_user);
6325 init_unistr(&job_info->document, queue->fs_file);
6326 init_unistr(&job_info->datatype, "RAW");
6327 init_unistr(&job_info->text_status, "");
6328 job_info->status=nt_printj_status(queue->status);
6329 job_info->priority=queue->priority;
6330 job_info->position=position;
6331 job_info->totalpages=queue->page_count;
6332 job_info->pagesprinted=0;
6334 make_systemtime(&job_info->submitted, t);
6337 /****************************************************************************
6338 ****************************************************************************/
6340 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6341 int position, int snum,
6342 NT_PRINTER_INFO_LEVEL *ntprinter,
6343 DEVICEMODE *devmode)
6345 pstring temp_name;
6346 struct tm *t;
6348 t=gmtime(&queue->time);
6349 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6351 job_info->jobid=queue->job;
6353 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6355 init_unistr(&job_info->machinename, temp_name);
6356 init_unistr(&job_info->username, queue->fs_user);
6357 init_unistr(&job_info->document, queue->fs_file);
6358 init_unistr(&job_info->notifyname, queue->fs_user);
6359 init_unistr(&job_info->datatype, "RAW");
6360 init_unistr(&job_info->printprocessor, "winprint");
6361 init_unistr(&job_info->parameters, "");
6362 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6363 init_unistr(&job_info->text_status, "");
6365 /* and here the security descriptor */
6367 job_info->status=nt_printj_status(queue->status);
6368 job_info->priority=queue->priority;
6369 job_info->position=position;
6370 job_info->starttime=0;
6371 job_info->untiltime=0;
6372 job_info->totalpages=queue->page_count;
6373 job_info->size=queue->size;
6374 make_systemtime(&(job_info->submitted), t);
6375 job_info->timeelapsed=0;
6376 job_info->pagesprinted=0;
6378 job_info->devmode = devmode;
6380 return (True);
6383 /****************************************************************************
6384 Enumjobs at level 1.
6385 ****************************************************************************/
6387 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6388 NEW_BUFFER *buffer, uint32 offered,
6389 uint32 *needed, uint32 *returned)
6391 JOB_INFO_1 *info;
6392 int i;
6394 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6395 if (info==NULL) {
6396 SAFE_FREE(queue);
6397 *returned=0;
6398 return WERR_NOMEM;
6401 for (i=0; i<*returned; i++)
6402 fill_job_info_1(&info[i], &queue[i], i, snum);
6404 SAFE_FREE(queue);
6406 /* check the required size. */
6407 for (i=0; i<*returned; i++)
6408 (*needed) += spoolss_size_job_info_1(&info[i]);
6410 if (!alloc_buffer_size(buffer, *needed)) {
6411 SAFE_FREE(info);
6412 return WERR_INSUFFICIENT_BUFFER;
6415 /* fill the buffer with the structures */
6416 for (i=0; i<*returned; i++)
6417 smb_io_job_info_1("", buffer, &info[i], 0);
6419 /* clear memory */
6420 SAFE_FREE(info);
6422 if (*needed > offered) {
6423 *returned=0;
6424 return WERR_INSUFFICIENT_BUFFER;
6427 return WERR_OK;
6430 /****************************************************************************
6431 Enumjobs at level 2.
6432 ****************************************************************************/
6434 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6435 NEW_BUFFER *buffer, uint32 offered,
6436 uint32 *needed, uint32 *returned)
6438 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6439 JOB_INFO_2 *info = NULL;
6440 int i;
6441 WERROR result;
6442 DEVICEMODE *devmode = NULL;
6444 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6445 if (info==NULL) {
6446 *returned=0;
6447 result = WERR_NOMEM;
6448 goto done;
6451 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6452 if (!W_ERROR_IS_OK(result)) {
6453 *returned = 0;
6454 goto done;
6457 /* this should not be a failure condition if the devmode is NULL */
6459 devmode = construct_dev_mode(snum);
6461 for (i=0; i<*returned; i++)
6462 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6463 devmode);
6465 free_a_printer(&ntprinter, 2);
6466 SAFE_FREE(queue);
6468 /* check the required size. */
6469 for (i=0; i<*returned; i++)
6470 (*needed) += spoolss_size_job_info_2(&info[i]);
6472 if (*needed > offered) {
6473 *returned=0;
6474 result = WERR_INSUFFICIENT_BUFFER;
6475 goto done;
6478 if (!alloc_buffer_size(buffer, *needed)) {
6479 SAFE_FREE(info);
6480 result = WERR_INSUFFICIENT_BUFFER;
6481 goto done;
6484 /* fill the buffer with the structures */
6485 for (i=0; i<*returned; i++)
6486 smb_io_job_info_2("", buffer, &info[i], 0);
6488 result = WERR_OK;
6490 done:
6491 free_a_printer(&ntprinter, 2);
6492 free_devmode(devmode);
6493 SAFE_FREE(queue);
6494 SAFE_FREE(info);
6496 return result;
6500 /****************************************************************************
6501 Enumjobs.
6502 ****************************************************************************/
6504 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6506 POLICY_HND *handle = &q_u->handle;
6507 uint32 level = q_u->level;
6508 NEW_BUFFER *buffer = NULL;
6509 uint32 offered = q_u->offered;
6510 uint32 *needed = &r_u->needed;
6511 uint32 *returned = &r_u->returned;
6512 WERROR wret;
6514 int snum;
6515 print_status_struct prt_status;
6516 print_queue_struct *queue=NULL;
6518 /* that's an [in out] buffer */
6519 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6520 buffer = r_u->buffer;
6522 DEBUG(4,("_spoolss_enumjobs\n"));
6524 *needed=0;
6525 *returned=0;
6527 if (!get_printer_snum(p, handle, &snum))
6528 return WERR_BADFID;
6530 *returned = print_queue_status(snum, &queue, &prt_status);
6531 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6533 if (*returned == 0) {
6534 SAFE_FREE(queue);
6535 return WERR_OK;
6538 switch (level) {
6539 case 1:
6540 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6541 return wret;
6542 case 2:
6543 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6544 return wret;
6545 default:
6546 SAFE_FREE(queue);
6547 *returned=0;
6548 return WERR_UNKNOWN_LEVEL;
6552 /****************************************************************************
6553 ****************************************************************************/
6555 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6557 return WERR_OK;
6560 /****************************************************************************
6561 ****************************************************************************/
6563 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6565 POLICY_HND *handle = &q_u->handle;
6566 uint32 jobid = q_u->jobid;
6567 uint32 command = q_u->command;
6569 struct current_user user;
6570 int snum;
6571 WERROR errcode = WERR_BADFUNC;
6573 if (!get_printer_snum(p, handle, &snum)) {
6574 return WERR_BADFID;
6577 if (!print_job_exists(snum, jobid)) {
6578 return WERR_INVALID_PRINTER_NAME;
6581 get_current_user(&user, p);
6583 switch (command) {
6584 case JOB_CONTROL_CANCEL:
6585 case JOB_CONTROL_DELETE:
6586 if (print_job_delete(&user, snum, jobid, &errcode)) {
6587 errcode = WERR_OK;
6589 break;
6590 case JOB_CONTROL_PAUSE:
6591 if (print_job_pause(&user, snum, jobid, &errcode)) {
6592 errcode = WERR_OK;
6594 break;
6595 case JOB_CONTROL_RESTART:
6596 case JOB_CONTROL_RESUME:
6597 if (print_job_resume(&user, snum, jobid, &errcode)) {
6598 errcode = WERR_OK;
6600 break;
6601 default:
6602 return WERR_UNKNOWN_LEVEL;
6605 return errcode;
6608 /****************************************************************************
6609 Enumerates all printer drivers at level 1.
6610 ****************************************************************************/
6612 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6614 int i;
6615 int ndrivers;
6616 uint32 version;
6617 fstring *list = NULL;
6619 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6620 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6622 *returned=0;
6624 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6625 list=NULL;
6626 ndrivers=get_ntdrivers(&list, architecture, version);
6627 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6629 if(ndrivers == -1)
6630 return WERR_NOMEM;
6632 if(ndrivers != 0) {
6633 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6634 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6635 SAFE_FREE(driver_info_1);
6636 SAFE_FREE(list);
6637 return WERR_NOMEM;
6639 else driver_info_1 = tdi1;
6642 for (i=0; i<ndrivers; i++) {
6643 WERROR status;
6644 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6645 ZERO_STRUCT(driver);
6646 status = get_a_printer_driver(&driver, 3, list[i],
6647 architecture, version);
6648 if (!W_ERROR_IS_OK(status)) {
6649 SAFE_FREE(list);
6650 return status;
6652 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6653 free_a_printer_driver(driver, 3);
6656 *returned+=ndrivers;
6657 SAFE_FREE(list);
6660 /* check the required size. */
6661 for (i=0; i<*returned; i++) {
6662 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6663 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6666 if (!alloc_buffer_size(buffer, *needed)) {
6667 SAFE_FREE(driver_info_1);
6668 return WERR_INSUFFICIENT_BUFFER;
6671 /* fill the buffer with the driver structures */
6672 for (i=0; i<*returned; i++) {
6673 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6674 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6677 SAFE_FREE(driver_info_1);
6679 if (*needed > offered) {
6680 *returned=0;
6681 return WERR_INSUFFICIENT_BUFFER;
6684 return WERR_OK;
6687 /****************************************************************************
6688 Enumerates all printer drivers at level 2.
6689 ****************************************************************************/
6691 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6693 int i;
6694 int ndrivers;
6695 uint32 version;
6696 fstring *list = NULL;
6698 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6699 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6701 *returned=0;
6703 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6704 list=NULL;
6705 ndrivers=get_ntdrivers(&list, architecture, version);
6706 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6708 if(ndrivers == -1)
6709 return WERR_NOMEM;
6711 if(ndrivers != 0) {
6712 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6713 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6714 SAFE_FREE(driver_info_2);
6715 SAFE_FREE(list);
6716 return WERR_NOMEM;
6718 else driver_info_2 = tdi2;
6721 for (i=0; i<ndrivers; i++) {
6722 WERROR status;
6724 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6725 ZERO_STRUCT(driver);
6726 status = get_a_printer_driver(&driver, 3, list[i],
6727 architecture, version);
6728 if (!W_ERROR_IS_OK(status)) {
6729 SAFE_FREE(list);
6730 return status;
6732 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6733 free_a_printer_driver(driver, 3);
6736 *returned+=ndrivers;
6737 SAFE_FREE(list);
6740 /* check the required size. */
6741 for (i=0; i<*returned; i++) {
6742 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6743 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6746 if (!alloc_buffer_size(buffer, *needed)) {
6747 SAFE_FREE(driver_info_2);
6748 return WERR_INSUFFICIENT_BUFFER;
6751 /* fill the buffer with the form structures */
6752 for (i=0; i<*returned; i++) {
6753 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6754 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6757 SAFE_FREE(driver_info_2);
6759 if (*needed > offered) {
6760 *returned=0;
6761 return WERR_INSUFFICIENT_BUFFER;
6764 return WERR_OK;
6767 /****************************************************************************
6768 Enumerates all printer drivers at level 3.
6769 ****************************************************************************/
6771 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6773 int i;
6774 int ndrivers;
6775 uint32 version;
6776 fstring *list = NULL;
6778 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6779 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6781 *returned=0;
6783 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6784 list=NULL;
6785 ndrivers=get_ntdrivers(&list, architecture, version);
6786 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6788 if(ndrivers == -1)
6789 return WERR_NOMEM;
6791 if(ndrivers != 0) {
6792 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6793 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6794 SAFE_FREE(driver_info_3);
6795 SAFE_FREE(list);
6796 return WERR_NOMEM;
6798 else driver_info_3 = tdi3;
6801 for (i=0; i<ndrivers; i++) {
6802 WERROR status;
6804 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6805 ZERO_STRUCT(driver);
6806 status = get_a_printer_driver(&driver, 3, list[i],
6807 architecture, version);
6808 if (!W_ERROR_IS_OK(status)) {
6809 SAFE_FREE(list);
6810 return status;
6812 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6813 free_a_printer_driver(driver, 3);
6816 *returned+=ndrivers;
6817 SAFE_FREE(list);
6820 /* check the required size. */
6821 for (i=0; i<*returned; i++) {
6822 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6823 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6826 if (!alloc_buffer_size(buffer, *needed)) {
6827 SAFE_FREE(driver_info_3);
6828 return WERR_INSUFFICIENT_BUFFER;
6831 /* fill the buffer with the driver structures */
6832 for (i=0; i<*returned; i++) {
6833 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6834 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6837 for (i=0; i<*returned; i++)
6838 SAFE_FREE(driver_info_3[i].dependentfiles);
6840 SAFE_FREE(driver_info_3);
6842 if (*needed > offered) {
6843 *returned=0;
6844 return WERR_INSUFFICIENT_BUFFER;
6847 return WERR_OK;
6850 /****************************************************************************
6851 Enumerates all printer drivers.
6852 ****************************************************************************/
6854 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6856 UNISTR2 *environment = &q_u->environment;
6857 uint32 level = q_u->level;
6858 NEW_BUFFER *buffer = NULL;
6859 uint32 offered = q_u->offered;
6860 uint32 *needed = &r_u->needed;
6861 uint32 *returned = &r_u->returned;
6863 fstring *list = NULL;
6864 fstring servername;
6865 fstring architecture;
6867 /* that's an [in out] buffer */
6868 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6869 buffer = r_u->buffer;
6871 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6872 fstrcpy(servername, get_called_name());
6873 *needed=0;
6874 *returned=0;
6876 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6878 switch (level) {
6879 case 1:
6880 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6881 case 2:
6882 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6883 case 3:
6884 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6885 default:
6886 *returned=0;
6887 SAFE_FREE(list);
6888 return WERR_UNKNOWN_LEVEL;
6892 /****************************************************************************
6893 ****************************************************************************/
6895 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6897 form->flag=list->flag;
6898 init_unistr(&form->name, list->name);
6899 form->width=list->width;
6900 form->length=list->length;
6901 form->left=list->left;
6902 form->top=list->top;
6903 form->right=list->right;
6904 form->bottom=list->bottom;
6907 /****************************************************************************
6908 ****************************************************************************/
6910 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6912 uint32 level = q_u->level;
6913 NEW_BUFFER *buffer = NULL;
6914 uint32 offered = q_u->offered;
6915 uint32 *needed = &r_u->needed;
6916 uint32 *numofforms = &r_u->numofforms;
6917 uint32 numbuiltinforms;
6919 nt_forms_struct *list=NULL;
6920 nt_forms_struct *builtinlist=NULL;
6921 FORM_1 *forms_1;
6922 int buffer_size=0;
6923 int i;
6925 /* that's an [in out] buffer */
6926 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6927 buffer = r_u->buffer;
6929 DEBUG(4,("_spoolss_enumforms\n"));
6930 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6931 DEBUGADD(5,("Info level [%d]\n", level));
6933 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6934 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6935 *numofforms = get_ntforms(&list);
6936 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6937 *numofforms += numbuiltinforms;
6939 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6941 switch (level) {
6942 case 1:
6943 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6944 *numofforms=0;
6945 return WERR_NOMEM;
6948 /* construct the list of form structures */
6949 for (i=0; i<numbuiltinforms; i++) {
6950 DEBUGADD(6,("Filling form number [%d]\n",i));
6951 fill_form_1(&forms_1[i], &builtinlist[i]);
6954 SAFE_FREE(builtinlist);
6956 for (; i<*numofforms; i++) {
6957 DEBUGADD(6,("Filling form number [%d]\n",i));
6958 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6961 SAFE_FREE(list);
6963 /* check the required size. */
6964 for (i=0; i<numbuiltinforms; i++) {
6965 DEBUGADD(6,("adding form [%d]'s size\n",i));
6966 buffer_size += spoolss_size_form_1(&forms_1[i]);
6968 for (; i<*numofforms; i++) {
6969 DEBUGADD(6,("adding form [%d]'s size\n",i));
6970 buffer_size += spoolss_size_form_1(&forms_1[i]);
6973 *needed=buffer_size;
6975 if (!alloc_buffer_size(buffer, buffer_size)){
6976 SAFE_FREE(forms_1);
6977 return WERR_INSUFFICIENT_BUFFER;
6980 /* fill the buffer with the form structures */
6981 for (i=0; i<numbuiltinforms; i++) {
6982 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6983 smb_io_form_1("", buffer, &forms_1[i], 0);
6985 for (; i<*numofforms; i++) {
6986 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6987 smb_io_form_1("", buffer, &forms_1[i], 0);
6990 SAFE_FREE(forms_1);
6992 if (*needed > offered) {
6993 *numofforms=0;
6994 return WERR_INSUFFICIENT_BUFFER;
6996 else
6997 return WERR_OK;
6999 default:
7000 SAFE_FREE(list);
7001 SAFE_FREE(builtinlist);
7002 return WERR_UNKNOWN_LEVEL;
7007 /****************************************************************************
7008 ****************************************************************************/
7010 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7012 uint32 level = q_u->level;
7013 UNISTR2 *uni_formname = &q_u->formname;
7014 NEW_BUFFER *buffer = NULL;
7015 uint32 offered = q_u->offered;
7016 uint32 *needed = &r_u->needed;
7018 nt_forms_struct *list=NULL;
7019 nt_forms_struct builtin_form;
7020 BOOL foundBuiltin;
7021 FORM_1 form_1;
7022 fstring form_name;
7023 int buffer_size=0;
7024 int numofforms=0, i=0;
7026 /* that's an [in out] buffer */
7027 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7028 buffer = r_u->buffer;
7030 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7032 DEBUG(4,("_spoolss_getform\n"));
7033 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7034 DEBUGADD(5,("Info level [%d]\n", level));
7036 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7037 if (!foundBuiltin) {
7038 numofforms = get_ntforms(&list);
7039 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7041 if (numofforms == 0)
7042 return WERR_BADFID;
7045 switch (level) {
7046 case 1:
7047 if (foundBuiltin) {
7048 fill_form_1(&form_1, &builtin_form);
7049 } else {
7051 /* Check if the requested name is in the list of form structures */
7052 for (i=0; i<numofforms; i++) {
7054 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7056 if (strequal(form_name, list[i].name)) {
7057 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7058 fill_form_1(&form_1, &list[i]);
7059 break;
7063 SAFE_FREE(list);
7064 if (i == numofforms) {
7065 return WERR_BADFID;
7068 /* check the required size. */
7070 *needed=spoolss_size_form_1(&form_1);
7072 if (!alloc_buffer_size(buffer, buffer_size)){
7073 return WERR_INSUFFICIENT_BUFFER;
7076 if (*needed > offered) {
7077 return WERR_INSUFFICIENT_BUFFER;
7080 /* fill the buffer with the form structures */
7081 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7082 smb_io_form_1("", buffer, &form_1, 0);
7084 return WERR_OK;
7086 default:
7087 SAFE_FREE(list);
7088 return WERR_UNKNOWN_LEVEL;
7092 /****************************************************************************
7093 ****************************************************************************/
7095 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7097 init_unistr(&port->port_name, name);
7100 /****************************************************************************
7101 ****************************************************************************/
7103 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7105 init_unistr(&port->port_name, name);
7106 init_unistr(&port->monitor_name, "Local Monitor");
7107 init_unistr(&port->description, "Local Port");
7108 port->port_type=PORT_TYPE_WRITE;
7109 port->reserved=0x0;
7112 /****************************************************************************
7113 enumports level 1.
7114 ****************************************************************************/
7116 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7118 PORT_INFO_1 *ports=NULL;
7119 int i=0;
7121 if (*lp_enumports_cmd()) {
7122 char *cmd = lp_enumports_cmd();
7123 char **qlines;
7124 pstring command;
7125 int numlines;
7126 int ret;
7127 int fd;
7129 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7131 DEBUG(10,("Running [%s]\n", command));
7132 ret = smbrun(command, &fd);
7133 DEBUG(10,("Returned [%d]\n", ret));
7134 if (ret != 0) {
7135 if (fd != -1)
7136 close(fd);
7137 /* Is this the best error to return here? */
7138 return WERR_ACCESS_DENIED;
7141 numlines = 0;
7142 qlines = fd_lines_load(fd, &numlines);
7143 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7144 close(fd);
7146 if(numlines) {
7147 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7148 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7149 dos_errstr(WERR_NOMEM)));
7150 file_lines_free(qlines);
7151 return WERR_NOMEM;
7154 for (i=0; i<numlines; i++) {
7155 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7156 fill_port_1(&ports[i], qlines[i]);
7159 file_lines_free(qlines);
7162 *returned = numlines;
7164 } else {
7165 *returned = 1; /* Sole Samba port returned. */
7167 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7168 return WERR_NOMEM;
7170 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7172 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7175 /* check the required size. */
7176 for (i=0; i<*returned; i++) {
7177 DEBUGADD(6,("adding port [%d]'s size\n", i));
7178 *needed += spoolss_size_port_info_1(&ports[i]);
7181 if (!alloc_buffer_size(buffer, *needed)) {
7182 SAFE_FREE(ports);
7183 return WERR_INSUFFICIENT_BUFFER;
7186 /* fill the buffer with the ports structures */
7187 for (i=0; i<*returned; i++) {
7188 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7189 smb_io_port_1("", buffer, &ports[i], 0);
7192 SAFE_FREE(ports);
7194 if (*needed > offered) {
7195 *returned=0;
7196 return WERR_INSUFFICIENT_BUFFER;
7199 return WERR_OK;
7202 /****************************************************************************
7203 enumports level 2.
7204 ****************************************************************************/
7206 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7208 PORT_INFO_2 *ports=NULL;
7209 int i=0;
7211 if (*lp_enumports_cmd()) {
7212 char *cmd = lp_enumports_cmd();
7213 char *path;
7214 char **qlines;
7215 pstring tmp_file;
7216 pstring command;
7217 int numlines;
7218 int ret;
7219 int fd;
7221 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7222 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7223 else
7224 path = lp_lockdir();
7226 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7227 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7229 unlink(tmp_file);
7230 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7231 ret = smbrun(command, &fd);
7232 DEBUGADD(10,("returned [%d]\n", ret));
7233 if (ret != 0) {
7234 if (fd != -1)
7235 close(fd);
7236 /* Is this the best error to return here? */
7237 return WERR_ACCESS_DENIED;
7240 numlines = 0;
7241 qlines = fd_lines_load(fd, &numlines);
7242 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7243 close(fd);
7245 if(numlines) {
7246 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7247 file_lines_free(qlines);
7248 return WERR_NOMEM;
7251 for (i=0; i<numlines; i++) {
7252 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7253 fill_port_2(&(ports[i]), qlines[i]);
7256 file_lines_free(qlines);
7259 *returned = numlines;
7261 } else {
7263 *returned = 1;
7265 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7266 return WERR_NOMEM;
7268 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7270 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7273 /* check the required size. */
7274 for (i=0; i<*returned; i++) {
7275 DEBUGADD(6,("adding port [%d]'s size\n", i));
7276 *needed += spoolss_size_port_info_2(&ports[i]);
7279 if (!alloc_buffer_size(buffer, *needed)) {
7280 SAFE_FREE(ports);
7281 return WERR_INSUFFICIENT_BUFFER;
7284 /* fill the buffer with the ports structures */
7285 for (i=0; i<*returned; i++) {
7286 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7287 smb_io_port_2("", buffer, &ports[i], 0);
7290 SAFE_FREE(ports);
7292 if (*needed > offered) {
7293 *returned=0;
7294 return WERR_INSUFFICIENT_BUFFER;
7297 return WERR_OK;
7300 /****************************************************************************
7301 enumports.
7302 ****************************************************************************/
7304 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7306 uint32 level = q_u->level;
7307 NEW_BUFFER *buffer = NULL;
7308 uint32 offered = q_u->offered;
7309 uint32 *needed = &r_u->needed;
7310 uint32 *returned = &r_u->returned;
7312 /* that's an [in out] buffer */
7313 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7314 buffer = r_u->buffer;
7316 DEBUG(4,("_spoolss_enumports\n"));
7318 *returned=0;
7319 *needed=0;
7321 switch (level) {
7322 case 1:
7323 return enumports_level_1(buffer, offered, needed, returned);
7324 case 2:
7325 return enumports_level_2(buffer, offered, needed, returned);
7326 default:
7327 return WERR_UNKNOWN_LEVEL;
7331 /****************************************************************************
7332 ****************************************************************************/
7334 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7335 const SPOOL_PRINTER_INFO_LEVEL *info,
7336 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7337 uint32 user_switch, const SPOOL_USER_CTR *user,
7338 POLICY_HND *handle)
7340 NT_PRINTER_INFO_LEVEL *printer = NULL;
7341 fstring name;
7342 int snum;
7343 WERROR err = WERR_OK;
7345 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7346 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7347 return WERR_NOMEM;
7350 ZERO_STRUCTP(printer);
7352 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7353 if (!convert_printer_info(info, printer, 2)) {
7354 free_a_printer(&printer, 2);
7355 return WERR_NOMEM;
7358 /* check to see if the printer already exists */
7360 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7361 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7362 printer->info_2->sharename));
7363 free_a_printer(&printer, 2);
7364 return WERR_PRINTER_ALREADY_EXISTS;
7367 /* FIXME!!! smbd should check to see if the driver is installed before
7368 trying to add a printer like this --jerry */
7370 if (*lp_addprinter_cmd() ) {
7371 if ( !add_printer_hook(printer) ) {
7372 free_a_printer(&printer,2);
7373 return WERR_ACCESS_DENIED;
7377 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7378 printer->info_2->sharename);
7381 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7382 free_a_printer(&printer,2);
7383 return WERR_ACCESS_DENIED;
7386 /* you must be a printer admin to add a new printer */
7387 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7388 free_a_printer(&printer,2);
7389 return WERR_ACCESS_DENIED;
7393 * Do sanity check on the requested changes for Samba.
7396 if (!check_printer_ok(printer->info_2, snum)) {
7397 free_a_printer(&printer,2);
7398 return WERR_INVALID_PARAM;
7402 * When a printer is created, the drivername bound to the printer is used
7403 * to lookup previously saved driver initialization info, which is then
7404 * bound to the new printer, simulating what happens in the Windows arch.
7407 if (!devmode)
7409 set_driver_init(printer, 2);
7411 else
7413 /* A valid devmode was included, convert and link it
7415 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7417 if (!convert_devicemode(printer->info_2->printername, devmode,
7418 &printer->info_2->devmode))
7419 return WERR_NOMEM;
7422 /* write the ASCII on disk */
7423 err = mod_a_printer(*printer, 2);
7424 if (!W_ERROR_IS_OK(err)) {
7425 free_a_printer(&printer,2);
7426 return err;
7429 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7430 /* Handle open failed - remove addition. */
7431 del_a_printer(printer->info_2->sharename);
7432 free_a_printer(&printer,2);
7433 return WERR_ACCESS_DENIED;
7436 update_c_setprinter(False);
7437 free_a_printer(&printer,2);
7439 return WERR_OK;
7442 /****************************************************************************
7443 ****************************************************************************/
7445 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7447 UNISTR2 *uni_srv_name = &q_u->server_name;
7448 uint32 level = q_u->level;
7449 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7450 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7451 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7452 uint32 user_switch = q_u->user_switch;
7453 SPOOL_USER_CTR *user = &q_u->user_ctr;
7454 POLICY_HND *handle = &r_u->handle;
7456 switch (level) {
7457 case 1:
7458 /* we don't handle yet */
7459 /* but I know what to do ... */
7460 return WERR_UNKNOWN_LEVEL;
7461 case 2:
7462 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7463 devmode, sdb,
7464 user_switch, user, handle);
7465 default:
7466 return WERR_UNKNOWN_LEVEL;
7470 /****************************************************************************
7471 ****************************************************************************/
7473 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7475 uint32 level = q_u->level;
7476 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7477 WERROR err = WERR_OK;
7478 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7479 struct current_user user;
7480 fstring driver_name;
7481 uint32 version;
7483 ZERO_STRUCT(driver);
7485 get_current_user(&user, p);
7487 if (!convert_printer_driver_info(info, &driver, level)) {
7488 err = WERR_NOMEM;
7489 goto done;
7492 DEBUG(5,("Cleaning driver's information\n"));
7493 err = clean_up_driver_struct(driver, level, &user);
7494 if (!W_ERROR_IS_OK(err))
7495 goto done;
7497 DEBUG(5,("Moving driver to final destination\n"));
7498 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7499 if (W_ERROR_IS_OK(err))
7500 err = WERR_ACCESS_DENIED;
7501 goto done;
7504 if (add_a_printer_driver(driver, level)!=0) {
7505 err = WERR_ACCESS_DENIED;
7506 goto done;
7509 /* BEGIN_ADMIN_LOG */
7510 switch(level) {
7511 case 3:
7512 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7513 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7514 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7515 break;
7516 case 6:
7517 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7518 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7519 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7520 break;
7522 /* END_ADMIN_LOG */
7525 * I think this is where he DrvUpgradePrinter() hook would be
7526 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7527 * server. Right now, we just need to send ourselves a message
7528 * to update each printer bound to this driver. --jerry
7531 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7532 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7533 driver_name));
7537 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7538 * decide if the driver init data should be deleted. The rules are:
7539 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7540 * 2) delete init data only if there is no 2k/Xp driver
7541 * 3) always delete init data
7542 * The generalized rule is always use init data from the highest order driver.
7543 * It is necessary to follow the driver install by an initialization step to
7544 * finish off this process.
7546 if (level == 3)
7547 version = driver.info_3->cversion;
7548 else if (level == 6)
7549 version = driver.info_6->version;
7550 else
7551 version = -1;
7552 switch (version) {
7554 * 9x printer driver - never delete init data
7556 case 0:
7557 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7558 driver_name));
7559 break;
7562 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7563 * there is no 2k/Xp driver init data for this driver name.
7565 case 2:
7567 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7569 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7571 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7573 if (!del_driver_init(driver_name))
7574 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7575 } else {
7577 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7579 free_a_printer_driver(driver1,3);
7580 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7581 driver_name));
7584 break;
7587 * 2k or Xp printer driver - always delete init data
7589 case 3:
7590 if (!del_driver_init(driver_name))
7591 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7592 break;
7594 default:
7595 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7596 break;
7600 done:
7601 free_a_printer_driver(driver, level);
7602 return err;
7605 /********************************************************************
7606 * spoolss_addprinterdriverex
7607 ********************************************************************/
7609 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7611 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7612 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7615 * we only support the semantics of AddPrinterDriver()
7616 * i.e. only copy files that are newer than existing ones
7619 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7620 return WERR_ACCESS_DENIED;
7622 ZERO_STRUCT(q_u_local);
7623 ZERO_STRUCT(r_u_local);
7625 /* just pass the information off to _spoolss_addprinterdriver() */
7626 q_u_local.server_name_ptr = q_u->server_name_ptr;
7627 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7628 q_u_local.level = q_u->level;
7629 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7631 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7634 /****************************************************************************
7635 ****************************************************************************/
7637 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7639 init_unistr(&info->name, name);
7642 /****************************************************************************
7643 ****************************************************************************/
7645 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7647 pstring path;
7648 pstring long_archi;
7649 const char *short_archi;
7650 DRIVER_DIRECTORY_1 *info=NULL;
7652 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7654 if (!(short_archi = get_short_archi(long_archi)))
7655 return WERR_INVALID_ENVIRONMENT;
7657 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7658 return WERR_NOMEM;
7660 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7662 DEBUG(4,("printer driver directory: [%s]\n", path));
7664 fill_driverdir_1(info, path);
7666 *needed += spoolss_size_driverdir_info_1(info);
7668 if (!alloc_buffer_size(buffer, *needed)) {
7669 SAFE_FREE(info);
7670 return WERR_INSUFFICIENT_BUFFER;
7673 smb_io_driverdir_1("", buffer, info, 0);
7675 SAFE_FREE(info);
7677 if (*needed > offered)
7678 return WERR_INSUFFICIENT_BUFFER;
7680 return WERR_OK;
7683 /****************************************************************************
7684 ****************************************************************************/
7686 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7688 UNISTR2 *name = &q_u->name;
7689 UNISTR2 *uni_environment = &q_u->environment;
7690 uint32 level = q_u->level;
7691 NEW_BUFFER *buffer = NULL;
7692 uint32 offered = q_u->offered;
7693 uint32 *needed = &r_u->needed;
7695 /* that's an [in out] buffer */
7696 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7697 buffer = r_u->buffer;
7699 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7701 *needed=0;
7703 switch(level) {
7704 case 1:
7705 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7706 default:
7707 return WERR_UNKNOWN_LEVEL;
7711 /****************************************************************************
7712 ****************************************************************************/
7714 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7716 POLICY_HND *handle = &q_u->handle;
7717 uint32 idx = q_u->index;
7718 uint32 in_value_len = q_u->valuesize;
7719 uint32 in_data_len = q_u->datasize;
7720 uint32 *out_max_value_len = &r_u->valuesize;
7721 uint16 **out_value = &r_u->value;
7722 uint32 *out_value_len = &r_u->realvaluesize;
7723 uint32 *out_type = &r_u->type;
7724 uint32 *out_max_data_len = &r_u->datasize;
7725 uint8 **data_out = &r_u->data;
7726 uint32 *out_data_len = &r_u->realdatasize;
7728 NT_PRINTER_INFO_LEVEL *printer = NULL;
7730 uint32 biggest_valuesize;
7731 uint32 biggest_datasize;
7732 uint32 data_len;
7733 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7734 int snum;
7735 WERROR result;
7736 REGISTRY_VALUE *val = NULL;
7737 NT_PRINTER_DATA *p_data;
7738 int i, key_index, num_values;
7739 int name_length;
7741 ZERO_STRUCT( printer );
7743 *out_type = 0;
7745 *out_max_data_len = 0;
7746 *data_out = NULL;
7747 *out_data_len = 0;
7749 DEBUG(5,("spoolss_enumprinterdata\n"));
7751 if (!Printer) {
7752 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7753 return WERR_BADFID;
7756 if (!get_printer_snum(p,handle, &snum))
7757 return WERR_BADFID;
7759 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7760 if (!W_ERROR_IS_OK(result))
7761 return result;
7763 p_data = &printer->info_2->data;
7764 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7766 result = WERR_OK;
7769 * The NT machine wants to know the biggest size of value and data
7771 * cf: MSDN EnumPrinterData remark section
7774 if ( !in_value_len && !in_data_len && (key_index != -1) )
7776 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7778 biggest_valuesize = 0;
7779 biggest_datasize = 0;
7781 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7783 for ( i=0; i<num_values; i++ )
7785 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7787 name_length = strlen(val->valuename);
7788 if ( strlen(val->valuename) > biggest_valuesize )
7789 biggest_valuesize = name_length;
7791 if ( val->size > biggest_datasize )
7792 biggest_datasize = val->size;
7794 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7795 biggest_datasize));
7798 /* the value is an UNICODE string but real_value_size is the length
7799 in bytes including the trailing 0 */
7801 *out_value_len = 2 * (1+biggest_valuesize);
7802 *out_data_len = biggest_datasize;
7804 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7806 goto done;
7810 * the value len is wrong in NT sp3
7811 * that's the number of bytes not the number of unicode chars
7814 if ( key_index != -1 )
7815 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7817 if ( !val )
7820 /* out_value should default to "" or else NT4 has
7821 problems unmarshalling the response */
7823 *out_max_value_len=(in_value_len/sizeof(uint16));
7825 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7827 result = WERR_NOMEM;
7828 goto done;
7831 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7833 /* the data is counted in bytes */
7835 *out_max_data_len = in_data_len;
7836 *out_data_len = in_data_len;
7838 /* only allocate when given a non-zero data_len */
7840 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7842 result = WERR_NOMEM;
7843 goto done;
7846 result = WERR_NO_MORE_ITEMS;
7848 else
7851 * the value is:
7852 * - counted in bytes in the request
7853 * - counted in UNICODE chars in the max reply
7854 * - counted in bytes in the real size
7856 * take a pause *before* coding not *during* coding
7859 /* name */
7860 *out_max_value_len=(in_value_len/sizeof(uint16));
7861 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7863 result = WERR_NOMEM;
7864 goto done;
7867 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7869 /* type */
7871 *out_type = regval_type( val );
7873 /* data - counted in bytes */
7875 *out_max_data_len = in_data_len;
7876 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7878 result = WERR_NOMEM;
7879 goto done;
7881 data_len = (size_t)regval_size(val);
7882 memcpy( *data_out, regval_data_p(val), data_len );
7883 *out_data_len = data_len;
7886 done:
7887 free_a_printer(&printer, 2);
7888 return result;
7891 /****************************************************************************
7892 ****************************************************************************/
7894 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7896 POLICY_HND *handle = &q_u->handle;
7897 UNISTR2 *value = &q_u->value;
7898 uint32 type = q_u->type;
7899 uint8 *data = q_u->data;
7900 uint32 real_len = q_u->real_len;
7902 NT_PRINTER_INFO_LEVEL *printer = NULL;
7903 int snum=0;
7904 WERROR status = WERR_OK;
7905 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7906 fstring valuename;
7908 DEBUG(5,("spoolss_setprinterdata\n"));
7910 if (!Printer) {
7911 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7912 return WERR_BADFID;
7915 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7916 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7917 return WERR_INVALID_PARAM;
7920 if (!get_printer_snum(p,handle, &snum))
7921 return WERR_BADFID;
7924 * Access check : NT returns "access denied" if you make a
7925 * SetPrinterData call without the necessary privildge.
7926 * we were originally returning OK if nothing changed
7927 * which made Win2k issue **a lot** of SetPrinterData
7928 * when connecting to a printer --jerry
7931 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7933 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7934 status = WERR_ACCESS_DENIED;
7935 goto done;
7938 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7939 if (!W_ERROR_IS_OK(status))
7940 return status;
7942 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7945 * When client side code sets a magic printer data key, detect it and save
7946 * the current printer data and the magic key's data (its the DEVMODE) for
7947 * future printer/driver initializations.
7949 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7951 /* Set devmode and printer initialization info */
7952 status = save_driver_init( printer, 2, data, real_len );
7954 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7956 else
7958 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7959 type, data, real_len );
7960 if ( W_ERROR_IS_OK(status) )
7961 status = mod_a_printer(*printer, 2);
7964 done:
7965 free_a_printer(&printer, 2);
7967 return status;
7970 /****************************************************************************
7971 ****************************************************************************/
7973 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7975 POLICY_HND *handle = &q_u->handle;
7976 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7977 int snum;
7979 DEBUG(5,("_spoolss_resetprinter\n"));
7982 * All we do is to check to see if the handle and queue is valid.
7983 * This call really doesn't mean anything to us because we only
7984 * support RAW printing. --jerry
7987 if (!Printer) {
7988 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7989 return WERR_BADFID;
7992 if (!get_printer_snum(p,handle, &snum))
7993 return WERR_BADFID;
7996 /* blindly return success */
7997 return WERR_OK;
8001 /****************************************************************************
8002 ****************************************************************************/
8004 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8006 POLICY_HND *handle = &q_u->handle;
8007 UNISTR2 *value = &q_u->valuename;
8009 NT_PRINTER_INFO_LEVEL *printer = NULL;
8010 int snum=0;
8011 WERROR status = WERR_OK;
8012 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8013 pstring valuename;
8015 DEBUG(5,("spoolss_deleteprinterdata\n"));
8017 if (!Printer) {
8018 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8019 return WERR_BADFID;
8022 if (!get_printer_snum(p, handle, &snum))
8023 return WERR_BADFID;
8025 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8026 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8027 return WERR_ACCESS_DENIED;
8030 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8031 if (!W_ERROR_IS_OK(status))
8032 return status;
8034 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8036 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8038 if ( W_ERROR_IS_OK(status) )
8039 mod_a_printer( *printer, 2 );
8041 free_a_printer(&printer, 2);
8043 return status;
8046 /****************************************************************************
8047 ****************************************************************************/
8049 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8051 POLICY_HND *handle = &q_u->handle;
8052 FORM *form = &q_u->form;
8053 nt_forms_struct tmpForm;
8054 int snum;
8055 WERROR status = WERR_OK;
8056 NT_PRINTER_INFO_LEVEL *printer = NULL;
8058 int count=0;
8059 nt_forms_struct *list=NULL;
8060 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8062 DEBUG(5,("spoolss_addform\n"));
8064 if (!Printer) {
8065 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8066 return WERR_BADFID;
8070 /* forms can be added on printer of on the print server handle */
8072 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8074 if (!get_printer_snum(p,handle, &snum))
8075 return WERR_BADFID;
8077 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8078 if (!W_ERROR_IS_OK(status))
8079 goto done;
8082 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8083 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8084 status = WERR_ACCESS_DENIED;
8085 goto done;
8088 /* can't add if builtin */
8090 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8091 status = WERR_ALREADY_EXISTS;
8092 goto done;
8095 count = get_ntforms(&list);
8097 if(!add_a_form(&list, form, &count)) {
8098 status = WERR_NOMEM;
8099 goto done;
8102 write_ntforms(&list, count);
8105 * ChangeID must always be set if this is a printer
8108 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8109 status = mod_a_printer(*printer, 2);
8111 done:
8112 if ( printer )
8113 free_a_printer(&printer, 2);
8114 SAFE_FREE(list);
8116 return status;
8119 /****************************************************************************
8120 ****************************************************************************/
8122 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8124 POLICY_HND *handle = &q_u->handle;
8125 UNISTR2 *form_name = &q_u->name;
8126 nt_forms_struct tmpForm;
8127 int count=0;
8128 nt_forms_struct *list=NULL;
8129 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8130 int snum;
8131 WERROR status = WERR_OK;
8132 NT_PRINTER_INFO_LEVEL *printer = NULL;
8134 DEBUG(5,("spoolss_deleteform\n"));
8136 if (!Printer) {
8137 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8138 return WERR_BADFID;
8141 /* forms can be deleted on printer of on the print server handle */
8143 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8145 if (!get_printer_snum(p,handle, &snum))
8146 return WERR_BADFID;
8148 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8149 if (!W_ERROR_IS_OK(status))
8150 goto done;
8153 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8154 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8155 status = WERR_ACCESS_DENIED;
8156 goto done;
8159 /* can't delete if builtin */
8161 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8162 status = WERR_INVALID_PARAM;
8163 goto done;
8166 count = get_ntforms(&list);
8168 if ( !delete_a_form(&list, form_name, &count, &status ))
8169 goto done;
8172 * ChangeID must always be set if this is a printer
8175 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8176 status = mod_a_printer(*printer, 2);
8178 done:
8179 if ( printer )
8180 free_a_printer(&printer, 2);
8181 SAFE_FREE(list);
8183 return status;
8186 /****************************************************************************
8187 ****************************************************************************/
8189 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8191 POLICY_HND *handle = &q_u->handle;
8192 FORM *form = &q_u->form;
8193 nt_forms_struct tmpForm;
8194 int snum;
8195 WERROR status = WERR_OK;
8196 NT_PRINTER_INFO_LEVEL *printer = NULL;
8198 int count=0;
8199 nt_forms_struct *list=NULL;
8200 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8202 DEBUG(5,("spoolss_setform\n"));
8204 if (!Printer) {
8205 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8206 return WERR_BADFID;
8209 /* forms can be modified on printer of on the print server handle */
8211 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8213 if (!get_printer_snum(p,handle, &snum))
8214 return WERR_BADFID;
8216 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8217 if (!W_ERROR_IS_OK(status))
8218 goto done;
8221 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8222 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8223 status = WERR_ACCESS_DENIED;
8224 goto done;
8227 /* can't set if builtin */
8228 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8229 status = WERR_INVALID_PARAM;
8230 goto done;
8233 count = get_ntforms(&list);
8234 update_a_form(&list, form, count);
8235 write_ntforms(&list, count);
8238 * ChangeID must always be set if this is a printer
8241 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8242 status = mod_a_printer(*printer, 2);
8245 done:
8246 if ( printer )
8247 free_a_printer(&printer, 2);
8248 SAFE_FREE(list);
8250 return status;
8253 /****************************************************************************
8254 enumprintprocessors level 1.
8255 ****************************************************************************/
8257 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8259 PRINTPROCESSOR_1 *info_1=NULL;
8261 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8262 return WERR_NOMEM;
8264 (*returned) = 0x1;
8266 init_unistr(&info_1->name, "winprint");
8268 *needed += spoolss_size_printprocessor_info_1(info_1);
8270 if (!alloc_buffer_size(buffer, *needed))
8271 return WERR_INSUFFICIENT_BUFFER;
8273 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8275 SAFE_FREE(info_1);
8277 if (*needed > offered) {
8278 *returned=0;
8279 return WERR_INSUFFICIENT_BUFFER;
8282 return WERR_OK;
8285 /****************************************************************************
8286 ****************************************************************************/
8288 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8290 uint32 level = q_u->level;
8291 NEW_BUFFER *buffer = NULL;
8292 uint32 offered = q_u->offered;
8293 uint32 *needed = &r_u->needed;
8294 uint32 *returned = &r_u->returned;
8296 /* that's an [in out] buffer */
8297 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8298 buffer = r_u->buffer;
8300 DEBUG(5,("spoolss_enumprintprocessors\n"));
8303 * Enumerate the print processors ...
8305 * Just reply with "winprint", to keep NT happy
8306 * and I can use my nice printer checker.
8309 *returned=0;
8310 *needed=0;
8312 switch (level) {
8313 case 1:
8314 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8315 default:
8316 return WERR_UNKNOWN_LEVEL;
8320 /****************************************************************************
8321 enumprintprocdatatypes level 1.
8322 ****************************************************************************/
8324 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8326 PRINTPROCDATATYPE_1 *info_1=NULL;
8328 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8329 return WERR_NOMEM;
8331 (*returned) = 0x1;
8333 init_unistr(&info_1->name, "RAW");
8335 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8337 if (!alloc_buffer_size(buffer, *needed))
8338 return WERR_INSUFFICIENT_BUFFER;
8340 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8342 SAFE_FREE(info_1);
8344 if (*needed > offered) {
8345 *returned=0;
8346 return WERR_INSUFFICIENT_BUFFER;
8349 return WERR_OK;
8352 /****************************************************************************
8353 ****************************************************************************/
8355 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8357 uint32 level = q_u->level;
8358 NEW_BUFFER *buffer = NULL;
8359 uint32 offered = q_u->offered;
8360 uint32 *needed = &r_u->needed;
8361 uint32 *returned = &r_u->returned;
8363 /* that's an [in out] buffer */
8364 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8365 buffer = r_u->buffer;
8367 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8369 *returned=0;
8370 *needed=0;
8372 switch (level) {
8373 case 1:
8374 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8375 default:
8376 return WERR_UNKNOWN_LEVEL;
8380 /****************************************************************************
8381 enumprintmonitors level 1.
8382 ****************************************************************************/
8384 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8386 PRINTMONITOR_1 *info_1=NULL;
8388 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8389 return WERR_NOMEM;
8391 (*returned) = 0x1;
8393 init_unistr(&info_1->name, "Local Port");
8395 *needed += spoolss_size_printmonitor_info_1(info_1);
8397 if (!alloc_buffer_size(buffer, *needed))
8398 return WERR_INSUFFICIENT_BUFFER;
8400 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8402 SAFE_FREE(info_1);
8404 if (*needed > offered) {
8405 *returned=0;
8406 return WERR_INSUFFICIENT_BUFFER;
8409 return WERR_OK;
8412 /****************************************************************************
8413 enumprintmonitors level 2.
8414 ****************************************************************************/
8416 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8418 PRINTMONITOR_2 *info_2=NULL;
8420 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8421 return WERR_NOMEM;
8423 (*returned) = 0x1;
8425 init_unistr(&info_2->name, "Local Port");
8426 init_unistr(&info_2->environment, "Windows NT X86");
8427 init_unistr(&info_2->dll_name, "localmon.dll");
8429 *needed += spoolss_size_printmonitor_info_2(info_2);
8431 if (!alloc_buffer_size(buffer, *needed))
8432 return WERR_INSUFFICIENT_BUFFER;
8434 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8436 SAFE_FREE(info_2);
8438 if (*needed > offered) {
8439 *returned=0;
8440 return WERR_INSUFFICIENT_BUFFER;
8443 return WERR_OK;
8446 /****************************************************************************
8447 ****************************************************************************/
8449 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8451 uint32 level = q_u->level;
8452 NEW_BUFFER *buffer = NULL;
8453 uint32 offered = q_u->offered;
8454 uint32 *needed = &r_u->needed;
8455 uint32 *returned = &r_u->returned;
8457 /* that's an [in out] buffer */
8458 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8459 buffer = r_u->buffer;
8461 DEBUG(5,("spoolss_enumprintmonitors\n"));
8464 * Enumerate the print monitors ...
8466 * Just reply with "Local Port", to keep NT happy
8467 * and I can use my nice printer checker.
8470 *returned=0;
8471 *needed=0;
8473 switch (level) {
8474 case 1:
8475 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8476 case 2:
8477 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8478 default:
8479 return WERR_UNKNOWN_LEVEL;
8483 /****************************************************************************
8484 ****************************************************************************/
8486 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8488 int i=0;
8489 BOOL found=False;
8490 JOB_INFO_1 *info_1=NULL;
8492 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8494 if (info_1 == NULL) {
8495 return WERR_NOMEM;
8498 for (i=0; i<count && found==False; i++) {
8499 if ((*queue)[i].job==(int)jobid)
8500 found=True;
8503 if (found==False) {
8504 SAFE_FREE(info_1);
8505 /* NT treats not found as bad param... yet another bad choice */
8506 return WERR_INVALID_PARAM;
8509 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8511 *needed += spoolss_size_job_info_1(info_1);
8513 if (!alloc_buffer_size(buffer, *needed)) {
8514 SAFE_FREE(info_1);
8515 return WERR_INSUFFICIENT_BUFFER;
8518 smb_io_job_info_1("", buffer, info_1, 0);
8520 SAFE_FREE(info_1);
8522 if (*needed > offered)
8523 return WERR_INSUFFICIENT_BUFFER;
8525 return WERR_OK;
8528 /****************************************************************************
8529 ****************************************************************************/
8531 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8533 int i = 0;
8534 BOOL found = False;
8535 JOB_INFO_2 *info_2;
8536 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8537 WERROR ret;
8538 DEVICEMODE *devmode = NULL;
8539 NT_DEVICEMODE *nt_devmode = NULL;
8541 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8543 ZERO_STRUCTP(info_2);
8545 if (info_2 == NULL) {
8546 ret = WERR_NOMEM;
8547 goto done;
8550 for ( i=0; i<count && found==False; i++ )
8552 if ((*queue)[i].job == (int)jobid)
8553 found = True;
8556 if ( !found )
8558 /* NT treats not found as bad param... yet another bad
8559 choice */
8560 ret = WERR_INVALID_PARAM;
8561 goto done;
8564 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8565 if (!W_ERROR_IS_OK(ret))
8566 goto done;
8569 * if the print job does not have a DEVMODE associated with it,
8570 * just use the one for the printer. A NULL devicemode is not
8571 * a failure condition
8574 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8575 devmode = construct_dev_mode(snum);
8576 else {
8577 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8578 ZERO_STRUCTP( devmode );
8579 convert_nt_devicemode( devmode, nt_devmode );
8583 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8585 *needed += spoolss_size_job_info_2(info_2);
8587 if (!alloc_buffer_size(buffer, *needed)) {
8588 ret = WERR_INSUFFICIENT_BUFFER;
8589 goto done;
8592 smb_io_job_info_2("", buffer, info_2, 0);
8594 if (*needed > offered) {
8595 ret = WERR_INSUFFICIENT_BUFFER;
8596 goto done;
8599 ret = WERR_OK;
8601 done:
8602 /* Cleanup allocated memory */
8604 free_job_info_2(info_2); /* Also frees devmode */
8605 SAFE_FREE(info_2);
8606 free_a_printer(&ntprinter, 2);
8608 return ret;
8611 /****************************************************************************
8612 ****************************************************************************/
8614 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8616 POLICY_HND *handle = &q_u->handle;
8617 uint32 jobid = q_u->jobid;
8618 uint32 level = q_u->level;
8619 NEW_BUFFER *buffer = NULL;
8620 uint32 offered = q_u->offered;
8621 uint32 *needed = &r_u->needed;
8622 WERROR wstatus = WERR_OK;
8624 int snum;
8625 int count;
8626 print_queue_struct *queue = NULL;
8627 print_status_struct prt_status;
8629 /* that's an [in out] buffer */
8630 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8631 buffer = r_u->buffer;
8633 DEBUG(5,("spoolss_getjob\n"));
8635 *needed = 0;
8637 if (!get_printer_snum(p, handle, &snum))
8638 return WERR_BADFID;
8640 count = print_queue_status(snum, &queue, &prt_status);
8642 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8643 count, prt_status.status, prt_status.message));
8645 switch ( level ) {
8646 case 1:
8647 wstatus = getjob_level_1(&queue, count, snum, jobid,
8648 buffer, offered, needed);
8649 break;
8650 case 2:
8651 wstatus = getjob_level_2(&queue, count, snum, jobid,
8652 buffer, offered, needed);
8653 break;
8654 default:
8655 wstatus = WERR_UNKNOWN_LEVEL;
8656 break;
8659 SAFE_FREE(queue);
8660 return wstatus;
8663 /********************************************************************
8664 spoolss_getprinterdataex
8666 From MSDN documentation of GetPrinterDataEx: pass request
8667 to GetPrinterData if key is "PrinterDriverData".
8668 ********************************************************************/
8670 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8672 POLICY_HND *handle = &q_u->handle;
8673 uint32 in_size = q_u->size;
8674 uint32 *type = &r_u->type;
8675 uint32 *out_size = &r_u->size;
8676 uint8 **data = &r_u->data;
8677 uint32 *needed = &r_u->needed;
8678 fstring keyname, valuename;
8680 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8682 NT_PRINTER_INFO_LEVEL *printer = NULL;
8683 int snum = 0;
8684 WERROR status = WERR_OK;
8686 DEBUG(4,("_spoolss_getprinterdataex\n"));
8688 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8689 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8691 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8692 keyname, valuename));
8694 /* in case of problem, return some default values */
8696 *needed = 0;
8697 *type = 0;
8698 *out_size = in_size;
8700 if (!Printer) {
8701 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8702 status = WERR_BADFID;
8703 goto done;
8706 /* Is the handle to a printer or to the server? */
8708 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8709 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8710 status = WERR_INVALID_PARAM;
8711 goto done;
8714 if ( !get_printer_snum(p,handle, &snum) )
8715 return WERR_BADFID;
8717 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8718 if ( !W_ERROR_IS_OK(status) )
8719 goto done;
8721 /* check to see if the keyname is valid */
8722 if ( !strlen(keyname) ) {
8723 status = WERR_INVALID_PARAM;
8724 goto done;
8727 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8728 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8729 free_a_printer( &printer, 2 );
8730 status = WERR_BADFILE;
8731 goto done;
8734 /* When given a new keyname, we should just create it */
8736 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8738 if (*needed > *out_size)
8739 status = WERR_MORE_DATA;
8741 done:
8742 if ( !W_ERROR_IS_OK(status) )
8744 DEBUG(5, ("error: allocating %d\n", *out_size));
8746 /* reply this param doesn't exist */
8748 if ( *out_size )
8750 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8751 status = WERR_NOMEM;
8752 goto done;
8755 else {
8756 *data = NULL;
8760 if ( printer )
8761 free_a_printer( &printer, 2 );
8763 return status;
8766 /********************************************************************
8767 * spoolss_setprinterdataex
8768 ********************************************************************/
8770 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8772 POLICY_HND *handle = &q_u->handle;
8773 uint32 type = q_u->type;
8774 uint8 *data = q_u->data;
8775 uint32 real_len = q_u->real_len;
8777 NT_PRINTER_INFO_LEVEL *printer = NULL;
8778 int snum = 0;
8779 WERROR status = WERR_OK;
8780 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8781 fstring valuename;
8782 fstring keyname;
8783 char *oid_string;
8785 DEBUG(4,("_spoolss_setprinterdataex\n"));
8787 /* From MSDN documentation of SetPrinterDataEx: pass request to
8788 SetPrinterData if key is "PrinterDriverData" */
8790 if (!Printer) {
8791 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8792 return WERR_BADFID;
8795 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8796 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8797 return WERR_INVALID_PARAM;
8800 if ( !get_printer_snum(p,handle, &snum) )
8801 return WERR_BADFID;
8804 * Access check : NT returns "access denied" if you make a
8805 * SetPrinterData call without the necessary privildge.
8806 * we were originally returning OK if nothing changed
8807 * which made Win2k issue **a lot** of SetPrinterData
8808 * when connecting to a printer --jerry
8811 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8813 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8814 return WERR_ACCESS_DENIED;
8817 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8818 if (!W_ERROR_IS_OK(status))
8819 return status;
8821 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8822 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8824 /* check for OID in valuename */
8826 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8828 *oid_string = '\0';
8829 oid_string++;
8832 /* save the registry data */
8834 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8836 if ( W_ERROR_IS_OK(status) )
8838 /* save the OID if one was specified */
8839 if ( oid_string ) {
8840 fstrcat( keyname, "\\" );
8841 fstrcat( keyname, SPOOL_OID_KEY );
8844 * I'm not checking the status here on purpose. Don't know
8845 * if this is right, but I'm returning the status from the
8846 * previous set_printer_dataex() call. I have no idea if
8847 * this is right. --jerry
8850 set_printer_dataex( printer, keyname, valuename,
8851 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8854 status = mod_a_printer(*printer, 2);
8857 free_a_printer(&printer, 2);
8859 return status;
8863 /********************************************************************
8864 * spoolss_deleteprinterdataex
8865 ********************************************************************/
8867 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8869 POLICY_HND *handle = &q_u->handle;
8870 UNISTR2 *value = &q_u->valuename;
8871 UNISTR2 *key = &q_u->keyname;
8873 NT_PRINTER_INFO_LEVEL *printer = NULL;
8874 int snum=0;
8875 WERROR status = WERR_OK;
8876 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8877 pstring valuename, keyname;
8879 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8881 if (!Printer) {
8882 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8883 return WERR_BADFID;
8886 if (!get_printer_snum(p, handle, &snum))
8887 return WERR_BADFID;
8889 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8890 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8891 return WERR_ACCESS_DENIED;
8894 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8895 if (!W_ERROR_IS_OK(status))
8896 return status;
8898 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8899 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8901 status = delete_printer_dataex( printer, keyname, valuename );
8903 if ( W_ERROR_IS_OK(status) )
8904 mod_a_printer( *printer, 2 );
8906 free_a_printer(&printer, 2);
8908 return status;
8911 /********************************************************************
8912 * spoolss_enumprinterkey
8913 ********************************************************************/
8916 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8918 fstring key;
8919 fstring *keynames = NULL;
8920 uint16 *enumkeys = NULL;
8921 int num_keys;
8922 int printerkey_len;
8923 POLICY_HND *handle = &q_u->handle;
8924 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8925 NT_PRINTER_DATA *data;
8926 NT_PRINTER_INFO_LEVEL *printer = NULL;
8927 int snum = 0;
8928 WERROR status = WERR_BADFILE;
8931 DEBUG(4,("_spoolss_enumprinterkey\n"));
8933 if (!Printer) {
8934 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8935 return WERR_BADFID;
8938 if ( !get_printer_snum(p,handle, &snum) )
8939 return WERR_BADFID;
8941 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8942 if (!W_ERROR_IS_OK(status))
8943 return status;
8945 /* get the list of subkey names */
8947 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8948 data = &printer->info_2->data;
8950 num_keys = get_printer_subkeys( data, key, &keynames );
8952 if ( num_keys == -1 ) {
8953 status = WERR_BADFILE;
8954 goto done;
8957 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8959 r_u->needed = printerkey_len*2;
8961 if ( q_u->size < r_u->needed ) {
8962 status = WERR_MORE_DATA;
8963 goto done;
8966 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8967 status = WERR_NOMEM;
8968 goto done;
8971 status = WERR_OK;
8973 if ( q_u->size < r_u->needed )
8974 status = WERR_MORE_DATA;
8976 done:
8977 free_a_printer( &printer, 2 );
8978 SAFE_FREE( keynames );
8980 return status;
8983 /********************************************************************
8984 * spoolss_deleteprinterkey
8985 ********************************************************************/
8987 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8989 POLICY_HND *handle = &q_u->handle;
8990 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8991 fstring key;
8992 NT_PRINTER_INFO_LEVEL *printer = NULL;
8993 int snum=0;
8994 WERROR status;
8996 DEBUG(5,("spoolss_deleteprinterkey\n"));
8998 if (!Printer) {
8999 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9000 return WERR_BADFID;
9003 /* if keyname == NULL, return error */
9005 if ( !q_u->keyname.buffer )
9006 return WERR_INVALID_PARAM;
9008 if (!get_printer_snum(p, handle, &snum))
9009 return WERR_BADFID;
9011 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9012 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9013 return WERR_ACCESS_DENIED;
9016 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9017 if (!W_ERROR_IS_OK(status))
9018 return status;
9020 /* delete the key and all subneys */
9022 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9024 status = delete_all_printer_data( printer->info_2, key );
9026 if ( W_ERROR_IS_OK(status) )
9027 status = mod_a_printer(*printer, 2);
9029 free_a_printer( &printer, 2 );
9031 return status;
9035 /********************************************************************
9036 * spoolss_enumprinterdataex
9037 ********************************************************************/
9039 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9041 POLICY_HND *handle = &q_u->handle;
9042 uint32 in_size = q_u->size;
9043 uint32 num_entries,
9044 needed;
9045 NT_PRINTER_INFO_LEVEL *printer = NULL;
9046 PRINTER_ENUM_VALUES *enum_values = NULL;
9047 NT_PRINTER_DATA *p_data;
9048 fstring key;
9049 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9050 int snum;
9051 WERROR result;
9052 int key_index;
9053 int i;
9054 REGISTRY_VALUE *val;
9055 char *value_name;
9056 int data_len;
9059 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9061 if (!Printer) {
9062 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9063 return WERR_BADFID;
9067 * first check for a keyname of NULL or "". Win2k seems to send
9068 * this a lot and we should send back WERR_INVALID_PARAM
9069 * no need to spend time looking up the printer in this case.
9070 * --jerry
9073 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9074 if ( !strlen(key) ) {
9075 result = WERR_INVALID_PARAM;
9076 goto done;
9079 /* get the printer off of disk */
9081 if (!get_printer_snum(p,handle, &snum))
9082 return WERR_BADFID;
9084 ZERO_STRUCT(printer);
9085 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9086 if (!W_ERROR_IS_OK(result))
9087 return result;
9089 /* now look for a match on the key name */
9091 p_data = &printer->info_2->data;
9093 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9094 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9096 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9097 result = WERR_INVALID_PARAM;
9098 goto done;
9101 result = WERR_OK;
9102 needed = 0;
9104 /* allocate the memory for the array of pointers -- if necessary */
9106 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9107 if ( num_entries )
9109 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9111 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9112 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9113 result = WERR_NOMEM;
9114 goto done;
9117 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9121 * loop through all params and build the array to pass
9122 * back to the client
9125 for ( i=0; i<num_entries; i++ )
9127 /* lookup the registry value */
9129 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9130 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9132 /* copy the data */
9134 value_name = regval_name( val );
9135 init_unistr( &enum_values[i].valuename, value_name );
9136 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9137 enum_values[i].type = regval_type( val );
9139 data_len = regval_size( val );
9140 if ( data_len ) {
9141 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9143 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9144 data_len ));
9145 result = WERR_NOMEM;
9146 goto done;
9149 enum_values[i].data_len = data_len;
9151 /* keep track of the size of the array in bytes */
9153 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9156 /* housekeeping information in the reply */
9158 r_u->needed = needed;
9159 r_u->returned = num_entries;
9161 if (needed > in_size) {
9162 result = WERR_MORE_DATA;
9163 goto done;
9166 /* copy data into the reply */
9168 r_u->ctr.size = r_u->needed;
9169 r_u->ctr.size_of_array = r_u->returned;
9170 r_u->ctr.values = enum_values;
9174 done:
9175 if ( printer )
9176 free_a_printer(&printer, 2);
9178 return result;
9181 /****************************************************************************
9182 ****************************************************************************/
9184 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9186 init_unistr(&info->name, name);
9189 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9190 UNISTR2 *environment,
9191 NEW_BUFFER *buffer,
9192 uint32 offered,
9193 uint32 *needed)
9195 pstring path;
9196 pstring long_archi;
9197 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9199 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9201 if (!get_short_archi(long_archi))
9202 return WERR_INVALID_ENVIRONMENT;
9204 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9205 return WERR_NOMEM;
9207 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9209 fill_printprocessordirectory_1(info, path);
9211 *needed += spoolss_size_printprocessordirectory_info_1(info);
9213 if (!alloc_buffer_size(buffer, *needed)) {
9214 safe_free(info);
9215 return WERR_INSUFFICIENT_BUFFER;
9218 smb_io_printprocessordirectory_1("", buffer, info, 0);
9220 safe_free(info);
9222 if (*needed > offered)
9223 return WERR_INSUFFICIENT_BUFFER;
9224 else
9225 return WERR_OK;
9228 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9230 uint32 level = q_u->level;
9231 NEW_BUFFER *buffer = NULL;
9232 uint32 offered = q_u->offered;
9233 uint32 *needed = &r_u->needed;
9234 WERROR result;
9236 /* that's an [in out] buffer */
9237 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9238 buffer = r_u->buffer;
9240 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9242 *needed=0;
9244 switch(level) {
9245 case 1:
9246 result = getprintprocessordirectory_level_1
9247 (&q_u->name, &q_u->environment, buffer, offered, needed);
9248 break;
9249 default:
9250 result = WERR_UNKNOWN_LEVEL;
9253 return result;
9256 #if 0
9258 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9259 SPOOL_R_REPLYOPENPRINTER *r_u)
9261 DEBUG(5,("_spoolss_replyopenprinter\n"));
9263 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9265 return WERR_OK;
9268 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9269 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9271 DEBUG(5,("_spoolss_replycloseprinter\n"));
9272 return WERR_OK;
9275 #endif