r2565: syncing up for 3.0.8pre1
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blobd50237905aefba2f375ab39477eec8871a18fbc0
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
29 #include "includes.h"
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_RPC_SRV
34 #ifndef MAX_OPEN_PRINTER_EXS
35 #define MAX_OPEN_PRINTER_EXS 50
36 #endif
38 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
39 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42 /* Table to map the driver version */
43 /* to OS */
44 static const char * drv_ver_to_os[] = {
45 "WIN9X", /* driver version/cversion 0 */
46 "", /* unused ? */
47 "WINNT", /* driver version/cversion 2 */
48 "WIN2K", /* driver version/cversion 3 */
51 static const char *get_drv_ver_to_os(int ver)
53 if (ver < 0 || ver > 3)
54 return "";
55 return drv_ver_to_os[ver];
58 struct table_node {
59 const char *long_archi;
60 const char *short_archi;
61 int version;
64 static Printer_entry *printers_list;
66 typedef struct _counter_printer_0 {
67 struct _counter_printer_0 *next;
68 struct _counter_printer_0 *prev;
70 int snum;
71 uint32 counter;
72 } counter_printer_0;
74 static counter_printer_0 *counter_list;
76 static struct cli_state notify_cli; /* print notify back-channel */
77 static uint32 smb_connections=0;
80 /* in printing/nt_printing.c */
82 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
84 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
85 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
87 /* translate between internal status numbers and NT status numbers */
88 static int nt_printj_status(int v)
90 switch (v) {
91 case LPQ_QUEUED:
92 return 0;
93 case LPQ_PAUSED:
94 return JOB_STATUS_PAUSED;
95 case LPQ_SPOOLING:
96 return JOB_STATUS_SPOOLING;
97 case LPQ_PRINTING:
98 return JOB_STATUS_PRINTING;
99 case LPQ_ERROR:
100 return JOB_STATUS_ERROR;
101 case LPQ_DELETING:
102 return JOB_STATUS_DELETING;
103 case LPQ_OFFLINE:
104 return JOB_STATUS_OFFLINE;
105 case LPQ_PAPEROUT:
106 return JOB_STATUS_PAPEROUT;
107 case LPQ_PRINTED:
108 return JOB_STATUS_PRINTED;
109 case LPQ_DELETED:
110 return JOB_STATUS_DELETED;
111 case LPQ_BLOCKED:
112 return JOB_STATUS_BLOCKED;
113 case LPQ_USER_INTERVENTION:
114 return JOB_STATUS_USER_INTERVENTION;
116 return 0;
119 static int nt_printq_status(int v)
121 switch (v) {
122 case LPQ_PAUSED:
123 return PRINTER_STATUS_PAUSED;
124 case LPQ_QUEUED:
125 case LPQ_SPOOLING:
126 case LPQ_PRINTING:
127 return 0;
129 return 0;
132 /****************************************************************************
133 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
134 ****************************************************************************/
136 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
138 if (*pp == NULL)
139 return;
141 SAFE_FREE((*pp)->ctr.type);
142 SAFE_FREE(*pp);
145 /***************************************************************************
146 Disconnect from the client
147 ****************************************************************************/
149 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
151 WERROR result;
154 * Tell the specific printing tdb we no longer want messages for this printer
155 * by deregistering our PID.
158 if (!print_notify_deregister_pid(snum))
159 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
161 /* weird if the test succeds !!! */
162 if (smb_connections==0) {
163 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
164 return;
167 result = cli_spoolss_reply_close_printer(&notify_cli, notify_cli.mem_ctx, handle);
169 if (!W_ERROR_IS_OK(result))
170 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171 dos_errstr(result)));
173 /* if it's the last connection, deconnect the IPC$ share */
174 if (smb_connections==1) {
175 cli_nt_session_close(&notify_cli);
176 cli_ulogoff(&notify_cli);
177 cli_shutdown(&notify_cli);
178 message_deregister(MSG_PRINTER_NOTIFY2);
180 /* Tell the connections db we're no longer interested in
181 * printer notify messages. */
183 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
186 smb_connections--;
189 /****************************************************************************
190 Functions to free a printer entry datastruct.
191 ****************************************************************************/
193 static void free_printer_entry(void *ptr)
195 Printer_entry *Printer = (Printer_entry *)ptr;
197 if (Printer->notify.client_connected==True) {
198 int snum = -1;
200 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
201 snum = -1;
202 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
204 snum = print_queue_snum(Printer->dev.handlename);
205 if (snum != -1)
206 srv_spoolss_replycloseprinter(snum,
207 &Printer->notify.client_hnd);
211 Printer->notify.flags=0;
212 Printer->notify.options=0;
213 Printer->notify.localmachine[0]='\0';
214 Printer->notify.printerlocal=0;
215 free_spool_notify_option(&Printer->notify.option);
216 Printer->notify.option=NULL;
217 Printer->notify.client_connected=False;
219 free_nt_devicemode( &Printer->nt_devmode );
220 free_a_printer( &Printer->printer_info, 2 );
222 talloc_destroy( Printer->ctx );
224 /* Remove from the internal list. */
225 DLIST_REMOVE(printers_list, Printer);
227 SAFE_FREE(Printer);
230 /****************************************************************************
231 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
232 ****************************************************************************/
234 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
236 SPOOL_NOTIFY_OPTION *new_sp = NULL;
238 if (!sp)
239 return NULL;
241 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
242 if (!new_sp)
243 return NULL;
245 *new_sp = *sp;
247 if (sp->ctr.count) {
248 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
250 if (!new_sp->ctr.type) {
251 SAFE_FREE(new_sp);
252 return NULL;
256 return new_sp;
259 /****************************************************************************
260 find printer index by handle
261 ****************************************************************************/
263 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
265 Printer_entry *find_printer = NULL;
267 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
268 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
269 return NULL;
272 return find_printer;
275 /****************************************************************************
276 look for a printer object cached on an open printer handle
277 ****************************************************************************/
279 WERROR find_printer_in_print_hnd_cache( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 **info2,
280 const char *printername )
282 Printer_entry *p;
284 DEBUG(10,("find_printer_in_print_hnd_cache: printer [%s]\n", printername));
286 for ( p=printers_list; p; p=p->next )
288 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
289 && p->printer_info
290 && StrCaseCmp(p->dev.handlename, printername) == 0 )
292 DEBUG(10,("Found printer\n"));
293 *info2 = dup_printer_2( ctx, p->printer_info->info_2 );
294 if ( *info2 )
295 return WERR_OK;
299 return WERR_INVALID_PRINTER_NAME;
302 /****************************************************************************
303 destroy any cached printer_info_2 structures on open handles
304 ****************************************************************************/
306 void invalidate_printer_hnd_cache( char *printername )
308 Printer_entry *p;
310 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
312 for ( p=printers_list; p; p=p->next )
314 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
315 && p->printer_info
316 && StrCaseCmp(p->dev.handlename, printername)==0)
318 DEBUG(10,("invalidating printer_info cache for handl:\n"));
319 free_a_printer( &p->printer_info, 2 );
320 p->printer_info = NULL;
324 return;
326 /****************************************************************************
327 Close printer index by handle.
328 ****************************************************************************/
330 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
332 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
334 if (!Printer) {
335 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
336 return False;
339 close_policy_hnd(p, hnd);
341 return True;
344 /****************************************************************************
345 Delete a printer given a handle.
346 ****************************************************************************/
348 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
350 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
352 if (!Printer) {
353 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
354 return WERR_BADFID;
358 * It turns out that Windows allows delete printer on a handle
359 * opened by an admin user, then used on a pipe handle created
360 * by an anonymous user..... but they're working on security.... riiight !
361 * JRA.
364 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
365 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
366 return WERR_ACCESS_DENIED;
369 #if 0
370 /* Check calling user has permission to delete printer. Note that
371 since we set the snum parameter to -1 only administrators can
372 delete the printer. This stops people with the Full Control
373 permission from deleting the printer. */
375 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
376 DEBUG(3, ("printer delete denied by security descriptor\n"));
377 return WERR_ACCESS_DENIED;
379 #endif
381 if (del_a_printer(Printer->dev.handlename) != 0) {
382 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
383 return WERR_BADFID;
386 if (*lp_deleteprinter_cmd()) {
388 char *cmd = lp_deleteprinter_cmd();
389 pstring command;
390 int ret;
392 /* Printer->dev.handlename equals portname equals sharename */
393 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
394 Printer->dev.handlename);
396 DEBUG(10,("Running [%s]\n", command));
397 ret = smbrun(command, NULL);
398 if (ret != 0) {
399 return WERR_BADFID; /* What to return here? */
401 DEBUGADD(10,("returned [%d]\n", ret));
403 /* Send SIGHUP to process group... is there a better way? */
404 kill(0, SIGHUP);
406 /* go ahead and re-read the services immediately */
407 reload_services( False );
409 if ( lp_servicenumber( Printer->dev.handlename ) < 0 )
410 return WERR_ACCESS_DENIED;
413 return WERR_OK;
416 /****************************************************************************
417 Return the snum of a printer corresponding to an handle.
418 ****************************************************************************/
420 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
422 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
424 if (!Printer) {
425 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
426 return False;
429 switch (Printer->printer_type) {
430 case PRINTER_HANDLE_IS_PRINTER:
431 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
432 *number = print_queue_snum(Printer->dev.handlename);
433 return (*number != -1);
434 case PRINTER_HANDLE_IS_PRINTSERVER:
435 return False;
436 default:
437 return False;
441 /****************************************************************************
442 Set printer handle type.
443 Check if it's \\server or \\server\printer
444 ****************************************************************************/
446 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
448 DEBUG(3,("Setting printer type=%s\n", handlename));
450 if ( strlen(handlename) < 3 ) {
451 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
452 return False;
455 /* it's a print server */
456 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
457 DEBUGADD(4,("Printer is a print server\n"));
458 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
460 /* it's a printer */
461 else {
462 DEBUGADD(4,("Printer is a printer\n"));
463 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
466 return True;
469 /****************************************************************************
470 Set printer handle name.
471 ****************************************************************************/
473 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
475 int snum;
476 int n_services=lp_numservices();
477 char *aprinter, *printername;
478 fstring sname;
479 BOOL found=False;
480 NT_PRINTER_INFO_LEVEL *printer;
481 WERROR result;
483 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
485 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
486 ZERO_STRUCT(Printer->dev.printerservername);
487 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
488 return True;
491 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
492 return False;
494 if (*handlename=='\\') {
495 aprinter=strchr_m(handlename+2, '\\');
496 aprinter++;
498 else {
499 aprinter=handlename;
502 DEBUGADD(5, ("searching for [%s] (len=%lu)\n", aprinter, (unsigned long)strlen(aprinter)));
504 /* have to search on sharename and PRINTER_INFO2->printername */
506 for (snum=0; snum<n_services; snum++) {
508 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
509 continue;
511 /* ------ sharename ------ */
513 fstrcpy(sname, lp_servicename(snum));
515 DEBUGADD(10, ("share: %s\n",sname));
517 if ( strequal(sname, aprinter) ) {
518 found = True;
519 break;
522 /* ------ printername ------ */
524 printer = NULL;
525 result = get_a_printer( NULL, &printer, 2, sname );
526 if ( !W_ERROR_IS_OK(result) ) {
527 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
528 sname, dos_errstr(result)));
529 continue;
532 /* printername is always returned as \\server\printername */
533 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
534 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
535 printer->info_2->printername));
536 free_a_printer( &printer, 2);
537 continue;
540 printername++;
542 if ( strequal(printername, aprinter) ) {
543 found = True;
546 DEBUGADD(10, ("printername: %s\n", printername));
548 free_a_printer( &printer, 2);
550 if ( found )
551 break;
555 if (!found) {
556 DEBUGADD(4,("Printer not found\n"));
557 return False;
560 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
562 ZERO_STRUCT(Printer->dev.handlename);
563 fstrcpy(Printer->dev.handlename, sname);
565 return True;
568 /****************************************************************************
569 Find first available printer slot. creates a printer handle for you.
570 ****************************************************************************/
572 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
574 Printer_entry *new_printer;
576 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
578 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
579 return False;
581 ZERO_STRUCTP(new_printer);
583 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
584 SAFE_FREE(new_printer);
585 return False;
588 /* Add to the internal list. */
589 DLIST_ADD(printers_list, new_printer);
591 new_printer->notify.option=NULL;
593 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
594 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
595 close_printer_handle(p, hnd);
596 return False;
599 if (!set_printer_hnd_printertype(new_printer, name)) {
600 close_printer_handle(p, hnd);
601 return False;
604 if (!set_printer_hnd_name(new_printer, name)) {
605 close_printer_handle(p, hnd);
606 return False;
609 new_printer->access_granted = access_granted;
611 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
613 return True;
616 /****************************************************************************
617 Allocate more memory for a BUFFER.
618 ****************************************************************************/
620 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
622 prs_struct *ps;
623 uint32 extra_space;
624 uint32 old_offset;
626 ps= &buffer->prs;
628 /* damn, I'm doing the reverse operation of prs_grow() :) */
629 if (buffer_size < prs_data_size(ps))
630 extra_space=0;
631 else
632 extra_space = buffer_size - prs_data_size(ps);
635 * save the offset and move to the end of the buffer
636 * prs_grow() checks the extra_space against the offset
638 old_offset=prs_offset(ps);
639 prs_set_offset(ps, prs_data_size(ps));
641 if (!prs_grow(ps, extra_space))
642 return False;
644 prs_set_offset(ps, old_offset);
646 buffer->string_at_end=prs_data_size(ps);
648 return True;
651 /***************************************************************************
652 check to see if the client motify handle is monitoring the notification
653 given by (notify_type, notify_field).
654 **************************************************************************/
656 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
657 uint16 notify_field)
659 return True;
662 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
663 uint16 notify_field)
665 SPOOL_NOTIFY_OPTION *option = p->notify.option;
666 uint32 i, j;
669 * Flags should always be zero when the change notify
670 * is registered by the client's spooler. A user Win32 app
671 * might use the flags though instead of the NOTIFY_OPTION_INFO
672 * --jerry
675 if (!option) {
676 return False;
679 if (p->notify.flags)
680 return is_monitoring_event_flags(
681 p->notify.flags, notify_type, notify_field);
683 for (i = 0; i < option->count; i++) {
685 /* Check match for notify_type */
687 if (option->ctr.type[i].type != notify_type)
688 continue;
690 /* Check match for field */
692 for (j = 0; j < option->ctr.type[i].count; j++) {
693 if (option->ctr.type[i].fields[j] == notify_field) {
694 return True;
699 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
700 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
701 p->dev.handlename : p->dev.printerservername,
702 notify_type, notify_field));
704 return False;
707 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
709 static void notify_one_value(struct spoolss_notify_msg *msg,
710 SPOOL_NOTIFY_INFO_DATA *data,
711 TALLOC_CTX *mem_ctx)
713 data->notify_data.value[0] = msg->notify.value[0];
714 data->notify_data.value[1] = 0;
717 static void notify_string(struct spoolss_notify_msg *msg,
718 SPOOL_NOTIFY_INFO_DATA *data,
719 TALLOC_CTX *mem_ctx)
721 UNISTR2 unistr;
723 /* The length of the message includes the trailing \0 */
725 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
727 data->notify_data.data.length = msg->len * 2;
728 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
730 if (!data->notify_data.data.string) {
731 data->notify_data.data.length = 0;
732 return;
735 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
738 static void notify_system_time(struct spoolss_notify_msg *msg,
739 SPOOL_NOTIFY_INFO_DATA *data,
740 TALLOC_CTX *mem_ctx)
742 SYSTEMTIME systime;
743 prs_struct ps;
745 if (msg->len != sizeof(time_t)) {
746 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
747 msg->len));
748 return;
751 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
752 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
753 return;
756 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
757 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
758 return;
761 if (!spoolss_io_system_time("", &ps, 0, &systime))
762 return;
764 data->notify_data.data.length = prs_offset(&ps);
765 data->notify_data.data.string = talloc(mem_ctx, prs_offset(&ps));
767 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
769 prs_mem_free(&ps);
772 struct notify2_message_table {
773 const char *name;
774 void (*fn)(struct spoolss_notify_msg *msg,
775 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
778 static struct notify2_message_table printer_notify_table[] = {
779 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
780 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
781 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
782 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
783 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
784 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
785 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
786 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
787 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
788 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
789 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
790 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
791 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
792 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
793 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
794 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
795 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
796 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
797 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
800 static struct notify2_message_table job_notify_table[] = {
801 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
802 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
803 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
804 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
805 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
806 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
807 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
808 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
809 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
810 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
811 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
812 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
813 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
814 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
815 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
816 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
817 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
818 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
819 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
820 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
821 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
822 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
823 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
824 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
828 /***********************************************************************
829 Allocate talloc context for container object
830 **********************************************************************/
832 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
834 if ( !ctr )
835 return;
837 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
839 return;
842 /***********************************************************************
843 release all allocated memory and zero out structure
844 **********************************************************************/
846 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
848 if ( !ctr )
849 return;
851 if ( ctr->ctx )
852 talloc_destroy(ctr->ctx);
854 ZERO_STRUCTP(ctr);
856 return;
859 /***********************************************************************
860 **********************************************************************/
862 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
864 if ( !ctr )
865 return NULL;
867 return ctr->ctx;
870 /***********************************************************************
871 **********************************************************************/
873 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
875 if ( !ctr || !ctr->msg_groups )
876 return NULL;
878 if ( idx >= ctr->num_groups )
879 return NULL;
881 return &ctr->msg_groups[idx];
885 /***********************************************************************
886 How many groups of change messages do we have ?
887 **********************************************************************/
889 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
891 if ( !ctr )
892 return 0;
894 return ctr->num_groups;
897 /***********************************************************************
898 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
899 **********************************************************************/
901 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
903 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
904 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
905 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
906 int i, new_slot;
908 if ( !ctr || !msg )
909 return 0;
911 /* loop over all groups looking for a matching printer name */
913 for ( i=0; i<ctr->num_groups; i++ ) {
914 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
915 break;
918 /* add a new group? */
920 if ( i == ctr->num_groups ) {
921 ctr->num_groups++;
923 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
924 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
925 return 0;
927 ctr->msg_groups = groups;
929 /* clear the new entry and set the printer name */
931 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
932 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
935 /* add the change messages; 'i' is the correct index now regardless */
937 msg_grp = &ctr->msg_groups[i];
939 msg_grp->num_msgs++;
941 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
942 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
943 return 0;
945 msg_grp->msgs = msg_list;
947 new_slot = msg_grp->num_msgs-1;
948 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
950 /* need to allocate own copy of data */
952 if ( msg->len != 0 )
953 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
955 return ctr->num_groups;
958 /***********************************************************************
959 Send a change notication message on all handles which have a call
960 back registered
961 **********************************************************************/
963 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
965 Printer_entry *p;
966 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
967 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
968 SPOOLSS_NOTIFY_MSG *messages;
969 int sending_msg_count;
971 if ( !msg_group ) {
972 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
973 return;
976 messages = msg_group->msgs;
978 if ( !messages ) {
979 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
980 return;
983 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
985 /* loop over all printers */
987 for (p = printers_list; p; p = p->next) {
988 SPOOL_NOTIFY_INFO_DATA *data;
989 uint32 data_len = 0;
990 uint32 id;
991 int i;
993 /* Is there notification on this handle? */
995 if ( !p->notify.client_connected )
996 continue;
998 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
1000 /* For this printer? Print servers always receive
1001 notifications. */
1003 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
1004 ( !strequal(msg_group->printername, p->dev.handlename) ) )
1005 continue;
1007 DEBUG(10,("Our printer\n"));
1009 /* allocate the max entries possible */
1011 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
1012 ZERO_STRUCTP(data);
1014 /* build the array of change notifications */
1016 sending_msg_count = 0;
1018 for ( i=0; i<msg_group->num_msgs; i++ ) {
1019 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1021 /* Are we monitoring this event? */
1023 if (!is_monitoring_event(p, msg->type, msg->field))
1024 continue;
1026 sending_msg_count++;
1029 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1030 msg->type, msg->field, p->dev.handlename));
1033 * if the is a printer notification handle and not a job notification
1034 * type, then set the id to 0. Other wise just use what was specified
1035 * in the message.
1037 * When registering change notification on a print server handle
1038 * we always need to send back the id (snum) matching the printer
1039 * for which the change took place. For change notify registered
1040 * on a printer handle, this does not matter and the id should be 0.
1042 * --jerry
1045 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1046 id = 0;
1047 else
1048 id = msg->id;
1051 /* Convert unix jobid to smb jobid */
1053 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1054 id = sysjob_to_jobid(msg->id);
1056 if (id == -1) {
1057 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1058 goto done;
1062 construct_info_data( &data[data_len], msg->type, msg->field, id );
1064 switch(msg->type) {
1065 case PRINTER_NOTIFY_TYPE:
1066 if ( printer_notify_table[msg->field].fn )
1067 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1068 break;
1070 case JOB_NOTIFY_TYPE:
1071 if ( job_notify_table[msg->field].fn )
1072 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1073 break;
1075 default:
1076 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1077 goto done;
1080 data_len++;
1083 if ( sending_msg_count ) {
1084 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
1085 data_len, data, p->notify.change, 0 );
1089 done:
1090 DEBUG(8,("send_notify2_changes: Exit...\n"));
1091 return;
1094 /***********************************************************************
1095 **********************************************************************/
1097 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1100 uint32 tv_sec, tv_usec;
1101 size_t offset = 0;
1103 /* Unpack message */
1105 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1106 msg->printer);
1108 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1109 &tv_sec, &tv_usec,
1110 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1112 if (msg->len == 0)
1113 tdb_unpack((char *)buf + offset, len - offset, "dd",
1114 &msg->notify.value[0], &msg->notify.value[1]);
1115 else
1116 tdb_unpack((char *)buf + offset, len - offset, "B",
1117 &msg->len, &msg->notify.data);
1119 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1120 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1122 tv->tv_sec = tv_sec;
1123 tv->tv_usec = tv_usec;
1125 if (msg->len == 0)
1126 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1127 msg->notify.value[1]));
1128 else
1129 dump_data(3, msg->notify.data, msg->len);
1131 return True;
1134 /********************************************************************
1135 Receive a notify2 message list
1136 ********************************************************************/
1138 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1140 size_t msg_count, i;
1141 char *buf = (char *)msg;
1142 char *msg_ptr;
1143 size_t msg_len;
1144 SPOOLSS_NOTIFY_MSG notify;
1145 SPOOLSS_NOTIFY_MSG_CTR messages;
1146 int num_groups;
1148 if (len < 4) {
1149 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1150 return;
1153 msg_count = IVAL(buf, 0);
1154 msg_ptr = buf + 4;
1156 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1158 if (msg_count == 0) {
1159 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1160 return;
1163 /* initialize the container */
1165 ZERO_STRUCT( messages );
1166 notify_msg_ctr_init( &messages );
1169 * build message groups for each printer identified
1170 * in a change_notify msg. Remember that a PCN message
1171 * includes the handle returned for the srv_spoolss_replyopenprinter()
1172 * call. Therefore messages are grouped according to printer handle.
1175 for ( i=0; i<msg_count; i++ ) {
1176 struct timeval msg_tv;
1178 if (msg_ptr + 4 - buf > len) {
1179 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1180 return;
1183 msg_len = IVAL(msg_ptr,0);
1184 msg_ptr += 4;
1186 if (msg_ptr + msg_len - buf > len) {
1187 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1188 return;
1191 /* unpack messages */
1193 ZERO_STRUCT( notify );
1194 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1195 msg_ptr += msg_len;
1197 /* add to correct list in container */
1199 notify_msg_ctr_addmsg( &messages, &notify );
1201 /* free memory that might have been allocated by notify2_unpack_msg() */
1203 if ( notify.len != 0 )
1204 SAFE_FREE( notify.notify.data );
1207 /* process each group of messages */
1209 num_groups = notify_msg_ctr_numgroups( &messages );
1210 for ( i=0; i<num_groups; i++ )
1211 send_notify2_changes( &messages, i );
1214 /* cleanup */
1216 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1218 notify_msg_ctr_destroy( &messages );
1220 return;
1223 /********************************************************************
1224 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1225 one smbd, all of processes must clear their printer cache immediately.
1226 ********************************************************************/
1228 void receive_printer_mod_msg(int msg_type, pid_t src, void *buf, size_t len)
1230 fstring printername;
1232 fstrcpy( printername, buf );
1234 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername ));
1236 invalidate_printer_hnd_cache( printername );
1239 /********************************************************************
1240 Send a message to ourself about new driver being installed
1241 so we can upgrade the information for each printer bound to this
1242 driver
1243 ********************************************************************/
1245 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1247 int len = strlen(drivername);
1249 if (!len)
1250 return False;
1252 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1253 drivername));
1255 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1257 return True;
1260 /**********************************************************************
1261 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1262 over all printers, upgrading ones as necessary
1263 **********************************************************************/
1265 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1267 fstring drivername;
1268 int snum;
1269 int n_services = lp_numservices();
1271 len = MIN(len,sizeof(drivername)-1);
1272 strncpy(drivername, buf, len);
1274 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1276 /* Iterate the printer list */
1278 for (snum=0; snum<n_services; snum++)
1280 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1282 WERROR result;
1283 NT_PRINTER_INFO_LEVEL *printer = NULL;
1285 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1286 if (!W_ERROR_IS_OK(result))
1287 continue;
1289 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1291 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1293 /* all we care about currently is the change_id */
1295 result = mod_a_printer(*printer, 2);
1296 if (!W_ERROR_IS_OK(result)) {
1297 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1298 dos_errstr(result)));
1302 free_a_printer(&printer, 2);
1306 /* all done */
1309 /********************************************************************
1310 Update the cache for all printq's with a registered client
1311 connection
1312 ********************************************************************/
1314 void update_monitored_printq_cache( void )
1316 Printer_entry *printer = printers_list;
1317 int snum;
1319 /* loop through all printers and update the cache where
1320 client_connected == True */
1321 while ( printer )
1323 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1324 && printer->notify.client_connected )
1326 snum = print_queue_snum(printer->dev.handlename);
1327 print_queue_status( snum, NULL, NULL );
1330 printer = printer->next;
1333 return;
1335 /********************************************************************
1336 Send a message to ourself about new driver being installed
1337 so we can upgrade the information for each printer bound to this
1338 driver
1339 ********************************************************************/
1341 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1343 int len = strlen(drivername);
1345 if (!len)
1346 return False;
1348 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1349 drivername));
1351 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1353 return True;
1356 /**********************************************************************
1357 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1358 over all printers, resetting printer data as neessary
1359 **********************************************************************/
1361 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1363 fstring drivername;
1364 int snum;
1365 int n_services = lp_numservices();
1367 len = MIN( len, sizeof(drivername)-1 );
1368 strncpy( drivername, buf, len );
1370 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1372 /* Iterate the printer list */
1374 for ( snum=0; snum<n_services; snum++ )
1376 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1378 WERROR result;
1379 NT_PRINTER_INFO_LEVEL *printer = NULL;
1381 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1382 if ( !W_ERROR_IS_OK(result) )
1383 continue;
1386 * if the printer is bound to the driver,
1387 * then reset to the new driver initdata
1390 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1392 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1394 if ( !set_driver_init(printer, 2) ) {
1395 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1396 printer->info_2->printername, printer->info_2->drivername));
1399 result = mod_a_printer( *printer, 2 );
1400 if ( !W_ERROR_IS_OK(result) ) {
1401 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1402 get_dos_error_msg(result)));
1406 free_a_printer( &printer, 2 );
1410 /* all done */
1412 return;
1415 /********************************************************************
1416 Copy routines used by convert_to_openprinterex()
1417 *******************************************************************/
1419 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1421 DEVICEMODE *d;
1422 int len;
1424 if (!devmode)
1425 return NULL;
1427 DEBUG (8,("dup_devmode\n"));
1429 /* bulk copy first */
1431 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1432 if (!d)
1433 return NULL;
1435 /* dup the pointer members separately */
1437 len = unistrlen(devmode->devicename.buffer);
1438 if (len != -1) {
1439 d->devicename.buffer = talloc(ctx, len*2);
1440 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1441 return NULL;
1445 len = unistrlen(devmode->formname.buffer);
1446 if (len != -1) {
1447 d->devicename.buffer = talloc(ctx, len*2);
1448 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1449 return NULL;
1452 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1454 return d;
1457 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1459 if (!new_ctr || !ctr)
1460 return;
1462 DEBUG(8,("copy_devmode_ctr\n"));
1464 new_ctr->size = ctr->size;
1465 new_ctr->devmode_ptr = ctr->devmode_ptr;
1467 if(ctr->devmode_ptr)
1468 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1471 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1473 if (!new_def || !def)
1474 return;
1476 DEBUG(8,("copy_printer_defaults\n"));
1478 new_def->datatype_ptr = def->datatype_ptr;
1480 if (def->datatype_ptr)
1481 copy_unistr2(&new_def->datatype, &def->datatype);
1483 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1485 new_def->access_required = def->access_required;
1488 /********************************************************************
1489 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1490 * SPOOL_Q_OPEN_PRINTER_EX structure
1491 ********************************************************************/
1493 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1495 if (!q_u_ex || !q_u)
1496 return;
1498 DEBUG(8,("convert_to_openprinterex\n"));
1500 q_u_ex->printername_ptr = q_u->printername_ptr;
1502 if (q_u->printername_ptr)
1503 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1505 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1508 /********************************************************************
1509 * spoolss_open_printer
1511 * called from the spoolss dispatcher
1512 ********************************************************************/
1514 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1516 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1517 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1519 if (!q_u || !r_u)
1520 return WERR_NOMEM;
1522 ZERO_STRUCT(q_u_ex);
1523 ZERO_STRUCT(r_u_ex);
1525 /* convert the OpenPrinter() call to OpenPrinterEx() */
1527 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1529 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1531 /* convert back to OpenPrinter() */
1533 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1535 return r_u->status;
1538 /********************************************************************
1539 * spoolss_open_printer
1541 * If the openprinterex rpc call contains a devmode,
1542 * it's a per-user one. This per-user devmode is derivated
1543 * from the global devmode. Openprinterex() contains a per-user
1544 * devmode for when you do EMF printing and spooling.
1545 * In the EMF case, the NT workstation is only doing half the job
1546 * of rendering the page. The other half is done by running the printer
1547 * driver on the server.
1548 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1549 * The EMF file only contains what is to be printed on the page.
1550 * So in order for the server to know how to print, the NT client sends
1551 * a devicemode attached to the openprinterex call.
1552 * But this devicemode is short lived, it's only valid for the current print job.
1554 * If Samba would have supported EMF spooling, this devicemode would
1555 * have been attached to the handle, to sent it to the driver to correctly
1556 * rasterize the EMF file.
1558 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1559 * we just act as a pass-thru between windows and the printer.
1561 * In order to know that Samba supports only RAW spooling, NT has to call
1562 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1563 * and until NT sends a RAW job, we refuse it.
1565 * But to call getprinter() or startdoc(), you first need a valid handle,
1566 * and to get an handle you have to call openprintex(). Hence why you have
1567 * a devicemode in the openprinterex() call.
1570 * Differences between NT4 and NT 2000.
1571 * NT4:
1572 * ---
1573 * On NT4, you only have a global devicemode. This global devicemode can be changed
1574 * by the administrator (or by a user with enough privs). Everytime a user
1575 * wants to print, the devicemode is resetted to the default. In Word, everytime
1576 * you print, the printer's characteristics are always reset to the global devicemode.
1578 * NT 2000:
1579 * -------
1580 * In W2K, there is the notion of per-user devicemode. The first time you use
1581 * a printer, a per-user devicemode is build from the global devicemode.
1582 * If you change your per-user devicemode, it is saved in the registry, under the
1583 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1584 * printer preferences available.
1586 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1587 * on the General Tab of the printer properties windows.
1589 * To change the global devicemode: it's the "Printing Defaults..." button
1590 * on the Advanced Tab of the printer properties window.
1592 * JFM.
1593 ********************************************************************/
1595 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1597 UNISTR2 *printername = NULL;
1598 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1599 POLICY_HND *handle = &r_u->handle;
1601 fstring name;
1602 int snum;
1603 struct current_user user;
1604 Printer_entry *Printer=NULL;
1606 if (q_u->printername_ptr != 0)
1607 printername = &q_u->printername;
1609 if (printername == NULL)
1610 return WERR_INVALID_PRINTER_NAME;
1612 /* some sanity check because you can open a printer or a print server */
1613 /* aka: \\server\printer or \\server */
1614 unistr2_to_ascii(name, printername, sizeof(name)-1);
1616 DEBUGADD(3,("checking name: %s\n",name));
1618 if (!open_printer_hnd(p, handle, name, 0))
1619 return WERR_INVALID_PRINTER_NAME;
1621 Printer=find_printer_index_by_hnd(p, handle);
1622 if (!Printer) {
1623 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1624 Can't find printer handle we created for printer %s\n", name ));
1625 close_printer_handle(p,handle);
1626 return WERR_INVALID_PRINTER_NAME;
1629 get_current_user(&user, p);
1632 * First case: the user is opening the print server:
1634 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1635 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1637 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1638 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1639 * or if the user is listed in the smb.conf printer admin parameter.
1641 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1642 * client view printer folder, but does not show the MSAPW.
1644 * Note: this test needs code to check access rights here too. Jeremy
1645 * could you look at this?
1647 * Second case: the user is opening a printer:
1648 * NT doesn't let us connect to a printer if the connecting user
1649 * doesn't have print permission.
1652 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1654 /* Printserver handles use global struct... */
1656 snum = -1;
1658 /* Map standard access rights to object specific access rights */
1660 se_map_standard(&printer_default->access_required,
1661 &printserver_std_mapping);
1663 /* Deny any object specific bits that don't apply to print
1664 servers (i.e printer and job specific bits) */
1666 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1668 if (printer_default->access_required &
1669 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1670 DEBUG(3, ("access DENIED for non-printserver bits"));
1671 close_printer_handle(p, handle);
1672 return WERR_ACCESS_DENIED;
1675 /* Allow admin access */
1677 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1679 if (!lp_ms_add_printer_wizard()) {
1680 close_printer_handle(p, handle);
1681 return WERR_ACCESS_DENIED;
1684 /* if the user is not root and not a printer admin, then fail */
1686 if ( user.uid != 0
1687 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1689 close_printer_handle(p, handle);
1690 return WERR_ACCESS_DENIED;
1693 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1695 else
1697 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1700 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1701 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1703 /* We fall through to return WERR_OK */
1706 else
1708 /* NT doesn't let us connect to a printer if the connecting user
1709 doesn't have print permission. */
1711 if (!get_printer_snum(p, handle, &snum)) {
1712 close_printer_handle(p, handle);
1713 return WERR_BADFID;
1716 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1718 /* map an empty access mask to the minimum access mask */
1719 if (printer_default->access_required == 0x0)
1720 printer_default->access_required = PRINTER_ACCESS_USE;
1723 * If we are not serving the printer driver for this printer,
1724 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1725 * will keep NT clients happy --jerry
1728 if (lp_use_client_driver(snum)
1729 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1731 printer_default->access_required = PRINTER_ACCESS_USE;
1734 /* check smb.conf parameters and the the sec_desc */
1736 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1737 DEBUG(3, ("access DENIED for printer open\n"));
1738 close_printer_handle(p, handle);
1739 return WERR_ACCESS_DENIED;
1742 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1743 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1744 close_printer_handle(p, handle);
1745 return WERR_ACCESS_DENIED;
1748 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1749 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1750 else
1751 printer_default->access_required = PRINTER_ACCESS_USE;
1753 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1754 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1758 Printer->access_granted = printer_default->access_required;
1761 * If the client sent a devmode in the OpenPrinter() call, then
1762 * save it here in case we get a job submission on this handle
1765 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1766 && q_u->printer_default.devmode_cont.devmode_ptr )
1768 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1769 &Printer->nt_devmode );
1772 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1773 optimization in Windows 2000 clients --jerry */
1775 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1776 && (RA_WIN2K == get_remote_arch()) )
1778 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1779 sys_usleep( 500000 );
1782 return WERR_OK;
1785 /****************************************************************************
1786 ****************************************************************************/
1788 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1789 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1791 BOOL ret = True;
1793 switch (level) {
1794 case 2:
1795 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1796 break;
1797 default:
1798 break;
1801 return ret;
1804 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1805 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1807 BOOL result = True;
1809 switch (level) {
1810 case 3:
1811 printer->info_3=NULL;
1812 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1813 result = False;
1814 break;
1815 case 6:
1816 printer->info_6=NULL;
1817 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1818 result = False;
1819 break;
1820 default:
1821 break;
1824 return result;
1827 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1828 NT_DEVICEMODE **pp_nt_devmode)
1830 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1833 * Ensure nt_devmode is a valid pointer
1834 * as we will be overwriting it.
1837 if (nt_devmode == NULL) {
1838 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1839 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1840 return False;
1843 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1844 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1846 nt_devmode->specversion=devmode->specversion;
1847 nt_devmode->driverversion=devmode->driverversion;
1848 nt_devmode->size=devmode->size;
1849 nt_devmode->fields=devmode->fields;
1850 nt_devmode->orientation=devmode->orientation;
1851 nt_devmode->papersize=devmode->papersize;
1852 nt_devmode->paperlength=devmode->paperlength;
1853 nt_devmode->paperwidth=devmode->paperwidth;
1854 nt_devmode->scale=devmode->scale;
1855 nt_devmode->copies=devmode->copies;
1856 nt_devmode->defaultsource=devmode->defaultsource;
1857 nt_devmode->printquality=devmode->printquality;
1858 nt_devmode->color=devmode->color;
1859 nt_devmode->duplex=devmode->duplex;
1860 nt_devmode->yresolution=devmode->yresolution;
1861 nt_devmode->ttoption=devmode->ttoption;
1862 nt_devmode->collate=devmode->collate;
1864 nt_devmode->logpixels=devmode->logpixels;
1865 nt_devmode->bitsperpel=devmode->bitsperpel;
1866 nt_devmode->pelswidth=devmode->pelswidth;
1867 nt_devmode->pelsheight=devmode->pelsheight;
1868 nt_devmode->displayflags=devmode->displayflags;
1869 nt_devmode->displayfrequency=devmode->displayfrequency;
1870 nt_devmode->icmmethod=devmode->icmmethod;
1871 nt_devmode->icmintent=devmode->icmintent;
1872 nt_devmode->mediatype=devmode->mediatype;
1873 nt_devmode->dithertype=devmode->dithertype;
1874 nt_devmode->reserved1=devmode->reserved1;
1875 nt_devmode->reserved2=devmode->reserved2;
1876 nt_devmode->panningwidth=devmode->panningwidth;
1877 nt_devmode->panningheight=devmode->panningheight;
1880 * Only change private and driverextra if the incoming devmode
1881 * has a new one. JRA.
1884 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1885 SAFE_FREE(nt_devmode->private);
1886 nt_devmode->driverextra=devmode->driverextra;
1887 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1888 return False;
1889 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1892 *pp_nt_devmode = nt_devmode;
1894 return True;
1897 /********************************************************************
1898 * _spoolss_enddocprinter_internal.
1899 ********************************************************************/
1901 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1903 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1904 int snum;
1906 if (!Printer) {
1907 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1908 return WERR_BADFID;
1911 if (!get_printer_snum(p, handle, &snum))
1912 return WERR_BADFID;
1914 Printer->document_started=False;
1915 print_job_end(snum, Printer->jobid,True);
1916 /* error codes unhandled so far ... */
1918 return WERR_OK;
1921 /********************************************************************
1922 * api_spoolss_closeprinter
1923 ********************************************************************/
1925 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1927 POLICY_HND *handle = &q_u->handle;
1929 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1931 if (Printer && Printer->document_started)
1932 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1934 if (!close_printer_handle(p, handle))
1935 return WERR_BADFID;
1937 /* clear the returned printer handle. Observed behavior
1938 from Win2k server. Don't think this really matters.
1939 Previous code just copied the value of the closed
1940 handle. --jerry */
1942 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1944 return WERR_OK;
1947 /********************************************************************
1948 * api_spoolss_deleteprinter
1950 ********************************************************************/
1952 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1954 POLICY_HND *handle = &q_u->handle;
1955 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1956 WERROR result;
1958 if (Printer && Printer->document_started)
1959 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1961 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1963 result = delete_printer_handle(p, handle);
1965 update_c_setprinter(False);
1967 return result;
1970 /*******************************************************************
1971 * static function to lookup the version id corresponding to an
1972 * long architecture string
1973 ******************************************************************/
1975 static int get_version_id (char * arch)
1977 int i;
1978 struct table_node archi_table[]= {
1980 {"Windows 4.0", "WIN40", 0 },
1981 {"Windows NT x86", "W32X86", 2 },
1982 {"Windows NT R4000", "W32MIPS", 2 },
1983 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1984 {"Windows NT PowerPC", "W32PPC", 2 },
1985 {"Windows IA64", "IA64", 3 },
1986 {NULL, "", -1 }
1989 for (i=0; archi_table[i].long_archi != NULL; i++)
1991 if (strcmp(arch, archi_table[i].long_archi) == 0)
1992 return (archi_table[i].version);
1995 return -1;
1998 /********************************************************************
1999 * _spoolss_deleteprinterdriver
2000 ********************************************************************/
2002 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2004 fstring driver;
2005 fstring arch;
2006 NT_PRINTER_DRIVER_INFO_LEVEL info;
2007 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2008 int version;
2009 struct current_user user;
2010 WERROR status;
2011 WERROR status_win2k = WERR_ACCESS_DENIED;
2013 get_current_user(&user, p);
2015 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2016 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2018 /* check that we have a valid driver name first */
2020 if ((version=get_version_id(arch)) == -1)
2021 return WERR_INVALID_ENVIRONMENT;
2023 ZERO_STRUCT(info);
2024 ZERO_STRUCT(info_win2k);
2026 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2028 /* try for Win2k driver if "Windows NT x86" */
2030 if ( version == 2 ) {
2031 version = 3;
2032 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2033 status = WERR_UNKNOWN_PRINTER_DRIVER;
2034 goto done;
2037 /* otherwise it was a failure */
2038 else {
2039 status = WERR_UNKNOWN_PRINTER_DRIVER;
2040 goto done;
2045 if (printer_driver_in_use(info.info_3)) {
2046 status = WERR_PRINTER_DRIVER_IN_USE;
2047 goto done;
2050 if ( version == 2 )
2052 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2054 /* if we get to here, we now have 2 driver info structures to remove */
2055 /* remove the Win2k driver first*/
2057 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2058 free_a_printer_driver( info_win2k, 3 );
2060 /* this should not have failed---if it did, report to client */
2061 if ( !W_ERROR_IS_OK(status_win2k) )
2062 goto done;
2066 status = delete_printer_driver(info.info_3, &user, version, False);
2068 /* if at least one of the deletes succeeded return OK */
2070 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2071 status = WERR_OK;
2073 done:
2074 free_a_printer_driver( info, 3 );
2076 return status;
2079 /********************************************************************
2080 * spoolss_deleteprinterdriverex
2081 ********************************************************************/
2083 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2085 fstring driver;
2086 fstring arch;
2087 NT_PRINTER_DRIVER_INFO_LEVEL info;
2088 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2089 int version;
2090 uint32 flags = q_u->delete_flags;
2091 BOOL delete_files;
2092 struct current_user user;
2093 WERROR status;
2094 WERROR status_win2k = WERR_ACCESS_DENIED;
2096 get_current_user(&user, p);
2098 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2099 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2101 /* check that we have a valid driver name first */
2102 if ((version=get_version_id(arch)) == -1) {
2103 /* this is what NT returns */
2104 return WERR_INVALID_ENVIRONMENT;
2107 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2108 version = q_u->version;
2110 ZERO_STRUCT(info);
2111 ZERO_STRUCT(info_win2k);
2113 status = get_a_printer_driver(&info, 3, driver, arch, version);
2115 if ( !W_ERROR_IS_OK(status) )
2118 * if the client asked for a specific version,
2119 * or this is something other than Windows NT x86,
2120 * then we've failed
2123 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2124 goto done;
2126 /* try for Win2k driver if "Windows NT x86" */
2128 version = 3;
2129 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2130 status = WERR_UNKNOWN_PRINTER_DRIVER;
2131 goto done;
2135 if ( printer_driver_in_use(info.info_3) ) {
2136 status = WERR_PRINTER_DRIVER_IN_USE;
2137 goto done;
2141 * we have a couple of cases to consider.
2142 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2143 * then the delete should fail if **any** files overlap with
2144 * other drivers
2145 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2146 * non-overlapping files
2147 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2148 * is set, the do not delete any files
2149 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2152 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2154 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2156 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2157 /* no idea of the correct error here */
2158 status = WERR_ACCESS_DENIED;
2159 goto done;
2163 /* also check for W32X86/3 if necessary; maybe we already have? */
2165 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2166 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2169 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2170 /* no idea of the correct error here */
2171 free_a_printer_driver( info_win2k, 3 );
2172 status = WERR_ACCESS_DENIED;
2173 goto done;
2176 /* if we get to here, we now have 2 driver info structures to remove */
2177 /* remove the Win2k driver first*/
2179 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2180 free_a_printer_driver( info_win2k, 3 );
2182 /* this should not have failed---if it did, report to client */
2184 if ( !W_ERROR_IS_OK(status_win2k) )
2185 goto done;
2189 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2191 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2192 status = WERR_OK;
2193 done:
2194 free_a_printer_driver( info, 3 );
2196 return status;
2200 /****************************************************************************
2201 Internal routine for retreiving printerdata
2202 ***************************************************************************/
2204 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2205 const char *key, const char *value, uint32 *type, uint8 **data,
2206 uint32 *needed, uint32 in_size )
2208 REGISTRY_VALUE *val;
2209 int size, data_len;
2211 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2212 return WERR_BADFILE;
2214 *type = regval_type( val );
2216 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2218 size = regval_size( val );
2220 /* copy the min(in_size, len) */
2222 if ( in_size ) {
2223 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2225 /* special case for 0 length values */
2226 if ( data_len ) {
2227 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2228 return WERR_NOMEM;
2230 else {
2231 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2232 return WERR_NOMEM;
2235 else
2236 *data = NULL;
2238 *needed = size;
2240 DEBUG(5,("get_printer_dataex: copy done\n"));
2242 return WERR_OK;
2245 /****************************************************************************
2246 Internal routine for removing printerdata
2247 ***************************************************************************/
2249 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2251 return delete_printer_data( printer->info_2, key, value );
2254 /****************************************************************************
2255 Internal routine for storing printerdata
2256 ***************************************************************************/
2258 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2259 uint32 type, uint8 *data, int real_len )
2261 delete_printer_data( printer->info_2, key, value );
2263 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2266 /********************************************************************
2267 GetPrinterData on a printer server Handle.
2268 ********************************************************************/
2270 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2272 int i;
2274 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2276 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2277 *type = 0x4;
2278 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2279 return WERR_NOMEM;
2280 *needed = 0x4;
2281 return WERR_OK;
2284 if (!StrCaseCmp(value, "BeepEnabled")) {
2285 *type = 0x4;
2286 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2287 return WERR_NOMEM;
2288 SIVAL(*data, 0, 0x00);
2289 *needed = 0x4;
2290 return WERR_OK;
2293 if (!StrCaseCmp(value, "EventLog")) {
2294 *type = 0x4;
2295 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2296 return WERR_NOMEM;
2297 /* formally was 0x1b */
2298 SIVAL(*data, 0, 0x0);
2299 *needed = 0x4;
2300 return WERR_OK;
2303 if (!StrCaseCmp(value, "NetPopup")) {
2304 *type = 0x4;
2305 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2306 return WERR_NOMEM;
2307 SIVAL(*data, 0, 0x00);
2308 *needed = 0x4;
2309 return WERR_OK;
2312 if (!StrCaseCmp(value, "MajorVersion")) {
2313 *type = 0x4;
2314 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2315 return WERR_NOMEM;
2317 /* Windows NT 4.0 seems to not allow uploading of drivers
2318 to a server that reports 0x3 as the MajorVersion.
2319 need to investigate more how Win2k gets around this .
2320 -- jerry */
2322 if ( RA_WINNT == get_remote_arch() )
2323 SIVAL(*data, 0, 2);
2324 else
2325 SIVAL(*data, 0, 3);
2327 *needed = 0x4;
2328 return WERR_OK;
2331 if (!StrCaseCmp(value, "MinorVersion")) {
2332 *type = 0x4;
2333 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2334 return WERR_NOMEM;
2335 SIVAL(*data, 0, 0);
2336 *needed = 0x4;
2337 return WERR_OK;
2340 /* REG_BINARY
2341 * uint32 size = 0x114
2342 * uint32 major = 5
2343 * uint32 minor = [0|1]
2344 * uint32 build = [2195|2600]
2345 * extra unicode string = e.g. "Service Pack 3"
2347 if (!StrCaseCmp(value, "OSVersion")) {
2348 *type = 0x3;
2349 *needed = 0x114;
2351 if((*data = (uint8 *)talloc(ctx, (*needed)*sizeof(uint8) )) == NULL)
2352 return WERR_NOMEM;
2353 ZERO_STRUCTP( *data );
2355 SIVAL(*data, 0, *needed); /* size */
2356 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2357 SIVAL(*data, 8, 0);
2358 SIVAL(*data, 12, 2195); /* build */
2360 /* leave extra string empty */
2362 return WERR_OK;
2366 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2367 const char *string="C:\\PRINTERS";
2368 *type = 0x1;
2369 *needed = 2*(strlen(string)+1);
2370 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2371 return WERR_NOMEM;
2372 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2374 /* it's done by hand ready to go on the wire */
2375 for (i=0; i<strlen(string); i++) {
2376 (*data)[2*i]=string[i];
2377 (*data)[2*i+1]='\0';
2379 return WERR_OK;
2382 if (!StrCaseCmp(value, "Architecture")) {
2383 const char *string="Windows NT x86";
2384 *type = 0x1;
2385 *needed = 2*(strlen(string)+1);
2386 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2387 return WERR_NOMEM;
2388 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2389 for (i=0; i<strlen(string); i++) {
2390 (*data)[2*i]=string[i];
2391 (*data)[2*i+1]='\0';
2393 return WERR_OK;
2396 if (!StrCaseCmp(value, "DsPresent")) {
2397 *type = 0x4;
2398 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2399 return WERR_NOMEM;
2400 SIVAL(*data, 0, 0x01);
2401 *needed = 0x4;
2402 return WERR_OK;
2405 if (!StrCaseCmp(value, "DNSMachineName")) {
2406 pstring hostname;
2408 if (!get_mydnsfullname(hostname))
2409 return WERR_BADFILE;
2410 *type = 0x1;
2411 *needed = 2*(strlen(hostname)+1);
2412 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2413 return WERR_NOMEM;
2414 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2415 for (i=0; i<strlen(hostname); i++) {
2416 (*data)[2*i]=hostname[i];
2417 (*data)[2*i+1]='\0';
2419 return WERR_OK;
2423 return WERR_BADFILE;
2426 /********************************************************************
2427 * spoolss_getprinterdata
2428 ********************************************************************/
2430 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2432 POLICY_HND *handle = &q_u->handle;
2433 UNISTR2 *valuename = &q_u->valuename;
2434 uint32 in_size = q_u->size;
2435 uint32 *type = &r_u->type;
2436 uint32 *out_size = &r_u->size;
2437 uint8 **data = &r_u->data;
2438 uint32 *needed = &r_u->needed;
2439 WERROR status;
2440 fstring value;
2441 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2442 NT_PRINTER_INFO_LEVEL *printer = NULL;
2443 int snum = 0;
2446 * Reminder: when it's a string, the length is in BYTES
2447 * even if UNICODE is negociated.
2449 * JFM, 4/19/1999
2452 *out_size = in_size;
2454 /* in case of problem, return some default values */
2456 *needed = 0;
2457 *type = 0;
2459 DEBUG(4,("_spoolss_getprinterdata\n"));
2461 if ( !Printer ) {
2462 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2463 status = WERR_BADFID;
2464 goto done;
2467 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2469 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2470 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2471 else
2473 if ( !get_printer_snum(p,handle, &snum) ) {
2474 status = WERR_BADFID;
2475 goto done;
2478 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2479 if ( !W_ERROR_IS_OK(status) )
2480 goto done;
2482 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2484 if ( strequal(value, "ChangeId") ) {
2485 *type = REG_DWORD;
2486 *needed = sizeof(uint32);
2487 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2488 status = WERR_NOMEM;
2489 goto done;
2491 SIVAL( *data, 0, printer->info_2->changeid );
2492 status = WERR_OK;
2494 else
2495 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2498 if (*needed > *out_size)
2499 status = WERR_MORE_DATA;
2501 done:
2502 if ( !W_ERROR_IS_OK(status) )
2504 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2506 /* reply this param doesn't exist */
2508 if ( *out_size ) {
2509 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2510 if ( printer )
2511 free_a_printer( &printer, 2 );
2512 return WERR_NOMEM;
2515 else {
2516 *data = NULL;
2520 /* cleanup & exit */
2522 if ( printer )
2523 free_a_printer( &printer, 2 );
2525 return status;
2528 /*********************************************************
2529 Connect to the client machine.
2530 **********************************************************/
2532 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2533 struct in_addr *client_ip, const char *remote_machine)
2535 ZERO_STRUCTP(the_cli);
2537 if(cli_initialise(the_cli) == NULL) {
2538 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2539 return False;
2542 if ( is_zero_ip(*client_ip) ) {
2543 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2544 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2545 cli_shutdown(the_cli);
2546 return False;
2549 if (ismyip(the_cli->dest_ip)) {
2550 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2551 cli_shutdown(the_cli);
2552 return False;
2555 else {
2556 the_cli->dest_ip.s_addr = client_ip->s_addr;
2557 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2558 inet_ntoa(*client_ip) ));
2561 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2562 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) ));
2563 cli_shutdown(the_cli);
2564 return False;
2567 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2568 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2569 remote_machine));
2570 cli_shutdown(the_cli);
2571 return False;
2574 the_cli->protocol = PROTOCOL_NT1;
2575 cli_setup_signing_state(the_cli, lp_client_signing());
2577 if (!cli_negprot(the_cli)) {
2578 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2579 cli_shutdown(the_cli);
2580 return False;
2583 if (the_cli->protocol != PROTOCOL_NT1) {
2584 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2585 cli_shutdown(the_cli);
2586 return False;
2590 * Do an anonymous session setup.
2593 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2594 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2595 cli_shutdown(the_cli);
2596 return False;
2599 if (!(the_cli->sec_mode & 1)) {
2600 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2601 cli_shutdown(the_cli);
2602 return False;
2605 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2606 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) ));
2607 cli_shutdown(the_cli);
2608 return False;
2612 * Ok - we have an anonymous connection to the IPC$ share.
2613 * Now start the NT Domain stuff :-).
2616 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2617 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)));
2618 cli_nt_session_close(the_cli);
2619 cli_ulogoff(the_cli);
2620 cli_shutdown(the_cli);
2621 return False;
2624 return True;
2627 /***************************************************************************
2628 Connect to the client.
2629 ****************************************************************************/
2631 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2632 uint32 localprinter, uint32 type,
2633 POLICY_HND *handle, struct in_addr *client_ip)
2635 WERROR result;
2638 * If it's the first connection, contact the client
2639 * and connect to the IPC$ share anonymously
2641 if (smb_connections==0) {
2642 fstring unix_printer;
2644 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2646 ZERO_STRUCT(notify_cli);
2648 if(!spoolss_connect_to_client(&notify_cli, client_ip, unix_printer))
2649 return False;
2651 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2652 /* Tell the connections db we're now interested in printer
2653 * notify messages. */
2654 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2658 * Tell the specific printing tdb we want messages for this printer
2659 * by registering our PID.
2662 if (!print_notify_register_pid(snum))
2663 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2665 smb_connections++;
2667 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2668 type, handle);
2670 if (!W_ERROR_IS_OK(result))
2671 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2672 dos_errstr(result)));
2674 return (W_ERROR_IS_OK(result));
2677 /********************************************************************
2678 * _spoolss_rffpcnex
2679 * ReplyFindFirstPrinterChangeNotifyEx
2681 * before replying OK: status=0 a rpc call is made to the workstation
2682 * asking ReplyOpenPrinter
2684 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2685 * called from api_spoolss_rffpcnex
2686 ********************************************************************/
2688 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2690 POLICY_HND *handle = &q_u->handle;
2691 uint32 flags = q_u->flags;
2692 uint32 options = q_u->options;
2693 UNISTR2 *localmachine = &q_u->localmachine;
2694 uint32 printerlocal = q_u->printerlocal;
2695 int snum = -1;
2696 SPOOL_NOTIFY_OPTION *option = q_u->option;
2697 struct in_addr client_ip;
2699 /* store the notify value in the printer struct */
2701 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2703 if (!Printer) {
2704 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2705 return WERR_BADFID;
2708 Printer->notify.flags=flags;
2709 Printer->notify.options=options;
2710 Printer->notify.printerlocal=printerlocal;
2712 if (Printer->notify.option)
2713 free_spool_notify_option(&Printer->notify.option);
2715 Printer->notify.option=dup_spool_notify_option(option);
2717 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2718 sizeof(Printer->notify.localmachine)-1);
2720 /* Connect to the client machine and send a ReplyOpenPrinter */
2722 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2723 snum = -1;
2724 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2725 !get_printer_snum(p, handle, &snum) )
2726 return WERR_BADFID;
2728 client_ip.s_addr = inet_addr(p->conn->client_address);
2730 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2731 Printer->notify.printerlocal, 1,
2732 &Printer->notify.client_hnd, &client_ip))
2733 return WERR_SERVER_UNAVAILABLE;
2735 Printer->notify.client_connected=True;
2737 return WERR_OK;
2740 /*******************************************************************
2741 * fill a notify_info_data with the servername
2742 ********************************************************************/
2744 void spoolss_notify_server_name(int snum,
2745 SPOOL_NOTIFY_INFO_DATA *data,
2746 print_queue_struct *queue,
2747 NT_PRINTER_INFO_LEVEL *printer,
2748 TALLOC_CTX *mem_ctx)
2750 pstring temp_name, temp;
2751 uint32 len;
2753 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2755 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2757 data->notify_data.data.length = len;
2758 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2760 if (!data->notify_data.data.string) {
2761 data->notify_data.data.length = 0;
2762 return;
2765 memcpy(data->notify_data.data.string, temp, len);
2768 /*******************************************************************
2769 * fill a notify_info_data with the printername (not including the servername).
2770 ********************************************************************/
2772 void spoolss_notify_printer_name(int snum,
2773 SPOOL_NOTIFY_INFO_DATA *data,
2774 print_queue_struct *queue,
2775 NT_PRINTER_INFO_LEVEL *printer,
2776 TALLOC_CTX *mem_ctx)
2778 pstring temp;
2779 uint32 len;
2781 /* the notify name should not contain the \\server\ part */
2782 char *p = strrchr(printer->info_2->printername, '\\');
2784 if (!p) {
2785 p = printer->info_2->printername;
2786 } else {
2787 p++;
2790 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2792 data->notify_data.data.length = len;
2793 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2795 if (!data->notify_data.data.string) {
2796 data->notify_data.data.length = 0;
2797 return;
2800 memcpy(data->notify_data.data.string, temp, len);
2803 /*******************************************************************
2804 * fill a notify_info_data with the servicename
2805 ********************************************************************/
2807 void spoolss_notify_share_name(int snum,
2808 SPOOL_NOTIFY_INFO_DATA *data,
2809 print_queue_struct *queue,
2810 NT_PRINTER_INFO_LEVEL *printer,
2811 TALLOC_CTX *mem_ctx)
2813 pstring temp;
2814 uint32 len;
2816 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2818 data->notify_data.data.length = len;
2819 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2821 if (!data->notify_data.data.string) {
2822 data->notify_data.data.length = 0;
2823 return;
2826 memcpy(data->notify_data.data.string, temp, len);
2829 /*******************************************************************
2830 * fill a notify_info_data with the port name
2831 ********************************************************************/
2833 void spoolss_notify_port_name(int snum,
2834 SPOOL_NOTIFY_INFO_DATA *data,
2835 print_queue_struct *queue,
2836 NT_PRINTER_INFO_LEVEL *printer,
2837 TALLOC_CTX *mem_ctx)
2839 pstring temp;
2840 uint32 len;
2842 /* even if it's strange, that's consistant in all the code */
2844 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2846 data->notify_data.data.length = len;
2847 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2849 if (!data->notify_data.data.string) {
2850 data->notify_data.data.length = 0;
2851 return;
2854 memcpy(data->notify_data.data.string, temp, len);
2857 /*******************************************************************
2858 * fill a notify_info_data with the printername
2859 * but it doesn't exist, have to see what to do
2860 ********************************************************************/
2862 void spoolss_notify_driver_name(int snum,
2863 SPOOL_NOTIFY_INFO_DATA *data,
2864 print_queue_struct *queue,
2865 NT_PRINTER_INFO_LEVEL *printer,
2866 TALLOC_CTX *mem_ctx)
2868 pstring temp;
2869 uint32 len;
2871 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2873 data->notify_data.data.length = len;
2874 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2876 if (!data->notify_data.data.string) {
2877 data->notify_data.data.length = 0;
2878 return;
2881 memcpy(data->notify_data.data.string, temp, len);
2884 /*******************************************************************
2885 * fill a notify_info_data with the comment
2886 ********************************************************************/
2888 void spoolss_notify_comment(int snum,
2889 SPOOL_NOTIFY_INFO_DATA *data,
2890 print_queue_struct *queue,
2891 NT_PRINTER_INFO_LEVEL *printer,
2892 TALLOC_CTX *mem_ctx)
2894 pstring temp;
2895 uint32 len;
2897 if (*printer->info_2->comment == '\0')
2898 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2899 else
2900 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2902 data->notify_data.data.length = len;
2903 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2905 if (!data->notify_data.data.string) {
2906 data->notify_data.data.length = 0;
2907 return;
2910 memcpy(data->notify_data.data.string, temp, len);
2913 /*******************************************************************
2914 * fill a notify_info_data with the comment
2915 * location = "Room 1, floor 2, building 3"
2916 ********************************************************************/
2918 void spoolss_notify_location(int snum,
2919 SPOOL_NOTIFY_INFO_DATA *data,
2920 print_queue_struct *queue,
2921 NT_PRINTER_INFO_LEVEL *printer,
2922 TALLOC_CTX *mem_ctx)
2924 pstring temp;
2925 uint32 len;
2927 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2929 data->notify_data.data.length = len;
2930 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2932 if (!data->notify_data.data.string) {
2933 data->notify_data.data.length = 0;
2934 return;
2937 memcpy(data->notify_data.data.string, temp, len);
2940 /*******************************************************************
2941 * fill a notify_info_data with the device mode
2942 * jfm:xxxx don't to it for know but that's a real problem !!!
2943 ********************************************************************/
2945 static void spoolss_notify_devmode(int snum,
2946 SPOOL_NOTIFY_INFO_DATA *data,
2947 print_queue_struct *queue,
2948 NT_PRINTER_INFO_LEVEL *printer,
2949 TALLOC_CTX *mem_ctx)
2953 /*******************************************************************
2954 * fill a notify_info_data with the separator file name
2955 ********************************************************************/
2957 void spoolss_notify_sepfile(int snum,
2958 SPOOL_NOTIFY_INFO_DATA *data,
2959 print_queue_struct *queue,
2960 NT_PRINTER_INFO_LEVEL *printer,
2961 TALLOC_CTX *mem_ctx)
2963 pstring temp;
2964 uint32 len;
2966 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2968 data->notify_data.data.length = len;
2969 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2971 if (!data->notify_data.data.string) {
2972 data->notify_data.data.length = 0;
2973 return;
2976 memcpy(data->notify_data.data.string, temp, len);
2979 /*******************************************************************
2980 * fill a notify_info_data with the print processor
2981 * jfm:xxxx return always winprint to indicate we don't do anything to it
2982 ********************************************************************/
2984 void spoolss_notify_print_processor(int snum,
2985 SPOOL_NOTIFY_INFO_DATA *data,
2986 print_queue_struct *queue,
2987 NT_PRINTER_INFO_LEVEL *printer,
2988 TALLOC_CTX *mem_ctx)
2990 pstring temp;
2991 uint32 len;
2993 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2995 data->notify_data.data.length = len;
2996 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2998 if (!data->notify_data.data.string) {
2999 data->notify_data.data.length = 0;
3000 return;
3003 memcpy(data->notify_data.data.string, temp, len);
3006 /*******************************************************************
3007 * fill a notify_info_data with the print processor options
3008 * jfm:xxxx send an empty string
3009 ********************************************************************/
3011 void spoolss_notify_parameters(int snum,
3012 SPOOL_NOTIFY_INFO_DATA *data,
3013 print_queue_struct *queue,
3014 NT_PRINTER_INFO_LEVEL *printer,
3015 TALLOC_CTX *mem_ctx)
3017 pstring temp;
3018 uint32 len;
3020 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3022 data->notify_data.data.length = len;
3023 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3025 if (!data->notify_data.data.string) {
3026 data->notify_data.data.length = 0;
3027 return;
3030 memcpy(data->notify_data.data.string, temp, len);
3033 /*******************************************************************
3034 * fill a notify_info_data with the data type
3035 * jfm:xxxx always send RAW as data type
3036 ********************************************************************/
3038 void spoolss_notify_datatype(int snum,
3039 SPOOL_NOTIFY_INFO_DATA *data,
3040 print_queue_struct *queue,
3041 NT_PRINTER_INFO_LEVEL *printer,
3042 TALLOC_CTX *mem_ctx)
3044 pstring temp;
3045 uint32 len;
3047 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3049 data->notify_data.data.length = len;
3050 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3052 if (!data->notify_data.data.string) {
3053 data->notify_data.data.length = 0;
3054 return;
3057 memcpy(data->notify_data.data.string, temp, len);
3060 /*******************************************************************
3061 * fill a notify_info_data with the security descriptor
3062 * jfm:xxxx send an null pointer to say no security desc
3063 * have to implement security before !
3064 ********************************************************************/
3066 static void spoolss_notify_security_desc(int snum,
3067 SPOOL_NOTIFY_INFO_DATA *data,
3068 print_queue_struct *queue,
3069 NT_PRINTER_INFO_LEVEL *printer,
3070 TALLOC_CTX *mem_ctx)
3072 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3073 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3076 /*******************************************************************
3077 * fill a notify_info_data with the attributes
3078 * jfm:xxxx a samba printer is always shared
3079 ********************************************************************/
3081 void spoolss_notify_attributes(int snum,
3082 SPOOL_NOTIFY_INFO_DATA *data,
3083 print_queue_struct *queue,
3084 NT_PRINTER_INFO_LEVEL *printer,
3085 TALLOC_CTX *mem_ctx)
3087 data->notify_data.value[0] = printer->info_2->attributes;
3088 data->notify_data.value[1] = 0;
3091 /*******************************************************************
3092 * fill a notify_info_data with the priority
3093 ********************************************************************/
3095 static void spoolss_notify_priority(int snum,
3096 SPOOL_NOTIFY_INFO_DATA *data,
3097 print_queue_struct *queue,
3098 NT_PRINTER_INFO_LEVEL *printer,
3099 TALLOC_CTX *mem_ctx)
3101 data->notify_data.value[0] = printer->info_2->priority;
3102 data->notify_data.value[1] = 0;
3105 /*******************************************************************
3106 * fill a notify_info_data with the default priority
3107 ********************************************************************/
3109 static void spoolss_notify_default_priority(int snum,
3110 SPOOL_NOTIFY_INFO_DATA *data,
3111 print_queue_struct *queue,
3112 NT_PRINTER_INFO_LEVEL *printer,
3113 TALLOC_CTX *mem_ctx)
3115 data->notify_data.value[0] = printer->info_2->default_priority;
3116 data->notify_data.value[1] = 0;
3119 /*******************************************************************
3120 * fill a notify_info_data with the start time
3121 ********************************************************************/
3123 static void spoolss_notify_start_time(int snum,
3124 SPOOL_NOTIFY_INFO_DATA *data,
3125 print_queue_struct *queue,
3126 NT_PRINTER_INFO_LEVEL *printer,
3127 TALLOC_CTX *mem_ctx)
3129 data->notify_data.value[0] = printer->info_2->starttime;
3130 data->notify_data.value[1] = 0;
3133 /*******************************************************************
3134 * fill a notify_info_data with the until time
3135 ********************************************************************/
3137 static void spoolss_notify_until_time(int snum,
3138 SPOOL_NOTIFY_INFO_DATA *data,
3139 print_queue_struct *queue,
3140 NT_PRINTER_INFO_LEVEL *printer,
3141 TALLOC_CTX *mem_ctx)
3143 data->notify_data.value[0] = printer->info_2->untiltime;
3144 data->notify_data.value[1] = 0;
3147 /*******************************************************************
3148 * fill a notify_info_data with the status
3149 ********************************************************************/
3151 static void spoolss_notify_status(int snum,
3152 SPOOL_NOTIFY_INFO_DATA *data,
3153 print_queue_struct *queue,
3154 NT_PRINTER_INFO_LEVEL *printer,
3155 TALLOC_CTX *mem_ctx)
3157 print_status_struct status;
3159 print_queue_length(snum, &status);
3160 data->notify_data.value[0]=(uint32) status.status;
3161 data->notify_data.value[1] = 0;
3164 /*******************************************************************
3165 * fill a notify_info_data with the number of jobs queued
3166 ********************************************************************/
3168 void spoolss_notify_cjobs(int snum,
3169 SPOOL_NOTIFY_INFO_DATA *data,
3170 print_queue_struct *queue,
3171 NT_PRINTER_INFO_LEVEL *printer,
3172 TALLOC_CTX *mem_ctx)
3174 data->notify_data.value[0] = print_queue_length(snum, NULL);
3175 data->notify_data.value[1] = 0;
3178 /*******************************************************************
3179 * fill a notify_info_data with the average ppm
3180 ********************************************************************/
3182 static void spoolss_notify_average_ppm(int snum,
3183 SPOOL_NOTIFY_INFO_DATA *data,
3184 print_queue_struct *queue,
3185 NT_PRINTER_INFO_LEVEL *printer,
3186 TALLOC_CTX *mem_ctx)
3188 /* always respond 8 pages per minutes */
3189 /* a little hard ! */
3190 data->notify_data.value[0] = printer->info_2->averageppm;
3191 data->notify_data.value[1] = 0;
3194 /*******************************************************************
3195 * fill a notify_info_data with username
3196 ********************************************************************/
3198 static void spoolss_notify_username(int snum,
3199 SPOOL_NOTIFY_INFO_DATA *data,
3200 print_queue_struct *queue,
3201 NT_PRINTER_INFO_LEVEL *printer,
3202 TALLOC_CTX *mem_ctx)
3204 pstring temp;
3205 uint32 len;
3207 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3209 data->notify_data.data.length = len;
3210 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3212 if (!data->notify_data.data.string) {
3213 data->notify_data.data.length = 0;
3214 return;
3217 memcpy(data->notify_data.data.string, temp, len);
3220 /*******************************************************************
3221 * fill a notify_info_data with job status
3222 ********************************************************************/
3224 static void spoolss_notify_job_status(int snum,
3225 SPOOL_NOTIFY_INFO_DATA *data,
3226 print_queue_struct *queue,
3227 NT_PRINTER_INFO_LEVEL *printer,
3228 TALLOC_CTX *mem_ctx)
3230 data->notify_data.value[0]=nt_printj_status(queue->status);
3231 data->notify_data.value[1] = 0;
3234 /*******************************************************************
3235 * fill a notify_info_data with job name
3236 ********************************************************************/
3238 static void spoolss_notify_job_name(int snum,
3239 SPOOL_NOTIFY_INFO_DATA *data,
3240 print_queue_struct *queue,
3241 NT_PRINTER_INFO_LEVEL *printer,
3242 TALLOC_CTX *mem_ctx)
3244 pstring temp;
3245 uint32 len;
3247 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3249 data->notify_data.data.length = len;
3250 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3252 if (!data->notify_data.data.string) {
3253 data->notify_data.data.length = 0;
3254 return;
3257 memcpy(data->notify_data.data.string, temp, len);
3260 /*******************************************************************
3261 * fill a notify_info_data with job status
3262 ********************************************************************/
3264 static void spoolss_notify_job_status_string(int snum,
3265 SPOOL_NOTIFY_INFO_DATA *data,
3266 print_queue_struct *queue,
3267 NT_PRINTER_INFO_LEVEL *printer,
3268 TALLOC_CTX *mem_ctx)
3271 * Now we're returning job status codes we just return a "" here. JRA.
3274 const char *p = "";
3275 pstring temp;
3276 uint32 len;
3278 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3279 p = "unknown";
3281 switch (queue->status) {
3282 case LPQ_QUEUED:
3283 p = "Queued";
3284 break;
3285 case LPQ_PAUSED:
3286 p = ""; /* NT provides the paused string */
3287 break;
3288 case LPQ_SPOOLING:
3289 p = "Spooling";
3290 break;
3291 case LPQ_PRINTING:
3292 p = "Printing";
3293 break;
3295 #endif /* NO LONGER NEEDED. */
3297 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3299 data->notify_data.data.length = len;
3300 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3302 if (!data->notify_data.data.string) {
3303 data->notify_data.data.length = 0;
3304 return;
3307 memcpy(data->notify_data.data.string, temp, len);
3310 /*******************************************************************
3311 * fill a notify_info_data with job time
3312 ********************************************************************/
3314 static void spoolss_notify_job_time(int snum,
3315 SPOOL_NOTIFY_INFO_DATA *data,
3316 print_queue_struct *queue,
3317 NT_PRINTER_INFO_LEVEL *printer,
3318 TALLOC_CTX *mem_ctx)
3320 data->notify_data.value[0]=0x0;
3321 data->notify_data.value[1]=0;
3324 /*******************************************************************
3325 * fill a notify_info_data with job size
3326 ********************************************************************/
3328 static void spoolss_notify_job_size(int snum,
3329 SPOOL_NOTIFY_INFO_DATA *data,
3330 print_queue_struct *queue,
3331 NT_PRINTER_INFO_LEVEL *printer,
3332 TALLOC_CTX *mem_ctx)
3334 data->notify_data.value[0]=queue->size;
3335 data->notify_data.value[1]=0;
3338 /*******************************************************************
3339 * fill a notify_info_data with page info
3340 ********************************************************************/
3341 static void spoolss_notify_total_pages(int snum,
3342 SPOOL_NOTIFY_INFO_DATA *data,
3343 print_queue_struct *queue,
3344 NT_PRINTER_INFO_LEVEL *printer,
3345 TALLOC_CTX *mem_ctx)
3347 data->notify_data.value[0]=queue->page_count;
3348 data->notify_data.value[1]=0;
3351 /*******************************************************************
3352 * fill a notify_info_data with pages printed info.
3353 ********************************************************************/
3354 static void spoolss_notify_pages_printed(int snum,
3355 SPOOL_NOTIFY_INFO_DATA *data,
3356 print_queue_struct *queue,
3357 NT_PRINTER_INFO_LEVEL *printer,
3358 TALLOC_CTX *mem_ctx)
3360 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3361 data->notify_data.value[1]=0;
3364 /*******************************************************************
3365 Fill a notify_info_data with job position.
3366 ********************************************************************/
3368 static void spoolss_notify_job_position(int snum,
3369 SPOOL_NOTIFY_INFO_DATA *data,
3370 print_queue_struct *queue,
3371 NT_PRINTER_INFO_LEVEL *printer,
3372 TALLOC_CTX *mem_ctx)
3374 data->notify_data.value[0]=queue->job;
3375 data->notify_data.value[1]=0;
3378 /*******************************************************************
3379 Fill a notify_info_data with submitted time.
3380 ********************************************************************/
3382 static void spoolss_notify_submitted_time(int snum,
3383 SPOOL_NOTIFY_INFO_DATA *data,
3384 print_queue_struct *queue,
3385 NT_PRINTER_INFO_LEVEL *printer,
3386 TALLOC_CTX *mem_ctx)
3388 struct tm *t;
3389 uint32 len;
3390 SYSTEMTIME st;
3391 char *p;
3393 t=gmtime(&queue->time);
3395 len = sizeof(SYSTEMTIME);
3397 data->notify_data.data.length = len;
3398 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3400 if (!data->notify_data.data.string) {
3401 data->notify_data.data.length = 0;
3402 return;
3405 make_systemtime(&st, t);
3408 * Systemtime must be linearized as a set of UINT16's.
3409 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3412 p = (char *)data->notify_data.data.string;
3413 SSVAL(p, 0, st.year);
3414 SSVAL(p, 2, st.month);
3415 SSVAL(p, 4, st.dayofweek);
3416 SSVAL(p, 6, st.day);
3417 SSVAL(p, 8, st.hour);
3418 SSVAL(p, 10, st.minute);
3419 SSVAL(p, 12, st.second);
3420 SSVAL(p, 14, st.milliseconds);
3423 struct s_notify_info_data_table
3425 uint16 type;
3426 uint16 field;
3427 const char *name;
3428 uint32 size;
3429 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3430 print_queue_struct *queue,
3431 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3434 /* A table describing the various print notification constants and
3435 whether the notification data is a pointer to a variable sized
3436 buffer, a one value uint32 or a two value uint32. */
3438 static const struct s_notify_info_data_table notify_info_data_table[] =
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3491 /*******************************************************************
3492 Return the size of info_data structure.
3493 ********************************************************************/
3495 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3497 int i=0;
3499 for (i = 0; i < sizeof(notify_info_data_table); i++)
3501 if ( (notify_info_data_table[i].type == type)
3502 && (notify_info_data_table[i].field == field) )
3504 switch(notify_info_data_table[i].size)
3506 case NOTIFY_ONE_VALUE:
3507 case NOTIFY_TWO_VALUE:
3508 return 1;
3509 case NOTIFY_STRING:
3510 return 2;
3512 /* The only pointer notify data I have seen on
3513 the wire is the submitted time and this has
3514 the notify size set to 4. -tpot */
3516 case NOTIFY_POINTER:
3517 return 4;
3519 case NOTIFY_SECDESC:
3520 return 5;
3525 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3527 return 0;
3530 /*******************************************************************
3531 Return the type of notify_info_data.
3532 ********************************************************************/
3534 static int type_of_notify_info_data(uint16 type, uint16 field)
3536 int i=0;
3538 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3539 if (notify_info_data_table[i].type == type &&
3540 notify_info_data_table[i].field == field)
3541 return notify_info_data_table[i].size;
3544 return False;
3547 /****************************************************************************
3548 ****************************************************************************/
3550 static int search_notify(uint16 type, uint16 field, int *value)
3552 int i;
3554 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3555 if (notify_info_data_table[i].type == type &&
3556 notify_info_data_table[i].field == field &&
3557 notify_info_data_table[i].fn != NULL) {
3558 *value = i;
3559 return True;
3563 return False;
3566 /****************************************************************************
3567 ****************************************************************************/
3569 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3571 info_data->type = type;
3572 info_data->field = field;
3573 info_data->reserved = 0;
3575 info_data->size = size_of_notify_info_data(type, field);
3576 info_data->enc_type = type_of_notify_info_data(type, field);
3578 info_data->id = id;
3583 /*******************************************************************
3585 * fill a notify_info struct with info asked
3587 ********************************************************************/
3589 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3590 snum, SPOOL_NOTIFY_OPTION_TYPE
3591 *option_type, uint32 id,
3592 TALLOC_CTX *mem_ctx)
3594 int field_num,j;
3595 uint16 type;
3596 uint16 field;
3598 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3599 NT_PRINTER_INFO_LEVEL *printer = NULL;
3600 print_queue_struct *queue=NULL;
3602 type=option_type->type;
3604 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3605 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3606 option_type->count, lp_servicename(snum)));
3608 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3609 return False;
3611 for(field_num=0; field_num<option_type->count; field_num++) {
3612 field = option_type->fields[field_num];
3614 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3616 if (!search_notify(type, field, &j) )
3617 continue;
3619 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3620 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3621 return False;
3622 } else
3623 info->data = tid;
3625 current_data = &info->data[info->count];
3627 construct_info_data(current_data, type, field, id);
3629 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3630 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3632 notify_info_data_table[j].fn(snum, current_data, queue,
3633 printer, mem_ctx);
3635 info->count++;
3638 free_a_printer(&printer, 2);
3639 return True;
3642 /*******************************************************************
3644 * fill a notify_info struct with info asked
3646 ********************************************************************/
3648 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3649 SPOOL_NOTIFY_INFO *info,
3650 NT_PRINTER_INFO_LEVEL *printer,
3651 int snum, SPOOL_NOTIFY_OPTION_TYPE
3652 *option_type, uint32 id,
3653 TALLOC_CTX *mem_ctx)
3655 int field_num,j;
3656 uint16 type;
3657 uint16 field;
3659 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3661 DEBUG(4,("construct_notify_jobs_info\n"));
3663 type = option_type->type;
3665 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3666 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3667 option_type->count));
3669 for(field_num=0; field_num<option_type->count; field_num++) {
3670 field = option_type->fields[field_num];
3672 if (!search_notify(type, field, &j) )
3673 continue;
3675 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3676 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3677 return False;
3679 else info->data = tid;
3681 current_data=&(info->data[info->count]);
3683 construct_info_data(current_data, type, field, id);
3684 notify_info_data_table[j].fn(snum, current_data, queue,
3685 printer, mem_ctx);
3686 info->count++;
3689 return True;
3693 * JFM: The enumeration is not that simple, it's even non obvious.
3695 * let's take an example: I want to monitor the PRINTER SERVER for
3696 * the printer's name and the number of jobs currently queued.
3697 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3698 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3700 * I have 3 printers on the back of my server.
3702 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3703 * structures.
3704 * Number Data Id
3705 * 1 printer 1 name 1
3706 * 2 printer 1 cjob 1
3707 * 3 printer 2 name 2
3708 * 4 printer 2 cjob 2
3709 * 5 printer 3 name 3
3710 * 6 printer 3 name 3
3712 * that's the print server case, the printer case is even worse.
3715 /*******************************************************************
3717 * enumerate all printers on the printserver
3718 * fill a notify_info struct with info asked
3720 ********************************************************************/
3722 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3723 SPOOL_NOTIFY_INFO *info,
3724 TALLOC_CTX *mem_ctx)
3726 int snum;
3727 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3728 int n_services=lp_numservices();
3729 int i;
3730 SPOOL_NOTIFY_OPTION *option;
3731 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3733 DEBUG(4,("printserver_notify_info\n"));
3735 if (!Printer)
3736 return WERR_BADFID;
3738 option=Printer->notify.option;
3739 info->version=2;
3740 info->data=NULL;
3741 info->count=0;
3743 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3744 sending a ffpcn() request first */
3746 if ( !option )
3747 return WERR_BADFID;
3749 for (i=0; i<option->count; i++) {
3750 option_type=&(option->ctr.type[i]);
3752 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3753 continue;
3755 for (snum=0; snum<n_services; snum++)
3757 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3758 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3762 #if 0
3764 * Debugging information, don't delete.
3767 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3768 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3769 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3771 for (i=0; i<info->count; i++) {
3772 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3773 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3774 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3776 #endif
3778 return WERR_OK;
3781 /*******************************************************************
3783 * fill a notify_info struct with info asked
3785 ********************************************************************/
3787 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3788 TALLOC_CTX *mem_ctx)
3790 int snum;
3791 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3792 int i;
3793 uint32 id;
3794 SPOOL_NOTIFY_OPTION *option;
3795 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3796 int count,j;
3797 print_queue_struct *queue=NULL;
3798 print_status_struct status;
3800 DEBUG(4,("printer_notify_info\n"));
3802 if (!Printer)
3803 return WERR_BADFID;
3805 option=Printer->notify.option;
3806 id = 0x0;
3807 info->version=2;
3808 info->data=NULL;
3809 info->count=0;
3811 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3812 sending a ffpcn() request first */
3814 if ( !option )
3815 return WERR_BADFID;
3817 get_printer_snum(p, hnd, &snum);
3819 for (i=0; i<option->count; i++) {
3820 option_type=&option->ctr.type[i];
3822 switch ( option_type->type ) {
3823 case PRINTER_NOTIFY_TYPE:
3824 if(construct_notify_printer_info(Printer, info, snum,
3825 option_type, id,
3826 mem_ctx))
3827 id--;
3828 break;
3830 case JOB_NOTIFY_TYPE: {
3831 NT_PRINTER_INFO_LEVEL *printer = NULL;
3833 count = print_queue_status(snum, &queue, &status);
3835 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3836 goto done;
3838 for (j=0; j<count; j++) {
3839 construct_notify_jobs_info(&queue[j], info,
3840 printer, snum,
3841 option_type,
3842 queue[j].job,
3843 mem_ctx);
3846 free_a_printer(&printer, 2);
3848 done:
3849 SAFE_FREE(queue);
3850 break;
3856 * Debugging information, don't delete.
3859 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3860 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3861 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3863 for (i=0; i<info->count; i++) {
3864 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3865 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3866 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3869 return WERR_OK;
3872 /********************************************************************
3873 * spoolss_rfnpcnex
3874 ********************************************************************/
3876 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3878 POLICY_HND *handle = &q_u->handle;
3879 SPOOL_NOTIFY_INFO *info = &r_u->info;
3881 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3882 WERROR result = WERR_BADFID;
3884 /* we always have a NOTIFY_INFO struct */
3885 r_u->info_ptr=0x1;
3887 if (!Printer) {
3888 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3889 OUR_HANDLE(handle)));
3890 goto done;
3893 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3896 * We are now using the change value, and
3897 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3898 * I don't have a global notification system, I'm sending back all the
3899 * informations even when _NOTHING_ has changed.
3902 /* We need to keep track of the change value to send back in
3903 RRPCN replies otherwise our updates are ignored. */
3905 Printer->notify.fnpcn = True;
3907 if (Printer->notify.client_connected) {
3908 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3909 Printer->notify.change = q_u->change;
3912 /* just ignore the SPOOL_NOTIFY_OPTION */
3914 switch (Printer->printer_type) {
3915 case PRINTER_HANDLE_IS_PRINTSERVER:
3916 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3917 break;
3919 case PRINTER_HANDLE_IS_PRINTER:
3920 result = printer_notify_info(p, handle, info, p->mem_ctx);
3921 break;
3924 Printer->notify.fnpcn = False;
3926 done:
3927 return result;
3930 /********************************************************************
3931 * construct_printer_info_0
3932 * fill a printer_info_0 struct
3933 ********************************************************************/
3935 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3937 pstring chaine;
3938 int count;
3939 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3940 counter_printer_0 *session_counter;
3941 uint32 global_counter;
3942 struct tm *t;
3943 time_t setuptime;
3944 print_status_struct status;
3946 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3947 return False;
3949 count = print_queue_length(snum, &status);
3951 /* check if we already have a counter for this printer */
3952 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3953 if (session_counter->snum == snum)
3954 break;
3957 /* it's the first time, add it to the list */
3958 if (session_counter==NULL) {
3959 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3960 free_a_printer(&ntprinter, 2);
3961 return False;
3963 ZERO_STRUCTP(session_counter);
3964 session_counter->snum=snum;
3965 session_counter->counter=0;
3966 DLIST_ADD(counter_list, session_counter);
3969 /* increment it */
3970 session_counter->counter++;
3972 /* JFM:
3973 * the global_counter should be stored in a TDB as it's common to all the clients
3974 * and should be zeroed on samba startup
3976 global_counter=session_counter->counter;
3978 pstrcpy(chaine,ntprinter->info_2->printername);
3980 init_unistr(&printer->printername, chaine);
3982 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3983 init_unistr(&printer->servername, chaine);
3985 printer->cjobs = count;
3986 printer->total_jobs = 0;
3987 printer->total_bytes = 0;
3989 setuptime = (time_t)ntprinter->info_2->setuptime;
3990 t=gmtime(&setuptime);
3992 printer->year = t->tm_year+1900;
3993 printer->month = t->tm_mon+1;
3994 printer->dayofweek = t->tm_wday;
3995 printer->day = t->tm_mday;
3996 printer->hour = t->tm_hour;
3997 printer->minute = t->tm_min;
3998 printer->second = t->tm_sec;
3999 printer->milliseconds = 0;
4001 printer->global_counter = global_counter;
4002 printer->total_pages = 0;
4004 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4005 printer->major_version = 0x0005; /* NT 5 */
4006 printer->build_version = 0x0893; /* build 2195 */
4008 printer->unknown7 = 0x1;
4009 printer->unknown8 = 0x0;
4010 printer->unknown9 = 0x0;
4011 printer->session_counter = session_counter->counter;
4012 printer->unknown11 = 0x0;
4013 printer->printer_errors = 0x0; /* number of print failure */
4014 printer->unknown13 = 0x0;
4015 printer->unknown14 = 0x1;
4016 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4017 printer->unknown16 = 0x0;
4018 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4019 printer->unknown18 = 0x0;
4020 printer->status = nt_printq_status(status.status);
4021 printer->unknown20 = 0x0;
4022 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4023 printer->unknown22 = 0x0;
4024 printer->unknown23 = 0x6; /* 6 ???*/
4025 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4026 printer->unknown25 = 0;
4027 printer->unknown26 = 0;
4028 printer->unknown27 = 0;
4029 printer->unknown28 = 0;
4030 printer->unknown29 = 0;
4032 free_a_printer(&ntprinter,2);
4033 return (True);
4036 /********************************************************************
4037 * construct_printer_info_1
4038 * fill a printer_info_1 struct
4039 ********************************************************************/
4040 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4042 pstring chaine;
4043 pstring chaine2;
4044 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4046 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4047 return False;
4049 printer->flags=flags;
4051 if (*ntprinter->info_2->comment == '\0') {
4052 init_unistr(&printer->comment, lp_comment(snum));
4053 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4054 ntprinter->info_2->drivername, lp_comment(snum));
4056 else {
4057 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4058 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4059 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4062 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4064 init_unistr(&printer->description, chaine);
4065 init_unistr(&printer->name, chaine2);
4067 free_a_printer(&ntprinter,2);
4069 return True;
4072 /****************************************************************************
4073 Free a DEVMODE struct.
4074 ****************************************************************************/
4076 static void free_dev_mode(DEVICEMODE *dev)
4078 if (dev == NULL)
4079 return;
4081 SAFE_FREE(dev->private);
4082 SAFE_FREE(dev);
4086 /****************************************************************************
4087 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4088 should be valid upon entry
4089 ****************************************************************************/
4091 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4093 if ( !devmode || !ntdevmode )
4094 return False;
4096 init_unistr(&devmode->devicename, ntdevmode->devicename);
4098 init_unistr(&devmode->formname, ntdevmode->formname);
4100 devmode->specversion = ntdevmode->specversion;
4101 devmode->driverversion = ntdevmode->driverversion;
4102 devmode->size = ntdevmode->size;
4103 devmode->driverextra = ntdevmode->driverextra;
4104 devmode->fields = ntdevmode->fields;
4106 devmode->orientation = ntdevmode->orientation;
4107 devmode->papersize = ntdevmode->papersize;
4108 devmode->paperlength = ntdevmode->paperlength;
4109 devmode->paperwidth = ntdevmode->paperwidth;
4110 devmode->scale = ntdevmode->scale;
4111 devmode->copies = ntdevmode->copies;
4112 devmode->defaultsource = ntdevmode->defaultsource;
4113 devmode->printquality = ntdevmode->printquality;
4114 devmode->color = ntdevmode->color;
4115 devmode->duplex = ntdevmode->duplex;
4116 devmode->yresolution = ntdevmode->yresolution;
4117 devmode->ttoption = ntdevmode->ttoption;
4118 devmode->collate = ntdevmode->collate;
4119 devmode->icmmethod = ntdevmode->icmmethod;
4120 devmode->icmintent = ntdevmode->icmintent;
4121 devmode->mediatype = ntdevmode->mediatype;
4122 devmode->dithertype = ntdevmode->dithertype;
4124 if (ntdevmode->private != NULL) {
4125 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4126 return False;
4129 return True;
4132 /****************************************************************************
4133 Create a DEVMODE struct. Returns malloced memory.
4134 ****************************************************************************/
4136 DEVICEMODE *construct_dev_mode(int snum)
4138 NT_PRINTER_INFO_LEVEL *printer = NULL;
4139 DEVICEMODE *devmode = NULL;
4141 DEBUG(7,("construct_dev_mode\n"));
4143 DEBUGADD(8,("getting printer characteristics\n"));
4145 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4146 return NULL;
4148 if ( !printer->info_2->devmode ) {
4149 DEBUG(5, ("BONG! There was no device mode!\n"));
4150 goto done;
4153 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4154 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4155 goto done;
4158 ZERO_STRUCTP(devmode);
4160 DEBUGADD(8,("loading DEVICEMODE\n"));
4162 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4163 free_dev_mode( devmode );
4164 devmode = NULL;
4167 done:
4168 free_a_printer(&printer,2);
4170 return devmode;
4173 /********************************************************************
4174 * construct_printer_info_2
4175 * fill a printer_info_2 struct
4176 ********************************************************************/
4178 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4180 int count;
4181 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4183 print_status_struct status;
4185 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4186 return False;
4188 count = print_queue_length(snum, &status);
4190 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4191 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4192 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4193 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4194 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4196 if (*ntprinter->info_2->comment == '\0')
4197 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4198 else
4199 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4201 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4202 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4203 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4204 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4205 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4207 printer->attributes = ntprinter->info_2->attributes;
4209 printer->priority = ntprinter->info_2->priority; /* priority */
4210 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4211 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4212 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4213 printer->status = nt_printq_status(status.status); /* status */
4214 printer->cjobs = count; /* jobs */
4215 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4217 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4218 DEBUG(8, ("Returning NULL Devicemode!\n"));
4221 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4222 /* steal the printer info sec_desc structure. [badly done]. */
4223 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4224 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4225 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4226 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4228 else {
4229 printer->secdesc = NULL;
4232 free_a_printer(&ntprinter, 2);
4233 return True;
4236 /********************************************************************
4237 * construct_printer_info_3
4238 * fill a printer_info_3 struct
4239 ********************************************************************/
4241 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4243 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4244 PRINTER_INFO_3 *printer = NULL;
4246 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4247 return False;
4249 *pp_printer = NULL;
4250 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4251 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4252 return False;
4255 ZERO_STRUCTP(printer);
4257 printer->flags = 4; /* These are the components of the SD we are returning. */
4258 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4259 /* steal the printer info sec_desc structure. [badly done]. */
4260 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4262 #if 0
4264 * Set the flags for the components we are returning.
4267 if (printer->secdesc->owner_sid)
4268 printer->flags |= OWNER_SECURITY_INFORMATION;
4270 if (printer->secdesc->grp_sid)
4271 printer->flags |= GROUP_SECURITY_INFORMATION;
4273 if (printer->secdesc->dacl)
4274 printer->flags |= DACL_SECURITY_INFORMATION;
4276 if (printer->secdesc->sacl)
4277 printer->flags |= SACL_SECURITY_INFORMATION;
4278 #endif
4280 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4281 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4282 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4285 free_a_printer(&ntprinter, 2);
4287 *pp_printer = printer;
4288 return True;
4291 /********************************************************************
4292 * construct_printer_info_4
4293 * fill a printer_info_4 struct
4294 ********************************************************************/
4296 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4298 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4300 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4301 return False;
4303 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4304 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4305 printer->attributes = ntprinter->info_2->attributes;
4307 free_a_printer(&ntprinter, 2);
4308 return True;
4311 /********************************************************************
4312 * construct_printer_info_5
4313 * fill a printer_info_5 struct
4314 ********************************************************************/
4316 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4318 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4320 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4321 return False;
4323 init_unistr(&printer->printername, ntprinter->info_2->printername);
4324 init_unistr(&printer->portname, ntprinter->info_2->portname);
4325 printer->attributes = ntprinter->info_2->attributes;
4327 /* these two are not used by NT+ according to MSDN */
4329 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4330 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4332 free_a_printer(&ntprinter, 2);
4334 return True;
4337 /********************************************************************
4338 * construct_printer_info_7
4339 * fill a printer_info_7 struct
4340 ********************************************************************/
4342 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4344 char *guid_str = NULL;
4345 struct uuid guid;
4347 if (is_printer_published(print_hnd, snum, &guid)) {
4348 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4349 strupper_m(guid_str);
4350 init_unistr(&printer->guid, guid_str);
4351 printer->action = SPOOL_DS_PUBLISH;
4352 } else {
4353 init_unistr(&printer->guid, "");
4354 printer->action = SPOOL_DS_UNPUBLISH;
4357 return True;
4360 /********************************************************************
4361 Spoolss_enumprinters.
4362 ********************************************************************/
4364 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4366 int snum;
4367 int i;
4368 int n_services=lp_numservices();
4369 PRINTER_INFO_1 *tp, *printers=NULL;
4370 PRINTER_INFO_1 current_prt;
4372 DEBUG(4,("enum_all_printers_info_1\n"));
4374 for (snum=0; snum<n_services; snum++) {
4375 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4376 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4378 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4379 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4380 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4381 SAFE_FREE(printers);
4382 *returned=0;
4383 return WERR_NOMEM;
4385 else printers = tp;
4386 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4388 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4389 (*returned)++;
4394 /* check the required size. */
4395 for (i=0; i<*returned; i++)
4396 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4398 if (!alloc_buffer_size(buffer, *needed))
4399 return WERR_INSUFFICIENT_BUFFER;
4401 /* fill the buffer with the structures */
4402 for (i=0; i<*returned; i++)
4403 smb_io_printer_info_1("", buffer, &printers[i], 0);
4405 /* clear memory */
4406 SAFE_FREE(printers);
4408 if (*needed > offered) {
4409 *returned=0;
4410 return WERR_INSUFFICIENT_BUFFER;
4412 else
4413 return WERR_OK;
4416 /********************************************************************
4417 enum_all_printers_info_1_local.
4418 *********************************************************************/
4420 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4422 DEBUG(4,("enum_all_printers_info_1_local\n"));
4424 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4427 /********************************************************************
4428 enum_all_printers_info_1_name.
4429 *********************************************************************/
4431 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4433 char *s = name;
4435 DEBUG(4,("enum_all_printers_info_1_name\n"));
4437 if ((name[0] == '\\') && (name[1] == '\\'))
4438 s = name + 2;
4440 if (is_myname_or_ipaddr(s)) {
4441 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4443 else
4444 return WERR_INVALID_NAME;
4447 /********************************************************************
4448 enum_all_printers_info_1_remote.
4449 *********************************************************************/
4451 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4453 PRINTER_INFO_1 *printer;
4454 fstring printername;
4455 fstring desc;
4456 fstring comment;
4457 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4459 /* JFM: currently it's more a place holder than anything else.
4460 * In the spooler world there is a notion of server registration.
4461 * the print servers are registring (sp ?) on the PDC (in the same domain)
4463 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4466 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4467 return WERR_NOMEM;
4469 *returned=1;
4471 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4472 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4473 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4475 init_unistr(&printer->description, desc);
4476 init_unistr(&printer->name, printername);
4477 init_unistr(&printer->comment, comment);
4478 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4480 /* check the required size. */
4481 *needed += spoolss_size_printer_info_1(printer);
4483 if (!alloc_buffer_size(buffer, *needed)) {
4484 SAFE_FREE(printer);
4485 return WERR_INSUFFICIENT_BUFFER;
4488 /* fill the buffer with the structures */
4489 smb_io_printer_info_1("", buffer, printer, 0);
4491 /* clear memory */
4492 SAFE_FREE(printer);
4494 if (*needed > offered) {
4495 *returned=0;
4496 return WERR_INSUFFICIENT_BUFFER;
4498 else
4499 return WERR_OK;
4502 /********************************************************************
4503 enum_all_printers_info_1_network.
4504 *********************************************************************/
4506 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4508 char *s = name;
4510 DEBUG(4,("enum_all_printers_info_1_network\n"));
4512 /* If we respond to a enum_printers level 1 on our name with flags
4513 set to PRINTER_ENUM_REMOTE with a list of printers then these
4514 printers incorrectly appear in the APW browse list.
4515 Specifically the printers for the server appear at the workgroup
4516 level where all the other servers in the domain are
4517 listed. Windows responds to this call with a
4518 WERR_CAN_NOT_COMPLETE so we should do the same. */
4520 if (name[0] == '\\' && name[1] == '\\')
4521 s = name + 2;
4523 if (is_myname_or_ipaddr(s))
4524 return WERR_CAN_NOT_COMPLETE;
4526 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4529 /********************************************************************
4530 * api_spoolss_enumprinters
4532 * called from api_spoolss_enumprinters (see this to understand)
4533 ********************************************************************/
4535 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4537 int snum;
4538 int i;
4539 int n_services=lp_numservices();
4540 PRINTER_INFO_2 *tp, *printers=NULL;
4541 PRINTER_INFO_2 current_prt;
4543 for (snum=0; snum<n_services; snum++) {
4544 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4545 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4547 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4548 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4549 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4550 SAFE_FREE(printers);
4551 *returned = 0;
4552 return WERR_NOMEM;
4554 else printers = tp;
4555 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4556 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4557 (*returned)++;
4562 /* check the required size. */
4563 for (i=0; i<*returned; i++)
4564 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4566 if (!alloc_buffer_size(buffer, *needed)) {
4567 for (i=0; i<*returned; i++) {
4568 free_devmode(printers[i].devmode);
4570 SAFE_FREE(printers);
4571 return WERR_INSUFFICIENT_BUFFER;
4574 /* fill the buffer with the structures */
4575 for (i=0; i<*returned; i++)
4576 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4578 /* clear memory */
4579 for (i=0; i<*returned; i++) {
4580 free_devmode(printers[i].devmode);
4582 SAFE_FREE(printers);
4584 if (*needed > offered) {
4585 *returned=0;
4586 return WERR_INSUFFICIENT_BUFFER;
4588 else
4589 return WERR_OK;
4592 /********************************************************************
4593 * handle enumeration of printers at level 1
4594 ********************************************************************/
4596 static WERROR enumprinters_level1( uint32 flags, fstring name,
4597 NEW_BUFFER *buffer, uint32 offered,
4598 uint32 *needed, uint32 *returned)
4600 /* Not all the flags are equals */
4602 if (flags & PRINTER_ENUM_LOCAL)
4603 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4605 if (flags & PRINTER_ENUM_NAME)
4606 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4608 if (flags & PRINTER_ENUM_REMOTE)
4609 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4611 if (flags & PRINTER_ENUM_NETWORK)
4612 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4614 return WERR_OK; /* NT4sp5 does that */
4617 /********************************************************************
4618 * handle enumeration of printers at level 2
4619 ********************************************************************/
4621 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4622 NEW_BUFFER *buffer, uint32 offered,
4623 uint32 *needed, uint32 *returned)
4625 char *s = servername;
4627 if (flags & PRINTER_ENUM_LOCAL) {
4628 return enum_all_printers_info_2(buffer, offered, needed, returned);
4631 if (flags & PRINTER_ENUM_NAME) {
4632 if ((servername[0] == '\\') && (servername[1] == '\\'))
4633 s = servername + 2;
4634 if (is_myname_or_ipaddr(s))
4635 return enum_all_printers_info_2(buffer, offered, needed, returned);
4636 else
4637 return WERR_INVALID_NAME;
4640 if (flags & PRINTER_ENUM_REMOTE)
4641 return WERR_UNKNOWN_LEVEL;
4643 return WERR_OK;
4646 /********************************************************************
4647 * handle enumeration of printers at level 5
4648 ********************************************************************/
4650 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4651 NEW_BUFFER *buffer, uint32 offered,
4652 uint32 *needed, uint32 *returned)
4654 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4655 return WERR_OK;
4658 /********************************************************************
4659 * api_spoolss_enumprinters
4661 * called from api_spoolss_enumprinters (see this to understand)
4662 ********************************************************************/
4664 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4666 uint32 flags = q_u->flags;
4667 UNISTR2 *servername = &q_u->servername;
4668 uint32 level = q_u->level;
4669 NEW_BUFFER *buffer = NULL;
4670 uint32 offered = q_u->offered;
4671 uint32 *needed = &r_u->needed;
4672 uint32 *returned = &r_u->returned;
4674 fstring name;
4676 /* that's an [in out] buffer */
4677 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4678 buffer = r_u->buffer;
4680 DEBUG(4,("_spoolss_enumprinters\n"));
4682 *needed=0;
4683 *returned=0;
4686 * Level 1:
4687 * flags==PRINTER_ENUM_NAME
4688 * if name=="" then enumerates all printers
4689 * if name!="" then enumerate the printer
4690 * flags==PRINTER_ENUM_REMOTE
4691 * name is NULL, enumerate printers
4692 * Level 2: name!="" enumerates printers, name can't be NULL
4693 * Level 3: doesn't exist
4694 * Level 4: does a local registry lookup
4695 * Level 5: same as Level 2
4698 unistr2_to_ascii(name, servername, sizeof(name)-1);
4699 strupper_m(name);
4701 switch (level) {
4702 case 1:
4703 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4704 case 2:
4705 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4706 case 5:
4707 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4708 case 3:
4709 case 4:
4710 break;
4712 return WERR_UNKNOWN_LEVEL;
4715 /****************************************************************************
4716 ****************************************************************************/
4718 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4720 PRINTER_INFO_0 *printer=NULL;
4722 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4723 return WERR_NOMEM;
4725 construct_printer_info_0(print_hnd, printer, snum);
4727 /* check the required size. */
4728 *needed += spoolss_size_printer_info_0(printer);
4730 if (!alloc_buffer_size(buffer, *needed)) {
4731 SAFE_FREE(printer);
4732 return WERR_INSUFFICIENT_BUFFER;
4735 /* fill the buffer with the structures */
4736 smb_io_printer_info_0("", buffer, printer, 0);
4738 /* clear memory */
4739 SAFE_FREE(printer);
4741 if (*needed > offered) {
4742 return WERR_INSUFFICIENT_BUFFER;
4745 return WERR_OK;
4748 /****************************************************************************
4749 ****************************************************************************/
4751 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4753 PRINTER_INFO_1 *printer=NULL;
4755 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4756 return WERR_NOMEM;
4758 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4760 /* check the required size. */
4761 *needed += spoolss_size_printer_info_1(printer);
4763 if (!alloc_buffer_size(buffer, *needed)) {
4764 SAFE_FREE(printer);
4765 return WERR_INSUFFICIENT_BUFFER;
4768 /* fill the buffer with the structures */
4769 smb_io_printer_info_1("", buffer, printer, 0);
4771 /* clear memory */
4772 SAFE_FREE(printer);
4774 if (*needed > offered) {
4775 return WERR_INSUFFICIENT_BUFFER;
4778 return WERR_OK;
4781 /****************************************************************************
4782 ****************************************************************************/
4784 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4786 PRINTER_INFO_2 *printer=NULL;
4788 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4789 return WERR_NOMEM;
4791 construct_printer_info_2(print_hnd, printer, snum);
4793 /* check the required size. */
4794 *needed += spoolss_size_printer_info_2(printer);
4796 if (!alloc_buffer_size(buffer, *needed)) {
4797 free_printer_info_2(printer);
4798 return WERR_INSUFFICIENT_BUFFER;
4801 /* fill the buffer with the structures */
4802 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4803 free_printer_info_2(printer);
4804 return WERR_NOMEM;
4807 /* clear memory */
4808 free_printer_info_2(printer);
4810 if (*needed > offered) {
4811 return WERR_INSUFFICIENT_BUFFER;
4814 return WERR_OK;
4817 /****************************************************************************
4818 ****************************************************************************/
4820 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4822 PRINTER_INFO_3 *printer=NULL;
4824 if (!construct_printer_info_3(print_hnd, &printer, snum))
4825 return WERR_NOMEM;
4827 /* check the required size. */
4828 *needed += spoolss_size_printer_info_3(printer);
4830 if (!alloc_buffer_size(buffer, *needed)) {
4831 free_printer_info_3(printer);
4832 return WERR_INSUFFICIENT_BUFFER;
4835 /* fill the buffer with the structures */
4836 smb_io_printer_info_3("", buffer, printer, 0);
4838 /* clear memory */
4839 free_printer_info_3(printer);
4841 if (*needed > offered) {
4842 return WERR_INSUFFICIENT_BUFFER;
4845 return WERR_OK;
4848 /****************************************************************************
4849 ****************************************************************************/
4851 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4853 PRINTER_INFO_4 *printer=NULL;
4855 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4856 return WERR_NOMEM;
4858 if (!construct_printer_info_4(print_hnd, printer, snum))
4859 return WERR_NOMEM;
4861 /* check the required size. */
4862 *needed += spoolss_size_printer_info_4(printer);
4864 if (!alloc_buffer_size(buffer, *needed)) {
4865 free_printer_info_4(printer);
4866 return WERR_INSUFFICIENT_BUFFER;
4869 /* fill the buffer with the structures */
4870 smb_io_printer_info_4("", buffer, printer, 0);
4872 /* clear memory */
4873 free_printer_info_4(printer);
4875 if (*needed > offered) {
4876 return WERR_INSUFFICIENT_BUFFER;
4879 return WERR_OK;
4882 /****************************************************************************
4883 ****************************************************************************/
4885 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4887 PRINTER_INFO_5 *printer=NULL;
4889 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4890 return WERR_NOMEM;
4892 if (!construct_printer_info_5(print_hnd, printer, snum))
4893 return WERR_NOMEM;
4895 /* check the required size. */
4896 *needed += spoolss_size_printer_info_5(printer);
4898 if (!alloc_buffer_size(buffer, *needed)) {
4899 free_printer_info_5(printer);
4900 return WERR_INSUFFICIENT_BUFFER;
4903 /* fill the buffer with the structures */
4904 smb_io_printer_info_5("", buffer, printer, 0);
4906 /* clear memory */
4907 free_printer_info_5(printer);
4909 if (*needed > offered) {
4910 return WERR_INSUFFICIENT_BUFFER;
4913 return WERR_OK;
4916 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4918 PRINTER_INFO_7 *printer=NULL;
4920 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4921 return WERR_NOMEM;
4923 if (!construct_printer_info_7(print_hnd, printer, snum))
4924 return WERR_NOMEM;
4926 /* check the required size. */
4927 *needed += spoolss_size_printer_info_7(printer);
4929 if (!alloc_buffer_size(buffer, *needed)) {
4930 free_printer_info_7(printer);
4931 return WERR_INSUFFICIENT_BUFFER;
4934 /* fill the buffer with the structures */
4935 smb_io_printer_info_7("", buffer, printer, 0);
4937 /* clear memory */
4938 free_printer_info_7(printer);
4940 if (*needed > offered) {
4941 return WERR_INSUFFICIENT_BUFFER;
4944 return WERR_OK;
4947 /****************************************************************************
4948 ****************************************************************************/
4950 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4952 POLICY_HND *handle = &q_u->handle;
4953 uint32 level = q_u->level;
4954 NEW_BUFFER *buffer = NULL;
4955 uint32 offered = q_u->offered;
4956 uint32 *needed = &r_u->needed;
4957 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4959 int snum;
4961 /* that's an [in out] buffer */
4962 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4963 buffer = r_u->buffer;
4965 *needed=0;
4967 if (!get_printer_snum(p, handle, &snum))
4968 return WERR_BADFID;
4970 switch (level) {
4971 case 0:
4972 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4973 case 1:
4974 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4975 case 2:
4976 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4977 case 3:
4978 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4979 case 4:
4980 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4981 case 5:
4982 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4983 case 7:
4984 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4986 return WERR_UNKNOWN_LEVEL;
4989 /********************************************************************
4990 * fill a DRIVER_INFO_1 struct
4991 ********************************************************************/
4993 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4995 init_unistr( &info->name, driver.info_3->name);
4998 /********************************************************************
4999 * construct_printer_driver_info_1
5000 ********************************************************************/
5002 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5004 NT_PRINTER_INFO_LEVEL *printer = NULL;
5005 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5007 ZERO_STRUCT(driver);
5009 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5010 return WERR_INVALID_PRINTER_NAME;
5012 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5013 return WERR_UNKNOWN_PRINTER_DRIVER;
5015 fill_printer_driver_info_1(info, driver, servername, architecture);
5017 free_a_printer(&printer,2);
5019 return WERR_OK;
5022 /********************************************************************
5023 * construct_printer_driver_info_2
5024 * fill a printer_info_2 struct
5025 ********************************************************************/
5027 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5029 pstring temp;
5031 info->version=driver.info_3->cversion;
5033 init_unistr( &info->name, driver.info_3->name );
5034 init_unistr( &info->architecture, driver.info_3->environment );
5037 if (strlen(driver.info_3->driverpath)) {
5038 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5039 init_unistr( &info->driverpath, temp );
5040 } else
5041 init_unistr( &info->driverpath, "" );
5043 if (strlen(driver.info_3->datafile)) {
5044 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5045 init_unistr( &info->datafile, temp );
5046 } else
5047 init_unistr( &info->datafile, "" );
5049 if (strlen(driver.info_3->configfile)) {
5050 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5051 init_unistr( &info->configfile, temp );
5052 } else
5053 init_unistr( &info->configfile, "" );
5056 /********************************************************************
5057 * construct_printer_driver_info_2
5058 * fill a printer_info_2 struct
5059 ********************************************************************/
5061 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5063 NT_PRINTER_INFO_LEVEL *printer = NULL;
5064 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5066 ZERO_STRUCT(printer);
5067 ZERO_STRUCT(driver);
5069 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5070 return WERR_INVALID_PRINTER_NAME;
5072 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5073 return WERR_UNKNOWN_PRINTER_DRIVER;
5075 fill_printer_driver_info_2(info, driver, servername);
5077 free_a_printer(&printer,2);
5079 return WERR_OK;
5082 /********************************************************************
5083 * copy a strings array and convert to UNICODE
5085 * convert an array of ascii string to a UNICODE string
5086 ********************************************************************/
5088 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5090 int i=0;
5091 int j=0;
5092 const char *v;
5093 pstring line;
5094 uint16 *tuary;
5096 DEBUG(6,("init_unistr_array\n"));
5097 *uni_array=NULL;
5099 while (True)
5101 if ( !char_array )
5102 v = "";
5103 else
5105 v = char_array[i];
5106 if (!v)
5107 v = ""; /* hack to handle null lists */
5110 /* hack to allow this to be used in places other than when generating
5111 the list of dependent files */
5113 if ( servername )
5114 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5115 else
5116 pstrcpy( line, v );
5118 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5120 /* add one extra unit16 for the second terminating NULL */
5122 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5123 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5124 return 0;
5125 } else
5126 *uni_array = tuary;
5128 if ( !strlen(v) )
5129 break;
5131 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5132 i++;
5135 if (*uni_array) {
5136 /* special case for ""; we need to add both NULL's here */
5137 if (!j)
5138 (*uni_array)[j++]=0x0000;
5139 (*uni_array)[j]=0x0000;
5142 DEBUGADD(6,("last one:done\n"));
5144 /* return size of array in uint16's */
5146 return j+1;
5149 /********************************************************************
5150 * construct_printer_info_3
5151 * fill a printer_info_3 struct
5152 ********************************************************************/
5154 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5156 pstring temp;
5158 ZERO_STRUCTP(info);
5160 info->version=driver.info_3->cversion;
5162 init_unistr( &info->name, driver.info_3->name );
5163 init_unistr( &info->architecture, driver.info_3->environment );
5165 if (strlen(driver.info_3->driverpath)) {
5166 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5167 init_unistr( &info->driverpath, temp );
5168 } else
5169 init_unistr( &info->driverpath, "" );
5171 if (strlen(driver.info_3->datafile)) {
5172 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5173 init_unistr( &info->datafile, temp );
5174 } else
5175 init_unistr( &info->datafile, "" );
5177 if (strlen(driver.info_3->configfile)) {
5178 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5179 init_unistr( &info->configfile, temp );
5180 } else
5181 init_unistr( &info->configfile, "" );
5183 if (strlen(driver.info_3->helpfile)) {
5184 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5185 init_unistr( &info->helpfile, temp );
5186 } else
5187 init_unistr( &info->helpfile, "" );
5189 init_unistr( &info->monitorname, driver.info_3->monitorname );
5190 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5192 info->dependentfiles=NULL;
5193 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5196 /********************************************************************
5197 * construct_printer_info_3
5198 * fill a printer_info_3 struct
5199 ********************************************************************/
5201 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5203 NT_PRINTER_INFO_LEVEL *printer = NULL;
5204 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5205 WERROR status;
5206 ZERO_STRUCT(driver);
5208 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5209 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5210 if (!W_ERROR_IS_OK(status))
5211 return WERR_INVALID_PRINTER_NAME;
5213 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5214 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5216 #if 0 /* JERRY */
5219 * I put this code in during testing. Helpful when commenting out the
5220 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5221 * as win2k always queries the driver using an infor level of 6.
5222 * I've left it in (but ifdef'd out) because I'll probably
5223 * use it in experimentation again in the future. --jerry 22/01/2002
5226 if (!W_ERROR_IS_OK(status)) {
5228 * Is this a W2k client ?
5230 if (version == 3) {
5231 /* Yes - try again with a WinNT driver. */
5232 version = 2;
5233 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5234 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5236 #endif
5238 if (!W_ERROR_IS_OK(status)) {
5239 free_a_printer(&printer,2);
5240 return WERR_UNKNOWN_PRINTER_DRIVER;
5243 #if 0 /* JERRY */
5245 #endif
5248 fill_printer_driver_info_3(info, driver, servername);
5250 free_a_printer(&printer,2);
5252 return WERR_OK;
5255 /********************************************************************
5256 * construct_printer_info_6
5257 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5258 ********************************************************************/
5260 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5262 pstring temp;
5263 fstring nullstr;
5265 ZERO_STRUCTP(info);
5266 memset(&nullstr, '\0', sizeof(fstring));
5268 info->version=driver.info_3->cversion;
5270 init_unistr( &info->name, driver.info_3->name );
5271 init_unistr( &info->architecture, driver.info_3->environment );
5273 if (strlen(driver.info_3->driverpath)) {
5274 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5275 init_unistr( &info->driverpath, temp );
5276 } else
5277 init_unistr( &info->driverpath, "" );
5279 if (strlen(driver.info_3->datafile)) {
5280 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5281 init_unistr( &info->datafile, temp );
5282 } else
5283 init_unistr( &info->datafile, "" );
5285 if (strlen(driver.info_3->configfile)) {
5286 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5287 init_unistr( &info->configfile, temp );
5288 } else
5289 init_unistr( &info->configfile, "" );
5291 if (strlen(driver.info_3->helpfile)) {
5292 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5293 init_unistr( &info->helpfile, temp );
5294 } else
5295 init_unistr( &info->helpfile, "" );
5297 init_unistr( &info->monitorname, driver.info_3->monitorname );
5298 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5300 info->dependentfiles = NULL;
5301 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5303 info->previousdrivernames=NULL;
5304 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5306 info->driver_date.low=0;
5307 info->driver_date.high=0;
5309 info->padding=0;
5310 info->driver_version_low=0;
5311 info->driver_version_high=0;
5313 init_unistr( &info->mfgname, "");
5314 init_unistr( &info->oem_url, "");
5315 init_unistr( &info->hardware_id, "");
5316 init_unistr( &info->provider, "");
5319 /********************************************************************
5320 * construct_printer_info_6
5321 * fill a printer_info_6 struct
5322 ********************************************************************/
5324 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5325 fstring servername, fstring architecture, uint32 version)
5327 NT_PRINTER_INFO_LEVEL *printer = NULL;
5328 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5329 WERROR status;
5331 ZERO_STRUCT(driver);
5333 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5335 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5337 if (!W_ERROR_IS_OK(status))
5338 return WERR_INVALID_PRINTER_NAME;
5340 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5342 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5344 if (!W_ERROR_IS_OK(status))
5347 * Is this a W2k client ?
5350 if (version < 3) {
5351 free_a_printer(&printer,2);
5352 return WERR_UNKNOWN_PRINTER_DRIVER;
5355 /* Yes - try again with a WinNT driver. */
5356 version = 2;
5357 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5358 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5359 if (!W_ERROR_IS_OK(status)) {
5360 free_a_printer(&printer,2);
5361 return WERR_UNKNOWN_PRINTER_DRIVER;
5365 fill_printer_driver_info_6(info, driver, servername);
5367 free_a_printer(&printer,2);
5368 free_a_printer_driver(driver, 3);
5370 return WERR_OK;
5373 /****************************************************************************
5374 ****************************************************************************/
5376 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5378 SAFE_FREE(info->dependentfiles);
5381 /****************************************************************************
5382 ****************************************************************************/
5384 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5386 SAFE_FREE(info->dependentfiles);
5390 /****************************************************************************
5391 ****************************************************************************/
5393 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5395 DRIVER_INFO_1 *info=NULL;
5396 WERROR status;
5398 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5399 return WERR_NOMEM;
5401 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5402 if (!W_ERROR_IS_OK(status)) {
5403 SAFE_FREE(info);
5404 return status;
5407 /* check the required size. */
5408 *needed += spoolss_size_printer_driver_info_1(info);
5410 if (!alloc_buffer_size(buffer, *needed)) {
5411 SAFE_FREE(info);
5412 return WERR_INSUFFICIENT_BUFFER;
5415 /* fill the buffer with the structures */
5416 smb_io_printer_driver_info_1("", buffer, info, 0);
5418 /* clear memory */
5419 SAFE_FREE(info);
5421 if (*needed > offered)
5422 return WERR_INSUFFICIENT_BUFFER;
5424 return WERR_OK;
5427 /****************************************************************************
5428 ****************************************************************************/
5430 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5432 DRIVER_INFO_2 *info=NULL;
5433 WERROR status;
5435 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5436 return WERR_NOMEM;
5438 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5439 if (!W_ERROR_IS_OK(status)) {
5440 SAFE_FREE(info);
5441 return status;
5444 /* check the required size. */
5445 *needed += spoolss_size_printer_driver_info_2(info);
5447 if (!alloc_buffer_size(buffer, *needed)) {
5448 SAFE_FREE(info);
5449 return WERR_INSUFFICIENT_BUFFER;
5452 /* fill the buffer with the structures */
5453 smb_io_printer_driver_info_2("", buffer, info, 0);
5455 /* clear memory */
5456 SAFE_FREE(info);
5458 if (*needed > offered)
5459 return WERR_INSUFFICIENT_BUFFER;
5461 return WERR_OK;
5464 /****************************************************************************
5465 ****************************************************************************/
5467 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5469 DRIVER_INFO_3 info;
5470 WERROR status;
5472 ZERO_STRUCT(info);
5474 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5475 if (!W_ERROR_IS_OK(status)) {
5476 return status;
5479 /* check the required size. */
5480 *needed += spoolss_size_printer_driver_info_3(&info);
5482 if (!alloc_buffer_size(buffer, *needed)) {
5483 free_printer_driver_info_3(&info);
5484 return WERR_INSUFFICIENT_BUFFER;
5487 /* fill the buffer with the structures */
5488 smb_io_printer_driver_info_3("", buffer, &info, 0);
5490 free_printer_driver_info_3(&info);
5492 if (*needed > offered)
5493 return WERR_INSUFFICIENT_BUFFER;
5495 return WERR_OK;
5498 /****************************************************************************
5499 ****************************************************************************/
5501 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5503 DRIVER_INFO_6 info;
5504 WERROR status;
5506 ZERO_STRUCT(info);
5508 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5509 if (!W_ERROR_IS_OK(status)) {
5510 return status;
5513 /* check the required size. */
5514 *needed += spoolss_size_printer_driver_info_6(&info);
5516 if (!alloc_buffer_size(buffer, *needed)) {
5517 free_printer_driver_info_6(&info);
5518 return WERR_INSUFFICIENT_BUFFER;
5521 /* fill the buffer with the structures */
5522 smb_io_printer_driver_info_6("", buffer, &info, 0);
5524 free_printer_driver_info_6(&info);
5526 if (*needed > offered)
5527 return WERR_INSUFFICIENT_BUFFER;
5529 return WERR_OK;
5532 /****************************************************************************
5533 ****************************************************************************/
5535 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5537 POLICY_HND *handle = &q_u->handle;
5538 UNISTR2 *uni_arch = &q_u->architecture;
5539 uint32 level = q_u->level;
5540 uint32 clientmajorversion = q_u->clientmajorversion;
5541 NEW_BUFFER *buffer = NULL;
5542 uint32 offered = q_u->offered;
5543 uint32 *needed = &r_u->needed;
5544 uint32 *servermajorversion = &r_u->servermajorversion;
5545 uint32 *serverminorversion = &r_u->serverminorversion;
5547 fstring servername;
5548 fstring architecture;
5549 int snum;
5551 /* that's an [in out] buffer */
5552 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5553 buffer = r_u->buffer;
5555 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5557 *needed = 0;
5558 *servermajorversion = 0;
5559 *serverminorversion = 0;
5561 fstrcpy(servername, get_called_name());
5562 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5564 if (!get_printer_snum(p, handle, &snum))
5565 return WERR_BADFID;
5567 switch (level) {
5568 case 1:
5569 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5570 case 2:
5571 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5572 case 3:
5573 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5574 case 6:
5575 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5576 #if 0 /* JERRY */
5577 case 101:
5578 /* apparently this call is the equivalent of
5579 EnumPrinterDataEx() for the DsDriver key */
5580 break;
5581 #endif
5584 return WERR_UNKNOWN_LEVEL;
5587 /****************************************************************************
5588 ****************************************************************************/
5590 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5592 POLICY_HND *handle = &q_u->handle;
5594 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5596 if (!Printer) {
5597 DEBUG(3,("Error in startpageprinter printer handle\n"));
5598 return WERR_BADFID;
5601 Printer->page_started=True;
5602 return WERR_OK;
5605 /****************************************************************************
5606 ****************************************************************************/
5608 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5610 POLICY_HND *handle = &q_u->handle;
5611 int snum;
5613 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5615 if (!Printer) {
5616 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5617 return WERR_BADFID;
5620 if (!get_printer_snum(p, handle, &snum))
5621 return WERR_BADFID;
5623 Printer->page_started=False;
5624 print_job_endpage(snum, Printer->jobid);
5626 return WERR_OK;
5629 /********************************************************************
5630 * api_spoolss_getprinter
5631 * called from the spoolss dispatcher
5633 ********************************************************************/
5635 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5637 POLICY_HND *handle = &q_u->handle;
5638 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5639 uint32 *jobid = &r_u->jobid;
5641 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5642 int snum;
5643 pstring jobname;
5644 fstring datatype;
5645 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5646 struct current_user user;
5648 if (!Printer) {
5649 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5650 return WERR_BADFID;
5653 get_current_user(&user, p);
5656 * a nice thing with NT is it doesn't listen to what you tell it.
5657 * when asked to send _only_ RAW datas, it tries to send datas
5658 * in EMF format.
5660 * So I add checks like in NT Server ...
5663 if (info_1->p_datatype != 0) {
5664 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5665 if (strcmp(datatype, "RAW") != 0) {
5666 (*jobid)=0;
5667 return WERR_INVALID_DATATYPE;
5671 /* get the share number of the printer */
5672 if (!get_printer_snum(p, handle, &snum)) {
5673 return WERR_BADFID;
5676 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5678 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5680 /* An error occured in print_job_start() so return an appropriate
5681 NT error code. */
5683 if (Printer->jobid == -1) {
5684 return map_werror_from_unix(errno);
5687 Printer->document_started=True;
5688 (*jobid) = Printer->jobid;
5690 return WERR_OK;
5693 /********************************************************************
5694 * api_spoolss_getprinter
5695 * called from the spoolss dispatcher
5697 ********************************************************************/
5699 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5701 POLICY_HND *handle = &q_u->handle;
5703 return _spoolss_enddocprinter_internal(p, handle);
5706 /****************************************************************************
5707 ****************************************************************************/
5709 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5711 POLICY_HND *handle = &q_u->handle;
5712 uint32 buffer_size = q_u->buffer_size;
5713 uint8 *buffer = q_u->buffer;
5714 uint32 *buffer_written = &q_u->buffer_size2;
5715 int snum;
5716 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5718 if (!Printer) {
5719 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5720 r_u->buffer_written = q_u->buffer_size2;
5721 return WERR_BADFID;
5724 if (!get_printer_snum(p, handle, &snum))
5725 return WERR_BADFID;
5727 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5728 if (*buffer_written == -1) {
5729 r_u->buffer_written = 0;
5730 if (errno == ENOSPC)
5731 return WERR_NO_SPOOL_SPACE;
5732 else
5733 return WERR_ACCESS_DENIED;
5736 r_u->buffer_written = q_u->buffer_size2;
5738 return WERR_OK;
5741 /********************************************************************
5742 * api_spoolss_getprinter
5743 * called from the spoolss dispatcher
5745 ********************************************************************/
5747 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5748 pipes_struct *p)
5750 struct current_user user;
5751 int snum;
5752 WERROR errcode = WERR_BADFUNC;
5753 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5755 get_current_user(&user, p);
5757 if (!Printer) {
5758 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5759 return WERR_BADFID;
5762 if (!get_printer_snum(p, handle, &snum))
5763 return WERR_BADFID;
5765 switch (command) {
5766 case PRINTER_CONTROL_PAUSE:
5767 if (print_queue_pause(&user, snum, &errcode)) {
5768 errcode = WERR_OK;
5770 break;
5771 case PRINTER_CONTROL_RESUME:
5772 case PRINTER_CONTROL_UNPAUSE:
5773 if (print_queue_resume(&user, snum, &errcode)) {
5774 errcode = WERR_OK;
5776 break;
5777 case PRINTER_CONTROL_PURGE:
5778 if (print_queue_purge(&user, snum, &errcode)) {
5779 errcode = WERR_OK;
5781 break;
5782 default:
5783 return WERR_UNKNOWN_LEVEL;
5786 return errcode;
5789 /********************************************************************
5790 * api_spoolss_abortprinter
5791 * From MSDN: "Deletes printer's spool file if printer is configured
5792 * for spooling"
5793 ********************************************************************/
5795 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5797 POLICY_HND *handle = &q_u->handle;
5798 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5799 int snum;
5800 struct current_user user;
5801 WERROR errcode = WERR_OK;
5803 if (!Printer) {
5804 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5805 return WERR_BADFID;
5808 if (!get_printer_snum(p, handle, &snum))
5809 return WERR_BADFID;
5811 get_current_user( &user, p );
5813 print_job_delete( &user, snum, Printer->jobid, &errcode );
5815 return errcode;
5818 /********************************************************************
5819 * called by spoolss_api_setprinter
5820 * when updating a printer description
5821 ********************************************************************/
5823 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5824 const SPOOL_PRINTER_INFO_LEVEL *info,
5825 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5827 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5828 struct current_user user;
5829 WERROR result;
5830 int snum;
5832 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5834 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5835 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5836 OUR_HANDLE(handle)));
5838 result = WERR_BADFID;
5839 goto done;
5842 /* NT seems to like setting the security descriptor even though
5843 nothing may have actually changed. This causes annoying
5844 dialog boxes when the user doesn't have permission to change
5845 the security descriptor. */
5847 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5849 if (DEBUGLEVEL >= 10) {
5850 SEC_ACL *the_acl;
5851 int i;
5853 the_acl = old_secdesc_ctr->sec->dacl;
5854 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5855 PRINTERNAME(snum), the_acl->num_aces));
5857 for (i = 0; i < the_acl->num_aces; i++) {
5858 fstring sid_str;
5860 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5862 DEBUG(10, ("%s 0x%08x\n", sid_str,
5863 the_acl->ace[i].info.mask));
5866 the_acl = secdesc_ctr->sec->dacl;
5868 if (the_acl) {
5869 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5870 PRINTERNAME(snum), the_acl->num_aces));
5872 for (i = 0; i < the_acl->num_aces; i++) {
5873 fstring sid_str;
5875 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5877 DEBUG(10, ("%s 0x%08x\n", sid_str,
5878 the_acl->ace[i].info.mask));
5880 } else {
5881 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5885 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5887 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5888 result = WERR_OK;
5889 goto done;
5892 /* Work out which user is performing the operation */
5894 get_current_user(&user, p);
5896 /* Check the user has permissions to change the security
5897 descriptor. By experimentation with two NT machines, the user
5898 requires Full Access to the printer to change security
5899 information. */
5901 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5902 result = WERR_ACCESS_DENIED;
5903 goto done;
5906 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5908 done:
5910 return result;
5913 /********************************************************************
5914 Do Samba sanity checks on a printer info struct.
5915 this has changed purpose: it now "canonicalises" printer
5916 info from a client rather than just checking it is correct
5917 ********************************************************************/
5919 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5921 fstring printername;
5922 const char *p;
5924 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5925 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5927 /* we force some elements to "correct" values */
5928 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5929 fstrcpy(info->sharename, lp_servicename(snum));
5931 /* make sure printername is in \\server\printername format */
5933 fstrcpy( printername, info->printername );
5934 p = printername;
5935 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5936 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5937 p++;
5940 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5941 get_called_name(), p );
5943 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5944 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5948 return True;
5951 /****************************************************************************
5952 ****************************************************************************/
5954 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5956 extern userdom_struct current_user_info;
5957 char *cmd = lp_addprinter_cmd();
5958 char **qlines;
5959 pstring command;
5960 int numlines;
5961 int ret;
5962 int fd;
5963 fstring remote_machine = "%m";
5965 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5967 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5968 cmd, printer->info_2->printername, printer->info_2->sharename,
5969 printer->info_2->portname, printer->info_2->drivername,
5970 printer->info_2->location, printer->info_2->comment, remote_machine);
5972 DEBUG(10,("Running [%s]\n", command));
5973 ret = smbrun(command, &fd);
5974 DEBUGADD(10,("returned [%d]\n", ret));
5976 if ( ret != 0 ) {
5977 if (fd != -1)
5978 close(fd);
5979 return False;
5982 numlines = 0;
5983 /* Get lines and convert them back to dos-codepage */
5984 qlines = fd_lines_load(fd, &numlines);
5985 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5986 close(fd);
5988 if(numlines) {
5989 /* Set the portname to what the script says the portname should be. */
5990 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5991 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5993 /* Send SIGHUP to process group... is there a better way? */
5994 kill(0, SIGHUP);
5996 /* reload our services immediately */
5997 reload_services( False );
6000 file_lines_free(qlines);
6001 return True;
6004 /********************************************************************
6005 * Called by spoolss_api_setprinter
6006 * when updating a printer description.
6007 ********************************************************************/
6009 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6010 const SPOOL_PRINTER_INFO_LEVEL *info,
6011 DEVICEMODE *devmode)
6013 int snum;
6014 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6015 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6016 WERROR result;
6017 UNISTR2 buffer;
6018 fstring asc_buffer;
6020 DEBUG(8,("update_printer\n"));
6022 result = WERR_OK;
6024 if (!Printer) {
6025 result = WERR_BADFID;
6026 goto done;
6029 if (!get_printer_snum(p, handle, &snum)) {
6030 result = WERR_BADFID;
6031 goto done;
6034 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6035 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6036 result = WERR_BADFID;
6037 goto done;
6040 DEBUGADD(8,("Converting info_2 struct\n"));
6043 * convert_printer_info converts the incoming
6044 * info from the client and overwrites the info
6045 * just read from the tdb in the pointer 'printer'.
6048 if (!convert_printer_info(info, printer, level)) {
6049 result = WERR_NOMEM;
6050 goto done;
6053 if (devmode) {
6054 /* we have a valid devmode
6055 convert it and link it*/
6057 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6058 if (!convert_devicemode(printer->info_2->printername, devmode,
6059 &printer->info_2->devmode)) {
6060 result = WERR_NOMEM;
6061 goto done;
6065 /* Do sanity check on the requested changes for Samba */
6067 if (!check_printer_ok(printer->info_2, snum)) {
6068 result = WERR_INVALID_PARAM;
6069 goto done;
6072 /* FIXME!!! If the driver has changed we really should verify that
6073 it is installed before doing much else --jerry */
6075 /* Check calling user has permission to update printer description */
6077 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6078 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6079 result = WERR_ACCESS_DENIED;
6080 goto done;
6083 /* Call addprinter hook */
6084 /* Check changes to see if this is really needed */
6086 if ( *lp_addprinter_cmd()
6087 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6088 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6089 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6090 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6092 if ( !add_printer_hook(printer) ) {
6093 result = WERR_ACCESS_DENIED;
6094 goto done;
6098 * make sure we actually reload the services after
6099 * this as smb.conf could have a new section in it
6100 * .... shouldn't .... but could
6102 reload_services(False);
6106 * When a *new* driver is bound to a printer, the drivername is used to
6107 * lookup previously saved driver initialization info, which is then
6108 * bound to the printer, simulating what happens in the Windows arch.
6110 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6112 if (!set_driver_init(printer, 2))
6114 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6115 printer->info_2->drivername));
6118 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6119 printer->info_2->drivername));
6121 notify_printer_driver(snum, printer->info_2->drivername);
6125 * flag which changes actually occured. This is a small subset of
6126 * all the possible changes. We also have to update things in the
6127 * DsSpooler key.
6130 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6131 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6132 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6133 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6135 notify_printer_comment(snum, printer->info_2->comment);
6138 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6139 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6140 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6141 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6143 notify_printer_sharename(snum, printer->info_2->sharename);
6146 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6147 char *pname;
6149 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6150 pname++;
6151 else
6152 pname = printer->info_2->printername;
6155 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6156 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6157 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6159 notify_printer_printername( snum, pname );
6162 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6163 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6164 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6165 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6167 notify_printer_port(snum, printer->info_2->portname);
6170 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6171 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6172 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6173 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6175 notify_printer_location(snum, printer->info_2->location);
6178 /* here we need to update some more DsSpooler keys */
6179 /* uNCName, serverName, shortServerName */
6181 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6182 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6183 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6184 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6185 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6187 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6188 global_myname(), printer->info_2->sharename );
6189 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6190 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6191 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6193 /* Update printer info */
6194 result = mod_a_printer(*printer, 2);
6196 done:
6197 free_a_printer(&printer, 2);
6198 free_a_printer(&old_printer, 2);
6201 return result;
6204 /****************************************************************************
6205 ****************************************************************************/
6206 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6207 const SPOOL_PRINTER_INFO_LEVEL *info)
6209 #ifdef HAVE_ADS
6210 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6211 int snum;
6212 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6214 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6216 if (!Printer)
6217 return WERR_BADFID;
6219 if (!get_printer_snum(p, handle, &snum))
6220 return WERR_BADFID;
6222 nt_printer_publish(Printer, snum, info7->action);
6224 return WERR_OK;
6225 #else
6226 return WERR_UNKNOWN_LEVEL;
6227 #endif
6229 /****************************************************************************
6230 ****************************************************************************/
6232 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6234 POLICY_HND *handle = &q_u->handle;
6235 uint32 level = q_u->level;
6236 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6237 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6238 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6239 uint32 command = q_u->command;
6240 WERROR result;
6242 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6244 if (!Printer) {
6245 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6246 return WERR_BADFID;
6249 /* check the level */
6250 switch (level) {
6251 case 0:
6252 return control_printer(handle, command, p);
6253 case 2:
6254 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6255 if (!W_ERROR_IS_OK(result))
6256 return result;
6257 if (secdesc_ctr)
6258 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6259 return result;
6260 case 3:
6261 return update_printer_sec(handle, level, info, p,
6262 secdesc_ctr);
6263 case 7:
6264 return publish_or_unpublish_printer(p, handle, info);
6265 default:
6266 return WERR_UNKNOWN_LEVEL;
6270 /****************************************************************************
6271 ****************************************************************************/
6273 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6275 POLICY_HND *handle = &q_u->handle;
6276 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6278 if (!Printer) {
6279 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6280 return WERR_BADFID;
6283 if (Printer->notify.client_connected==True) {
6284 int snum = -1;
6286 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6287 snum = -1;
6288 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6289 !get_printer_snum(p, handle, &snum) )
6290 return WERR_BADFID;
6292 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6295 Printer->notify.flags=0;
6296 Printer->notify.options=0;
6297 Printer->notify.localmachine[0]='\0';
6298 Printer->notify.printerlocal=0;
6299 if (Printer->notify.option)
6300 free_spool_notify_option(&Printer->notify.option);
6301 Printer->notify.client_connected=False;
6303 return WERR_OK;
6306 /****************************************************************************
6307 ****************************************************************************/
6309 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6311 /* that's an [in out] buffer (despite appearences to the contrary) */
6312 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6314 r_u->needed = 0;
6315 return WERR_INVALID_PARAM; /* this is what a NT server
6316 returns for AddJob. AddJob
6317 must fail on non-local
6318 printers */
6321 /****************************************************************************
6322 ****************************************************************************/
6324 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6325 int position, int snum)
6327 pstring temp_name;
6329 struct tm *t;
6331 t=gmtime(&queue->time);
6332 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6334 job_info->jobid=queue->job;
6335 init_unistr(&job_info->printername, lp_servicename(snum));
6336 init_unistr(&job_info->machinename, temp_name);
6337 init_unistr(&job_info->username, queue->fs_user);
6338 init_unistr(&job_info->document, queue->fs_file);
6339 init_unistr(&job_info->datatype, "RAW");
6340 init_unistr(&job_info->text_status, "");
6341 job_info->status=nt_printj_status(queue->status);
6342 job_info->priority=queue->priority;
6343 job_info->position=position;
6344 job_info->totalpages=queue->page_count;
6345 job_info->pagesprinted=0;
6347 make_systemtime(&job_info->submitted, t);
6350 /****************************************************************************
6351 ****************************************************************************/
6353 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6354 int position, int snum,
6355 NT_PRINTER_INFO_LEVEL *ntprinter,
6356 DEVICEMODE *devmode)
6358 pstring temp_name;
6359 struct tm *t;
6361 t=gmtime(&queue->time);
6362 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6364 job_info->jobid=queue->job;
6366 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6368 init_unistr(&job_info->machinename, temp_name);
6369 init_unistr(&job_info->username, queue->fs_user);
6370 init_unistr(&job_info->document, queue->fs_file);
6371 init_unistr(&job_info->notifyname, queue->fs_user);
6372 init_unistr(&job_info->datatype, "RAW");
6373 init_unistr(&job_info->printprocessor, "winprint");
6374 init_unistr(&job_info->parameters, "");
6375 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6376 init_unistr(&job_info->text_status, "");
6378 /* and here the security descriptor */
6380 job_info->status=nt_printj_status(queue->status);
6381 job_info->priority=queue->priority;
6382 job_info->position=position;
6383 job_info->starttime=0;
6384 job_info->untiltime=0;
6385 job_info->totalpages=queue->page_count;
6386 job_info->size=queue->size;
6387 make_systemtime(&(job_info->submitted), t);
6388 job_info->timeelapsed=0;
6389 job_info->pagesprinted=0;
6391 job_info->devmode = devmode;
6393 return (True);
6396 /****************************************************************************
6397 Enumjobs at level 1.
6398 ****************************************************************************/
6400 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6401 NEW_BUFFER *buffer, uint32 offered,
6402 uint32 *needed, uint32 *returned)
6404 JOB_INFO_1 *info;
6405 int i;
6407 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6408 if (info==NULL) {
6409 SAFE_FREE(queue);
6410 *returned=0;
6411 return WERR_NOMEM;
6414 for (i=0; i<*returned; i++)
6415 fill_job_info_1(&info[i], &queue[i], i, snum);
6417 SAFE_FREE(queue);
6419 /* check the required size. */
6420 for (i=0; i<*returned; i++)
6421 (*needed) += spoolss_size_job_info_1(&info[i]);
6423 if (!alloc_buffer_size(buffer, *needed)) {
6424 SAFE_FREE(info);
6425 return WERR_INSUFFICIENT_BUFFER;
6428 /* fill the buffer with the structures */
6429 for (i=0; i<*returned; i++)
6430 smb_io_job_info_1("", buffer, &info[i], 0);
6432 /* clear memory */
6433 SAFE_FREE(info);
6435 if (*needed > offered) {
6436 *returned=0;
6437 return WERR_INSUFFICIENT_BUFFER;
6440 return WERR_OK;
6443 /****************************************************************************
6444 Enumjobs at level 2.
6445 ****************************************************************************/
6447 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6448 NEW_BUFFER *buffer, uint32 offered,
6449 uint32 *needed, uint32 *returned)
6451 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6452 JOB_INFO_2 *info = NULL;
6453 int i;
6454 WERROR result;
6455 DEVICEMODE *devmode = NULL;
6457 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6458 if (info==NULL) {
6459 *returned=0;
6460 result = WERR_NOMEM;
6461 goto done;
6464 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6465 if (!W_ERROR_IS_OK(result)) {
6466 *returned = 0;
6467 goto done;
6470 /* this should not be a failure condition if the devmode is NULL */
6472 devmode = construct_dev_mode(snum);
6474 for (i=0; i<*returned; i++)
6475 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6476 devmode);
6478 free_a_printer(&ntprinter, 2);
6479 SAFE_FREE(queue);
6481 /* check the required size. */
6482 for (i=0; i<*returned; i++)
6483 (*needed) += spoolss_size_job_info_2(&info[i]);
6485 if (*needed > offered) {
6486 *returned=0;
6487 result = WERR_INSUFFICIENT_BUFFER;
6488 goto done;
6491 if (!alloc_buffer_size(buffer, *needed)) {
6492 SAFE_FREE(info);
6493 result = WERR_INSUFFICIENT_BUFFER;
6494 goto done;
6497 /* fill the buffer with the structures */
6498 for (i=0; i<*returned; i++)
6499 smb_io_job_info_2("", buffer, &info[i], 0);
6501 result = WERR_OK;
6503 done:
6504 free_a_printer(&ntprinter, 2);
6505 free_devmode(devmode);
6506 SAFE_FREE(queue);
6507 SAFE_FREE(info);
6509 return result;
6513 /****************************************************************************
6514 Enumjobs.
6515 ****************************************************************************/
6517 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6519 POLICY_HND *handle = &q_u->handle;
6520 uint32 level = q_u->level;
6521 NEW_BUFFER *buffer = NULL;
6522 uint32 offered = q_u->offered;
6523 uint32 *needed = &r_u->needed;
6524 uint32 *returned = &r_u->returned;
6525 WERROR wret;
6527 int snum;
6528 print_status_struct prt_status;
6529 print_queue_struct *queue=NULL;
6531 /* that's an [in out] buffer */
6532 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6533 buffer = r_u->buffer;
6535 DEBUG(4,("_spoolss_enumjobs\n"));
6537 *needed=0;
6538 *returned=0;
6540 if (!get_printer_snum(p, handle, &snum))
6541 return WERR_BADFID;
6543 *returned = print_queue_status(snum, &queue, &prt_status);
6544 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6546 if (*returned == 0) {
6547 SAFE_FREE(queue);
6548 return WERR_OK;
6551 switch (level) {
6552 case 1:
6553 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6554 return wret;
6555 case 2:
6556 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6557 return wret;
6558 default:
6559 SAFE_FREE(queue);
6560 *returned=0;
6561 return WERR_UNKNOWN_LEVEL;
6565 /****************************************************************************
6566 ****************************************************************************/
6568 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6570 return WERR_OK;
6573 /****************************************************************************
6574 ****************************************************************************/
6576 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6578 POLICY_HND *handle = &q_u->handle;
6579 uint32 jobid = q_u->jobid;
6580 uint32 command = q_u->command;
6582 struct current_user user;
6583 int snum;
6584 WERROR errcode = WERR_BADFUNC;
6586 if (!get_printer_snum(p, handle, &snum)) {
6587 return WERR_BADFID;
6590 if (!print_job_exists(snum, jobid)) {
6591 return WERR_INVALID_PRINTER_NAME;
6594 get_current_user(&user, p);
6596 switch (command) {
6597 case JOB_CONTROL_CANCEL:
6598 case JOB_CONTROL_DELETE:
6599 if (print_job_delete(&user, snum, jobid, &errcode)) {
6600 errcode = WERR_OK;
6602 break;
6603 case JOB_CONTROL_PAUSE:
6604 if (print_job_pause(&user, snum, jobid, &errcode)) {
6605 errcode = WERR_OK;
6607 break;
6608 case JOB_CONTROL_RESTART:
6609 case JOB_CONTROL_RESUME:
6610 if (print_job_resume(&user, snum, jobid, &errcode)) {
6611 errcode = WERR_OK;
6613 break;
6614 default:
6615 return WERR_UNKNOWN_LEVEL;
6618 return errcode;
6621 /****************************************************************************
6622 Enumerates all printer drivers at level 1.
6623 ****************************************************************************/
6625 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6627 int i;
6628 int ndrivers;
6629 uint32 version;
6630 fstring *list = NULL;
6632 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6633 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6635 *returned=0;
6637 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6638 list=NULL;
6639 ndrivers=get_ntdrivers(&list, architecture, version);
6640 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6642 if(ndrivers == -1)
6643 return WERR_NOMEM;
6645 if(ndrivers != 0) {
6646 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6647 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6648 SAFE_FREE(driver_info_1);
6649 SAFE_FREE(list);
6650 return WERR_NOMEM;
6652 else driver_info_1 = tdi1;
6655 for (i=0; i<ndrivers; i++) {
6656 WERROR status;
6657 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6658 ZERO_STRUCT(driver);
6659 status = get_a_printer_driver(&driver, 3, list[i],
6660 architecture, version);
6661 if (!W_ERROR_IS_OK(status)) {
6662 SAFE_FREE(list);
6663 return status;
6665 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6666 free_a_printer_driver(driver, 3);
6669 *returned+=ndrivers;
6670 SAFE_FREE(list);
6673 /* check the required size. */
6674 for (i=0; i<*returned; i++) {
6675 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6676 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6679 if (!alloc_buffer_size(buffer, *needed)) {
6680 SAFE_FREE(driver_info_1);
6681 return WERR_INSUFFICIENT_BUFFER;
6684 /* fill the buffer with the driver structures */
6685 for (i=0; i<*returned; i++) {
6686 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6687 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6690 SAFE_FREE(driver_info_1);
6692 if (*needed > offered) {
6693 *returned=0;
6694 return WERR_INSUFFICIENT_BUFFER;
6697 return WERR_OK;
6700 /****************************************************************************
6701 Enumerates all printer drivers at level 2.
6702 ****************************************************************************/
6704 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6706 int i;
6707 int ndrivers;
6708 uint32 version;
6709 fstring *list = NULL;
6711 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6712 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6714 *returned=0;
6716 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6717 list=NULL;
6718 ndrivers=get_ntdrivers(&list, architecture, version);
6719 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6721 if(ndrivers == -1)
6722 return WERR_NOMEM;
6724 if(ndrivers != 0) {
6725 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6726 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6727 SAFE_FREE(driver_info_2);
6728 SAFE_FREE(list);
6729 return WERR_NOMEM;
6731 else driver_info_2 = tdi2;
6734 for (i=0; i<ndrivers; i++) {
6735 WERROR status;
6737 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6738 ZERO_STRUCT(driver);
6739 status = get_a_printer_driver(&driver, 3, list[i],
6740 architecture, version);
6741 if (!W_ERROR_IS_OK(status)) {
6742 SAFE_FREE(list);
6743 return status;
6745 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6746 free_a_printer_driver(driver, 3);
6749 *returned+=ndrivers;
6750 SAFE_FREE(list);
6753 /* check the required size. */
6754 for (i=0; i<*returned; i++) {
6755 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6756 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6759 if (!alloc_buffer_size(buffer, *needed)) {
6760 SAFE_FREE(driver_info_2);
6761 return WERR_INSUFFICIENT_BUFFER;
6764 /* fill the buffer with the form structures */
6765 for (i=0; i<*returned; i++) {
6766 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6767 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6770 SAFE_FREE(driver_info_2);
6772 if (*needed > offered) {
6773 *returned=0;
6774 return WERR_INSUFFICIENT_BUFFER;
6777 return WERR_OK;
6780 /****************************************************************************
6781 Enumerates all printer drivers at level 3.
6782 ****************************************************************************/
6784 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6786 int i;
6787 int ndrivers;
6788 uint32 version;
6789 fstring *list = NULL;
6791 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6792 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6794 *returned=0;
6796 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6797 list=NULL;
6798 ndrivers=get_ntdrivers(&list, architecture, version);
6799 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6801 if(ndrivers == -1)
6802 return WERR_NOMEM;
6804 if(ndrivers != 0) {
6805 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6806 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6807 SAFE_FREE(driver_info_3);
6808 SAFE_FREE(list);
6809 return WERR_NOMEM;
6811 else driver_info_3 = tdi3;
6814 for (i=0; i<ndrivers; i++) {
6815 WERROR status;
6817 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6818 ZERO_STRUCT(driver);
6819 status = get_a_printer_driver(&driver, 3, list[i],
6820 architecture, version);
6821 if (!W_ERROR_IS_OK(status)) {
6822 SAFE_FREE(list);
6823 return status;
6825 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6826 free_a_printer_driver(driver, 3);
6829 *returned+=ndrivers;
6830 SAFE_FREE(list);
6833 /* check the required size. */
6834 for (i=0; i<*returned; i++) {
6835 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6836 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6839 if (!alloc_buffer_size(buffer, *needed)) {
6840 SAFE_FREE(driver_info_3);
6841 return WERR_INSUFFICIENT_BUFFER;
6844 /* fill the buffer with the driver structures */
6845 for (i=0; i<*returned; i++) {
6846 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6847 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6850 for (i=0; i<*returned; i++)
6851 SAFE_FREE(driver_info_3[i].dependentfiles);
6853 SAFE_FREE(driver_info_3);
6855 if (*needed > offered) {
6856 *returned=0;
6857 return WERR_INSUFFICIENT_BUFFER;
6860 return WERR_OK;
6863 /****************************************************************************
6864 Enumerates all printer drivers.
6865 ****************************************************************************/
6867 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6869 UNISTR2 *environment = &q_u->environment;
6870 uint32 level = q_u->level;
6871 NEW_BUFFER *buffer = NULL;
6872 uint32 offered = q_u->offered;
6873 uint32 *needed = &r_u->needed;
6874 uint32 *returned = &r_u->returned;
6876 fstring *list = NULL;
6877 fstring servername;
6878 fstring architecture;
6880 /* that's an [in out] buffer */
6881 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6882 buffer = r_u->buffer;
6884 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6885 fstrcpy(servername, get_called_name());
6886 *needed=0;
6887 *returned=0;
6889 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6891 switch (level) {
6892 case 1:
6893 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6894 case 2:
6895 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6896 case 3:
6897 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6898 default:
6899 *returned=0;
6900 SAFE_FREE(list);
6901 return WERR_UNKNOWN_LEVEL;
6905 /****************************************************************************
6906 ****************************************************************************/
6908 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6910 form->flag=list->flag;
6911 init_unistr(&form->name, list->name);
6912 form->width=list->width;
6913 form->length=list->length;
6914 form->left=list->left;
6915 form->top=list->top;
6916 form->right=list->right;
6917 form->bottom=list->bottom;
6920 /****************************************************************************
6921 ****************************************************************************/
6923 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6925 uint32 level = q_u->level;
6926 NEW_BUFFER *buffer = NULL;
6927 uint32 offered = q_u->offered;
6928 uint32 *needed = &r_u->needed;
6929 uint32 *numofforms = &r_u->numofforms;
6930 uint32 numbuiltinforms;
6932 nt_forms_struct *list=NULL;
6933 nt_forms_struct *builtinlist=NULL;
6934 FORM_1 *forms_1;
6935 int buffer_size=0;
6936 int i;
6938 /* that's an [in out] buffer */
6939 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6940 buffer = r_u->buffer;
6942 DEBUG(4,("_spoolss_enumforms\n"));
6943 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6944 DEBUGADD(5,("Info level [%d]\n", level));
6946 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6947 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6948 *numofforms = get_ntforms(&list);
6949 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6950 *numofforms += numbuiltinforms;
6952 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6954 switch (level) {
6955 case 1:
6956 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6957 *numofforms=0;
6958 return WERR_NOMEM;
6961 /* construct the list of form structures */
6962 for (i=0; i<numbuiltinforms; i++) {
6963 DEBUGADD(6,("Filling form number [%d]\n",i));
6964 fill_form_1(&forms_1[i], &builtinlist[i]);
6967 SAFE_FREE(builtinlist);
6969 for (; i<*numofforms; i++) {
6970 DEBUGADD(6,("Filling form number [%d]\n",i));
6971 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6974 SAFE_FREE(list);
6976 /* check the required size. */
6977 for (i=0; i<numbuiltinforms; i++) {
6978 DEBUGADD(6,("adding form [%d]'s size\n",i));
6979 buffer_size += spoolss_size_form_1(&forms_1[i]);
6981 for (; i<*numofforms; i++) {
6982 DEBUGADD(6,("adding form [%d]'s size\n",i));
6983 buffer_size += spoolss_size_form_1(&forms_1[i]);
6986 *needed=buffer_size;
6988 if (!alloc_buffer_size(buffer, buffer_size)){
6989 SAFE_FREE(forms_1);
6990 return WERR_INSUFFICIENT_BUFFER;
6993 /* fill the buffer with the form structures */
6994 for (i=0; i<numbuiltinforms; i++) {
6995 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6996 smb_io_form_1("", buffer, &forms_1[i], 0);
6998 for (; i<*numofforms; i++) {
6999 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7000 smb_io_form_1("", buffer, &forms_1[i], 0);
7003 SAFE_FREE(forms_1);
7005 if (*needed > offered) {
7006 *numofforms=0;
7007 return WERR_INSUFFICIENT_BUFFER;
7009 else
7010 return WERR_OK;
7012 default:
7013 SAFE_FREE(list);
7014 SAFE_FREE(builtinlist);
7015 return WERR_UNKNOWN_LEVEL;
7020 /****************************************************************************
7021 ****************************************************************************/
7023 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7025 uint32 level = q_u->level;
7026 UNISTR2 *uni_formname = &q_u->formname;
7027 NEW_BUFFER *buffer = NULL;
7028 uint32 offered = q_u->offered;
7029 uint32 *needed = &r_u->needed;
7031 nt_forms_struct *list=NULL;
7032 nt_forms_struct builtin_form;
7033 BOOL foundBuiltin;
7034 FORM_1 form_1;
7035 fstring form_name;
7036 int buffer_size=0;
7037 int numofforms=0, i=0;
7039 /* that's an [in out] buffer */
7040 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7041 buffer = r_u->buffer;
7043 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7045 DEBUG(4,("_spoolss_getform\n"));
7046 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7047 DEBUGADD(5,("Info level [%d]\n", level));
7049 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7050 if (!foundBuiltin) {
7051 numofforms = get_ntforms(&list);
7052 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7054 if (numofforms == 0)
7055 return WERR_BADFID;
7058 switch (level) {
7059 case 1:
7060 if (foundBuiltin) {
7061 fill_form_1(&form_1, &builtin_form);
7062 } else {
7064 /* Check if the requested name is in the list of form structures */
7065 for (i=0; i<numofforms; i++) {
7067 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7069 if (strequal(form_name, list[i].name)) {
7070 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7071 fill_form_1(&form_1, &list[i]);
7072 break;
7076 SAFE_FREE(list);
7077 if (i == numofforms) {
7078 return WERR_BADFID;
7081 /* check the required size. */
7083 *needed=spoolss_size_form_1(&form_1);
7085 if (!alloc_buffer_size(buffer, buffer_size)){
7086 return WERR_INSUFFICIENT_BUFFER;
7089 if (*needed > offered) {
7090 return WERR_INSUFFICIENT_BUFFER;
7093 /* fill the buffer with the form structures */
7094 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7095 smb_io_form_1("", buffer, &form_1, 0);
7097 return WERR_OK;
7099 default:
7100 SAFE_FREE(list);
7101 return WERR_UNKNOWN_LEVEL;
7105 /****************************************************************************
7106 ****************************************************************************/
7108 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7110 init_unistr(&port->port_name, name);
7113 /****************************************************************************
7114 ****************************************************************************/
7116 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7118 init_unistr(&port->port_name, name);
7119 init_unistr(&port->monitor_name, "Local Monitor");
7120 init_unistr(&port->description, "Local Port");
7121 port->port_type=PORT_TYPE_WRITE;
7122 port->reserved=0x0;
7125 /****************************************************************************
7126 enumports level 1.
7127 ****************************************************************************/
7129 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7131 PORT_INFO_1 *ports=NULL;
7132 int i=0;
7134 if (*lp_enumports_cmd()) {
7135 char *cmd = lp_enumports_cmd();
7136 char **qlines;
7137 pstring command;
7138 int numlines;
7139 int ret;
7140 int fd;
7142 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7144 DEBUG(10,("Running [%s]\n", command));
7145 ret = smbrun(command, &fd);
7146 DEBUG(10,("Returned [%d]\n", ret));
7147 if (ret != 0) {
7148 if (fd != -1)
7149 close(fd);
7150 /* Is this the best error to return here? */
7151 return WERR_ACCESS_DENIED;
7154 numlines = 0;
7155 qlines = fd_lines_load(fd, &numlines);
7156 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7157 close(fd);
7159 if(numlines) {
7160 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7161 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7162 dos_errstr(WERR_NOMEM)));
7163 file_lines_free(qlines);
7164 return WERR_NOMEM;
7167 for (i=0; i<numlines; i++) {
7168 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7169 fill_port_1(&ports[i], qlines[i]);
7172 file_lines_free(qlines);
7175 *returned = numlines;
7177 } else {
7178 *returned = 1; /* Sole Samba port returned. */
7180 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7181 return WERR_NOMEM;
7183 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7185 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7188 /* check the required size. */
7189 for (i=0; i<*returned; i++) {
7190 DEBUGADD(6,("adding port [%d]'s size\n", i));
7191 *needed += spoolss_size_port_info_1(&ports[i]);
7194 if (!alloc_buffer_size(buffer, *needed)) {
7195 SAFE_FREE(ports);
7196 return WERR_INSUFFICIENT_BUFFER;
7199 /* fill the buffer with the ports structures */
7200 for (i=0; i<*returned; i++) {
7201 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7202 smb_io_port_1("", buffer, &ports[i], 0);
7205 SAFE_FREE(ports);
7207 if (*needed > offered) {
7208 *returned=0;
7209 return WERR_INSUFFICIENT_BUFFER;
7212 return WERR_OK;
7215 /****************************************************************************
7216 enumports level 2.
7217 ****************************************************************************/
7219 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7221 PORT_INFO_2 *ports=NULL;
7222 int i=0;
7224 if (*lp_enumports_cmd()) {
7225 char *cmd = lp_enumports_cmd();
7226 char *path;
7227 char **qlines;
7228 pstring tmp_file;
7229 pstring command;
7230 int numlines;
7231 int ret;
7232 int fd;
7234 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7235 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7236 else
7237 path = lp_lockdir();
7239 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7240 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7242 unlink(tmp_file);
7243 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7244 ret = smbrun(command, &fd);
7245 DEBUGADD(10,("returned [%d]\n", ret));
7246 if (ret != 0) {
7247 if (fd != -1)
7248 close(fd);
7249 /* Is this the best error to return here? */
7250 return WERR_ACCESS_DENIED;
7253 numlines = 0;
7254 qlines = fd_lines_load(fd, &numlines);
7255 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7256 close(fd);
7258 if(numlines) {
7259 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7260 file_lines_free(qlines);
7261 return WERR_NOMEM;
7264 for (i=0; i<numlines; i++) {
7265 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7266 fill_port_2(&(ports[i]), qlines[i]);
7269 file_lines_free(qlines);
7272 *returned = numlines;
7274 } else {
7276 *returned = 1;
7278 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7279 return WERR_NOMEM;
7281 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7283 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7286 /* check the required size. */
7287 for (i=0; i<*returned; i++) {
7288 DEBUGADD(6,("adding port [%d]'s size\n", i));
7289 *needed += spoolss_size_port_info_2(&ports[i]);
7292 if (!alloc_buffer_size(buffer, *needed)) {
7293 SAFE_FREE(ports);
7294 return WERR_INSUFFICIENT_BUFFER;
7297 /* fill the buffer with the ports structures */
7298 for (i=0; i<*returned; i++) {
7299 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7300 smb_io_port_2("", buffer, &ports[i], 0);
7303 SAFE_FREE(ports);
7305 if (*needed > offered) {
7306 *returned=0;
7307 return WERR_INSUFFICIENT_BUFFER;
7310 return WERR_OK;
7313 /****************************************************************************
7314 enumports.
7315 ****************************************************************************/
7317 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7319 uint32 level = q_u->level;
7320 NEW_BUFFER *buffer = NULL;
7321 uint32 offered = q_u->offered;
7322 uint32 *needed = &r_u->needed;
7323 uint32 *returned = &r_u->returned;
7325 /* that's an [in out] buffer */
7326 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7327 buffer = r_u->buffer;
7329 DEBUG(4,("_spoolss_enumports\n"));
7331 *returned=0;
7332 *needed=0;
7334 switch (level) {
7335 case 1:
7336 return enumports_level_1(buffer, offered, needed, returned);
7337 case 2:
7338 return enumports_level_2(buffer, offered, needed, returned);
7339 default:
7340 return WERR_UNKNOWN_LEVEL;
7344 /****************************************************************************
7345 ****************************************************************************/
7347 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7348 const SPOOL_PRINTER_INFO_LEVEL *info,
7349 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7350 uint32 user_switch, const SPOOL_USER_CTR *user,
7351 POLICY_HND *handle)
7353 NT_PRINTER_INFO_LEVEL *printer = NULL;
7354 fstring name;
7355 int snum;
7356 WERROR err = WERR_OK;
7358 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7359 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7360 return WERR_NOMEM;
7363 ZERO_STRUCTP(printer);
7365 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7366 if (!convert_printer_info(info, printer, 2)) {
7367 free_a_printer(&printer, 2);
7368 return WERR_NOMEM;
7371 /* check to see if the printer already exists */
7373 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7374 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7375 printer->info_2->sharename));
7376 free_a_printer(&printer, 2);
7377 return WERR_PRINTER_ALREADY_EXISTS;
7380 /* FIXME!!! smbd should check to see if the driver is installed before
7381 trying to add a printer like this --jerry */
7383 if (*lp_addprinter_cmd() ) {
7384 if ( !add_printer_hook(printer) ) {
7385 free_a_printer(&printer,2);
7386 return WERR_ACCESS_DENIED;
7390 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7391 printer->info_2->sharename);
7394 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7395 free_a_printer(&printer,2);
7396 return WERR_ACCESS_DENIED;
7399 /* you must be a printer admin to add a new printer */
7400 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7401 free_a_printer(&printer,2);
7402 return WERR_ACCESS_DENIED;
7406 * Do sanity check on the requested changes for Samba.
7409 if (!check_printer_ok(printer->info_2, snum)) {
7410 free_a_printer(&printer,2);
7411 return WERR_INVALID_PARAM;
7415 * When a printer is created, the drivername bound to the printer is used
7416 * to lookup previously saved driver initialization info, which is then
7417 * bound to the new printer, simulating what happens in the Windows arch.
7420 if (!devmode)
7422 set_driver_init(printer, 2);
7424 else
7426 /* A valid devmode was included, convert and link it
7428 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7430 if (!convert_devicemode(printer->info_2->printername, devmode,
7431 &printer->info_2->devmode))
7432 return WERR_NOMEM;
7435 /* write the ASCII on disk */
7436 err = mod_a_printer(*printer, 2);
7437 if (!W_ERROR_IS_OK(err)) {
7438 free_a_printer(&printer,2);
7439 return err;
7442 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7443 /* Handle open failed - remove addition. */
7444 del_a_printer(printer->info_2->sharename);
7445 free_a_printer(&printer,2);
7446 return WERR_ACCESS_DENIED;
7449 update_c_setprinter(False);
7450 free_a_printer(&printer,2);
7452 return WERR_OK;
7455 /****************************************************************************
7456 ****************************************************************************/
7458 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7460 UNISTR2 *uni_srv_name = &q_u->server_name;
7461 uint32 level = q_u->level;
7462 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7463 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7464 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7465 uint32 user_switch = q_u->user_switch;
7466 SPOOL_USER_CTR *user = &q_u->user_ctr;
7467 POLICY_HND *handle = &r_u->handle;
7469 switch (level) {
7470 case 1:
7471 /* we don't handle yet */
7472 /* but I know what to do ... */
7473 return WERR_UNKNOWN_LEVEL;
7474 case 2:
7475 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7476 devmode, sdb,
7477 user_switch, user, handle);
7478 default:
7479 return WERR_UNKNOWN_LEVEL;
7483 /****************************************************************************
7484 ****************************************************************************/
7486 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7488 uint32 level = q_u->level;
7489 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7490 WERROR err = WERR_OK;
7491 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7492 struct current_user user;
7493 fstring driver_name;
7494 uint32 version;
7496 ZERO_STRUCT(driver);
7498 get_current_user(&user, p);
7500 if (!convert_printer_driver_info(info, &driver, level)) {
7501 err = WERR_NOMEM;
7502 goto done;
7505 DEBUG(5,("Cleaning driver's information\n"));
7506 err = clean_up_driver_struct(driver, level, &user);
7507 if (!W_ERROR_IS_OK(err))
7508 goto done;
7510 DEBUG(5,("Moving driver to final destination\n"));
7511 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7512 if (W_ERROR_IS_OK(err))
7513 err = WERR_ACCESS_DENIED;
7514 goto done;
7517 if (add_a_printer_driver(driver, level)!=0) {
7518 err = WERR_ACCESS_DENIED;
7519 goto done;
7522 /* BEGIN_ADMIN_LOG */
7523 switch(level) {
7524 case 3:
7525 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7526 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7527 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7528 break;
7529 case 6:
7530 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7531 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7532 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7533 break;
7535 /* END_ADMIN_LOG */
7538 * I think this is where he DrvUpgradePrinter() hook would be
7539 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7540 * server. Right now, we just need to send ourselves a message
7541 * to update each printer bound to this driver. --jerry
7544 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7545 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7546 driver_name));
7550 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7551 * decide if the driver init data should be deleted. The rules are:
7552 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7553 * 2) delete init data only if there is no 2k/Xp driver
7554 * 3) always delete init data
7555 * The generalized rule is always use init data from the highest order driver.
7556 * It is necessary to follow the driver install by an initialization step to
7557 * finish off this process.
7559 if (level == 3)
7560 version = driver.info_3->cversion;
7561 else if (level == 6)
7562 version = driver.info_6->version;
7563 else
7564 version = -1;
7565 switch (version) {
7567 * 9x printer driver - never delete init data
7569 case 0:
7570 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7571 driver_name));
7572 break;
7575 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7576 * there is no 2k/Xp driver init data for this driver name.
7578 case 2:
7580 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7582 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7584 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7586 if (!del_driver_init(driver_name))
7587 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7588 } else {
7590 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7592 free_a_printer_driver(driver1,3);
7593 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7594 driver_name));
7597 break;
7600 * 2k or Xp printer driver - always delete init data
7602 case 3:
7603 if (!del_driver_init(driver_name))
7604 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7605 break;
7607 default:
7608 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7609 break;
7613 done:
7614 free_a_printer_driver(driver, level);
7615 return err;
7618 /********************************************************************
7619 * spoolss_addprinterdriverex
7620 ********************************************************************/
7622 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7624 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7625 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7628 * we only support the semantics of AddPrinterDriver()
7629 * i.e. only copy files that are newer than existing ones
7632 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7633 return WERR_ACCESS_DENIED;
7635 ZERO_STRUCT(q_u_local);
7636 ZERO_STRUCT(r_u_local);
7638 /* just pass the information off to _spoolss_addprinterdriver() */
7639 q_u_local.server_name_ptr = q_u->server_name_ptr;
7640 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7641 q_u_local.level = q_u->level;
7642 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7644 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7647 /****************************************************************************
7648 ****************************************************************************/
7650 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7652 init_unistr(&info->name, name);
7655 /****************************************************************************
7656 ****************************************************************************/
7658 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7660 pstring path;
7661 pstring long_archi;
7662 const char *short_archi;
7663 DRIVER_DIRECTORY_1 *info=NULL;
7665 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7667 if (!(short_archi = get_short_archi(long_archi)))
7668 return WERR_INVALID_ENVIRONMENT;
7670 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7671 return WERR_NOMEM;
7673 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7675 DEBUG(4,("printer driver directory: [%s]\n", path));
7677 fill_driverdir_1(info, path);
7679 *needed += spoolss_size_driverdir_info_1(info);
7681 if (!alloc_buffer_size(buffer, *needed)) {
7682 SAFE_FREE(info);
7683 return WERR_INSUFFICIENT_BUFFER;
7686 smb_io_driverdir_1("", buffer, info, 0);
7688 SAFE_FREE(info);
7690 if (*needed > offered)
7691 return WERR_INSUFFICIENT_BUFFER;
7693 return WERR_OK;
7696 /****************************************************************************
7697 ****************************************************************************/
7699 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7701 UNISTR2 *name = &q_u->name;
7702 UNISTR2 *uni_environment = &q_u->environment;
7703 uint32 level = q_u->level;
7704 NEW_BUFFER *buffer = NULL;
7705 uint32 offered = q_u->offered;
7706 uint32 *needed = &r_u->needed;
7708 /* that's an [in out] buffer */
7709 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7710 buffer = r_u->buffer;
7712 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7714 *needed=0;
7716 switch(level) {
7717 case 1:
7718 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7719 default:
7720 return WERR_UNKNOWN_LEVEL;
7724 /****************************************************************************
7725 ****************************************************************************/
7727 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7729 POLICY_HND *handle = &q_u->handle;
7730 uint32 idx = q_u->index;
7731 uint32 in_value_len = q_u->valuesize;
7732 uint32 in_data_len = q_u->datasize;
7733 uint32 *out_max_value_len = &r_u->valuesize;
7734 uint16 **out_value = &r_u->value;
7735 uint32 *out_value_len = &r_u->realvaluesize;
7736 uint32 *out_type = &r_u->type;
7737 uint32 *out_max_data_len = &r_u->datasize;
7738 uint8 **data_out = &r_u->data;
7739 uint32 *out_data_len = &r_u->realdatasize;
7741 NT_PRINTER_INFO_LEVEL *printer = NULL;
7743 uint32 biggest_valuesize;
7744 uint32 biggest_datasize;
7745 uint32 data_len;
7746 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7747 int snum;
7748 WERROR result;
7749 REGISTRY_VALUE *val = NULL;
7750 NT_PRINTER_DATA *p_data;
7751 int i, key_index, num_values;
7752 int name_length;
7754 ZERO_STRUCT( printer );
7756 *out_type = 0;
7758 *out_max_data_len = 0;
7759 *data_out = NULL;
7760 *out_data_len = 0;
7762 DEBUG(5,("spoolss_enumprinterdata\n"));
7764 if (!Printer) {
7765 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7766 return WERR_BADFID;
7769 if (!get_printer_snum(p,handle, &snum))
7770 return WERR_BADFID;
7772 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7773 if (!W_ERROR_IS_OK(result))
7774 return result;
7776 p_data = &printer->info_2->data;
7777 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7779 result = WERR_OK;
7782 * The NT machine wants to know the biggest size of value and data
7784 * cf: MSDN EnumPrinterData remark section
7787 if ( !in_value_len && !in_data_len && (key_index != -1) )
7789 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7791 biggest_valuesize = 0;
7792 biggest_datasize = 0;
7794 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7796 for ( i=0; i<num_values; i++ )
7798 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7800 name_length = strlen(val->valuename);
7801 if ( strlen(val->valuename) > biggest_valuesize )
7802 biggest_valuesize = name_length;
7804 if ( val->size > biggest_datasize )
7805 biggest_datasize = val->size;
7807 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7808 biggest_datasize));
7811 /* the value is an UNICODE string but real_value_size is the length
7812 in bytes including the trailing 0 */
7814 *out_value_len = 2 * (1+biggest_valuesize);
7815 *out_data_len = biggest_datasize;
7817 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7819 goto done;
7823 * the value len is wrong in NT sp3
7824 * that's the number of bytes not the number of unicode chars
7827 if ( key_index != -1 )
7828 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7830 if ( !val )
7833 /* out_value should default to "" or else NT4 has
7834 problems unmarshalling the response */
7836 *out_max_value_len=(in_value_len/sizeof(uint16));
7838 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7840 result = WERR_NOMEM;
7841 goto done;
7844 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7846 /* the data is counted in bytes */
7848 *out_max_data_len = in_data_len;
7849 *out_data_len = in_data_len;
7851 /* only allocate when given a non-zero data_len */
7853 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7855 result = WERR_NOMEM;
7856 goto done;
7859 result = WERR_NO_MORE_ITEMS;
7861 else
7864 * the value is:
7865 * - counted in bytes in the request
7866 * - counted in UNICODE chars in the max reply
7867 * - counted in bytes in the real size
7869 * take a pause *before* coding not *during* coding
7872 /* name */
7873 *out_max_value_len=(in_value_len/sizeof(uint16));
7874 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7876 result = WERR_NOMEM;
7877 goto done;
7880 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7882 /* type */
7884 *out_type = regval_type( val );
7886 /* data - counted in bytes */
7888 *out_max_data_len = in_data_len;
7889 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7891 result = WERR_NOMEM;
7892 goto done;
7894 data_len = (size_t)regval_size(val);
7895 memcpy( *data_out, regval_data_p(val), data_len );
7896 *out_data_len = data_len;
7899 done:
7900 free_a_printer(&printer, 2);
7901 return result;
7904 /****************************************************************************
7905 ****************************************************************************/
7907 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7909 POLICY_HND *handle = &q_u->handle;
7910 UNISTR2 *value = &q_u->value;
7911 uint32 type = q_u->type;
7912 uint8 *data = q_u->data;
7913 uint32 real_len = q_u->real_len;
7915 NT_PRINTER_INFO_LEVEL *printer = NULL;
7916 int snum=0;
7917 WERROR status = WERR_OK;
7918 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7919 fstring valuename;
7921 DEBUG(5,("spoolss_setprinterdata\n"));
7923 if (!Printer) {
7924 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7925 return WERR_BADFID;
7928 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7929 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7930 return WERR_INVALID_PARAM;
7933 if (!get_printer_snum(p,handle, &snum))
7934 return WERR_BADFID;
7937 * Access check : NT returns "access denied" if you make a
7938 * SetPrinterData call without the necessary privildge.
7939 * we were originally returning OK if nothing changed
7940 * which made Win2k issue **a lot** of SetPrinterData
7941 * when connecting to a printer --jerry
7944 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7946 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7947 status = WERR_ACCESS_DENIED;
7948 goto done;
7951 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7952 if (!W_ERROR_IS_OK(status))
7953 return status;
7955 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7958 * When client side code sets a magic printer data key, detect it and save
7959 * the current printer data and the magic key's data (its the DEVMODE) for
7960 * future printer/driver initializations.
7962 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7964 /* Set devmode and printer initialization info */
7965 status = save_driver_init( printer, 2, data, real_len );
7967 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7969 else
7971 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7972 type, data, real_len );
7973 if ( W_ERROR_IS_OK(status) )
7974 status = mod_a_printer(*printer, 2);
7977 done:
7978 free_a_printer(&printer, 2);
7980 return status;
7983 /****************************************************************************
7984 ****************************************************************************/
7986 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7988 POLICY_HND *handle = &q_u->handle;
7989 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7990 int snum;
7992 DEBUG(5,("_spoolss_resetprinter\n"));
7995 * All we do is to check to see if the handle and queue is valid.
7996 * This call really doesn't mean anything to us because we only
7997 * support RAW printing. --jerry
8000 if (!Printer) {
8001 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8002 return WERR_BADFID;
8005 if (!get_printer_snum(p,handle, &snum))
8006 return WERR_BADFID;
8009 /* blindly return success */
8010 return WERR_OK;
8014 /****************************************************************************
8015 ****************************************************************************/
8017 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8019 POLICY_HND *handle = &q_u->handle;
8020 UNISTR2 *value = &q_u->valuename;
8022 NT_PRINTER_INFO_LEVEL *printer = NULL;
8023 int snum=0;
8024 WERROR status = WERR_OK;
8025 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8026 pstring valuename;
8028 DEBUG(5,("spoolss_deleteprinterdata\n"));
8030 if (!Printer) {
8031 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8032 return WERR_BADFID;
8035 if (!get_printer_snum(p, handle, &snum))
8036 return WERR_BADFID;
8038 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8039 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8040 return WERR_ACCESS_DENIED;
8043 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8044 if (!W_ERROR_IS_OK(status))
8045 return status;
8047 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8049 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8051 if ( W_ERROR_IS_OK(status) )
8052 mod_a_printer( *printer, 2 );
8054 free_a_printer(&printer, 2);
8056 return status;
8059 /****************************************************************************
8060 ****************************************************************************/
8062 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8064 POLICY_HND *handle = &q_u->handle;
8065 FORM *form = &q_u->form;
8066 nt_forms_struct tmpForm;
8067 int snum;
8068 WERROR status = WERR_OK;
8069 NT_PRINTER_INFO_LEVEL *printer = NULL;
8071 int count=0;
8072 nt_forms_struct *list=NULL;
8073 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8075 DEBUG(5,("spoolss_addform\n"));
8077 if (!Printer) {
8078 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8079 return WERR_BADFID;
8083 /* forms can be added on printer of on the print server handle */
8085 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8087 if (!get_printer_snum(p,handle, &snum))
8088 return WERR_BADFID;
8090 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8091 if (!W_ERROR_IS_OK(status))
8092 goto done;
8095 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8096 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8097 status = WERR_ACCESS_DENIED;
8098 goto done;
8101 /* can't add if builtin */
8103 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8104 status = WERR_ALREADY_EXISTS;
8105 goto done;
8108 count = get_ntforms(&list);
8110 if(!add_a_form(&list, form, &count)) {
8111 status = WERR_NOMEM;
8112 goto done;
8115 write_ntforms(&list, count);
8118 * ChangeID must always be set if this is a printer
8121 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8122 status = mod_a_printer(*printer, 2);
8124 done:
8125 if ( printer )
8126 free_a_printer(&printer, 2);
8127 SAFE_FREE(list);
8129 return status;
8132 /****************************************************************************
8133 ****************************************************************************/
8135 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8137 POLICY_HND *handle = &q_u->handle;
8138 UNISTR2 *form_name = &q_u->name;
8139 nt_forms_struct tmpForm;
8140 int count=0;
8141 nt_forms_struct *list=NULL;
8142 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8143 int snum;
8144 WERROR status = WERR_OK;
8145 NT_PRINTER_INFO_LEVEL *printer = NULL;
8147 DEBUG(5,("spoolss_deleteform\n"));
8149 if (!Printer) {
8150 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8151 return WERR_BADFID;
8154 /* forms can be deleted on printer of on the print server handle */
8156 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8158 if (!get_printer_snum(p,handle, &snum))
8159 return WERR_BADFID;
8161 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8162 if (!W_ERROR_IS_OK(status))
8163 goto done;
8166 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8167 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8168 status = WERR_ACCESS_DENIED;
8169 goto done;
8172 /* can't delete if builtin */
8174 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8175 status = WERR_INVALID_PARAM;
8176 goto done;
8179 count = get_ntforms(&list);
8181 if ( !delete_a_form(&list, form_name, &count, &status ))
8182 goto done;
8185 * ChangeID must always be set if this is a printer
8188 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8189 status = mod_a_printer(*printer, 2);
8191 done:
8192 if ( printer )
8193 free_a_printer(&printer, 2);
8194 SAFE_FREE(list);
8196 return status;
8199 /****************************************************************************
8200 ****************************************************************************/
8202 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8204 POLICY_HND *handle = &q_u->handle;
8205 FORM *form = &q_u->form;
8206 nt_forms_struct tmpForm;
8207 int snum;
8208 WERROR status = WERR_OK;
8209 NT_PRINTER_INFO_LEVEL *printer = NULL;
8211 int count=0;
8212 nt_forms_struct *list=NULL;
8213 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8215 DEBUG(5,("spoolss_setform\n"));
8217 if (!Printer) {
8218 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8219 return WERR_BADFID;
8222 /* forms can be modified on printer of on the print server handle */
8224 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8226 if (!get_printer_snum(p,handle, &snum))
8227 return WERR_BADFID;
8229 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8230 if (!W_ERROR_IS_OK(status))
8231 goto done;
8234 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8235 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8236 status = WERR_ACCESS_DENIED;
8237 goto done;
8240 /* can't set if builtin */
8241 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8242 status = WERR_INVALID_PARAM;
8243 goto done;
8246 count = get_ntforms(&list);
8247 update_a_form(&list, form, count);
8248 write_ntforms(&list, count);
8251 * ChangeID must always be set if this is a printer
8254 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8255 status = mod_a_printer(*printer, 2);
8258 done:
8259 if ( printer )
8260 free_a_printer(&printer, 2);
8261 SAFE_FREE(list);
8263 return status;
8266 /****************************************************************************
8267 enumprintprocessors level 1.
8268 ****************************************************************************/
8270 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8272 PRINTPROCESSOR_1 *info_1=NULL;
8274 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8275 return WERR_NOMEM;
8277 (*returned) = 0x1;
8279 init_unistr(&info_1->name, "winprint");
8281 *needed += spoolss_size_printprocessor_info_1(info_1);
8283 if (!alloc_buffer_size(buffer, *needed))
8284 return WERR_INSUFFICIENT_BUFFER;
8286 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8288 SAFE_FREE(info_1);
8290 if (*needed > offered) {
8291 *returned=0;
8292 return WERR_INSUFFICIENT_BUFFER;
8295 return WERR_OK;
8298 /****************************************************************************
8299 ****************************************************************************/
8301 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8303 uint32 level = q_u->level;
8304 NEW_BUFFER *buffer = NULL;
8305 uint32 offered = q_u->offered;
8306 uint32 *needed = &r_u->needed;
8307 uint32 *returned = &r_u->returned;
8309 /* that's an [in out] buffer */
8310 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8311 buffer = r_u->buffer;
8313 DEBUG(5,("spoolss_enumprintprocessors\n"));
8316 * Enumerate the print processors ...
8318 * Just reply with "winprint", to keep NT happy
8319 * and I can use my nice printer checker.
8322 *returned=0;
8323 *needed=0;
8325 switch (level) {
8326 case 1:
8327 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8328 default:
8329 return WERR_UNKNOWN_LEVEL;
8333 /****************************************************************************
8334 enumprintprocdatatypes level 1.
8335 ****************************************************************************/
8337 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8339 PRINTPROCDATATYPE_1 *info_1=NULL;
8341 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8342 return WERR_NOMEM;
8344 (*returned) = 0x1;
8346 init_unistr(&info_1->name, "RAW");
8348 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8350 if (!alloc_buffer_size(buffer, *needed))
8351 return WERR_INSUFFICIENT_BUFFER;
8353 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8355 SAFE_FREE(info_1);
8357 if (*needed > offered) {
8358 *returned=0;
8359 return WERR_INSUFFICIENT_BUFFER;
8362 return WERR_OK;
8365 /****************************************************************************
8366 ****************************************************************************/
8368 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8370 uint32 level = q_u->level;
8371 NEW_BUFFER *buffer = NULL;
8372 uint32 offered = q_u->offered;
8373 uint32 *needed = &r_u->needed;
8374 uint32 *returned = &r_u->returned;
8376 /* that's an [in out] buffer */
8377 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8378 buffer = r_u->buffer;
8380 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8382 *returned=0;
8383 *needed=0;
8385 switch (level) {
8386 case 1:
8387 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8388 default:
8389 return WERR_UNKNOWN_LEVEL;
8393 /****************************************************************************
8394 enumprintmonitors level 1.
8395 ****************************************************************************/
8397 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8399 PRINTMONITOR_1 *info_1=NULL;
8401 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8402 return WERR_NOMEM;
8404 (*returned) = 0x1;
8406 init_unistr(&info_1->name, "Local Port");
8408 *needed += spoolss_size_printmonitor_info_1(info_1);
8410 if (!alloc_buffer_size(buffer, *needed))
8411 return WERR_INSUFFICIENT_BUFFER;
8413 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8415 SAFE_FREE(info_1);
8417 if (*needed > offered) {
8418 *returned=0;
8419 return WERR_INSUFFICIENT_BUFFER;
8422 return WERR_OK;
8425 /****************************************************************************
8426 enumprintmonitors level 2.
8427 ****************************************************************************/
8429 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8431 PRINTMONITOR_2 *info_2=NULL;
8433 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8434 return WERR_NOMEM;
8436 (*returned) = 0x1;
8438 init_unistr(&info_2->name, "Local Port");
8439 init_unistr(&info_2->environment, "Windows NT X86");
8440 init_unistr(&info_2->dll_name, "localmon.dll");
8442 *needed += spoolss_size_printmonitor_info_2(info_2);
8444 if (!alloc_buffer_size(buffer, *needed))
8445 return WERR_INSUFFICIENT_BUFFER;
8447 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8449 SAFE_FREE(info_2);
8451 if (*needed > offered) {
8452 *returned=0;
8453 return WERR_INSUFFICIENT_BUFFER;
8456 return WERR_OK;
8459 /****************************************************************************
8460 ****************************************************************************/
8462 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8464 uint32 level = q_u->level;
8465 NEW_BUFFER *buffer = NULL;
8466 uint32 offered = q_u->offered;
8467 uint32 *needed = &r_u->needed;
8468 uint32 *returned = &r_u->returned;
8470 /* that's an [in out] buffer */
8471 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8472 buffer = r_u->buffer;
8474 DEBUG(5,("spoolss_enumprintmonitors\n"));
8477 * Enumerate the print monitors ...
8479 * Just reply with "Local Port", to keep NT happy
8480 * and I can use my nice printer checker.
8483 *returned=0;
8484 *needed=0;
8486 switch (level) {
8487 case 1:
8488 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8489 case 2:
8490 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8491 default:
8492 return WERR_UNKNOWN_LEVEL;
8496 /****************************************************************************
8497 ****************************************************************************/
8499 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8501 int i=0;
8502 BOOL found=False;
8503 JOB_INFO_1 *info_1=NULL;
8505 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8507 if (info_1 == NULL) {
8508 return WERR_NOMEM;
8511 for (i=0; i<count && found==False; i++) {
8512 if ((*queue)[i].job==(int)jobid)
8513 found=True;
8516 if (found==False) {
8517 SAFE_FREE(info_1);
8518 /* NT treats not found as bad param... yet another bad choice */
8519 return WERR_INVALID_PARAM;
8522 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8524 *needed += spoolss_size_job_info_1(info_1);
8526 if (!alloc_buffer_size(buffer, *needed)) {
8527 SAFE_FREE(info_1);
8528 return WERR_INSUFFICIENT_BUFFER;
8531 smb_io_job_info_1("", buffer, info_1, 0);
8533 SAFE_FREE(info_1);
8535 if (*needed > offered)
8536 return WERR_INSUFFICIENT_BUFFER;
8538 return WERR_OK;
8541 /****************************************************************************
8542 ****************************************************************************/
8544 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8546 int i = 0;
8547 BOOL found = False;
8548 JOB_INFO_2 *info_2;
8549 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8550 WERROR ret;
8551 DEVICEMODE *devmode = NULL;
8552 NT_DEVICEMODE *nt_devmode = NULL;
8554 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8556 ZERO_STRUCTP(info_2);
8558 if (info_2 == NULL) {
8559 ret = WERR_NOMEM;
8560 goto done;
8563 for ( i=0; i<count && found==False; i++ )
8565 if ((*queue)[i].job == (int)jobid)
8566 found = True;
8569 if ( !found )
8571 /* NT treats not found as bad param... yet another bad
8572 choice */
8573 ret = WERR_INVALID_PARAM;
8574 goto done;
8577 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8578 if (!W_ERROR_IS_OK(ret))
8579 goto done;
8582 * if the print job does not have a DEVMODE associated with it,
8583 * just use the one for the printer. A NULL devicemode is not
8584 * a failure condition
8587 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8588 devmode = construct_dev_mode(snum);
8589 else {
8590 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8591 ZERO_STRUCTP( devmode );
8592 convert_nt_devicemode( devmode, nt_devmode );
8596 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8598 *needed += spoolss_size_job_info_2(info_2);
8600 if (!alloc_buffer_size(buffer, *needed)) {
8601 ret = WERR_INSUFFICIENT_BUFFER;
8602 goto done;
8605 smb_io_job_info_2("", buffer, info_2, 0);
8607 if (*needed > offered) {
8608 ret = WERR_INSUFFICIENT_BUFFER;
8609 goto done;
8612 ret = WERR_OK;
8614 done:
8615 /* Cleanup allocated memory */
8617 free_job_info_2(info_2); /* Also frees devmode */
8618 SAFE_FREE(info_2);
8619 free_a_printer(&ntprinter, 2);
8621 return ret;
8624 /****************************************************************************
8625 ****************************************************************************/
8627 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8629 POLICY_HND *handle = &q_u->handle;
8630 uint32 jobid = q_u->jobid;
8631 uint32 level = q_u->level;
8632 NEW_BUFFER *buffer = NULL;
8633 uint32 offered = q_u->offered;
8634 uint32 *needed = &r_u->needed;
8635 WERROR wstatus = WERR_OK;
8637 int snum;
8638 int count;
8639 print_queue_struct *queue = NULL;
8640 print_status_struct prt_status;
8642 /* that's an [in out] buffer */
8643 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8644 buffer = r_u->buffer;
8646 DEBUG(5,("spoolss_getjob\n"));
8648 *needed = 0;
8650 if (!get_printer_snum(p, handle, &snum))
8651 return WERR_BADFID;
8653 count = print_queue_status(snum, &queue, &prt_status);
8655 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8656 count, prt_status.status, prt_status.message));
8658 switch ( level ) {
8659 case 1:
8660 wstatus = getjob_level_1(&queue, count, snum, jobid,
8661 buffer, offered, needed);
8662 break;
8663 case 2:
8664 wstatus = getjob_level_2(&queue, count, snum, jobid,
8665 buffer, offered, needed);
8666 break;
8667 default:
8668 wstatus = WERR_UNKNOWN_LEVEL;
8669 break;
8672 SAFE_FREE(queue);
8673 return wstatus;
8676 /********************************************************************
8677 spoolss_getprinterdataex
8679 From MSDN documentation of GetPrinterDataEx: pass request
8680 to GetPrinterData if key is "PrinterDriverData".
8681 ********************************************************************/
8683 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8685 POLICY_HND *handle = &q_u->handle;
8686 uint32 in_size = q_u->size;
8687 uint32 *type = &r_u->type;
8688 uint32 *out_size = &r_u->size;
8689 uint8 **data = &r_u->data;
8690 uint32 *needed = &r_u->needed;
8691 fstring keyname, valuename;
8693 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8695 NT_PRINTER_INFO_LEVEL *printer = NULL;
8696 int snum = 0;
8697 WERROR status = WERR_OK;
8699 DEBUG(4,("_spoolss_getprinterdataex\n"));
8701 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8702 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8704 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8705 keyname, valuename));
8707 /* in case of problem, return some default values */
8709 *needed = 0;
8710 *type = 0;
8711 *out_size = in_size;
8713 if (!Printer) {
8714 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8715 status = WERR_BADFID;
8716 goto done;
8719 /* Is the handle to a printer or to the server? */
8721 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8722 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8723 status = WERR_INVALID_PARAM;
8724 goto done;
8727 if ( !get_printer_snum(p,handle, &snum) )
8728 return WERR_BADFID;
8730 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8731 if ( !W_ERROR_IS_OK(status) )
8732 goto done;
8734 /* check to see if the keyname is valid */
8735 if ( !strlen(keyname) ) {
8736 status = WERR_INVALID_PARAM;
8737 goto done;
8740 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8741 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8742 free_a_printer( &printer, 2 );
8743 status = WERR_BADFILE;
8744 goto done;
8747 /* When given a new keyname, we should just create it */
8749 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8751 if (*needed > *out_size)
8752 status = WERR_MORE_DATA;
8754 done:
8755 if ( !W_ERROR_IS_OK(status) )
8757 DEBUG(5, ("error: allocating %d\n", *out_size));
8759 /* reply this param doesn't exist */
8761 if ( *out_size )
8763 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8764 status = WERR_NOMEM;
8765 goto done;
8768 else {
8769 *data = NULL;
8773 if ( printer )
8774 free_a_printer( &printer, 2 );
8776 return status;
8779 /********************************************************************
8780 * spoolss_setprinterdataex
8781 ********************************************************************/
8783 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8785 POLICY_HND *handle = &q_u->handle;
8786 uint32 type = q_u->type;
8787 uint8 *data = q_u->data;
8788 uint32 real_len = q_u->real_len;
8790 NT_PRINTER_INFO_LEVEL *printer = NULL;
8791 int snum = 0;
8792 WERROR status = WERR_OK;
8793 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8794 fstring valuename;
8795 fstring keyname;
8796 char *oid_string;
8798 DEBUG(4,("_spoolss_setprinterdataex\n"));
8800 /* From MSDN documentation of SetPrinterDataEx: pass request to
8801 SetPrinterData if key is "PrinterDriverData" */
8803 if (!Printer) {
8804 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8805 return WERR_BADFID;
8808 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8809 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8810 return WERR_INVALID_PARAM;
8813 if ( !get_printer_snum(p,handle, &snum) )
8814 return WERR_BADFID;
8817 * Access check : NT returns "access denied" if you make a
8818 * SetPrinterData call without the necessary privildge.
8819 * we were originally returning OK if nothing changed
8820 * which made Win2k issue **a lot** of SetPrinterData
8821 * when connecting to a printer --jerry
8824 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8826 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8827 return WERR_ACCESS_DENIED;
8830 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8831 if (!W_ERROR_IS_OK(status))
8832 return status;
8834 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8835 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8837 /* check for OID in valuename */
8839 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8841 *oid_string = '\0';
8842 oid_string++;
8845 /* save the registry data */
8847 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8849 if ( W_ERROR_IS_OK(status) )
8851 /* save the OID if one was specified */
8852 if ( oid_string ) {
8853 fstrcat( keyname, "\\" );
8854 fstrcat( keyname, SPOOL_OID_KEY );
8857 * I'm not checking the status here on purpose. Don't know
8858 * if this is right, but I'm returning the status from the
8859 * previous set_printer_dataex() call. I have no idea if
8860 * this is right. --jerry
8863 set_printer_dataex( printer, keyname, valuename,
8864 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8867 status = mod_a_printer(*printer, 2);
8870 free_a_printer(&printer, 2);
8872 return status;
8876 /********************************************************************
8877 * spoolss_deleteprinterdataex
8878 ********************************************************************/
8880 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8882 POLICY_HND *handle = &q_u->handle;
8883 UNISTR2 *value = &q_u->valuename;
8884 UNISTR2 *key = &q_u->keyname;
8886 NT_PRINTER_INFO_LEVEL *printer = NULL;
8887 int snum=0;
8888 WERROR status = WERR_OK;
8889 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8890 pstring valuename, keyname;
8892 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8894 if (!Printer) {
8895 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8896 return WERR_BADFID;
8899 if (!get_printer_snum(p, handle, &snum))
8900 return WERR_BADFID;
8902 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8903 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8904 return WERR_ACCESS_DENIED;
8907 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8908 if (!W_ERROR_IS_OK(status))
8909 return status;
8911 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8912 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8914 status = delete_printer_dataex( printer, keyname, valuename );
8916 if ( W_ERROR_IS_OK(status) )
8917 mod_a_printer( *printer, 2 );
8919 free_a_printer(&printer, 2);
8921 return status;
8924 /********************************************************************
8925 * spoolss_enumprinterkey
8926 ********************************************************************/
8929 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8931 fstring key;
8932 fstring *keynames = NULL;
8933 uint16 *enumkeys = NULL;
8934 int num_keys;
8935 int printerkey_len;
8936 POLICY_HND *handle = &q_u->handle;
8937 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8938 NT_PRINTER_DATA *data;
8939 NT_PRINTER_INFO_LEVEL *printer = NULL;
8940 int snum = 0;
8941 WERROR status = WERR_BADFILE;
8944 DEBUG(4,("_spoolss_enumprinterkey\n"));
8946 if (!Printer) {
8947 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8948 return WERR_BADFID;
8951 if ( !get_printer_snum(p,handle, &snum) )
8952 return WERR_BADFID;
8954 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8955 if (!W_ERROR_IS_OK(status))
8956 return status;
8958 /* get the list of subkey names */
8960 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8961 data = &printer->info_2->data;
8963 num_keys = get_printer_subkeys( data, key, &keynames );
8965 if ( num_keys == -1 ) {
8966 status = WERR_BADFILE;
8967 goto done;
8970 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8972 r_u->needed = printerkey_len*2;
8974 if ( q_u->size < r_u->needed ) {
8975 status = WERR_MORE_DATA;
8976 goto done;
8979 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8980 status = WERR_NOMEM;
8981 goto done;
8984 status = WERR_OK;
8986 if ( q_u->size < r_u->needed )
8987 status = WERR_MORE_DATA;
8989 done:
8990 free_a_printer( &printer, 2 );
8991 SAFE_FREE( keynames );
8993 return status;
8996 /********************************************************************
8997 * spoolss_deleteprinterkey
8998 ********************************************************************/
9000 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9002 POLICY_HND *handle = &q_u->handle;
9003 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9004 fstring key;
9005 NT_PRINTER_INFO_LEVEL *printer = NULL;
9006 int snum=0;
9007 WERROR status;
9009 DEBUG(5,("spoolss_deleteprinterkey\n"));
9011 if (!Printer) {
9012 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9013 return WERR_BADFID;
9016 /* if keyname == NULL, return error */
9018 if ( !q_u->keyname.buffer )
9019 return WERR_INVALID_PARAM;
9021 if (!get_printer_snum(p, handle, &snum))
9022 return WERR_BADFID;
9024 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9025 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9026 return WERR_ACCESS_DENIED;
9029 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9030 if (!W_ERROR_IS_OK(status))
9031 return status;
9033 /* delete the key and all subneys */
9035 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9037 status = delete_all_printer_data( printer->info_2, key );
9039 if ( W_ERROR_IS_OK(status) )
9040 status = mod_a_printer(*printer, 2);
9042 free_a_printer( &printer, 2 );
9044 return status;
9048 /********************************************************************
9049 * spoolss_enumprinterdataex
9050 ********************************************************************/
9052 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9054 POLICY_HND *handle = &q_u->handle;
9055 uint32 in_size = q_u->size;
9056 uint32 num_entries,
9057 needed;
9058 NT_PRINTER_INFO_LEVEL *printer = NULL;
9059 PRINTER_ENUM_VALUES *enum_values = NULL;
9060 NT_PRINTER_DATA *p_data;
9061 fstring key;
9062 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9063 int snum;
9064 WERROR result;
9065 int key_index;
9066 int i;
9067 REGISTRY_VALUE *val;
9068 char *value_name;
9069 int data_len;
9072 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9074 if (!Printer) {
9075 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9076 return WERR_BADFID;
9080 * first check for a keyname of NULL or "". Win2k seems to send
9081 * this a lot and we should send back WERR_INVALID_PARAM
9082 * no need to spend time looking up the printer in this case.
9083 * --jerry
9086 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9087 if ( !strlen(key) ) {
9088 result = WERR_INVALID_PARAM;
9089 goto done;
9092 /* get the printer off of disk */
9094 if (!get_printer_snum(p,handle, &snum))
9095 return WERR_BADFID;
9097 ZERO_STRUCT(printer);
9098 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9099 if (!W_ERROR_IS_OK(result))
9100 return result;
9102 /* now look for a match on the key name */
9104 p_data = &printer->info_2->data;
9106 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9107 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9109 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9110 result = WERR_INVALID_PARAM;
9111 goto done;
9114 result = WERR_OK;
9115 needed = 0;
9117 /* allocate the memory for the array of pointers -- if necessary */
9119 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9120 if ( num_entries )
9122 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9124 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9125 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9126 result = WERR_NOMEM;
9127 goto done;
9130 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9134 * loop through all params and build the array to pass
9135 * back to the client
9138 for ( i=0; i<num_entries; i++ )
9140 /* lookup the registry value */
9142 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9143 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9145 /* copy the data */
9147 value_name = regval_name( val );
9148 init_unistr( &enum_values[i].valuename, value_name );
9149 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9150 enum_values[i].type = regval_type( val );
9152 data_len = regval_size( val );
9153 if ( data_len ) {
9154 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9156 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9157 data_len ));
9158 result = WERR_NOMEM;
9159 goto done;
9162 enum_values[i].data_len = data_len;
9164 /* keep track of the size of the array in bytes */
9166 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9169 /* housekeeping information in the reply */
9171 r_u->needed = needed;
9172 r_u->returned = num_entries;
9174 if (needed > in_size) {
9175 result = WERR_MORE_DATA;
9176 goto done;
9179 /* copy data into the reply */
9181 r_u->ctr.size = r_u->needed;
9182 r_u->ctr.size_of_array = r_u->returned;
9183 r_u->ctr.values = enum_values;
9187 done:
9188 if ( printer )
9189 free_a_printer(&printer, 2);
9191 return result;
9194 /****************************************************************************
9195 ****************************************************************************/
9197 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9199 init_unistr(&info->name, name);
9202 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9203 UNISTR2 *environment,
9204 NEW_BUFFER *buffer,
9205 uint32 offered,
9206 uint32 *needed)
9208 pstring path;
9209 pstring long_archi;
9210 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9212 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9214 if (!get_short_archi(long_archi))
9215 return WERR_INVALID_ENVIRONMENT;
9217 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9218 return WERR_NOMEM;
9220 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9222 fill_printprocessordirectory_1(info, path);
9224 *needed += spoolss_size_printprocessordirectory_info_1(info);
9226 if (!alloc_buffer_size(buffer, *needed)) {
9227 safe_free(info);
9228 return WERR_INSUFFICIENT_BUFFER;
9231 smb_io_printprocessordirectory_1("", buffer, info, 0);
9233 safe_free(info);
9235 if (*needed > offered)
9236 return WERR_INSUFFICIENT_BUFFER;
9237 else
9238 return WERR_OK;
9241 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9243 uint32 level = q_u->level;
9244 NEW_BUFFER *buffer = NULL;
9245 uint32 offered = q_u->offered;
9246 uint32 *needed = &r_u->needed;
9247 WERROR result;
9249 /* that's an [in out] buffer */
9250 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9251 buffer = r_u->buffer;
9253 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9255 *needed=0;
9257 switch(level) {
9258 case 1:
9259 result = getprintprocessordirectory_level_1
9260 (&q_u->name, &q_u->environment, buffer, offered, needed);
9261 break;
9262 default:
9263 result = WERR_UNKNOWN_LEVEL;
9266 return result;
9269 #if 0
9271 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9272 SPOOL_R_REPLYOPENPRINTER *r_u)
9274 DEBUG(5,("_spoolss_replyopenprinter\n"));
9276 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9278 return WERR_OK;
9281 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9282 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9284 DEBUG(5,("_spoolss_replycloseprinter\n"));
9285 return WERR_OK;
9288 #endif