First round of merging various UUID structures.
[Samba/gebeck_regimport.git] / source / rpc_server / srv_spoolss_nt.c
blobad8f5af432c466dc2748caf3bacb678adc311d7c
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-2003,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
29 #include "includes.h"
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_RPC_SRV
34 #ifndef MAX_OPEN_PRINTER_EXS
35 #define MAX_OPEN_PRINTER_EXS 50
36 #endif
38 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
39 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42 /* Table to map the driver version */
43 /* to OS */
44 static const char * drv_ver_to_os[] = {
45 "WIN9X", /* driver version/cversion 0 */
46 "", /* unused ? */
47 "WINNT", /* driver version/cversion 2 */
48 "WIN2K", /* driver version/cversion 3 */
51 static const char *get_drv_ver_to_os(int ver)
53 if (ver < 0 || ver > 3)
54 return "";
55 return drv_ver_to_os[ver];
58 struct table_node {
59 const char *long_archi;
60 const char *short_archi;
61 int version;
64 static Printer_entry *printers_list;
66 typedef struct _counter_printer_0 {
67 ubi_dlNode Next;
68 ubi_dlNode Prev;
70 int snum;
71 uint32 counter;
72 } counter_printer_0;
74 static ubi_dlList counter_list;
76 static struct cli_state notify_cli; /* print notify back-channel */
77 static uint32 smb_connections=0;
80 /* in printing/nt_printing.c */
82 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
84 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
85 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
87 /* translate between internal status numbers and NT status numbers */
88 static int nt_printj_status(int v)
90 switch (v) {
91 case LPQ_QUEUED:
92 return 0;
93 case LPQ_PAUSED:
94 return JOB_STATUS_PAUSED;
95 case LPQ_SPOOLING:
96 return JOB_STATUS_SPOOLING;
97 case LPQ_PRINTING:
98 return JOB_STATUS_PRINTING;
99 case LPQ_ERROR:
100 return JOB_STATUS_ERROR;
101 case LPQ_DELETING:
102 return JOB_STATUS_DELETING;
103 case LPQ_OFFLINE:
104 return JOB_STATUS_OFFLINE;
105 case LPQ_PAPEROUT:
106 return JOB_STATUS_PAPEROUT;
107 case LPQ_PRINTED:
108 return JOB_STATUS_PRINTED;
109 case LPQ_DELETED:
110 return JOB_STATUS_DELETED;
111 case LPQ_BLOCKED:
112 return JOB_STATUS_BLOCKED;
113 case LPQ_USER_INTERVENTION:
114 return JOB_STATUS_USER_INTERVENTION;
116 return 0;
119 static int nt_printq_status(int v)
121 switch (v) {
122 case LPQ_PAUSED:
123 return PRINTER_STATUS_PAUSED;
124 case LPQ_QUEUED:
125 case LPQ_SPOOLING:
126 case LPQ_PRINTING:
127 return 0;
129 return 0;
132 /****************************************************************************
133 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
134 ****************************************************************************/
136 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
138 if (*pp == NULL)
139 return;
141 SAFE_FREE((*pp)->ctr.type);
142 SAFE_FREE(*pp);
145 /***************************************************************************
146 Disconnect from the client
147 ****************************************************************************/
149 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
151 WERROR result;
154 * Tell the specific printing tdb we no longer want messages for this printer
155 * by deregistering our PID.
158 if (!print_notify_deregister_pid(snum))
159 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
161 /* weird if the test succeds !!! */
162 if (smb_connections==0) {
163 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
164 return;
167 result = cli_spoolss_reply_close_printer(&notify_cli, notify_cli.mem_ctx, handle);
169 if (!W_ERROR_IS_OK(result))
170 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171 dos_errstr(result)));
173 /* if it's the last connection, deconnect the IPC$ share */
174 if (smb_connections==1) {
175 cli_nt_session_close(&notify_cli);
176 cli_ulogoff(&notify_cli);
177 cli_shutdown(&notify_cli);
178 message_deregister(MSG_PRINTER_NOTIFY2);
180 /* Tell the connections db we're no longer interested in
181 * printer notify messages. */
183 register_message_flags( False, FLAG_MSG_PRINTING );
186 smb_connections--;
189 /****************************************************************************
190 Functions to free a printer entry datastruct.
191 ****************************************************************************/
193 static void free_printer_entry(void *ptr)
195 Printer_entry *Printer = (Printer_entry *)ptr;
197 if (Printer->notify.client_connected==True) {
198 int snum = -1;
200 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
201 snum = -1;
202 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
204 snum = print_queue_snum(Printer->dev.handlename);
205 if (snum != -1)
206 srv_spoolss_replycloseprinter(snum,
207 &Printer->notify.client_hnd);
211 Printer->notify.flags=0;
212 Printer->notify.options=0;
213 Printer->notify.localmachine[0]='\0';
214 Printer->notify.printerlocal=0;
215 free_spool_notify_option(&Printer->notify.option);
216 Printer->notify.option=NULL;
217 Printer->notify.client_connected=False;
219 free_nt_devicemode( &Printer->nt_devmode );
220 free_a_printer( &Printer->printer_info, 2 );
222 talloc_destroy( Printer->ctx );
224 /* Remove from the internal list. */
225 DLIST_REMOVE(printers_list, Printer);
227 SAFE_FREE(Printer);
230 /****************************************************************************
231 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
232 ****************************************************************************/
234 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
236 SPOOL_NOTIFY_OPTION *new_sp = NULL;
238 if (!sp)
239 return NULL;
241 new_sp = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(SPOOL_NOTIFY_OPTION));
242 if (!new_sp)
243 return NULL;
245 *new_sp = *sp;
247 if (sp->ctr.count) {
248 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
250 if (!new_sp->ctr.type) {
251 SAFE_FREE(new_sp);
252 return NULL;
256 return new_sp;
259 /****************************************************************************
260 find printer index by handle
261 ****************************************************************************/
263 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
265 Printer_entry *find_printer = NULL;
267 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
268 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
269 return NULL;
272 return find_printer;
275 /****************************************************************************
276 look for a printer object cached on an open printer handle
277 ****************************************************************************/
279 WERROR find_printer_in_print_hnd_cache( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 **info2,
280 const char *printername )
282 Printer_entry *p;
284 DEBUG(10,("find_printer_in_print_hnd_cache: printer [%s]\n", printername));
286 for ( p=printers_list; p; p=p->next )
288 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
289 && p->printer_info
290 && StrCaseCmp(p->dev.handlename, printername) == 0 )
292 DEBUG(10,("Found printer\n"));
293 *info2 = dup_printer_2( ctx, p->printer_info->info_2 );
294 if ( *info2 )
295 return WERR_OK;
299 return WERR_INVALID_PRINTER_NAME;
302 /****************************************************************************
303 destroy any cached printer_info_2 structures on open handles
304 ****************************************************************************/
306 void invalidate_printer_hnd_cache( char *printername )
308 Printer_entry *p;
310 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
312 for ( p=printers_list; p; p=p->next )
314 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
315 && StrCaseCmp(p->dev.handlename, printername)==0)
317 DEBUG(10,("invalidating printer_info cache for handl:\n"));
318 free_a_printer( &p->printer_info, 2 );
319 p->printer_info = NULL;
323 return;
325 /****************************************************************************
326 Close printer index by handle.
327 ****************************************************************************/
329 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
331 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
333 if (!Printer) {
334 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
335 return False;
338 close_policy_hnd(p, hnd);
340 return True;
343 /****************************************************************************
344 Delete a printer given a handle.
345 ****************************************************************************/
347 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
349 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
351 if (!Printer) {
352 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
353 return WERR_BADFID;
357 * It turns out that Windows allows delete printer on a handle
358 * opened by an admin user, then used on a pipe handle created
359 * by an anonymous user..... but they're working on security.... riiight !
360 * JRA.
363 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
364 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
365 return WERR_ACCESS_DENIED;
368 #if 0
369 /* Check calling user has permission to delete printer. Note that
370 since we set the snum parameter to -1 only administrators can
371 delete the printer. This stops people with the Full Control
372 permission from deleting the printer. */
374 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
375 DEBUG(3, ("printer delete denied by security descriptor\n"));
376 return WERR_ACCESS_DENIED;
378 #endif
380 if (del_a_printer(Printer->dev.handlename) != 0) {
381 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
382 return WERR_BADFID;
385 if (*lp_deleteprinter_cmd()) {
387 char *cmd = lp_deleteprinter_cmd();
388 pstring command;
389 int ret;
391 /* Printer->dev.handlename equals portname equals sharename */
392 slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd,
393 Printer->dev.handlename);
395 DEBUG(10,("Running [%s]\n", command));
396 ret = smbrun(command, NULL);
397 if (ret != 0) {
398 return WERR_BADFID; /* What to return here? */
400 DEBUGADD(10,("returned [%d]\n", ret));
402 /* Send SIGHUP to process group... is there a better way? */
403 kill(0, SIGHUP);
405 /* go ahead and re-read the services immediately */
406 reload_services( False );
408 if ( lp_servicenumber( Printer->dev.handlename ) < 0 )
409 return WERR_ACCESS_DENIED;
412 return WERR_OK;
415 /****************************************************************************
416 Return the snum of a printer corresponding to an handle.
417 ****************************************************************************/
419 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
421 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
423 if (!Printer) {
424 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
425 return False;
428 switch (Printer->printer_type) {
429 case PRINTER_HANDLE_IS_PRINTER:
430 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
431 *number = print_queue_snum(Printer->dev.handlename);
432 return (*number != -1);
433 case PRINTER_HANDLE_IS_PRINTSERVER:
434 return False;
435 default:
436 return False;
440 /****************************************************************************
441 Set printer handle type.
442 Check if it's \\server or \\server\printer
443 ****************************************************************************/
445 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
447 DEBUG(3,("Setting printer type=%s\n", handlename));
449 if ( strlen(handlename) < 3 ) {
450 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
451 return False;
454 /* it's a print server */
455 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
456 DEBUGADD(4,("Printer is a print server\n"));
457 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
459 /* it's a printer */
460 else {
461 DEBUGADD(4,("Printer is a printer\n"));
462 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
465 return True;
468 /****************************************************************************
469 Set printer handle name.
470 ****************************************************************************/
472 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
474 int snum;
475 int n_services=lp_numservices();
476 char *aprinter;
477 fstring sname;
478 BOOL found=False;
480 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
482 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
483 ZERO_STRUCT(Printer->dev.printerservername);
484 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
485 return True;
488 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
489 return False;
491 if (*handlename=='\\') {
492 aprinter=strchr_m(handlename+2, '\\');
493 aprinter++;
495 else {
496 aprinter=handlename;
499 DEBUGADD(5,("searching for [%s] (len=%lu)\n", aprinter, (unsigned long)strlen(aprinter)));
502 * The original code allowed smbd to store a printer name that
503 * was different from the share name. This is not possible
504 * anymore, so I've simplified this loop greatly. Here
505 * we are just verifying that the printer name is a valid
506 * printer service defined in smb.conf
507 * --jerry [Fri Feb 15 11:17:46 CST 2002]
510 for (snum=0; snum<n_services; snum++) {
512 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
513 continue;
515 fstrcpy(sname, lp_servicename(snum));
517 DEBUGADD(5,("share:%s\n",sname));
519 if (! StrCaseCmp(sname, aprinter)) {
520 found = True;
521 break;
527 if (!found) {
528 DEBUGADD(4,("Printer not found\n"));
529 return False;
532 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
534 ZERO_STRUCT(Printer->dev.handlename);
535 fstrcpy(Printer->dev.handlename, sname);
537 return True;
540 /****************************************************************************
541 Find first available printer slot. creates a printer handle for you.
542 ****************************************************************************/
544 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
546 Printer_entry *new_printer;
548 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
550 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
551 return False;
553 ZERO_STRUCTP(new_printer);
555 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
556 SAFE_FREE(new_printer);
557 return False;
560 /* Add to the internal list. */
561 DLIST_ADD(printers_list, new_printer);
563 new_printer->notify.option=NULL;
565 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
566 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
567 close_printer_handle(p, hnd);
568 return False;
571 if (!set_printer_hnd_printertype(new_printer, name)) {
572 close_printer_handle(p, hnd);
573 return False;
576 if (!set_printer_hnd_name(new_printer, name)) {
577 close_printer_handle(p, hnd);
578 return False;
581 new_printer->access_granted = access_granted;
583 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
585 return True;
588 /****************************************************************************
589 Allocate more memory for a BUFFER.
590 ****************************************************************************/
592 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
594 prs_struct *ps;
595 uint32 extra_space;
596 uint32 old_offset;
598 ps= &buffer->prs;
600 /* damn, I'm doing the reverse operation of prs_grow() :) */
601 if (buffer_size < prs_data_size(ps))
602 extra_space=0;
603 else
604 extra_space = buffer_size - prs_data_size(ps);
607 * save the offset and move to the end of the buffer
608 * prs_grow() checks the extra_space against the offset
610 old_offset=prs_offset(ps);
611 prs_set_offset(ps, prs_data_size(ps));
613 if (!prs_grow(ps, extra_space))
614 return False;
616 prs_set_offset(ps, old_offset);
618 buffer->string_at_end=prs_data_size(ps);
620 return True;
623 /***************************************************************************
624 check to see if the client motify handle is monitoring the notification
625 given by (notify_type, notify_field).
626 **************************************************************************/
628 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
629 uint16 notify_field)
631 return True;
634 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
635 uint16 notify_field)
637 SPOOL_NOTIFY_OPTION *option = p->notify.option;
638 uint32 i, j;
641 * Flags should always be zero when the change notify
642 * is registered by the client's spooler. A user Win32 app
643 * might use the flags though instead of the NOTIFY_OPTION_INFO
644 * --jerry
647 if (p->notify.flags)
648 return is_monitoring_event_flags(
649 p->notify.flags, notify_type, notify_field);
651 for (i = 0; i < option->count; i++) {
653 /* Check match for notify_type */
655 if (option->ctr.type[i].type != notify_type)
656 continue;
658 /* Check match for field */
660 for (j = 0; j < option->ctr.type[i].count; j++) {
661 if (option->ctr.type[i].fields[j] == notify_field) {
662 return True;
667 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
668 (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
669 p->dev.handlename : p->dev.printerservername,
670 notify_type, notify_field));
672 return False;
675 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
677 static void notify_one_value(struct spoolss_notify_msg *msg,
678 SPOOL_NOTIFY_INFO_DATA *data,
679 TALLOC_CTX *mem_ctx)
681 data->notify_data.value[0] = msg->notify.value[0];
682 data->notify_data.value[1] = 0;
685 static void notify_string(struct spoolss_notify_msg *msg,
686 SPOOL_NOTIFY_INFO_DATA *data,
687 TALLOC_CTX *mem_ctx)
689 UNISTR2 unistr;
691 /* The length of the message includes the trailing \0 */
693 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
695 data->notify_data.data.length = msg->len * 2;
696 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
698 if (!data->notify_data.data.string) {
699 data->notify_data.data.length = 0;
700 return;
703 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
706 static void notify_system_time(struct spoolss_notify_msg *msg,
707 SPOOL_NOTIFY_INFO_DATA *data,
708 TALLOC_CTX *mem_ctx)
710 SYSTEMTIME systime;
711 prs_struct ps;
713 if (msg->len != sizeof(time_t)) {
714 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
715 msg->len));
716 return;
719 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
720 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
721 return;
724 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
725 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
726 return;
729 if (!spoolss_io_system_time("", &ps, 0, &systime))
730 return;
732 data->notify_data.data.length = prs_offset(&ps);
733 data->notify_data.data.string = talloc(mem_ctx, prs_offset(&ps));
735 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
737 prs_mem_free(&ps);
740 struct notify2_message_table {
741 const char *name;
742 void (*fn)(struct spoolss_notify_msg *msg,
743 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
746 static struct notify2_message_table printer_notify_table[] = {
747 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
748 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
749 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
750 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
751 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
752 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
753 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
754 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
755 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
756 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
757 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
758 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
759 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
760 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
761 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
762 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
763 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
764 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
765 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
768 static struct notify2_message_table job_notify_table[] = {
769 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
770 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
771 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
772 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
773 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
774 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
775 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
776 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
777 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
778 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
779 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
780 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
781 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
782 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
783 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
784 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
785 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
786 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
787 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
788 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
789 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
790 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
791 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
792 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
796 /***********************************************************************
797 Allocate talloc context for container object
798 **********************************************************************/
800 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
802 if ( !ctr )
803 return;
805 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
807 return;
810 /***********************************************************************
811 release all allocated memory and zero out structure
812 **********************************************************************/
814 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
816 if ( !ctr )
817 return;
819 if ( ctr->ctx )
820 talloc_destroy(ctr->ctx);
822 ZERO_STRUCTP(ctr);
824 return;
827 /***********************************************************************
828 **********************************************************************/
830 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
832 if ( !ctr )
833 return NULL;
835 return ctr->ctx;
838 /***********************************************************************
839 **********************************************************************/
841 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
843 if ( !ctr || !ctr->msg_groups )
844 return NULL;
846 if ( idx >= ctr->num_groups )
847 return NULL;
849 return &ctr->msg_groups[idx];
853 /***********************************************************************
854 How many groups of change messages do we have ?
855 **********************************************************************/
857 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
859 if ( !ctr )
860 return 0;
862 return ctr->num_groups;
865 /***********************************************************************
866 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
867 **********************************************************************/
869 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
871 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
872 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
873 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
874 int i, new_slot;
876 if ( !ctr || !msg )
877 return 0;
879 /* loop over all groups looking for a matching printer name */
881 for ( i=0; i<ctr->num_groups; i++ ) {
882 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
883 break;
886 /* add a new group? */
888 if ( i == ctr->num_groups ) {
889 ctr->num_groups++;
891 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
892 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
893 return 0;
895 ctr->msg_groups = groups;
897 /* clear the new entry and set the printer name */
899 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
900 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
903 /* add the change messages; 'i' is the correct index now regardless */
905 msg_grp = &ctr->msg_groups[i];
907 msg_grp->num_msgs++;
909 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
910 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
911 return 0;
913 msg_grp->msgs = msg_list;
915 new_slot = msg_grp->num_msgs-1;
916 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
918 /* need to allocate own copy of data */
920 if ( msg->len != 0 )
921 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
923 return ctr->num_groups;
926 /***********************************************************************
927 Send a change notication message on all handles which have a call
928 back registered
929 **********************************************************************/
931 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
933 Printer_entry *p;
934 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
935 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
936 SPOOLSS_NOTIFY_MSG *messages;
937 int sending_msg_count;
939 if ( !msg_group ) {
940 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
941 return;
944 messages = msg_group->msgs;
946 if ( !messages ) {
947 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
948 return;
951 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
953 /* loop over all printers */
955 for (p = printers_list; p; p = p->next) {
956 SPOOL_NOTIFY_INFO_DATA *data;
957 uint32 data_len = 0;
958 uint32 id;
959 int i;
961 /* Is there notification on this handle? */
963 if ( !p->notify.client_connected )
964 continue;
966 DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
968 /* For this printer? Print servers always receive
969 notifications. */
971 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
972 ( !strequal(msg_group->printername, p->dev.handlename) ) )
973 continue;
975 DEBUG(10,("Our printer\n"));
977 /* allocate the max entries possible */
979 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
980 ZERO_STRUCTP(data);
982 /* build the array of change notifications */
984 sending_msg_count = 0;
986 for ( i=0; i<msg_group->num_msgs; i++ ) {
987 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
989 /* Are we monitoring this event? */
991 if (!is_monitoring_event(p, msg->type, msg->field))
992 continue;
994 sending_msg_count++;
997 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
998 msg->type, msg->field, p->dev.handlename));
1001 * if the is a printer notification handle and not a job notification
1002 * type, then set the id to 0. Other wise just use what was specified
1003 * in the message.
1005 * When registering change notification on a print server handle
1006 * we always need to send back the id (snum) matching the printer
1007 * for which the change took place. For change notify registered
1008 * on a printer handle, this does not matter and the id should be 0.
1010 * --jerry
1013 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1014 id = 0;
1015 else
1016 id = msg->id;
1019 /* Convert unix jobid to smb jobid */
1021 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1022 id = sysjob_to_jobid(msg->id);
1024 if (id == -1) {
1025 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1026 goto done;
1030 construct_info_data( &data[data_len], msg->type, msg->field, id );
1032 switch(msg->type) {
1033 case PRINTER_NOTIFY_TYPE:
1034 if ( printer_notify_table[msg->field].fn )
1035 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1036 break;
1038 case JOB_NOTIFY_TYPE:
1039 if ( job_notify_table[msg->field].fn )
1040 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1041 break;
1043 default:
1044 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1045 goto done;
1048 data_len++;
1051 if ( sending_msg_count ) {
1052 cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
1053 data_len, data, p->notify.change, 0 );
1057 done:
1058 DEBUG(8,("send_notify2_changes: Exit...\n"));
1059 return;
1062 /***********************************************************************
1063 **********************************************************************/
1065 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1068 uint32 tv_sec, tv_usec;
1069 size_t offset = 0;
1071 /* Unpack message */
1073 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1074 msg->printer);
1076 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1077 &tv_sec, &tv_usec,
1078 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1080 if (msg->len == 0)
1081 tdb_unpack((char *)buf + offset, len - offset, "dd",
1082 &msg->notify.value[0], &msg->notify.value[1]);
1083 else
1084 tdb_unpack((char *)buf + offset, len - offset, "B",
1085 &msg->len, &msg->notify.data);
1087 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1088 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1090 tv->tv_sec = tv_sec;
1091 tv->tv_usec = tv_usec;
1093 if (msg->len == 0)
1094 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1095 msg->notify.value[1]));
1096 else
1097 dump_data(3, msg->notify.data, msg->len);
1099 return True;
1102 /* ENUMJOB last timestamp list. */
1103 struct ejts_list {
1104 struct ejts_list *next, *prev;
1105 char *printer_name;
1106 struct timeval tv;
1109 static struct ejts_list *ejts_head;
1111 static struct ejts_list *find_enumjobs_timestamp(const char *printer_name)
1113 struct ejts_list *ejtsl;
1115 for( ejtsl = ejts_head; ejtsl; ejtsl = ejtsl->next)
1116 if (strequal(ejtsl->printer_name, printer_name))
1117 return ejtsl;
1118 return NULL;
1121 static void set_enumjobs_timestamp(int snum)
1123 const char *printer_name = lp_const_servicename(snum);
1124 struct ejts_list *ejtsl = find_enumjobs_timestamp(printer_name);
1126 if (!ejtsl) {
1127 ejtsl = (struct ejts_list *)malloc(sizeof(struct ejts_list));
1128 if (!ejtsl)
1129 return;
1130 ejtsl->printer_name = strdup(printer_name);
1131 if (!ejtsl->printer_name) {
1132 SAFE_FREE(ejtsl);
1133 return;
1135 DLIST_ADD(ejts_head, ejtsl);
1138 gettimeofday(&ejtsl->tv, NULL);
1141 static int timeval_diff(struct timeval *tv1, struct timeval *tv2)
1143 if (tv1->tv_sec > tv2->tv_sec)
1144 return 1;
1145 if (tv1->tv_sec < tv2->tv_sec)
1146 return -1;
1147 if (tv1->tv_usec > tv2->tv_usec)
1148 return 1;
1149 if (tv1->tv_usec < tv2->tv_usec)
1150 return -1;
1151 return 0;
1154 /********************************************************************
1155 Receive a notify2 message list
1156 ********************************************************************/
1158 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1160 size_t msg_count, i;
1161 char *buf = (char *)msg;
1162 char *msg_ptr;
1163 size_t msg_len;
1164 SPOOLSS_NOTIFY_MSG notify;
1165 SPOOLSS_NOTIFY_MSG_CTR messages;
1166 int num_groups;
1168 if (len < 4) {
1169 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1170 return;
1173 msg_count = IVAL(buf, 0);
1174 msg_ptr = buf + 4;
1176 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1178 if (msg_count == 0) {
1179 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1180 return;
1183 /* initialize the container */
1185 ZERO_STRUCT( messages );
1186 notify_msg_ctr_init( &messages );
1189 * build message groups for each printer identified
1190 * in a change_notify msg. Remember that a PCN message
1191 * includes the handle returned for the srv_spoolss_replyopenprinter()
1192 * call. Therefore messages are grouped according to printer handle.
1195 for ( i=0; i<msg_count; i++ ) {
1196 struct timeval msg_tv;
1198 if (msg_ptr + 4 - buf > len) {
1199 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1200 return;
1203 msg_len = IVAL(msg_ptr,0);
1204 msg_ptr += 4;
1206 if (msg_ptr + msg_len - buf > len) {
1207 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1208 return;
1211 /* unpack messages */
1213 ZERO_STRUCT( notify );
1214 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1215 msg_ptr += msg_len;
1217 /* See if it is still relevent. */
1218 if (notify.type == JOB_NOTIFY_TYPE) {
1219 BOOL status_is_deleting = False;
1221 if (notify.field == JOB_NOTIFY_STATUS && (notify.notify.value[0] & (JOB_STATUS_DELETING|JOB_STATUS_DELETED)))
1222 status_is_deleting = True;
1224 if (!status_is_deleting) {
1225 struct ejts_list *ejtsl = find_enumjobs_timestamp(notify.printer);
1227 if (ejtsl && (timeval_diff(&ejtsl->tv, &msg_tv) > 0)) {
1229 DEBUG(10, ("receive_notify2_message_list: enumjobs ts = %u, %u, msg ts = %u, %u discarding\n",
1230 (unsigned int)ejtsl->tv.tv_sec, (unsigned int)ejtsl->tv.tv_usec,
1231 (unsigned int)msg_tv.tv_sec, (unsigned int)msg_tv.tv_usec ));
1233 /* Message no longer relevent. Ignore it. */
1234 if ( notify.len != 0 )
1235 SAFE_FREE( notify.notify.data );
1236 continue;
1240 /* add to correct list in container */
1242 notify_msg_ctr_addmsg( &messages, &notify );
1244 /* free memory that might have been allocated by notify2_unpack_msg() */
1246 if ( notify.len != 0 )
1247 SAFE_FREE( notify.notify.data );
1250 /* process each group of messages */
1252 num_groups = notify_msg_ctr_numgroups( &messages );
1253 for ( i=0; i<num_groups; i++ )
1254 send_notify2_changes( &messages, i );
1257 /* cleanup */
1259 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1261 notify_msg_ctr_destroy( &messages );
1263 return;
1266 /********************************************************************
1267 Send a message to ourself about new driver being installed
1268 so we can upgrade the information for each printer bound to this
1269 driver
1270 ********************************************************************/
1272 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1274 int len = strlen(drivername);
1276 if (!len)
1277 return False;
1279 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1280 drivername));
1282 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1284 return True;
1287 /**********************************************************************
1288 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1289 over all printers, upgrading ones as necessary
1290 **********************************************************************/
1292 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1294 fstring drivername;
1295 int snum;
1296 int n_services = lp_numservices();
1298 len = MIN(len,sizeof(drivername)-1);
1299 strncpy(drivername, buf, len);
1301 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1303 /* Iterate the printer list */
1305 for (snum=0; snum<n_services; snum++)
1307 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1309 WERROR result;
1310 NT_PRINTER_INFO_LEVEL *printer = NULL;
1312 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1313 if (!W_ERROR_IS_OK(result))
1314 continue;
1316 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1318 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1320 /* all we care about currently is the change_id */
1322 result = mod_a_printer(*printer, 2);
1323 if (!W_ERROR_IS_OK(result)) {
1324 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1325 dos_errstr(result)));
1329 free_a_printer(&printer, 2);
1333 /* all done */
1336 /********************************************************************
1337 Update the cache for all printq's with a registered client
1338 connection
1339 ********************************************************************/
1341 void update_monitored_printq_cache( void )
1343 Printer_entry *printer = printers_list;
1344 int snum;
1346 /* loop through all printers and update the cache where
1347 client_connected == True */
1348 while ( printer )
1350 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1351 && printer->notify.client_connected )
1353 snum = print_queue_snum(printer->dev.handlename);
1354 print_queue_status( snum, NULL, NULL );
1357 printer = printer->next;
1360 return;
1362 /********************************************************************
1363 Send a message to ourself about new driver being installed
1364 so we can upgrade the information for each printer bound to this
1365 driver
1366 ********************************************************************/
1368 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1370 int len = strlen(drivername);
1372 if (!len)
1373 return False;
1375 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1376 drivername));
1378 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1380 return True;
1383 /**********************************************************************
1384 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1385 over all printers, resetting printer data as neessary
1386 **********************************************************************/
1388 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1390 fstring drivername;
1391 int snum;
1392 int n_services = lp_numservices();
1394 len = MIN( len, sizeof(drivername)-1 );
1395 strncpy( drivername, buf, len );
1397 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1399 /* Iterate the printer list */
1401 for ( snum=0; snum<n_services; snum++ )
1403 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1405 WERROR result;
1406 NT_PRINTER_INFO_LEVEL *printer = NULL;
1408 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1409 if ( !W_ERROR_IS_OK(result) )
1410 continue;
1413 * if the printer is bound to the driver,
1414 * then reset to the new driver initdata
1417 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1419 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1421 if ( !set_driver_init(printer, 2) ) {
1422 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1423 printer->info_2->printername, printer->info_2->drivername));
1426 result = mod_a_printer( *printer, 2 );
1427 if ( !W_ERROR_IS_OK(result) ) {
1428 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1429 get_dos_error_msg(result)));
1433 free_a_printer( &printer, 2 );
1437 /* all done */
1439 return;
1442 /********************************************************************
1443 Copy routines used by convert_to_openprinterex()
1444 *******************************************************************/
1446 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1448 DEVICEMODE *d;
1449 int len;
1451 if (!devmode)
1452 return NULL;
1454 DEBUG (8,("dup_devmode\n"));
1456 /* bulk copy first */
1458 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1459 if (!d)
1460 return NULL;
1462 /* dup the pointer members separately */
1464 len = unistrlen(devmode->devicename.buffer);
1465 if (len != -1) {
1466 d->devicename.buffer = talloc(ctx, len*2);
1467 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1468 return NULL;
1472 len = unistrlen(devmode->formname.buffer);
1473 if (len != -1) {
1474 d->devicename.buffer = talloc(ctx, len*2);
1475 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1476 return NULL;
1479 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1481 return d;
1484 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1486 if (!new_ctr || !ctr)
1487 return;
1489 DEBUG(8,("copy_devmode_ctr\n"));
1491 new_ctr->size = ctr->size;
1492 new_ctr->devmode_ptr = ctr->devmode_ptr;
1494 if(ctr->devmode_ptr)
1495 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1498 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1500 if (!new_def || !def)
1501 return;
1503 DEBUG(8,("copy_printer_defaults\n"));
1505 new_def->datatype_ptr = def->datatype_ptr;
1507 if (def->datatype_ptr)
1508 copy_unistr2(&new_def->datatype, &def->datatype);
1510 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1512 new_def->access_required = def->access_required;
1515 /********************************************************************
1516 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1517 * SPOOL_Q_OPEN_PRINTER_EX structure
1518 ********************************************************************/
1520 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1522 if (!q_u_ex || !q_u)
1523 return;
1525 DEBUG(8,("convert_to_openprinterex\n"));
1527 q_u_ex->printername_ptr = q_u->printername_ptr;
1529 if (q_u->printername_ptr)
1530 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1532 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1535 /********************************************************************
1536 * spoolss_open_printer
1538 * called from the spoolss dispatcher
1539 ********************************************************************/
1541 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1543 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1544 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1546 if (!q_u || !r_u)
1547 return WERR_NOMEM;
1549 ZERO_STRUCT(q_u_ex);
1550 ZERO_STRUCT(r_u_ex);
1552 /* convert the OpenPrinter() call to OpenPrinterEx() */
1554 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1556 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1558 /* convert back to OpenPrinter() */
1560 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1562 return r_u->status;
1565 /********************************************************************
1566 * spoolss_open_printer
1568 * If the openprinterex rpc call contains a devmode,
1569 * it's a per-user one. This per-user devmode is derivated
1570 * from the global devmode. Openprinterex() contains a per-user
1571 * devmode for when you do EMF printing and spooling.
1572 * In the EMF case, the NT workstation is only doing half the job
1573 * of rendering the page. The other half is done by running the printer
1574 * driver on the server.
1575 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1576 * The EMF file only contains what is to be printed on the page.
1577 * So in order for the server to know how to print, the NT client sends
1578 * a devicemode attached to the openprinterex call.
1579 * But this devicemode is short lived, it's only valid for the current print job.
1581 * If Samba would have supported EMF spooling, this devicemode would
1582 * have been attached to the handle, to sent it to the driver to correctly
1583 * rasterize the EMF file.
1585 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1586 * we just act as a pass-thru between windows and the printer.
1588 * In order to know that Samba supports only RAW spooling, NT has to call
1589 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1590 * and until NT sends a RAW job, we refuse it.
1592 * But to call getprinter() or startdoc(), you first need a valid handle,
1593 * and to get an handle you have to call openprintex(). Hence why you have
1594 * a devicemode in the openprinterex() call.
1597 * Differences between NT4 and NT 2000.
1598 * NT4:
1599 * ---
1600 * On NT4, you only have a global devicemode. This global devicemode can be changed
1601 * by the administrator (or by a user with enough privs). Everytime a user
1602 * wants to print, the devicemode is resetted to the default. In Word, everytime
1603 * you print, the printer's characteristics are always reset to the global devicemode.
1605 * NT 2000:
1606 * -------
1607 * In W2K, there is the notion of per-user devicemode. The first time you use
1608 * a printer, a per-user devicemode is build from the global devicemode.
1609 * If you change your per-user devicemode, it is saved in the registry, under the
1610 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1611 * printer preferences available.
1613 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1614 * on the General Tab of the printer properties windows.
1616 * To change the global devicemode: it's the "Printing Defaults..." button
1617 * on the Advanced Tab of the printer properties window.
1619 * JFM.
1620 ********************************************************************/
1622 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1624 UNISTR2 *printername = NULL;
1625 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1626 POLICY_HND *handle = &r_u->handle;
1628 fstring name;
1629 int snum;
1630 struct current_user user;
1631 Printer_entry *Printer=NULL;
1633 if (q_u->printername_ptr != 0)
1634 printername = &q_u->printername;
1636 if (printername == NULL)
1637 return WERR_INVALID_PRINTER_NAME;
1639 /* some sanity check because you can open a printer or a print server */
1640 /* aka: \\server\printer or \\server */
1641 unistr2_to_ascii(name, printername, sizeof(name)-1);
1643 DEBUGADD(3,("checking name: %s\n",name));
1645 if (!open_printer_hnd(p, handle, name, 0))
1646 return WERR_INVALID_PRINTER_NAME;
1648 Printer=find_printer_index_by_hnd(p, handle);
1649 if (!Printer) {
1650 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1651 Can't find printer handle we created for printer %s\n", name ));
1652 close_printer_handle(p,handle);
1653 return WERR_INVALID_PRINTER_NAME;
1656 get_current_user(&user, p);
1659 * First case: the user is opening the print server:
1661 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1662 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1664 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1665 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1666 * or if the user is listed in the smb.conf printer admin parameter.
1668 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1669 * client view printer folder, but does not show the MSAPW.
1671 * Note: this test needs code to check access rights here too. Jeremy
1672 * could you look at this?
1674 * Second case: the user is opening a printer:
1675 * NT doesn't let us connect to a printer if the connecting user
1676 * doesn't have print permission.
1679 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1681 /* Printserver handles use global struct... */
1683 snum = -1;
1685 /* Map standard access rights to object specific access rights */
1687 se_map_standard(&printer_default->access_required,
1688 &printserver_std_mapping);
1690 /* Deny any object specific bits that don't apply to print
1691 servers (i.e printer and job specific bits) */
1693 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1695 if (printer_default->access_required &
1696 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1697 DEBUG(3, ("access DENIED for non-printserver bits"));
1698 close_printer_handle(p, handle);
1699 return WERR_ACCESS_DENIED;
1702 /* Allow admin access */
1704 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1706 if (!lp_ms_add_printer_wizard()) {
1707 close_printer_handle(p, handle);
1708 return WERR_ACCESS_DENIED;
1711 /* if the user is not root and not a printer admin, then fail */
1713 if ( user.uid != 0
1714 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1716 close_printer_handle(p, handle);
1717 return WERR_ACCESS_DENIED;
1720 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1722 else
1724 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1727 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1728 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1730 /* We fall through to return WERR_OK */
1733 else
1735 /* NT doesn't let us connect to a printer if the connecting user
1736 doesn't have print permission. */
1738 if (!get_printer_snum(p, handle, &snum)) {
1739 close_printer_handle(p, handle);
1740 return WERR_BADFID;
1743 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1745 /* map an empty access mask to the minimum access mask */
1746 if (printer_default->access_required == 0x0)
1747 printer_default->access_required = PRINTER_ACCESS_USE;
1750 * If we are not serving the printer driver for this printer,
1751 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1752 * will keep NT clients happy --jerry
1755 if (lp_use_client_driver(snum)
1756 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1758 printer_default->access_required = PRINTER_ACCESS_USE;
1761 /* check smb.conf parameters and the the sec_desc */
1763 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1764 DEBUG(3, ("access DENIED for printer open\n"));
1765 close_printer_handle(p, handle);
1766 return WERR_ACCESS_DENIED;
1769 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1770 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1771 close_printer_handle(p, handle);
1772 return WERR_ACCESS_DENIED;
1775 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1776 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1777 else
1778 printer_default->access_required = PRINTER_ACCESS_USE;
1780 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1781 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1785 Printer->access_granted = printer_default->access_required;
1788 * If the client sent a devmode in the OpenPrinter() call, then
1789 * save it here in case we get a job submission on this handle
1792 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1793 && q_u->printer_default.devmode_cont.devmode_ptr )
1795 convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
1796 &Printer->nt_devmode );
1799 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1800 optimization in Windows 2000 clients --jerry */
1802 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1803 && (RA_WIN2K == get_remote_arch()) )
1805 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1806 sys_usleep( 500000 );
1809 return WERR_OK;
1812 /****************************************************************************
1813 ****************************************************************************/
1815 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1816 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1818 BOOL ret = True;
1820 switch (level) {
1821 case 2:
1822 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1823 break;
1824 default:
1825 break;
1828 return ret;
1831 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1832 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1834 BOOL result = True;
1836 switch (level) {
1837 case 3:
1838 printer->info_3=NULL;
1839 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1840 result = False;
1841 break;
1842 case 6:
1843 printer->info_6=NULL;
1844 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1845 result = False;
1846 break;
1847 default:
1848 break;
1851 return result;
1854 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1855 NT_DEVICEMODE **pp_nt_devmode)
1857 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1860 * Ensure nt_devmode is a valid pointer
1861 * as we will be overwriting it.
1864 if (nt_devmode == NULL) {
1865 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1866 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1867 return False;
1870 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1871 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1873 nt_devmode->specversion=devmode->specversion;
1874 nt_devmode->driverversion=devmode->driverversion;
1875 nt_devmode->size=devmode->size;
1876 nt_devmode->fields=devmode->fields;
1877 nt_devmode->orientation=devmode->orientation;
1878 nt_devmode->papersize=devmode->papersize;
1879 nt_devmode->paperlength=devmode->paperlength;
1880 nt_devmode->paperwidth=devmode->paperwidth;
1881 nt_devmode->scale=devmode->scale;
1882 nt_devmode->copies=devmode->copies;
1883 nt_devmode->defaultsource=devmode->defaultsource;
1884 nt_devmode->printquality=devmode->printquality;
1885 nt_devmode->color=devmode->color;
1886 nt_devmode->duplex=devmode->duplex;
1887 nt_devmode->yresolution=devmode->yresolution;
1888 nt_devmode->ttoption=devmode->ttoption;
1889 nt_devmode->collate=devmode->collate;
1891 nt_devmode->logpixels=devmode->logpixels;
1892 nt_devmode->bitsperpel=devmode->bitsperpel;
1893 nt_devmode->pelswidth=devmode->pelswidth;
1894 nt_devmode->pelsheight=devmode->pelsheight;
1895 nt_devmode->displayflags=devmode->displayflags;
1896 nt_devmode->displayfrequency=devmode->displayfrequency;
1897 nt_devmode->icmmethod=devmode->icmmethod;
1898 nt_devmode->icmintent=devmode->icmintent;
1899 nt_devmode->mediatype=devmode->mediatype;
1900 nt_devmode->dithertype=devmode->dithertype;
1901 nt_devmode->reserved1=devmode->reserved1;
1902 nt_devmode->reserved2=devmode->reserved2;
1903 nt_devmode->panningwidth=devmode->panningwidth;
1904 nt_devmode->panningheight=devmode->panningheight;
1907 * Only change private and driverextra if the incoming devmode
1908 * has a new one. JRA.
1911 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1912 SAFE_FREE(nt_devmode->private);
1913 nt_devmode->driverextra=devmode->driverextra;
1914 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1915 return False;
1916 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1919 *pp_nt_devmode = nt_devmode;
1921 return True;
1924 /********************************************************************
1925 * _spoolss_enddocprinter_internal.
1926 ********************************************************************/
1928 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1930 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1931 int snum;
1933 if (!Printer) {
1934 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1935 return WERR_BADFID;
1938 if (!get_printer_snum(p, handle, &snum))
1939 return WERR_BADFID;
1941 Printer->document_started=False;
1942 print_job_end(snum, Printer->jobid,True);
1943 /* error codes unhandled so far ... */
1945 return WERR_OK;
1948 /********************************************************************
1949 * api_spoolss_closeprinter
1950 ********************************************************************/
1952 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1954 POLICY_HND *handle = &q_u->handle;
1956 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1958 if (Printer && Printer->document_started)
1959 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1961 if (!close_printer_handle(p, handle))
1962 return WERR_BADFID;
1964 /* clear the returned printer handle. Observed behavior
1965 from Win2k server. Don't think this really matters.
1966 Previous code just copied the value of the closed
1967 handle. --jerry */
1969 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1971 return WERR_OK;
1974 /********************************************************************
1975 * api_spoolss_deleteprinter
1977 ********************************************************************/
1979 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1981 POLICY_HND *handle = &q_u->handle;
1982 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1983 WERROR result;
1985 if (Printer && Printer->document_started)
1986 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1988 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1990 result = delete_printer_handle(p, handle);
1992 update_c_setprinter(False);
1994 return result;
1997 /*******************************************************************
1998 * static function to lookup the version id corresponding to an
1999 * long architecture string
2000 ******************************************************************/
2002 static int get_version_id (char * arch)
2004 int i;
2005 struct table_node archi_table[]= {
2007 {"Windows 4.0", "WIN40", 0 },
2008 {"Windows NT x86", "W32X86", 2 },
2009 {"Windows NT R4000", "W32MIPS", 2 },
2010 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2011 {"Windows NT PowerPC", "W32PPC", 2 },
2012 {NULL, "", -1 }
2015 for (i=0; archi_table[i].long_archi != NULL; i++)
2017 if (strcmp(arch, archi_table[i].long_archi) == 0)
2018 return (archi_table[i].version);
2021 return -1;
2024 /********************************************************************
2025 * _spoolss_deleteprinterdriver
2026 ********************************************************************/
2028 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2030 fstring driver;
2031 fstring arch;
2032 NT_PRINTER_DRIVER_INFO_LEVEL info;
2033 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2034 int version;
2035 struct current_user user;
2036 WERROR status;
2037 WERROR status_win2k = WERR_ACCESS_DENIED;
2039 get_current_user(&user, p);
2041 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2042 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2044 /* check that we have a valid driver name first */
2046 if ((version=get_version_id(arch)) == -1)
2047 return WERR_INVALID_ENVIRONMENT;
2049 ZERO_STRUCT(info);
2050 ZERO_STRUCT(info_win2k);
2052 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2054 /* try for Win2k driver if "Windows NT x86" */
2056 if ( version == 2 ) {
2057 version = 3;
2058 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2059 status = WERR_UNKNOWN_PRINTER_DRIVER;
2060 goto done;
2063 /* otherwise it was a failure */
2064 else {
2065 status = WERR_UNKNOWN_PRINTER_DRIVER;
2066 goto done;
2071 if (printer_driver_in_use(info.info_3)) {
2072 status = WERR_PRINTER_DRIVER_IN_USE;
2073 goto done;
2076 if ( version == 2 )
2078 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2080 /* if we get to here, we now have 2 driver info structures to remove */
2081 /* remove the Win2k driver first*/
2083 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2084 free_a_printer_driver( info_win2k, 3 );
2086 /* this should not have failed---if it did, report to client */
2087 if ( !W_ERROR_IS_OK(status_win2k) )
2088 goto done;
2092 status = delete_printer_driver(info.info_3, &user, version, False);
2094 /* if at least one of the deletes succeeded return OK */
2096 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2097 status = WERR_OK;
2099 done:
2100 free_a_printer_driver( info, 3 );
2102 return status;
2105 /********************************************************************
2106 * spoolss_deleteprinterdriverex
2107 ********************************************************************/
2109 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2111 fstring driver;
2112 fstring arch;
2113 NT_PRINTER_DRIVER_INFO_LEVEL info;
2114 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2115 int version;
2116 uint32 flags = q_u->delete_flags;
2117 BOOL delete_files;
2118 struct current_user user;
2119 WERROR status;
2120 WERROR status_win2k = WERR_ACCESS_DENIED;
2122 get_current_user(&user, p);
2124 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2125 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2127 /* check that we have a valid driver name first */
2128 if ((version=get_version_id(arch)) == -1) {
2129 /* this is what NT returns */
2130 return WERR_INVALID_ENVIRONMENT;
2133 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2134 version = q_u->version;
2136 ZERO_STRUCT(info);
2137 ZERO_STRUCT(info_win2k);
2139 status = get_a_printer_driver(&info, 3, driver, arch, version);
2141 if ( !W_ERROR_IS_OK(status) )
2144 * if the client asked for a specific version,
2145 * or this is something other than Windows NT x86,
2146 * then we've failed
2149 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2150 goto done;
2152 /* try for Win2k driver if "Windows NT x86" */
2154 version = 3;
2155 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2156 status = WERR_UNKNOWN_PRINTER_DRIVER;
2157 goto done;
2161 if ( printer_driver_in_use(info.info_3) ) {
2162 status = WERR_PRINTER_DRIVER_IN_USE;
2163 goto done;
2167 * we have a couple of cases to consider.
2168 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2169 * then the delete should fail if **any** files overlap with
2170 * other drivers
2171 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2172 * non-overlapping files
2173 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2174 * is set, the do not delete any files
2175 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2178 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2180 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2182 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2183 /* no idea of the correct error here */
2184 status = WERR_ACCESS_DENIED;
2185 goto done;
2189 /* also check for W32X86/3 if necessary; maybe we already have? */
2191 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2192 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2195 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2196 /* no idea of the correct error here */
2197 free_a_printer_driver( info_win2k, 3 );
2198 status = WERR_ACCESS_DENIED;
2199 goto done;
2202 /* if we get to here, we now have 2 driver info structures to remove */
2203 /* remove the Win2k driver first*/
2205 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2206 free_a_printer_driver( info_win2k, 3 );
2208 /* this should not have failed---if it did, report to client */
2210 if ( !W_ERROR_IS_OK(status_win2k) )
2211 goto done;
2215 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2217 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2218 status = WERR_OK;
2219 done:
2220 free_a_printer_driver( info, 3 );
2222 return status;
2226 /****************************************************************************
2227 Internal routine for retreiving printerdata
2228 ***************************************************************************/
2230 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2231 const char *key, const char *value, uint32 *type, uint8 **data,
2232 uint32 *needed, uint32 in_size )
2234 REGISTRY_VALUE *val;
2235 int size, data_len;
2237 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2238 return WERR_BADFILE;
2240 *type = regval_type( val );
2242 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2244 size = regval_size( val );
2246 /* copy the min(in_size, len) */
2248 if ( in_size ) {
2249 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2251 /* special case for 0 length values */
2252 if ( data_len ) {
2253 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2254 return WERR_NOMEM;
2256 else {
2257 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2258 return WERR_NOMEM;
2261 else
2262 *data = NULL;
2264 *needed = size;
2266 DEBUG(5,("get_printer_dataex: copy done\n"));
2268 return WERR_OK;
2271 /****************************************************************************
2272 Internal routine for removing printerdata
2273 ***************************************************************************/
2275 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2277 return delete_printer_data( printer->info_2, key, value );
2280 /****************************************************************************
2281 Internal routine for storing printerdata
2282 ***************************************************************************/
2284 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2285 uint32 type, uint8 *data, int real_len )
2287 delete_printer_data( printer->info_2, key, value );
2289 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2292 /********************************************************************
2293 GetPrinterData on a printer server Handle.
2294 ********************************************************************/
2296 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2298 int i;
2300 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2302 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2303 *type = 0x4;
2304 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2305 return WERR_NOMEM;
2306 *needed = 0x4;
2307 return WERR_OK;
2310 if (!StrCaseCmp(value, "BeepEnabled")) {
2311 *type = 0x4;
2312 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2313 return WERR_NOMEM;
2314 SIVAL(*data, 0, 0x00);
2315 *needed = 0x4;
2316 return WERR_OK;
2319 if (!StrCaseCmp(value, "EventLog")) {
2320 *type = 0x4;
2321 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2322 return WERR_NOMEM;
2323 /* formally was 0x1b */
2324 SIVAL(*data, 0, 0x0);
2325 *needed = 0x4;
2326 return WERR_OK;
2329 if (!StrCaseCmp(value, "NetPopup")) {
2330 *type = 0x4;
2331 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2332 return WERR_NOMEM;
2333 SIVAL(*data, 0, 0x00);
2334 *needed = 0x4;
2335 return WERR_OK;
2338 if (!StrCaseCmp(value, "MajorVersion")) {
2339 *type = 0x4;
2340 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2341 return WERR_NOMEM;
2343 /* Windows NT 4.0 seems to not allow uploading of drivers
2344 to a server that reports 0x3 as the MajorVersion.
2345 need to investigate more how Win2k gets around this .
2346 -- jerry */
2348 if ( RA_WINNT == get_remote_arch() )
2349 SIVAL(*data, 0, 2);
2350 else
2351 SIVAL(*data, 0, 3);
2353 *needed = 0x4;
2354 return WERR_OK;
2357 if (!StrCaseCmp(value, "MinorVersion")) {
2358 *type = 0x4;
2359 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2360 return WERR_NOMEM;
2361 SIVAL(*data, 0, 0);
2362 *needed = 0x4;
2363 return WERR_OK;
2366 /* REG_BINARY
2367 * uint32 size = 0x114
2368 * uint32 major = 5
2369 * uint32 minor = [0|1]
2370 * uint32 build = [2195|2600]
2371 * extra unicode string = e.g. "Service Pack 3"
2373 if (!StrCaseCmp(value, "OSVersion")) {
2374 *type = 0x3;
2375 *needed = 0x114;
2377 if((*data = (uint8 *)talloc(ctx, (*needed)*sizeof(uint8) )) == NULL)
2378 return WERR_NOMEM;
2379 ZERO_STRUCTP( *data );
2381 SIVAL(*data, 0, *needed); /* size */
2382 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2383 SIVAL(*data, 8, 0);
2384 SIVAL(*data, 12, 2195); /* build */
2386 /* leave extra string empty */
2388 return WERR_OK;
2392 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2393 const char *string="C:\\PRINTERS";
2394 *type = 0x1;
2395 *needed = 2*(strlen(string)+1);
2396 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2397 return WERR_NOMEM;
2398 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2400 /* it's done by hand ready to go on the wire */
2401 for (i=0; i<strlen(string); i++) {
2402 (*data)[2*i]=string[i];
2403 (*data)[2*i+1]='\0';
2405 return WERR_OK;
2408 if (!StrCaseCmp(value, "Architecture")) {
2409 const char *string="Windows NT x86";
2410 *type = 0x1;
2411 *needed = 2*(strlen(string)+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(string); i++) {
2416 (*data)[2*i]=string[i];
2417 (*data)[2*i+1]='\0';
2419 return WERR_OK;
2422 if (!StrCaseCmp(value, "DsPresent")) {
2423 *type = 0x4;
2424 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2425 return WERR_NOMEM;
2426 SIVAL(*data, 0, 0x01);
2427 *needed = 0x4;
2428 return WERR_OK;
2431 if (!StrCaseCmp(value, "DNSMachineName")) {
2432 pstring hostname;
2434 if (!get_myfullname(hostname))
2435 return WERR_BADFILE;
2436 *type = 0x1;
2437 *needed = 2*(strlen(hostname)+1);
2438 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2439 return WERR_NOMEM;
2440 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2441 for (i=0; i<strlen(hostname); i++) {
2442 (*data)[2*i]=hostname[i];
2443 (*data)[2*i+1]='\0';
2445 return WERR_OK;
2449 return WERR_BADFILE;
2452 /********************************************************************
2453 * spoolss_getprinterdata
2454 ********************************************************************/
2456 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2458 POLICY_HND *handle = &q_u->handle;
2459 UNISTR2 *valuename = &q_u->valuename;
2460 uint32 in_size = q_u->size;
2461 uint32 *type = &r_u->type;
2462 uint32 *out_size = &r_u->size;
2463 uint8 **data = &r_u->data;
2464 uint32 *needed = &r_u->needed;
2465 WERROR status;
2466 fstring value;
2467 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2468 NT_PRINTER_INFO_LEVEL *printer = NULL;
2469 int snum = 0;
2472 * Reminder: when it's a string, the length is in BYTES
2473 * even if UNICODE is negociated.
2475 * JFM, 4/19/1999
2478 *out_size = in_size;
2480 /* in case of problem, return some default values */
2482 *needed = 0;
2483 *type = 0;
2485 DEBUG(4,("_spoolss_getprinterdata\n"));
2487 if ( !Printer ) {
2488 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2489 status = WERR_BADFID;
2490 goto done;
2493 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2495 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2496 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2497 else
2499 if ( !get_printer_snum(p,handle, &snum) ) {
2500 status = WERR_BADFID;
2501 goto done;
2504 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2505 if ( !W_ERROR_IS_OK(status) )
2506 goto done;
2508 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2510 if ( strequal(value, "ChangeId") ) {
2511 *type = REG_DWORD;
2512 *needed = sizeof(uint32);
2513 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2514 status = WERR_NOMEM;
2515 goto done;
2517 SIVAL( *data, 0, printer->info_2->changeid );
2518 status = WERR_OK;
2520 else
2521 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2524 if (*needed > *out_size)
2525 status = WERR_MORE_DATA;
2527 done:
2528 if ( !W_ERROR_IS_OK(status) )
2530 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2532 /* reply this param doesn't exist */
2534 if ( *out_size ) {
2535 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2536 if ( printer )
2537 free_a_printer( &printer, 2 );
2538 return WERR_NOMEM;
2541 else {
2542 *data = NULL;
2546 /* cleanup & exit */
2548 if ( printer )
2549 free_a_printer( &printer, 2 );
2551 return status;
2554 /*********************************************************
2555 Connect to the client machine.
2556 **********************************************************/
2558 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2559 struct in_addr *client_ip, const char *remote_machine)
2561 ZERO_STRUCTP(the_cli);
2563 if(cli_initialise(the_cli) == NULL) {
2564 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2565 return False;
2568 if ( is_zero_ip(*client_ip) ) {
2569 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2570 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2571 cli_shutdown(the_cli);
2572 return False;
2575 if (ismyip(the_cli->dest_ip)) {
2576 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2577 cli_shutdown(the_cli);
2578 return False;
2581 else {
2582 the_cli->dest_ip.s_addr = client_ip->s_addr;
2583 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2584 inet_ntoa(*client_ip) ));
2587 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2588 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) ));
2589 cli_shutdown(the_cli);
2590 return False;
2593 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2594 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2595 remote_machine));
2596 cli_shutdown(the_cli);
2597 return False;
2600 the_cli->protocol = PROTOCOL_NT1;
2601 cli_setup_signing_state(the_cli, lp_client_signing());
2603 if (!cli_negprot(the_cli)) {
2604 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2605 cli_shutdown(the_cli);
2606 return False;
2609 if (the_cli->protocol != PROTOCOL_NT1) {
2610 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2611 cli_shutdown(the_cli);
2612 return False;
2616 * Do an anonymous session setup.
2619 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2620 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2621 cli_shutdown(the_cli);
2622 return False;
2625 if (!(the_cli->sec_mode & 1)) {
2626 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2627 cli_shutdown(the_cli);
2628 return False;
2631 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2632 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) ));
2633 cli_shutdown(the_cli);
2634 return False;
2638 * Ok - we have an anonymous connection to the IPC$ share.
2639 * Now start the NT Domain stuff :-).
2642 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2643 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)));
2644 cli_nt_session_close(the_cli);
2645 cli_ulogoff(the_cli);
2646 cli_shutdown(the_cli);
2647 return False;
2650 return True;
2653 /***************************************************************************
2654 Connect to the client.
2655 ****************************************************************************/
2657 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2658 uint32 localprinter, uint32 type,
2659 POLICY_HND *handle, struct in_addr *client_ip)
2661 WERROR result;
2664 * If it's the first connection, contact the client
2665 * and connect to the IPC$ share anonymously
2667 if (smb_connections==0) {
2668 fstring unix_printer;
2670 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2672 ZERO_STRUCT(notify_cli);
2674 if(!spoolss_connect_to_client(&notify_cli, client_ip, unix_printer))
2675 return False;
2677 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2678 /* Tell the connections db we're now interested in printer
2679 * notify messages. */
2680 register_message_flags( True, FLAG_MSG_PRINTING );
2684 * Tell the specific printing tdb we want messages for this printer
2685 * by registering our PID.
2688 if (!print_notify_register_pid(snum))
2689 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2691 smb_connections++;
2693 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2694 type, handle);
2696 if (!W_ERROR_IS_OK(result))
2697 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2698 dos_errstr(result)));
2700 return (W_ERROR_IS_OK(result));
2703 /********************************************************************
2704 * _spoolss_rffpcnex
2705 * ReplyFindFirstPrinterChangeNotifyEx
2707 * before replying OK: status=0 a rpc call is made to the workstation
2708 * asking ReplyOpenPrinter
2710 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2711 * called from api_spoolss_rffpcnex
2712 ********************************************************************/
2714 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2716 POLICY_HND *handle = &q_u->handle;
2717 uint32 flags = q_u->flags;
2718 uint32 options = q_u->options;
2719 UNISTR2 *localmachine = &q_u->localmachine;
2720 uint32 printerlocal = q_u->printerlocal;
2721 int snum = -1;
2722 SPOOL_NOTIFY_OPTION *option = q_u->option;
2723 struct in_addr client_ip;
2725 /* store the notify value in the printer struct */
2727 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2729 if (!Printer) {
2730 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2731 return WERR_BADFID;
2734 Printer->notify.flags=flags;
2735 Printer->notify.options=options;
2736 Printer->notify.printerlocal=printerlocal;
2738 if (Printer->notify.option)
2739 free_spool_notify_option(&Printer->notify.option);
2741 Printer->notify.option=dup_spool_notify_option(option);
2743 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2744 sizeof(Printer->notify.localmachine)-1);
2746 /* Connect to the client machine and send a ReplyOpenPrinter */
2748 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2749 snum = -1;
2750 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2751 !get_printer_snum(p, handle, &snum) )
2752 return WERR_BADFID;
2754 client_ip.s_addr = inet_addr(p->conn->client_address);
2756 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2757 Printer->notify.printerlocal, 1,
2758 &Printer->notify.client_hnd, &client_ip))
2759 return WERR_SERVER_UNAVAILABLE;
2761 Printer->notify.client_connected=True;
2763 return WERR_OK;
2766 /*******************************************************************
2767 * fill a notify_info_data with the servername
2768 ********************************************************************/
2770 void spoolss_notify_server_name(int snum,
2771 SPOOL_NOTIFY_INFO_DATA *data,
2772 print_queue_struct *queue,
2773 NT_PRINTER_INFO_LEVEL *printer,
2774 TALLOC_CTX *mem_ctx)
2776 pstring temp_name, temp;
2777 uint32 len;
2779 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2781 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2783 data->notify_data.data.length = len;
2784 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2786 if (!data->notify_data.data.string) {
2787 data->notify_data.data.length = 0;
2788 return;
2791 memcpy(data->notify_data.data.string, temp, len);
2794 /*******************************************************************
2795 * fill a notify_info_data with the printername (not including the servername).
2796 ********************************************************************/
2798 void spoolss_notify_printer_name(int snum,
2799 SPOOL_NOTIFY_INFO_DATA *data,
2800 print_queue_struct *queue,
2801 NT_PRINTER_INFO_LEVEL *printer,
2802 TALLOC_CTX *mem_ctx)
2804 pstring temp;
2805 uint32 len;
2807 /* the notify name should not contain the \\server\ part */
2808 char *p = strrchr(printer->info_2->printername, '\\');
2810 if (!p) {
2811 p = printer->info_2->printername;
2812 } else {
2813 p++;
2816 len = rpcstr_push(temp, p, 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 servicename
2831 ********************************************************************/
2833 void spoolss_notify_share_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 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2844 data->notify_data.data.length = len;
2845 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2847 if (!data->notify_data.data.string) {
2848 data->notify_data.data.length = 0;
2849 return;
2852 memcpy(data->notify_data.data.string, temp, len);
2855 /*******************************************************************
2856 * fill a notify_info_data with the port name
2857 ********************************************************************/
2859 void spoolss_notify_port_name(int snum,
2860 SPOOL_NOTIFY_INFO_DATA *data,
2861 print_queue_struct *queue,
2862 NT_PRINTER_INFO_LEVEL *printer,
2863 TALLOC_CTX *mem_ctx)
2865 pstring temp;
2866 uint32 len;
2868 /* even if it's strange, that's consistant in all the code */
2870 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2872 data->notify_data.data.length = len;
2873 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2875 if (!data->notify_data.data.string) {
2876 data->notify_data.data.length = 0;
2877 return;
2880 memcpy(data->notify_data.data.string, temp, len);
2883 /*******************************************************************
2884 * fill a notify_info_data with the printername
2885 * but it doesn't exist, have to see what to do
2886 ********************************************************************/
2888 void spoolss_notify_driver_name(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 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2899 data->notify_data.data.length = len;
2900 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2902 if (!data->notify_data.data.string) {
2903 data->notify_data.data.length = 0;
2904 return;
2907 memcpy(data->notify_data.data.string, temp, len);
2910 /*******************************************************************
2911 * fill a notify_info_data with the comment
2912 ********************************************************************/
2914 void spoolss_notify_comment(int snum,
2915 SPOOL_NOTIFY_INFO_DATA *data,
2916 print_queue_struct *queue,
2917 NT_PRINTER_INFO_LEVEL *printer,
2918 TALLOC_CTX *mem_ctx)
2920 pstring temp;
2921 uint32 len;
2923 if (*printer->info_2->comment == '\0')
2924 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2925 else
2926 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2928 data->notify_data.data.length = len;
2929 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2931 if (!data->notify_data.data.string) {
2932 data->notify_data.data.length = 0;
2933 return;
2936 memcpy(data->notify_data.data.string, temp, len);
2939 /*******************************************************************
2940 * fill a notify_info_data with the comment
2941 * location = "Room 1, floor 2, building 3"
2942 ********************************************************************/
2944 void spoolss_notify_location(int snum,
2945 SPOOL_NOTIFY_INFO_DATA *data,
2946 print_queue_struct *queue,
2947 NT_PRINTER_INFO_LEVEL *printer,
2948 TALLOC_CTX *mem_ctx)
2950 pstring temp;
2951 uint32 len;
2953 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2955 data->notify_data.data.length = len;
2956 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2958 if (!data->notify_data.data.string) {
2959 data->notify_data.data.length = 0;
2960 return;
2963 memcpy(data->notify_data.data.string, temp, len);
2966 /*******************************************************************
2967 * fill a notify_info_data with the device mode
2968 * jfm:xxxx don't to it for know but that's a real problem !!!
2969 ********************************************************************/
2971 static void spoolss_notify_devmode(int snum,
2972 SPOOL_NOTIFY_INFO_DATA *data,
2973 print_queue_struct *queue,
2974 NT_PRINTER_INFO_LEVEL *printer,
2975 TALLOC_CTX *mem_ctx)
2979 /*******************************************************************
2980 * fill a notify_info_data with the separator file name
2981 ********************************************************************/
2983 void spoolss_notify_sepfile(int snum,
2984 SPOOL_NOTIFY_INFO_DATA *data,
2985 print_queue_struct *queue,
2986 NT_PRINTER_INFO_LEVEL *printer,
2987 TALLOC_CTX *mem_ctx)
2989 pstring temp;
2990 uint32 len;
2992 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2994 data->notify_data.data.length = len;
2995 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2997 if (!data->notify_data.data.string) {
2998 data->notify_data.data.length = 0;
2999 return;
3002 memcpy(data->notify_data.data.string, temp, len);
3005 /*******************************************************************
3006 * fill a notify_info_data with the print processor
3007 * jfm:xxxx return always winprint to indicate we don't do anything to it
3008 ********************************************************************/
3010 void spoolss_notify_print_processor(int snum,
3011 SPOOL_NOTIFY_INFO_DATA *data,
3012 print_queue_struct *queue,
3013 NT_PRINTER_INFO_LEVEL *printer,
3014 TALLOC_CTX *mem_ctx)
3016 pstring temp;
3017 uint32 len;
3019 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3021 data->notify_data.data.length = len;
3022 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3024 if (!data->notify_data.data.string) {
3025 data->notify_data.data.length = 0;
3026 return;
3029 memcpy(data->notify_data.data.string, temp, len);
3032 /*******************************************************************
3033 * fill a notify_info_data with the print processor options
3034 * jfm:xxxx send an empty string
3035 ********************************************************************/
3037 void spoolss_notify_parameters(int snum,
3038 SPOOL_NOTIFY_INFO_DATA *data,
3039 print_queue_struct *queue,
3040 NT_PRINTER_INFO_LEVEL *printer,
3041 TALLOC_CTX *mem_ctx)
3043 pstring temp;
3044 uint32 len;
3046 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3048 data->notify_data.data.length = len;
3049 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3051 if (!data->notify_data.data.string) {
3052 data->notify_data.data.length = 0;
3053 return;
3056 memcpy(data->notify_data.data.string, temp, len);
3059 /*******************************************************************
3060 * fill a notify_info_data with the data type
3061 * jfm:xxxx always send RAW as data type
3062 ********************************************************************/
3064 void spoolss_notify_datatype(int snum,
3065 SPOOL_NOTIFY_INFO_DATA *data,
3066 print_queue_struct *queue,
3067 NT_PRINTER_INFO_LEVEL *printer,
3068 TALLOC_CTX *mem_ctx)
3070 pstring temp;
3071 uint32 len;
3073 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3075 data->notify_data.data.length = len;
3076 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3078 if (!data->notify_data.data.string) {
3079 data->notify_data.data.length = 0;
3080 return;
3083 memcpy(data->notify_data.data.string, temp, len);
3086 /*******************************************************************
3087 * fill a notify_info_data with the security descriptor
3088 * jfm:xxxx send an null pointer to say no security desc
3089 * have to implement security before !
3090 ********************************************************************/
3092 static void spoolss_notify_security_desc(int snum,
3093 SPOOL_NOTIFY_INFO_DATA *data,
3094 print_queue_struct *queue,
3095 NT_PRINTER_INFO_LEVEL *printer,
3096 TALLOC_CTX *mem_ctx)
3098 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3099 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3102 /*******************************************************************
3103 * fill a notify_info_data with the attributes
3104 * jfm:xxxx a samba printer is always shared
3105 ********************************************************************/
3107 void spoolss_notify_attributes(int snum,
3108 SPOOL_NOTIFY_INFO_DATA *data,
3109 print_queue_struct *queue,
3110 NT_PRINTER_INFO_LEVEL *printer,
3111 TALLOC_CTX *mem_ctx)
3113 data->notify_data.value[0] = printer->info_2->attributes;
3114 data->notify_data.value[1] = 0;
3117 /*******************************************************************
3118 * fill a notify_info_data with the priority
3119 ********************************************************************/
3121 static void spoolss_notify_priority(int snum,
3122 SPOOL_NOTIFY_INFO_DATA *data,
3123 print_queue_struct *queue,
3124 NT_PRINTER_INFO_LEVEL *printer,
3125 TALLOC_CTX *mem_ctx)
3127 data->notify_data.value[0] = printer->info_2->priority;
3128 data->notify_data.value[1] = 0;
3131 /*******************************************************************
3132 * fill a notify_info_data with the default priority
3133 ********************************************************************/
3135 static void spoolss_notify_default_priority(int snum,
3136 SPOOL_NOTIFY_INFO_DATA *data,
3137 print_queue_struct *queue,
3138 NT_PRINTER_INFO_LEVEL *printer,
3139 TALLOC_CTX *mem_ctx)
3141 data->notify_data.value[0] = printer->info_2->default_priority;
3142 data->notify_data.value[1] = 0;
3145 /*******************************************************************
3146 * fill a notify_info_data with the start time
3147 ********************************************************************/
3149 static void spoolss_notify_start_time(int snum,
3150 SPOOL_NOTIFY_INFO_DATA *data,
3151 print_queue_struct *queue,
3152 NT_PRINTER_INFO_LEVEL *printer,
3153 TALLOC_CTX *mem_ctx)
3155 data->notify_data.value[0] = printer->info_2->starttime;
3156 data->notify_data.value[1] = 0;
3159 /*******************************************************************
3160 * fill a notify_info_data with the until time
3161 ********************************************************************/
3163 static void spoolss_notify_until_time(int snum,
3164 SPOOL_NOTIFY_INFO_DATA *data,
3165 print_queue_struct *queue,
3166 NT_PRINTER_INFO_LEVEL *printer,
3167 TALLOC_CTX *mem_ctx)
3169 data->notify_data.value[0] = printer->info_2->untiltime;
3170 data->notify_data.value[1] = 0;
3173 /*******************************************************************
3174 * fill a notify_info_data with the status
3175 ********************************************************************/
3177 static void spoolss_notify_status(int snum,
3178 SPOOL_NOTIFY_INFO_DATA *data,
3179 print_queue_struct *queue,
3180 NT_PRINTER_INFO_LEVEL *printer,
3181 TALLOC_CTX *mem_ctx)
3183 print_status_struct status;
3185 print_queue_length(snum, &status);
3186 data->notify_data.value[0]=(uint32) status.status;
3187 data->notify_data.value[1] = 0;
3190 /*******************************************************************
3191 * fill a notify_info_data with the number of jobs queued
3192 ********************************************************************/
3194 void spoolss_notify_cjobs(int snum,
3195 SPOOL_NOTIFY_INFO_DATA *data,
3196 print_queue_struct *queue,
3197 NT_PRINTER_INFO_LEVEL *printer,
3198 TALLOC_CTX *mem_ctx)
3200 data->notify_data.value[0] = print_queue_length(snum, NULL);
3201 data->notify_data.value[1] = 0;
3204 /*******************************************************************
3205 * fill a notify_info_data with the average ppm
3206 ********************************************************************/
3208 static void spoolss_notify_average_ppm(int snum,
3209 SPOOL_NOTIFY_INFO_DATA *data,
3210 print_queue_struct *queue,
3211 NT_PRINTER_INFO_LEVEL *printer,
3212 TALLOC_CTX *mem_ctx)
3214 /* always respond 8 pages per minutes */
3215 /* a little hard ! */
3216 data->notify_data.value[0] = printer->info_2->averageppm;
3217 data->notify_data.value[1] = 0;
3220 /*******************************************************************
3221 * fill a notify_info_data with username
3222 ********************************************************************/
3224 static void spoolss_notify_username(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 pstring temp;
3231 uint32 len;
3233 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3235 data->notify_data.data.length = len;
3236 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3238 if (!data->notify_data.data.string) {
3239 data->notify_data.data.length = 0;
3240 return;
3243 memcpy(data->notify_data.data.string, temp, len);
3246 /*******************************************************************
3247 * fill a notify_info_data with job status
3248 ********************************************************************/
3250 static void spoolss_notify_job_status(int snum,
3251 SPOOL_NOTIFY_INFO_DATA *data,
3252 print_queue_struct *queue,
3253 NT_PRINTER_INFO_LEVEL *printer,
3254 TALLOC_CTX *mem_ctx)
3256 data->notify_data.value[0]=nt_printj_status(queue->status);
3257 data->notify_data.value[1] = 0;
3260 /*******************************************************************
3261 * fill a notify_info_data with job name
3262 ********************************************************************/
3264 static void spoolss_notify_job_name(int snum,
3265 SPOOL_NOTIFY_INFO_DATA *data,
3266 print_queue_struct *queue,
3267 NT_PRINTER_INFO_LEVEL *printer,
3268 TALLOC_CTX *mem_ctx)
3270 pstring temp;
3271 uint32 len;
3273 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3275 data->notify_data.data.length = len;
3276 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3278 if (!data->notify_data.data.string) {
3279 data->notify_data.data.length = 0;
3280 return;
3283 memcpy(data->notify_data.data.string, temp, len);
3286 /*******************************************************************
3287 * fill a notify_info_data with job status
3288 ********************************************************************/
3290 static void spoolss_notify_job_status_string(int snum,
3291 SPOOL_NOTIFY_INFO_DATA *data,
3292 print_queue_struct *queue,
3293 NT_PRINTER_INFO_LEVEL *printer,
3294 TALLOC_CTX *mem_ctx)
3297 * Now we're returning job status codes we just return a "" here. JRA.
3300 const char *p = "";
3301 pstring temp;
3302 uint32 len;
3304 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3305 p = "unknown";
3307 switch (queue->status) {
3308 case LPQ_QUEUED:
3309 p = "Queued";
3310 break;
3311 case LPQ_PAUSED:
3312 p = ""; /* NT provides the paused string */
3313 break;
3314 case LPQ_SPOOLING:
3315 p = "Spooling";
3316 break;
3317 case LPQ_PRINTING:
3318 p = "Printing";
3319 break;
3321 #endif /* NO LONGER NEEDED. */
3323 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3325 data->notify_data.data.length = len;
3326 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3328 if (!data->notify_data.data.string) {
3329 data->notify_data.data.length = 0;
3330 return;
3333 memcpy(data->notify_data.data.string, temp, len);
3336 /*******************************************************************
3337 * fill a notify_info_data with job time
3338 ********************************************************************/
3340 static void spoolss_notify_job_time(int snum,
3341 SPOOL_NOTIFY_INFO_DATA *data,
3342 print_queue_struct *queue,
3343 NT_PRINTER_INFO_LEVEL *printer,
3344 TALLOC_CTX *mem_ctx)
3346 data->notify_data.value[0]=0x0;
3347 data->notify_data.value[1]=0;
3350 /*******************************************************************
3351 * fill a notify_info_data with job size
3352 ********************************************************************/
3354 static void spoolss_notify_job_size(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]=queue->size;
3361 data->notify_data.value[1]=0;
3364 /*******************************************************************
3365 * fill a notify_info_data with page info
3366 ********************************************************************/
3367 static void spoolss_notify_total_pages(int snum,
3368 SPOOL_NOTIFY_INFO_DATA *data,
3369 print_queue_struct *queue,
3370 NT_PRINTER_INFO_LEVEL *printer,
3371 TALLOC_CTX *mem_ctx)
3373 data->notify_data.value[0]=queue->page_count;
3374 data->notify_data.value[1]=0;
3377 /*******************************************************************
3378 * fill a notify_info_data with pages printed info.
3379 ********************************************************************/
3380 static void spoolss_notify_pages_printed(int snum,
3381 SPOOL_NOTIFY_INFO_DATA *data,
3382 print_queue_struct *queue,
3383 NT_PRINTER_INFO_LEVEL *printer,
3384 TALLOC_CTX *mem_ctx)
3386 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3387 data->notify_data.value[1]=0;
3390 /*******************************************************************
3391 Fill a notify_info_data with job position.
3392 ********************************************************************/
3394 static void spoolss_notify_job_position(int snum,
3395 SPOOL_NOTIFY_INFO_DATA *data,
3396 print_queue_struct *queue,
3397 NT_PRINTER_INFO_LEVEL *printer,
3398 TALLOC_CTX *mem_ctx)
3400 data->notify_data.value[0]=queue->job;
3401 data->notify_data.value[1]=0;
3404 /*******************************************************************
3405 Fill a notify_info_data with submitted time.
3406 ********************************************************************/
3408 static void spoolss_notify_submitted_time(int snum,
3409 SPOOL_NOTIFY_INFO_DATA *data,
3410 print_queue_struct *queue,
3411 NT_PRINTER_INFO_LEVEL *printer,
3412 TALLOC_CTX *mem_ctx)
3414 struct tm *t;
3415 uint32 len;
3416 SYSTEMTIME st;
3417 char *p;
3419 t=gmtime(&queue->time);
3421 len = sizeof(SYSTEMTIME);
3423 data->notify_data.data.length = len;
3424 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3426 if (!data->notify_data.data.string) {
3427 data->notify_data.data.length = 0;
3428 return;
3431 make_systemtime(&st, t);
3434 * Systemtime must be linearized as a set of UINT16's.
3435 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3438 p = (char *)data->notify_data.data.string;
3439 SSVAL(p, 0, st.year);
3440 SSVAL(p, 2, st.month);
3441 SSVAL(p, 4, st.dayofweek);
3442 SSVAL(p, 6, st.day);
3443 SSVAL(p, 8, st.hour);
3444 SSVAL(p, 10, st.minute);
3445 SSVAL(p, 12, st.second);
3446 SSVAL(p, 14, st.milliseconds);
3449 struct s_notify_info_data_table
3451 uint16 type;
3452 uint16 field;
3453 const char *name;
3454 uint32 size;
3455 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3456 print_queue_struct *queue,
3457 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3460 /* A table describing the various print notification constants and
3461 whether the notification data is a pointer to a variable sized
3462 buffer, a one value uint32 or a two value uint32. */
3464 static const struct s_notify_info_data_table notify_info_data_table[] =
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3485 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3486 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3487 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3488 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3489 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3490 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3491 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3508 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3509 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3510 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3511 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3512 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3513 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3514 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3517 /*******************************************************************
3518 Return the size of info_data structure.
3519 ********************************************************************/
3521 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3523 int i=0;
3525 for (i = 0; i < sizeof(notify_info_data_table); i++)
3527 if ( (notify_info_data_table[i].type == type)
3528 && (notify_info_data_table[i].field == field) )
3530 switch(notify_info_data_table[i].size)
3532 case NOTIFY_ONE_VALUE:
3533 case NOTIFY_TWO_VALUE:
3534 return 1;
3535 case NOTIFY_STRING:
3536 return 2;
3538 /* The only pointer notify data I have seen on
3539 the wire is the submitted time and this has
3540 the notify size set to 4. -tpot */
3542 case NOTIFY_POINTER:
3543 return 4;
3545 case NOTIFY_SECDESC:
3546 return 5;
3551 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3553 return 0;
3556 /*******************************************************************
3557 Return the type of notify_info_data.
3558 ********************************************************************/
3560 static int type_of_notify_info_data(uint16 type, uint16 field)
3562 int i=0;
3564 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3565 if (notify_info_data_table[i].type == type &&
3566 notify_info_data_table[i].field == field)
3567 return notify_info_data_table[i].size;
3570 return False;
3573 /****************************************************************************
3574 ****************************************************************************/
3576 static int search_notify(uint16 type, uint16 field, int *value)
3578 int i;
3580 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3581 if (notify_info_data_table[i].type == type &&
3582 notify_info_data_table[i].field == field &&
3583 notify_info_data_table[i].fn != NULL) {
3584 *value = i;
3585 return True;
3589 return False;
3592 /****************************************************************************
3593 ****************************************************************************/
3595 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3597 info_data->type = type;
3598 info_data->field = field;
3599 info_data->reserved = 0;
3601 info_data->size = size_of_notify_info_data(type, field);
3602 info_data->enc_type = type_of_notify_info_data(type, field);
3604 info_data->id = id;
3609 /*******************************************************************
3611 * fill a notify_info struct with info asked
3613 ********************************************************************/
3615 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3616 snum, SPOOL_NOTIFY_OPTION_TYPE
3617 *option_type, uint32 id,
3618 TALLOC_CTX *mem_ctx)
3620 int field_num,j;
3621 uint16 type;
3622 uint16 field;
3624 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3625 NT_PRINTER_INFO_LEVEL *printer = NULL;
3626 print_queue_struct *queue=NULL;
3628 type=option_type->type;
3630 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3631 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3632 option_type->count, lp_servicename(snum)));
3634 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3635 return False;
3637 for(field_num=0; field_num<option_type->count; field_num++) {
3638 field = option_type->fields[field_num];
3640 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3642 if (!search_notify(type, field, &j) )
3643 continue;
3645 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3646 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3647 return False;
3648 } else
3649 info->data = tid;
3651 current_data = &info->data[info->count];
3653 construct_info_data(current_data, type, field, id);
3655 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3656 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3658 notify_info_data_table[j].fn(snum, current_data, queue,
3659 printer, mem_ctx);
3661 info->count++;
3664 free_a_printer(&printer, 2);
3665 return True;
3668 /*******************************************************************
3670 * fill a notify_info struct with info asked
3672 ********************************************************************/
3674 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3675 SPOOL_NOTIFY_INFO *info,
3676 NT_PRINTER_INFO_LEVEL *printer,
3677 int snum, SPOOL_NOTIFY_OPTION_TYPE
3678 *option_type, uint32 id,
3679 TALLOC_CTX *mem_ctx)
3681 int field_num,j;
3682 uint16 type;
3683 uint16 field;
3685 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3687 DEBUG(4,("construct_notify_jobs_info\n"));
3689 type = option_type->type;
3691 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3692 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3693 option_type->count));
3695 for(field_num=0; field_num<option_type->count; field_num++) {
3696 field = option_type->fields[field_num];
3698 if (!search_notify(type, field, &j) )
3699 continue;
3701 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3702 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3703 return False;
3705 else info->data = tid;
3707 current_data=&(info->data[info->count]);
3709 construct_info_data(current_data, type, field, id);
3710 notify_info_data_table[j].fn(snum, current_data, queue,
3711 printer, mem_ctx);
3712 info->count++;
3715 return True;
3719 * JFM: The enumeration is not that simple, it's even non obvious.
3721 * let's take an example: I want to monitor the PRINTER SERVER for
3722 * the printer's name and the number of jobs currently queued.
3723 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3724 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3726 * I have 3 printers on the back of my server.
3728 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3729 * structures.
3730 * Number Data Id
3731 * 1 printer 1 name 1
3732 * 2 printer 1 cjob 1
3733 * 3 printer 2 name 2
3734 * 4 printer 2 cjob 2
3735 * 5 printer 3 name 3
3736 * 6 printer 3 name 3
3738 * that's the print server case, the printer case is even worse.
3741 /*******************************************************************
3743 * enumerate all printers on the printserver
3744 * fill a notify_info struct with info asked
3746 ********************************************************************/
3748 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3749 SPOOL_NOTIFY_INFO *info,
3750 TALLOC_CTX *mem_ctx)
3752 int snum;
3753 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3754 int n_services=lp_numservices();
3755 int i;
3756 SPOOL_NOTIFY_OPTION *option;
3757 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3759 DEBUG(4,("printserver_notify_info\n"));
3761 if (!Printer)
3762 return WERR_BADFID;
3764 option=Printer->notify.option;
3765 info->version=2;
3766 info->data=NULL;
3767 info->count=0;
3769 for (i=0; i<option->count; i++) {
3770 option_type=&(option->ctr.type[i]);
3772 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3773 continue;
3775 for (snum=0; snum<n_services; snum++)
3777 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3778 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3782 #if 0
3784 * Debugging information, don't delete.
3787 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3788 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3789 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3791 for (i=0; i<info->count; i++) {
3792 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3793 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3794 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3796 #endif
3798 return WERR_OK;
3801 /*******************************************************************
3803 * fill a notify_info struct with info asked
3805 ********************************************************************/
3807 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3808 TALLOC_CTX *mem_ctx)
3810 int snum;
3811 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3812 int i;
3813 uint32 id;
3814 SPOOL_NOTIFY_OPTION *option;
3815 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3816 int count,j;
3817 print_queue_struct *queue=NULL;
3818 print_status_struct status;
3820 DEBUG(4,("printer_notify_info\n"));
3822 if (!Printer)
3823 return WERR_BADFID;
3825 option=Printer->notify.option;
3826 id = 0x0;
3827 info->version=2;
3828 info->data=NULL;
3829 info->count=0;
3831 get_printer_snum(p, hnd, &snum);
3833 for (i=0; i<option->count; i++) {
3834 option_type=&option->ctr.type[i];
3836 switch ( option_type->type ) {
3837 case PRINTER_NOTIFY_TYPE:
3838 if(construct_notify_printer_info(Printer, info, snum,
3839 option_type, id,
3840 mem_ctx))
3841 id--;
3842 break;
3844 case JOB_NOTIFY_TYPE: {
3845 NT_PRINTER_INFO_LEVEL *printer = NULL;
3847 count = print_queue_status(snum, &queue, &status);
3849 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3850 goto done;
3852 for (j=0; j<count; j++) {
3853 construct_notify_jobs_info(&queue[j], info,
3854 printer, snum,
3855 option_type,
3856 queue[j].job,
3857 mem_ctx);
3860 free_a_printer(&printer, 2);
3862 done:
3863 SAFE_FREE(queue);
3864 break;
3870 * Debugging information, don't delete.
3873 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3874 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3875 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3877 for (i=0; i<info->count; i++) {
3878 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3879 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3880 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3883 return WERR_OK;
3886 /********************************************************************
3887 * spoolss_rfnpcnex
3888 ********************************************************************/
3890 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3892 POLICY_HND *handle = &q_u->handle;
3893 SPOOL_NOTIFY_INFO *info = &r_u->info;
3895 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3896 WERROR result = WERR_BADFID;
3898 /* we always have a NOTIFY_INFO struct */
3899 r_u->info_ptr=0x1;
3901 if (!Printer) {
3902 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3903 OUR_HANDLE(handle)));
3904 goto done;
3907 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3910 * We are now using the change value, and
3911 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3912 * I don't have a global notification system, I'm sending back all the
3913 * informations even when _NOTHING_ has changed.
3916 /* We need to keep track of the change value to send back in
3917 RRPCN replies otherwise our updates are ignored. */
3919 Printer->notify.fnpcn = True;
3921 if (Printer->notify.client_connected) {
3922 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3923 Printer->notify.change = q_u->change;
3926 /* just ignore the SPOOL_NOTIFY_OPTION */
3928 switch (Printer->printer_type) {
3929 case PRINTER_HANDLE_IS_PRINTSERVER:
3930 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3931 break;
3933 case PRINTER_HANDLE_IS_PRINTER:
3934 result = printer_notify_info(p, handle, info, p->mem_ctx);
3935 break;
3938 Printer->notify.fnpcn = False;
3940 done:
3941 return result;
3944 /********************************************************************
3945 * construct_printer_info_0
3946 * fill a printer_info_0 struct
3947 ********************************************************************/
3949 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3951 pstring chaine;
3952 int count;
3953 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3954 counter_printer_0 *session_counter;
3955 uint32 global_counter;
3956 struct tm *t;
3957 time_t setuptime;
3958 print_status_struct status;
3960 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3961 return False;
3963 count = print_queue_length(snum, &status);
3965 /* check if we already have a counter for this printer */
3966 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3968 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3969 if (session_counter->snum == snum)
3970 break;
3973 /* it's the first time, add it to the list */
3974 if (session_counter==NULL) {
3975 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3976 free_a_printer(&ntprinter, 2);
3977 return False;
3979 ZERO_STRUCTP(session_counter);
3980 session_counter->snum=snum;
3981 session_counter->counter=0;
3982 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3985 /* increment it */
3986 session_counter->counter++;
3988 /* JFM:
3989 * the global_counter should be stored in a TDB as it's common to all the clients
3990 * and should be zeroed on samba startup
3992 global_counter=session_counter->counter;
3994 pstrcpy(chaine,ntprinter->info_2->printername);
3996 init_unistr(&printer->printername, chaine);
3998 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3999 init_unistr(&printer->servername, chaine);
4001 printer->cjobs = count;
4002 printer->total_jobs = 0;
4003 printer->total_bytes = 0;
4005 setuptime = (time_t)ntprinter->info_2->setuptime;
4006 t=gmtime(&setuptime);
4008 printer->year = t->tm_year+1900;
4009 printer->month = t->tm_mon+1;
4010 printer->dayofweek = t->tm_wday;
4011 printer->day = t->tm_mday;
4012 printer->hour = t->tm_hour;
4013 printer->minute = t->tm_min;
4014 printer->second = t->tm_sec;
4015 printer->milliseconds = 0;
4017 printer->global_counter = global_counter;
4018 printer->total_pages = 0;
4020 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4021 printer->major_version = 0x0005; /* NT 5 */
4022 printer->build_version = 0x0893; /* build 2195 */
4024 printer->unknown7 = 0x1;
4025 printer->unknown8 = 0x0;
4026 printer->unknown9 = 0x0;
4027 printer->session_counter = session_counter->counter;
4028 printer->unknown11 = 0x0;
4029 printer->printer_errors = 0x0; /* number of print failure */
4030 printer->unknown13 = 0x0;
4031 printer->unknown14 = 0x1;
4032 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4033 printer->unknown16 = 0x0;
4034 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4035 printer->unknown18 = 0x0;
4036 printer->status = nt_printq_status(status.status);
4037 printer->unknown20 = 0x0;
4038 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4039 printer->unknown22 = 0x0;
4040 printer->unknown23 = 0x6; /* 6 ???*/
4041 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4042 printer->unknown25 = 0;
4043 printer->unknown26 = 0;
4044 printer->unknown27 = 0;
4045 printer->unknown28 = 0;
4046 printer->unknown29 = 0;
4048 free_a_printer(&ntprinter,2);
4049 return (True);
4052 /********************************************************************
4053 * construct_printer_info_1
4054 * fill a printer_info_1 struct
4055 ********************************************************************/
4056 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4058 pstring chaine;
4059 pstring chaine2;
4060 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4062 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4063 return False;
4065 printer->flags=flags;
4067 if (*ntprinter->info_2->comment == '\0') {
4068 init_unistr(&printer->comment, lp_comment(snum));
4069 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4070 ntprinter->info_2->drivername, lp_comment(snum));
4072 else {
4073 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4074 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4075 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4078 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4080 init_unistr(&printer->description, chaine);
4081 init_unistr(&printer->name, chaine2);
4083 free_a_printer(&ntprinter,2);
4085 return True;
4088 /****************************************************************************
4089 Free a DEVMODE struct.
4090 ****************************************************************************/
4092 static void free_dev_mode(DEVICEMODE *dev)
4094 if (dev == NULL)
4095 return;
4097 SAFE_FREE(dev->private);
4098 SAFE_FREE(dev);
4102 /****************************************************************************
4103 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4104 should be valid upon entry
4105 ****************************************************************************/
4107 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4109 if ( !devmode || !ntdevmode )
4110 return False;
4112 init_unistr(&devmode->devicename, ntdevmode->devicename);
4114 init_unistr(&devmode->formname, ntdevmode->formname);
4116 devmode->specversion = ntdevmode->specversion;
4117 devmode->driverversion = ntdevmode->driverversion;
4118 devmode->size = ntdevmode->size;
4119 devmode->driverextra = ntdevmode->driverextra;
4120 devmode->fields = ntdevmode->fields;
4122 devmode->orientation = ntdevmode->orientation;
4123 devmode->papersize = ntdevmode->papersize;
4124 devmode->paperlength = ntdevmode->paperlength;
4125 devmode->paperwidth = ntdevmode->paperwidth;
4126 devmode->scale = ntdevmode->scale;
4127 devmode->copies = ntdevmode->copies;
4128 devmode->defaultsource = ntdevmode->defaultsource;
4129 devmode->printquality = ntdevmode->printquality;
4130 devmode->color = ntdevmode->color;
4131 devmode->duplex = ntdevmode->duplex;
4132 devmode->yresolution = ntdevmode->yresolution;
4133 devmode->ttoption = ntdevmode->ttoption;
4134 devmode->collate = ntdevmode->collate;
4135 devmode->icmmethod = ntdevmode->icmmethod;
4136 devmode->icmintent = ntdevmode->icmintent;
4137 devmode->mediatype = ntdevmode->mediatype;
4138 devmode->dithertype = ntdevmode->dithertype;
4140 if (ntdevmode->private != NULL) {
4141 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4142 return False;
4145 return True;
4148 /****************************************************************************
4149 Create a DEVMODE struct. Returns malloced memory.
4150 ****************************************************************************/
4152 DEVICEMODE *construct_dev_mode(int snum)
4154 NT_PRINTER_INFO_LEVEL *printer = NULL;
4155 DEVICEMODE *devmode = NULL;
4157 DEBUG(7,("construct_dev_mode\n"));
4159 DEBUGADD(8,("getting printer characteristics\n"));
4161 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4162 return NULL;
4164 if ( !printer->info_2->devmode ) {
4165 DEBUG(5, ("BONG! There was no device mode!\n"));
4166 goto done;
4169 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4170 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4171 goto done;
4174 ZERO_STRUCTP(devmode);
4176 DEBUGADD(8,("loading DEVICEMODE\n"));
4178 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4179 free_dev_mode( devmode );
4180 devmode = NULL;
4183 done:
4184 free_a_printer(&printer,2);
4186 return devmode;
4189 /********************************************************************
4190 * construct_printer_info_2
4191 * fill a printer_info_2 struct
4192 ********************************************************************/
4194 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4196 int count;
4197 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4199 print_status_struct status;
4201 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4202 return False;
4204 count = print_queue_length(snum, &status);
4206 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4207 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4208 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4209 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4210 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4212 if (*ntprinter->info_2->comment == '\0')
4213 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4214 else
4215 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4217 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4218 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4219 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4220 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4221 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4223 printer->attributes = ntprinter->info_2->attributes;
4225 printer->priority = ntprinter->info_2->priority; /* priority */
4226 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4227 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4228 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4229 printer->status = nt_printq_status(status.status); /* status */
4230 printer->cjobs = count; /* jobs */
4231 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4233 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4234 DEBUG(8, ("Returning NULL Devicemode!\n"));
4237 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4238 /* steal the printer info sec_desc structure. [badly done]. */
4239 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4240 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4241 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4242 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4244 else {
4245 printer->secdesc = NULL;
4248 free_a_printer(&ntprinter, 2);
4249 return True;
4252 /********************************************************************
4253 * construct_printer_info_3
4254 * fill a printer_info_3 struct
4255 ********************************************************************/
4257 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4259 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4260 PRINTER_INFO_3 *printer = NULL;
4262 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4263 return False;
4265 *pp_printer = NULL;
4266 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4267 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4268 return False;
4271 ZERO_STRUCTP(printer);
4273 printer->flags = 4; /* These are the components of the SD we are returning. */
4274 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4275 /* steal the printer info sec_desc structure. [badly done]. */
4276 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4278 #if 0
4280 * Set the flags for the components we are returning.
4283 if (printer->secdesc->owner_sid)
4284 printer->flags |= OWNER_SECURITY_INFORMATION;
4286 if (printer->secdesc->grp_sid)
4287 printer->flags |= GROUP_SECURITY_INFORMATION;
4289 if (printer->secdesc->dacl)
4290 printer->flags |= DACL_SECURITY_INFORMATION;
4292 if (printer->secdesc->sacl)
4293 printer->flags |= SACL_SECURITY_INFORMATION;
4294 #endif
4296 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4297 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4298 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4301 free_a_printer(&ntprinter, 2);
4303 *pp_printer = printer;
4304 return True;
4307 /********************************************************************
4308 * construct_printer_info_4
4309 * fill a printer_info_4 struct
4310 ********************************************************************/
4312 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4314 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4316 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4317 return False;
4319 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4320 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4321 printer->attributes = ntprinter->info_2->attributes;
4323 free_a_printer(&ntprinter, 2);
4324 return True;
4327 /********************************************************************
4328 * construct_printer_info_5
4329 * fill a printer_info_5 struct
4330 ********************************************************************/
4332 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4334 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4336 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4337 return False;
4339 init_unistr(&printer->printername, ntprinter->info_2->printername);
4340 init_unistr(&printer->portname, ntprinter->info_2->portname);
4341 printer->attributes = ntprinter->info_2->attributes;
4343 /* these two are not used by NT+ according to MSDN */
4345 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4346 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4348 free_a_printer(&ntprinter, 2);
4350 return True;
4353 /********************************************************************
4354 * construct_printer_info_7
4355 * fill a printer_info_7 struct
4356 ********************************************************************/
4358 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4360 char *guid_str = NULL;
4361 UUID_FLAT guid;
4363 if (is_printer_published(print_hnd, snum, &guid)) {
4364 asprintf(&guid_str, "{%s}",
4365 smb_uuid_string_static(smb_uuid_unpack_static(guid)));
4366 strupper_m(guid_str);
4367 init_unistr(&printer->guid, guid_str);
4368 printer->action = SPOOL_DS_PUBLISH;
4369 } else {
4370 init_unistr(&printer->guid, "");
4371 printer->action = SPOOL_DS_UNPUBLISH;
4374 return True;
4377 /********************************************************************
4378 Spoolss_enumprinters.
4379 ********************************************************************/
4381 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4383 int snum;
4384 int i;
4385 int n_services=lp_numservices();
4386 PRINTER_INFO_1 *tp, *printers=NULL;
4387 PRINTER_INFO_1 current_prt;
4389 DEBUG(4,("enum_all_printers_info_1\n"));
4391 for (snum=0; snum<n_services; snum++) {
4392 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4393 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4395 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4396 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4397 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4398 SAFE_FREE(printers);
4399 *returned=0;
4400 return WERR_NOMEM;
4402 else printers = tp;
4403 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4405 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4406 (*returned)++;
4411 /* check the required size. */
4412 for (i=0; i<*returned; i++)
4413 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4415 if (!alloc_buffer_size(buffer, *needed))
4416 return WERR_INSUFFICIENT_BUFFER;
4418 /* fill the buffer with the structures */
4419 for (i=0; i<*returned; i++)
4420 smb_io_printer_info_1("", buffer, &printers[i], 0);
4422 /* clear memory */
4423 SAFE_FREE(printers);
4425 if (*needed > offered) {
4426 *returned=0;
4427 return WERR_INSUFFICIENT_BUFFER;
4429 else
4430 return WERR_OK;
4433 /********************************************************************
4434 enum_all_printers_info_1_local.
4435 *********************************************************************/
4437 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4439 DEBUG(4,("enum_all_printers_info_1_local\n"));
4441 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4444 /********************************************************************
4445 enum_all_printers_info_1_name.
4446 *********************************************************************/
4448 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4450 char *s = name;
4452 DEBUG(4,("enum_all_printers_info_1_name\n"));
4454 if ((name[0] == '\\') && (name[1] == '\\'))
4455 s = name + 2;
4457 if (is_myname_or_ipaddr(s)) {
4458 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4460 else
4461 return WERR_INVALID_NAME;
4464 /********************************************************************
4465 enum_all_printers_info_1_remote.
4466 *********************************************************************/
4468 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4470 PRINTER_INFO_1 *printer;
4471 fstring printername;
4472 fstring desc;
4473 fstring comment;
4474 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4476 /* JFM: currently it's more a place holder than anything else.
4477 * In the spooler world there is a notion of server registration.
4478 * the print servers are registring (sp ?) on the PDC (in the same domain)
4480 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4483 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4484 return WERR_NOMEM;
4486 *returned=1;
4488 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4489 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4490 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4492 init_unistr(&printer->description, desc);
4493 init_unistr(&printer->name, printername);
4494 init_unistr(&printer->comment, comment);
4495 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4497 /* check the required size. */
4498 *needed += spoolss_size_printer_info_1(printer);
4500 if (!alloc_buffer_size(buffer, *needed)) {
4501 SAFE_FREE(printer);
4502 return WERR_INSUFFICIENT_BUFFER;
4505 /* fill the buffer with the structures */
4506 smb_io_printer_info_1("", buffer, printer, 0);
4508 /* clear memory */
4509 SAFE_FREE(printer);
4511 if (*needed > offered) {
4512 *returned=0;
4513 return WERR_INSUFFICIENT_BUFFER;
4515 else
4516 return WERR_OK;
4519 /********************************************************************
4520 enum_all_printers_info_1_network.
4521 *********************************************************************/
4523 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4525 char *s = name;
4527 DEBUG(4,("enum_all_printers_info_1_network\n"));
4529 /* If we respond to a enum_printers level 1 on our name with flags
4530 set to PRINTER_ENUM_REMOTE with a list of printers then these
4531 printers incorrectly appear in the APW browse list.
4532 Specifically the printers for the server appear at the workgroup
4533 level where all the other servers in the domain are
4534 listed. Windows responds to this call with a
4535 WERR_CAN_NOT_COMPLETE so we should do the same. */
4537 if (name[0] == '\\' && name[1] == '\\')
4538 s = name + 2;
4540 if (is_myname_or_ipaddr(s))
4541 return WERR_CAN_NOT_COMPLETE;
4543 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4546 /********************************************************************
4547 * api_spoolss_enumprinters
4549 * called from api_spoolss_enumprinters (see this to understand)
4550 ********************************************************************/
4552 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4554 int snum;
4555 int i;
4556 int n_services=lp_numservices();
4557 PRINTER_INFO_2 *tp, *printers=NULL;
4558 PRINTER_INFO_2 current_prt;
4560 for (snum=0; snum<n_services; snum++) {
4561 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4562 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4564 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4565 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4566 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4567 SAFE_FREE(printers);
4568 *returned = 0;
4569 return WERR_NOMEM;
4571 else printers = tp;
4572 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4573 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4574 (*returned)++;
4579 /* check the required size. */
4580 for (i=0; i<*returned; i++)
4581 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4583 if (!alloc_buffer_size(buffer, *needed)) {
4584 for (i=0; i<*returned; i++) {
4585 free_devmode(printers[i].devmode);
4587 SAFE_FREE(printers);
4588 return WERR_INSUFFICIENT_BUFFER;
4591 /* fill the buffer with the structures */
4592 for (i=0; i<*returned; i++)
4593 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4595 /* clear memory */
4596 for (i=0; i<*returned; i++) {
4597 free_devmode(printers[i].devmode);
4599 SAFE_FREE(printers);
4601 if (*needed > offered) {
4602 *returned=0;
4603 return WERR_INSUFFICIENT_BUFFER;
4605 else
4606 return WERR_OK;
4609 /********************************************************************
4610 * handle enumeration of printers at level 1
4611 ********************************************************************/
4613 static WERROR enumprinters_level1( uint32 flags, fstring name,
4614 NEW_BUFFER *buffer, uint32 offered,
4615 uint32 *needed, uint32 *returned)
4617 /* Not all the flags are equals */
4619 if (flags & PRINTER_ENUM_LOCAL)
4620 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4622 if (flags & PRINTER_ENUM_NAME)
4623 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4625 if (flags & PRINTER_ENUM_REMOTE)
4626 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4628 if (flags & PRINTER_ENUM_NETWORK)
4629 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4631 return WERR_OK; /* NT4sp5 does that */
4634 /********************************************************************
4635 * handle enumeration of printers at level 2
4636 ********************************************************************/
4638 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4639 NEW_BUFFER *buffer, uint32 offered,
4640 uint32 *needed, uint32 *returned)
4642 char *s = servername;
4644 if (flags & PRINTER_ENUM_LOCAL) {
4645 return enum_all_printers_info_2(buffer, offered, needed, returned);
4648 if (flags & PRINTER_ENUM_NAME) {
4649 if ((servername[0] == '\\') && (servername[1] == '\\'))
4650 s = servername + 2;
4651 if (is_myname_or_ipaddr(s))
4652 return enum_all_printers_info_2(buffer, offered, needed, returned);
4653 else
4654 return WERR_INVALID_NAME;
4657 if (flags & PRINTER_ENUM_REMOTE)
4658 return WERR_UNKNOWN_LEVEL;
4660 return WERR_OK;
4663 /********************************************************************
4664 * handle enumeration of printers at level 5
4665 ********************************************************************/
4667 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4668 NEW_BUFFER *buffer, uint32 offered,
4669 uint32 *needed, uint32 *returned)
4671 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4672 return WERR_OK;
4675 /********************************************************************
4676 * api_spoolss_enumprinters
4678 * called from api_spoolss_enumprinters (see this to understand)
4679 ********************************************************************/
4681 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4683 uint32 flags = q_u->flags;
4684 UNISTR2 *servername = &q_u->servername;
4685 uint32 level = q_u->level;
4686 NEW_BUFFER *buffer = NULL;
4687 uint32 offered = q_u->offered;
4688 uint32 *needed = &r_u->needed;
4689 uint32 *returned = &r_u->returned;
4691 fstring name;
4693 /* that's an [in out] buffer */
4694 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4695 buffer = r_u->buffer;
4697 DEBUG(4,("_spoolss_enumprinters\n"));
4699 *needed=0;
4700 *returned=0;
4703 * Level 1:
4704 * flags==PRINTER_ENUM_NAME
4705 * if name=="" then enumerates all printers
4706 * if name!="" then enumerate the printer
4707 * flags==PRINTER_ENUM_REMOTE
4708 * name is NULL, enumerate printers
4709 * Level 2: name!="" enumerates printers, name can't be NULL
4710 * Level 3: doesn't exist
4711 * Level 4: does a local registry lookup
4712 * Level 5: same as Level 2
4715 unistr2_to_ascii(name, servername, sizeof(name)-1);
4716 strupper_m(name);
4718 switch (level) {
4719 case 1:
4720 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4721 case 2:
4722 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4723 case 5:
4724 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4725 case 3:
4726 case 4:
4727 break;
4729 return WERR_UNKNOWN_LEVEL;
4732 /****************************************************************************
4733 ****************************************************************************/
4735 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4737 PRINTER_INFO_0 *printer=NULL;
4739 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4740 return WERR_NOMEM;
4742 construct_printer_info_0(print_hnd, printer, snum);
4744 /* check the required size. */
4745 *needed += spoolss_size_printer_info_0(printer);
4747 if (!alloc_buffer_size(buffer, *needed)) {
4748 SAFE_FREE(printer);
4749 return WERR_INSUFFICIENT_BUFFER;
4752 /* fill the buffer with the structures */
4753 smb_io_printer_info_0("", buffer, printer, 0);
4755 /* clear memory */
4756 SAFE_FREE(printer);
4758 if (*needed > offered) {
4759 return WERR_INSUFFICIENT_BUFFER;
4762 return WERR_OK;
4765 /****************************************************************************
4766 ****************************************************************************/
4768 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4770 PRINTER_INFO_1 *printer=NULL;
4772 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4773 return WERR_NOMEM;
4775 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4777 /* check the required size. */
4778 *needed += spoolss_size_printer_info_1(printer);
4780 if (!alloc_buffer_size(buffer, *needed)) {
4781 SAFE_FREE(printer);
4782 return WERR_INSUFFICIENT_BUFFER;
4785 /* fill the buffer with the structures */
4786 smb_io_printer_info_1("", buffer, printer, 0);
4788 /* clear memory */
4789 SAFE_FREE(printer);
4791 if (*needed > offered) {
4792 return WERR_INSUFFICIENT_BUFFER;
4795 return WERR_OK;
4798 /****************************************************************************
4799 ****************************************************************************/
4801 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4803 PRINTER_INFO_2 *printer=NULL;
4805 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4806 return WERR_NOMEM;
4808 construct_printer_info_2(print_hnd, printer, snum);
4810 /* check the required size. */
4811 *needed += spoolss_size_printer_info_2(printer);
4813 if (!alloc_buffer_size(buffer, *needed)) {
4814 free_printer_info_2(printer);
4815 return WERR_INSUFFICIENT_BUFFER;
4818 /* fill the buffer with the structures */
4819 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4820 free_printer_info_2(printer);
4821 return WERR_NOMEM;
4824 /* clear memory */
4825 free_printer_info_2(printer);
4827 if (*needed > offered) {
4828 return WERR_INSUFFICIENT_BUFFER;
4831 return WERR_OK;
4834 /****************************************************************************
4835 ****************************************************************************/
4837 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4839 PRINTER_INFO_3 *printer=NULL;
4841 if (!construct_printer_info_3(print_hnd, &printer, snum))
4842 return WERR_NOMEM;
4844 /* check the required size. */
4845 *needed += spoolss_size_printer_info_3(printer);
4847 if (!alloc_buffer_size(buffer, *needed)) {
4848 free_printer_info_3(printer);
4849 return WERR_INSUFFICIENT_BUFFER;
4852 /* fill the buffer with the structures */
4853 smb_io_printer_info_3("", buffer, printer, 0);
4855 /* clear memory */
4856 free_printer_info_3(printer);
4858 if (*needed > offered) {
4859 return WERR_INSUFFICIENT_BUFFER;
4862 return WERR_OK;
4865 /****************************************************************************
4866 ****************************************************************************/
4868 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4870 PRINTER_INFO_4 *printer=NULL;
4872 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4873 return WERR_NOMEM;
4875 if (!construct_printer_info_4(print_hnd, printer, snum))
4876 return WERR_NOMEM;
4878 /* check the required size. */
4879 *needed += spoolss_size_printer_info_4(printer);
4881 if (!alloc_buffer_size(buffer, *needed)) {
4882 free_printer_info_4(printer);
4883 return WERR_INSUFFICIENT_BUFFER;
4886 /* fill the buffer with the structures */
4887 smb_io_printer_info_4("", buffer, printer, 0);
4889 /* clear memory */
4890 free_printer_info_4(printer);
4892 if (*needed > offered) {
4893 return WERR_INSUFFICIENT_BUFFER;
4896 return WERR_OK;
4899 /****************************************************************************
4900 ****************************************************************************/
4902 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4904 PRINTER_INFO_5 *printer=NULL;
4906 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4907 return WERR_NOMEM;
4909 if (!construct_printer_info_5(print_hnd, printer, snum))
4910 return WERR_NOMEM;
4912 /* check the required size. */
4913 *needed += spoolss_size_printer_info_5(printer);
4915 if (!alloc_buffer_size(buffer, *needed)) {
4916 free_printer_info_5(printer);
4917 return WERR_INSUFFICIENT_BUFFER;
4920 /* fill the buffer with the structures */
4921 smb_io_printer_info_5("", buffer, printer, 0);
4923 /* clear memory */
4924 free_printer_info_5(printer);
4926 if (*needed > offered) {
4927 return WERR_INSUFFICIENT_BUFFER;
4930 return WERR_OK;
4933 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4935 PRINTER_INFO_7 *printer=NULL;
4937 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4938 return WERR_NOMEM;
4940 if (!construct_printer_info_7(print_hnd, printer, snum))
4941 return WERR_NOMEM;
4943 /* check the required size. */
4944 *needed += spoolss_size_printer_info_7(printer);
4946 if (!alloc_buffer_size(buffer, *needed)) {
4947 free_printer_info_7(printer);
4948 return WERR_INSUFFICIENT_BUFFER;
4951 /* fill the buffer with the structures */
4952 smb_io_printer_info_7("", buffer, printer, 0);
4954 /* clear memory */
4955 free_printer_info_7(printer);
4957 if (*needed > offered) {
4958 return WERR_INSUFFICIENT_BUFFER;
4961 return WERR_OK;
4964 /****************************************************************************
4965 ****************************************************************************/
4967 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4969 POLICY_HND *handle = &q_u->handle;
4970 uint32 level = q_u->level;
4971 NEW_BUFFER *buffer = NULL;
4972 uint32 offered = q_u->offered;
4973 uint32 *needed = &r_u->needed;
4974 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4976 int snum;
4978 /* that's an [in out] buffer */
4979 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4980 buffer = r_u->buffer;
4982 *needed=0;
4984 if (!get_printer_snum(p, handle, &snum))
4985 return WERR_BADFID;
4987 switch (level) {
4988 case 0:
4989 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4990 case 1:
4991 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4992 case 2:
4993 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4994 case 3:
4995 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4996 case 4:
4997 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4998 case 5:
4999 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5000 case 7:
5001 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5003 return WERR_UNKNOWN_LEVEL;
5006 /********************************************************************
5007 * fill a DRIVER_INFO_1 struct
5008 ********************************************************************/
5010 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5012 init_unistr( &info->name, driver.info_3->name);
5015 /********************************************************************
5016 * construct_printer_driver_info_1
5017 ********************************************************************/
5019 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5021 NT_PRINTER_INFO_LEVEL *printer = NULL;
5022 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5024 ZERO_STRUCT(driver);
5026 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5027 return WERR_INVALID_PRINTER_NAME;
5029 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5030 return WERR_UNKNOWN_PRINTER_DRIVER;
5032 fill_printer_driver_info_1(info, driver, servername, architecture);
5034 free_a_printer(&printer,2);
5036 return WERR_OK;
5039 /********************************************************************
5040 * construct_printer_driver_info_2
5041 * fill a printer_info_2 struct
5042 ********************************************************************/
5044 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5046 pstring temp;
5048 info->version=driver.info_3->cversion;
5050 init_unistr( &info->name, driver.info_3->name );
5051 init_unistr( &info->architecture, driver.info_3->environment );
5054 if (strlen(driver.info_3->driverpath)) {
5055 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5056 init_unistr( &info->driverpath, temp );
5057 } else
5058 init_unistr( &info->driverpath, "" );
5060 if (strlen(driver.info_3->datafile)) {
5061 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5062 init_unistr( &info->datafile, temp );
5063 } else
5064 init_unistr( &info->datafile, "" );
5066 if (strlen(driver.info_3->configfile)) {
5067 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5068 init_unistr( &info->configfile, temp );
5069 } else
5070 init_unistr( &info->configfile, "" );
5073 /********************************************************************
5074 * construct_printer_driver_info_2
5075 * fill a printer_info_2 struct
5076 ********************************************************************/
5078 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5080 NT_PRINTER_INFO_LEVEL *printer = NULL;
5081 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5083 ZERO_STRUCT(printer);
5084 ZERO_STRUCT(driver);
5086 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5087 return WERR_INVALID_PRINTER_NAME;
5089 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5090 return WERR_UNKNOWN_PRINTER_DRIVER;
5092 fill_printer_driver_info_2(info, driver, servername);
5094 free_a_printer(&printer,2);
5096 return WERR_OK;
5099 /********************************************************************
5100 * copy a strings array and convert to UNICODE
5102 * convert an array of ascii string to a UNICODE string
5103 ********************************************************************/
5105 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5107 int i=0;
5108 int j=0;
5109 const char *v;
5110 pstring line;
5111 uint16 *tuary;
5113 DEBUG(6,("init_unistr_array\n"));
5114 *uni_array=NULL;
5116 while (True)
5118 if ( !char_array )
5119 v = "";
5120 else
5122 v = char_array[i];
5123 if (!v)
5124 v = ""; /* hack to handle null lists */
5127 /* hack to allow this to be used in places other than when generating
5128 the list of dependent files */
5130 if ( servername )
5131 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5132 else
5133 pstrcpy( line, v );
5135 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5137 /* add one extra unit16 for the second terminating NULL */
5139 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5140 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5141 return 0;
5142 } else
5143 *uni_array = tuary;
5145 if ( !strlen(v) )
5146 break;
5148 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5149 i++;
5152 if (*uni_array) {
5153 /* special case for ""; we need to add both NULL's here */
5154 if (!j)
5155 (*uni_array)[j++]=0x0000;
5156 (*uni_array)[j]=0x0000;
5159 DEBUGADD(6,("last one:done\n"));
5161 /* return size of array in uint16's */
5163 return j+1;
5166 /********************************************************************
5167 * construct_printer_info_3
5168 * fill a printer_info_3 struct
5169 ********************************************************************/
5171 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5173 pstring temp;
5175 ZERO_STRUCTP(info);
5177 info->version=driver.info_3->cversion;
5179 init_unistr( &info->name, driver.info_3->name );
5180 init_unistr( &info->architecture, driver.info_3->environment );
5182 if (strlen(driver.info_3->driverpath)) {
5183 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5184 init_unistr( &info->driverpath, temp );
5185 } else
5186 init_unistr( &info->driverpath, "" );
5188 if (strlen(driver.info_3->datafile)) {
5189 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5190 init_unistr( &info->datafile, temp );
5191 } else
5192 init_unistr( &info->datafile, "" );
5194 if (strlen(driver.info_3->configfile)) {
5195 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5196 init_unistr( &info->configfile, temp );
5197 } else
5198 init_unistr( &info->configfile, "" );
5200 if (strlen(driver.info_3->helpfile)) {
5201 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5202 init_unistr( &info->helpfile, temp );
5203 } else
5204 init_unistr( &info->helpfile, "" );
5206 init_unistr( &info->monitorname, driver.info_3->monitorname );
5207 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5209 info->dependentfiles=NULL;
5210 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5213 /********************************************************************
5214 * construct_printer_info_3
5215 * fill a printer_info_3 struct
5216 ********************************************************************/
5218 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5220 NT_PRINTER_INFO_LEVEL *printer = NULL;
5221 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5222 WERROR status;
5223 ZERO_STRUCT(driver);
5225 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5226 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5227 if (!W_ERROR_IS_OK(status))
5228 return WERR_INVALID_PRINTER_NAME;
5230 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5231 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5233 #if 0 /* JERRY */
5236 * I put this code in during testing. Helpful when commenting out the
5237 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5238 * as win2k always queries the driver using an infor level of 6.
5239 * I've left it in (but ifdef'd out) because I'll probably
5240 * use it in experimentation again in the future. --jerry 22/01/2002
5243 if (!W_ERROR_IS_OK(status)) {
5245 * Is this a W2k client ?
5247 if (version == 3) {
5248 /* Yes - try again with a WinNT driver. */
5249 version = 2;
5250 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5251 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5253 #endif
5255 if (!W_ERROR_IS_OK(status)) {
5256 free_a_printer(&printer,2);
5257 return WERR_UNKNOWN_PRINTER_DRIVER;
5260 #if 0 /* JERRY */
5262 #endif
5265 fill_printer_driver_info_3(info, driver, servername);
5267 free_a_printer(&printer,2);
5269 return WERR_OK;
5272 /********************************************************************
5273 * construct_printer_info_6
5274 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5275 ********************************************************************/
5277 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5279 pstring temp;
5280 fstring nullstr;
5282 ZERO_STRUCTP(info);
5283 memset(&nullstr, '\0', sizeof(fstring));
5285 info->version=driver.info_3->cversion;
5287 init_unistr( &info->name, driver.info_3->name );
5288 init_unistr( &info->architecture, driver.info_3->environment );
5290 if (strlen(driver.info_3->driverpath)) {
5291 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5292 init_unistr( &info->driverpath, temp );
5293 } else
5294 init_unistr( &info->driverpath, "" );
5296 if (strlen(driver.info_3->datafile)) {
5297 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5298 init_unistr( &info->datafile, temp );
5299 } else
5300 init_unistr( &info->datafile, "" );
5302 if (strlen(driver.info_3->configfile)) {
5303 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5304 init_unistr( &info->configfile, temp );
5305 } else
5306 init_unistr( &info->configfile, "" );
5308 if (strlen(driver.info_3->helpfile)) {
5309 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5310 init_unistr( &info->helpfile, temp );
5311 } else
5312 init_unistr( &info->helpfile, "" );
5314 init_unistr( &info->monitorname, driver.info_3->monitorname );
5315 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5317 info->dependentfiles = NULL;
5318 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5320 info->previousdrivernames=NULL;
5321 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5323 info->driver_date.low=0;
5324 info->driver_date.high=0;
5326 info->padding=0;
5327 info->driver_version_low=0;
5328 info->driver_version_high=0;
5330 init_unistr( &info->mfgname, "");
5331 init_unistr( &info->oem_url, "");
5332 init_unistr( &info->hardware_id, "");
5333 init_unistr( &info->provider, "");
5336 /********************************************************************
5337 * construct_printer_info_6
5338 * fill a printer_info_6 struct
5339 ********************************************************************/
5341 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5342 fstring servername, fstring architecture, uint32 version)
5344 NT_PRINTER_INFO_LEVEL *printer = NULL;
5345 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5346 WERROR status;
5348 ZERO_STRUCT(driver);
5350 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5352 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5354 if (!W_ERROR_IS_OK(status))
5355 return WERR_INVALID_PRINTER_NAME;
5357 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5359 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5361 if (!W_ERROR_IS_OK(status))
5364 * Is this a W2k client ?
5367 if (version < 3) {
5368 free_a_printer(&printer,2);
5369 return WERR_UNKNOWN_PRINTER_DRIVER;
5372 /* Yes - try again with a WinNT driver. */
5373 version = 2;
5374 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5375 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5376 if (!W_ERROR_IS_OK(status)) {
5377 free_a_printer(&printer,2);
5378 return WERR_UNKNOWN_PRINTER_DRIVER;
5382 fill_printer_driver_info_6(info, driver, servername);
5384 free_a_printer(&printer,2);
5385 free_a_printer_driver(driver, 3);
5387 return WERR_OK;
5390 /****************************************************************************
5391 ****************************************************************************/
5393 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5395 SAFE_FREE(info->dependentfiles);
5398 /****************************************************************************
5399 ****************************************************************************/
5401 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5403 SAFE_FREE(info->dependentfiles);
5407 /****************************************************************************
5408 ****************************************************************************/
5410 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5412 DRIVER_INFO_1 *info=NULL;
5413 WERROR status;
5415 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5416 return WERR_NOMEM;
5418 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5419 if (!W_ERROR_IS_OK(status)) {
5420 SAFE_FREE(info);
5421 return status;
5424 /* check the required size. */
5425 *needed += spoolss_size_printer_driver_info_1(info);
5427 if (!alloc_buffer_size(buffer, *needed)) {
5428 SAFE_FREE(info);
5429 return WERR_INSUFFICIENT_BUFFER;
5432 /* fill the buffer with the structures */
5433 smb_io_printer_driver_info_1("", buffer, info, 0);
5435 /* clear memory */
5436 SAFE_FREE(info);
5438 if (*needed > offered)
5439 return WERR_INSUFFICIENT_BUFFER;
5441 return WERR_OK;
5444 /****************************************************************************
5445 ****************************************************************************/
5447 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5449 DRIVER_INFO_2 *info=NULL;
5450 WERROR status;
5452 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5453 return WERR_NOMEM;
5455 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5456 if (!W_ERROR_IS_OK(status)) {
5457 SAFE_FREE(info);
5458 return status;
5461 /* check the required size. */
5462 *needed += spoolss_size_printer_driver_info_2(info);
5464 if (!alloc_buffer_size(buffer, *needed)) {
5465 SAFE_FREE(info);
5466 return WERR_INSUFFICIENT_BUFFER;
5469 /* fill the buffer with the structures */
5470 smb_io_printer_driver_info_2("", buffer, info, 0);
5472 /* clear memory */
5473 SAFE_FREE(info);
5475 if (*needed > offered)
5476 return WERR_INSUFFICIENT_BUFFER;
5478 return WERR_OK;
5481 /****************************************************************************
5482 ****************************************************************************/
5484 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5486 DRIVER_INFO_3 info;
5487 WERROR status;
5489 ZERO_STRUCT(info);
5491 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5492 if (!W_ERROR_IS_OK(status)) {
5493 return status;
5496 /* check the required size. */
5497 *needed += spoolss_size_printer_driver_info_3(&info);
5499 if (!alloc_buffer_size(buffer, *needed)) {
5500 free_printer_driver_info_3(&info);
5501 return WERR_INSUFFICIENT_BUFFER;
5504 /* fill the buffer with the structures */
5505 smb_io_printer_driver_info_3("", buffer, &info, 0);
5507 free_printer_driver_info_3(&info);
5509 if (*needed > offered)
5510 return WERR_INSUFFICIENT_BUFFER;
5512 return WERR_OK;
5515 /****************************************************************************
5516 ****************************************************************************/
5518 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5520 DRIVER_INFO_6 info;
5521 WERROR status;
5523 ZERO_STRUCT(info);
5525 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5526 if (!W_ERROR_IS_OK(status)) {
5527 return status;
5530 /* check the required size. */
5531 *needed += spoolss_size_printer_driver_info_6(&info);
5533 if (!alloc_buffer_size(buffer, *needed)) {
5534 free_printer_driver_info_6(&info);
5535 return WERR_INSUFFICIENT_BUFFER;
5538 /* fill the buffer with the structures */
5539 smb_io_printer_driver_info_6("", buffer, &info, 0);
5541 free_printer_driver_info_6(&info);
5543 if (*needed > offered)
5544 return WERR_INSUFFICIENT_BUFFER;
5546 return WERR_OK;
5549 /****************************************************************************
5550 ****************************************************************************/
5552 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5554 POLICY_HND *handle = &q_u->handle;
5555 UNISTR2 *uni_arch = &q_u->architecture;
5556 uint32 level = q_u->level;
5557 uint32 clientmajorversion = q_u->clientmajorversion;
5558 NEW_BUFFER *buffer = NULL;
5559 uint32 offered = q_u->offered;
5560 uint32 *needed = &r_u->needed;
5561 uint32 *servermajorversion = &r_u->servermajorversion;
5562 uint32 *serverminorversion = &r_u->serverminorversion;
5564 fstring servername;
5565 fstring architecture;
5566 int snum;
5568 /* that's an [in out] buffer */
5569 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5570 buffer = r_u->buffer;
5572 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5574 *needed = 0;
5575 *servermajorversion = 0;
5576 *serverminorversion = 0;
5578 fstrcpy(servername, get_called_name());
5579 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5581 if (!get_printer_snum(p, handle, &snum))
5582 return WERR_BADFID;
5584 switch (level) {
5585 case 1:
5586 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5587 case 2:
5588 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5589 case 3:
5590 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5591 case 6:
5592 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5595 return WERR_UNKNOWN_LEVEL;
5598 /****************************************************************************
5599 ****************************************************************************/
5601 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5603 POLICY_HND *handle = &q_u->handle;
5605 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5607 if (!Printer) {
5608 DEBUG(3,("Error in startpageprinter printer handle\n"));
5609 return WERR_BADFID;
5612 Printer->page_started=True;
5613 return WERR_OK;
5616 /****************************************************************************
5617 ****************************************************************************/
5619 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5621 POLICY_HND *handle = &q_u->handle;
5622 int snum;
5624 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5626 if (!Printer) {
5627 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5628 return WERR_BADFID;
5631 if (!get_printer_snum(p, handle, &snum))
5632 return WERR_BADFID;
5634 Printer->page_started=False;
5635 print_job_endpage(snum, Printer->jobid);
5637 return WERR_OK;
5640 /********************************************************************
5641 * api_spoolss_getprinter
5642 * called from the spoolss dispatcher
5644 ********************************************************************/
5646 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5648 POLICY_HND *handle = &q_u->handle;
5649 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5650 uint32 *jobid = &r_u->jobid;
5652 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5653 int snum;
5654 pstring jobname;
5655 fstring datatype;
5656 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5657 struct current_user user;
5659 if (!Printer) {
5660 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5661 return WERR_BADFID;
5664 get_current_user(&user, p);
5667 * a nice thing with NT is it doesn't listen to what you tell it.
5668 * when asked to send _only_ RAW datas, it tries to send datas
5669 * in EMF format.
5671 * So I add checks like in NT Server ...
5674 if (info_1->p_datatype != 0) {
5675 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5676 if (strcmp(datatype, "RAW") != 0) {
5677 (*jobid)=0;
5678 return WERR_INVALID_DATATYPE;
5682 /* get the share number of the printer */
5683 if (!get_printer_snum(p, handle, &snum)) {
5684 return WERR_BADFID;
5687 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5689 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5691 /* An error occured in print_job_start() so return an appropriate
5692 NT error code. */
5694 if (Printer->jobid == -1) {
5695 return map_werror_from_unix(errno);
5698 Printer->document_started=True;
5699 (*jobid) = Printer->jobid;
5701 return WERR_OK;
5704 /********************************************************************
5705 * api_spoolss_getprinter
5706 * called from the spoolss dispatcher
5708 ********************************************************************/
5710 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5712 POLICY_HND *handle = &q_u->handle;
5714 return _spoolss_enddocprinter_internal(p, handle);
5717 /****************************************************************************
5718 ****************************************************************************/
5720 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5722 POLICY_HND *handle = &q_u->handle;
5723 uint32 buffer_size = q_u->buffer_size;
5724 uint8 *buffer = q_u->buffer;
5725 uint32 *buffer_written = &q_u->buffer_size2;
5726 int snum;
5727 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5729 if (!Printer) {
5730 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5731 r_u->buffer_written = q_u->buffer_size2;
5732 return WERR_BADFID;
5735 if (!get_printer_snum(p, handle, &snum))
5736 return WERR_BADFID;
5738 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5739 if (*buffer_written == -1) {
5740 r_u->buffer_written = 0;
5741 if (errno == ENOSPC)
5742 return WERR_NO_SPOOL_SPACE;
5743 else
5744 return WERR_ACCESS_DENIED;
5747 r_u->buffer_written = q_u->buffer_size2;
5749 return WERR_OK;
5752 /********************************************************************
5753 * api_spoolss_getprinter
5754 * called from the spoolss dispatcher
5756 ********************************************************************/
5758 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5759 pipes_struct *p)
5761 struct current_user user;
5762 int snum;
5763 WERROR errcode = WERR_BADFUNC;
5764 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5766 get_current_user(&user, p);
5768 if (!Printer) {
5769 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5770 return WERR_BADFID;
5773 if (!get_printer_snum(p, handle, &snum))
5774 return WERR_BADFID;
5776 switch (command) {
5777 case PRINTER_CONTROL_PAUSE:
5778 if (print_queue_pause(&user, snum, &errcode)) {
5779 errcode = WERR_OK;
5781 break;
5782 case PRINTER_CONTROL_RESUME:
5783 case PRINTER_CONTROL_UNPAUSE:
5784 if (print_queue_resume(&user, snum, &errcode)) {
5785 errcode = WERR_OK;
5787 break;
5788 case PRINTER_CONTROL_PURGE:
5789 if (print_queue_purge(&user, snum, &errcode)) {
5790 errcode = WERR_OK;
5792 break;
5793 default:
5794 return WERR_UNKNOWN_LEVEL;
5797 return errcode;
5800 /********************************************************************
5801 * api_spoolss_abortprinter
5802 * From MSDN: "Deletes printer's spool file if printer is configured
5803 * for spooling"
5804 ********************************************************************/
5806 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5808 POLICY_HND *handle = &q_u->handle;
5809 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5810 int snum;
5811 struct current_user user;
5812 WERROR errcode = WERR_OK;
5814 if (!Printer) {
5815 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5816 return WERR_BADFID;
5819 if (!get_printer_snum(p, handle, &snum))
5820 return WERR_BADFID;
5822 get_current_user( &user, p );
5824 print_job_delete( &user, snum, Printer->jobid, &errcode );
5826 return errcode;
5829 /********************************************************************
5830 * called by spoolss_api_setprinter
5831 * when updating a printer description
5832 ********************************************************************/
5834 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5835 const SPOOL_PRINTER_INFO_LEVEL *info,
5836 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5838 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5839 struct current_user user;
5840 WERROR result;
5841 int snum;
5843 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5845 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5846 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5847 OUR_HANDLE(handle)));
5849 result = WERR_BADFID;
5850 goto done;
5853 /* NT seems to like setting the security descriptor even though
5854 nothing may have actually changed. This causes annoying
5855 dialog boxes when the user doesn't have permission to change
5856 the security descriptor. */
5858 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5860 if (DEBUGLEVEL >= 10) {
5861 SEC_ACL *the_acl;
5862 int i;
5864 the_acl = old_secdesc_ctr->sec->dacl;
5865 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5866 PRINTERNAME(snum), the_acl->num_aces));
5868 for (i = 0; i < the_acl->num_aces; i++) {
5869 fstring sid_str;
5871 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5873 DEBUG(10, ("%s 0x%08x\n", sid_str,
5874 the_acl->ace[i].info.mask));
5877 the_acl = secdesc_ctr->sec->dacl;
5879 if (the_acl) {
5880 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5881 PRINTERNAME(snum), the_acl->num_aces));
5883 for (i = 0; i < the_acl->num_aces; i++) {
5884 fstring sid_str;
5886 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5888 DEBUG(10, ("%s 0x%08x\n", sid_str,
5889 the_acl->ace[i].info.mask));
5891 } else {
5892 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5896 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5898 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5899 result = WERR_OK;
5900 goto done;
5903 /* Work out which user is performing the operation */
5905 get_current_user(&user, p);
5907 /* Check the user has permissions to change the security
5908 descriptor. By experimentation with two NT machines, the user
5909 requires Full Access to the printer to change security
5910 information. */
5912 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5913 result = WERR_ACCESS_DENIED;
5914 goto done;
5917 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5919 done:
5921 return result;
5924 /********************************************************************
5925 Do Samba sanity checks on a printer info struct.
5926 this has changed purpose: it now "canonicalises" printer
5927 info from a client rather than just checking it is correct
5928 ********************************************************************/
5930 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5932 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5933 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5935 /* we force some elements to "correct" values */
5936 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5937 fstrcpy(info->sharename, lp_servicename(snum));
5938 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5939 get_called_name(), info->sharename);
5940 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5943 return True;
5946 /****************************************************************************
5947 ****************************************************************************/
5949 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5951 extern userdom_struct current_user_info;
5952 char *cmd = lp_addprinter_cmd();
5953 char **qlines;
5954 pstring command;
5955 int numlines;
5956 int ret;
5957 int fd;
5958 fstring remote_machine = "%m";
5960 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5962 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5963 cmd, printer->info_2->printername, printer->info_2->sharename,
5964 printer->info_2->portname, printer->info_2->drivername,
5965 printer->info_2->location, printer->info_2->comment, remote_machine);
5967 DEBUG(10,("Running [%s]\n", command));
5968 ret = smbrun(command, &fd);
5969 DEBUGADD(10,("returned [%d]\n", ret));
5971 if ( ret != 0 ) {
5972 if (fd != -1)
5973 close(fd);
5974 return False;
5977 numlines = 0;
5978 /* Get lines and convert them back to dos-codepage */
5979 qlines = fd_lines_load(fd, &numlines);
5980 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5981 close(fd);
5983 if(numlines) {
5984 /* Set the portname to what the script says the portname should be. */
5985 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5986 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5988 /* Send SIGHUP to process group... is there a better way? */
5989 kill(0, SIGHUP);
5991 /* reload our services immediately */
5992 reload_services( False );
5995 file_lines_free(qlines);
5996 return True;
5999 /********************************************************************
6000 * Called by spoolss_api_setprinter
6001 * when updating a printer description.
6002 ********************************************************************/
6004 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6005 const SPOOL_PRINTER_INFO_LEVEL *info,
6006 DEVICEMODE *devmode)
6008 int snum;
6009 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6010 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6011 WERROR result;
6012 UNISTR2 buffer;
6013 fstring asc_buffer;
6015 DEBUG(8,("update_printer\n"));
6017 result = WERR_OK;
6019 if (!Printer) {
6020 result = WERR_BADFID;
6021 goto done;
6024 if (!get_printer_snum(p, handle, &snum)) {
6025 result = WERR_BADFID;
6026 goto done;
6029 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6030 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6031 result = WERR_BADFID;
6032 goto done;
6035 DEBUGADD(8,("Converting info_2 struct\n"));
6038 * convert_printer_info converts the incoming
6039 * info from the client and overwrites the info
6040 * just read from the tdb in the pointer 'printer'.
6043 if (!convert_printer_info(info, printer, level)) {
6044 result = WERR_NOMEM;
6045 goto done;
6048 if (devmode) {
6049 /* we have a valid devmode
6050 convert it and link it*/
6052 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6053 if (!convert_devicemode(printer->info_2->printername, devmode,
6054 &printer->info_2->devmode)) {
6055 result = WERR_NOMEM;
6056 goto done;
6060 /* Do sanity check on the requested changes for Samba */
6062 if (!check_printer_ok(printer->info_2, snum)) {
6063 result = WERR_INVALID_PARAM;
6064 goto done;
6067 /* FIXME!!! If the driver has changed we really should verify that
6068 it is installed before doing much else --jerry */
6070 /* Check calling user has permission to update printer description */
6072 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6073 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6074 result = WERR_ACCESS_DENIED;
6075 goto done;
6078 /* Call addprinter hook */
6079 /* Check changes to see if this is really needed */
6081 if ( *lp_addprinter_cmd()
6082 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6083 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6084 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6085 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6087 if ( !add_printer_hook(printer) ) {
6088 result = WERR_ACCESS_DENIED;
6089 goto done;
6093 * make sure we actually reload the services after
6094 * this as smb.conf could have a new section in it
6095 * .... shouldn't .... but could
6097 reload_services(False);
6101 * When a *new* driver is bound to a printer, the drivername is used to
6102 * lookup previously saved driver initialization info, which is then
6103 * bound to the printer, simulating what happens in the Windows arch.
6105 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6107 if (!set_driver_init(printer, 2))
6109 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6110 printer->info_2->drivername));
6113 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6114 printer->info_2->drivername));
6116 notify_printer_driver(snum, printer->info_2->drivername);
6120 * flag which changes actually occured. This is a small subset of
6121 * all the possible changes. We also have to update things in the
6122 * DsSpooler key.
6125 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6126 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6127 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6128 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6130 notify_printer_comment(snum, printer->info_2->comment);
6133 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6134 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6135 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6136 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6137 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6138 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6140 notify_printer_sharename(snum, printer->info_2->sharename);
6143 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6144 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6145 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6146 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6148 notify_printer_port(snum, printer->info_2->portname);
6151 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6152 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6153 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6154 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6156 notify_printer_location(snum, printer->info_2->location);
6159 /* here we need to update some more DsSpooler keys */
6160 /* uNCName, serverName, shortServerName */
6162 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6163 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6164 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6165 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6166 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6168 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6169 global_myname(), printer->info_2->sharename );
6170 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6171 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6172 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6174 /* Update printer info */
6175 result = mod_a_printer(*printer, 2);
6177 done:
6178 free_a_printer(&printer, 2);
6179 free_a_printer(&old_printer, 2);
6182 return result;
6185 /****************************************************************************
6186 ****************************************************************************/
6187 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6188 const SPOOL_PRINTER_INFO_LEVEL *info)
6190 #ifdef HAVE_ADS
6191 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6192 int snum;
6193 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6195 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6197 if (!Printer)
6198 return WERR_BADFID;
6200 if (!get_printer_snum(p, handle, &snum))
6201 return WERR_BADFID;
6203 nt_printer_publish(Printer, snum, info7->action);
6205 return WERR_OK;
6206 #else
6207 return WERR_UNKNOWN_LEVEL;
6208 #endif
6210 /****************************************************************************
6211 ****************************************************************************/
6213 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6215 POLICY_HND *handle = &q_u->handle;
6216 uint32 level = q_u->level;
6217 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6218 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6219 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6220 uint32 command = q_u->command;
6222 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6224 if (!Printer) {
6225 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6226 return WERR_BADFID;
6229 /* check the level */
6230 switch (level) {
6231 case 0:
6232 return control_printer(handle, command, p);
6233 case 2:
6234 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6235 case 3:
6236 return update_printer_sec(handle, level, info, p,
6237 secdesc_ctr);
6238 case 7:
6239 return publish_or_unpublish_printer(p, handle, info);
6240 default:
6241 return WERR_UNKNOWN_LEVEL;
6245 /****************************************************************************
6246 ****************************************************************************/
6248 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6250 POLICY_HND *handle = &q_u->handle;
6251 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6253 if (!Printer) {
6254 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6255 return WERR_BADFID;
6258 if (Printer->notify.client_connected==True) {
6259 int snum = -1;
6261 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6262 snum = -1;
6263 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6264 !get_printer_snum(p, handle, &snum) )
6265 return WERR_BADFID;
6267 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6270 Printer->notify.flags=0;
6271 Printer->notify.options=0;
6272 Printer->notify.localmachine[0]='\0';
6273 Printer->notify.printerlocal=0;
6274 if (Printer->notify.option)
6275 free_spool_notify_option(&Printer->notify.option);
6276 Printer->notify.client_connected=False;
6278 return WERR_OK;
6281 /****************************************************************************
6282 ****************************************************************************/
6284 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6286 /* that's an [in out] buffer (despite appearences to the contrary) */
6287 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6289 r_u->needed = 0;
6290 return WERR_INVALID_PARAM; /* this is what a NT server
6291 returns for AddJob. AddJob
6292 must fail on non-local
6293 printers */
6296 /****************************************************************************
6297 ****************************************************************************/
6299 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6300 int position, int snum)
6302 pstring temp_name;
6304 struct tm *t;
6306 t=gmtime(&queue->time);
6307 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6309 job_info->jobid=queue->job;
6310 init_unistr(&job_info->printername, lp_servicename(snum));
6311 init_unistr(&job_info->machinename, temp_name);
6312 init_unistr(&job_info->username, queue->fs_user);
6313 init_unistr(&job_info->document, queue->fs_file);
6314 init_unistr(&job_info->datatype, "RAW");
6315 init_unistr(&job_info->text_status, "");
6316 job_info->status=nt_printj_status(queue->status);
6317 job_info->priority=queue->priority;
6318 job_info->position=position;
6319 job_info->totalpages=queue->page_count;
6320 job_info->pagesprinted=0;
6322 make_systemtime(&job_info->submitted, t);
6325 /****************************************************************************
6326 ****************************************************************************/
6328 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6329 int position, int snum,
6330 NT_PRINTER_INFO_LEVEL *ntprinter,
6331 DEVICEMODE *devmode)
6333 pstring temp_name;
6334 struct tm *t;
6336 t=gmtime(&queue->time);
6337 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6339 job_info->jobid=queue->job;
6341 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6343 init_unistr(&job_info->machinename, temp_name);
6344 init_unistr(&job_info->username, queue->fs_user);
6345 init_unistr(&job_info->document, queue->fs_file);
6346 init_unistr(&job_info->notifyname, queue->fs_user);
6347 init_unistr(&job_info->datatype, "RAW");
6348 init_unistr(&job_info->printprocessor, "winprint");
6349 init_unistr(&job_info->parameters, "");
6350 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6351 init_unistr(&job_info->text_status, "");
6353 /* and here the security descriptor */
6355 job_info->status=nt_printj_status(queue->status);
6356 job_info->priority=queue->priority;
6357 job_info->position=position;
6358 job_info->starttime=0;
6359 job_info->untiltime=0;
6360 job_info->totalpages=queue->page_count;
6361 job_info->size=queue->size;
6362 make_systemtime(&(job_info->submitted), t);
6363 job_info->timeelapsed=0;
6364 job_info->pagesprinted=0;
6366 job_info->devmode = devmode;
6368 return (True);
6371 /****************************************************************************
6372 Enumjobs at level 1.
6373 ****************************************************************************/
6375 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6376 NEW_BUFFER *buffer, uint32 offered,
6377 uint32 *needed, uint32 *returned)
6379 JOB_INFO_1 *info;
6380 int i;
6382 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6383 if (info==NULL) {
6384 SAFE_FREE(queue);
6385 *returned=0;
6386 return WERR_NOMEM;
6389 for (i=0; i<*returned; i++)
6390 fill_job_info_1(&info[i], &queue[i], i, snum);
6392 SAFE_FREE(queue);
6394 /* check the required size. */
6395 for (i=0; i<*returned; i++)
6396 (*needed) += spoolss_size_job_info_1(&info[i]);
6398 if (!alloc_buffer_size(buffer, *needed)) {
6399 SAFE_FREE(info);
6400 return WERR_INSUFFICIENT_BUFFER;
6403 /* fill the buffer with the structures */
6404 for (i=0; i<*returned; i++)
6405 smb_io_job_info_1("", buffer, &info[i], 0);
6407 /* clear memory */
6408 SAFE_FREE(info);
6410 if (*needed > offered) {
6411 *returned=0;
6412 return WERR_INSUFFICIENT_BUFFER;
6415 return WERR_OK;
6418 /****************************************************************************
6419 Enumjobs at level 2.
6420 ****************************************************************************/
6422 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6423 NEW_BUFFER *buffer, uint32 offered,
6424 uint32 *needed, uint32 *returned)
6426 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6427 JOB_INFO_2 *info = NULL;
6428 int i;
6429 WERROR result;
6430 DEVICEMODE *devmode = NULL;
6432 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6433 if (info==NULL) {
6434 *returned=0;
6435 result = WERR_NOMEM;
6436 goto done;
6439 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6440 if (!W_ERROR_IS_OK(result)) {
6441 *returned = 0;
6442 goto done;
6445 /* this should not be a failure condition if the devmode is NULL */
6447 devmode = construct_dev_mode(snum);
6449 for (i=0; i<*returned; i++)
6450 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6451 devmode);
6453 free_a_printer(&ntprinter, 2);
6454 SAFE_FREE(queue);
6456 /* check the required size. */
6457 for (i=0; i<*returned; i++)
6458 (*needed) += spoolss_size_job_info_2(&info[i]);
6460 if (*needed > offered) {
6461 *returned=0;
6462 result = WERR_INSUFFICIENT_BUFFER;
6463 goto done;
6466 if (!alloc_buffer_size(buffer, *needed)) {
6467 SAFE_FREE(info);
6468 result = WERR_INSUFFICIENT_BUFFER;
6469 goto done;
6472 /* fill the buffer with the structures */
6473 for (i=0; i<*returned; i++)
6474 smb_io_job_info_2("", buffer, &info[i], 0);
6476 result = WERR_OK;
6478 done:
6479 free_a_printer(&ntprinter, 2);
6480 free_devmode(devmode);
6481 SAFE_FREE(queue);
6482 SAFE_FREE(info);
6484 return result;
6488 /****************************************************************************
6489 Enumjobs.
6490 ****************************************************************************/
6492 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6494 POLICY_HND *handle = &q_u->handle;
6495 uint32 level = q_u->level;
6496 NEW_BUFFER *buffer = NULL;
6497 uint32 offered = q_u->offered;
6498 uint32 *needed = &r_u->needed;
6499 uint32 *returned = &r_u->returned;
6500 WERROR wret;
6502 int snum;
6503 print_status_struct prt_status;
6504 print_queue_struct *queue=NULL;
6506 /* that's an [in out] buffer */
6507 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6508 buffer = r_u->buffer;
6510 DEBUG(4,("_spoolss_enumjobs\n"));
6512 *needed=0;
6513 *returned=0;
6515 if (!get_printer_snum(p, handle, &snum))
6516 return WERR_BADFID;
6518 *returned = print_queue_status(snum, &queue, &prt_status);
6519 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6521 if (*returned == 0) {
6522 set_enumjobs_timestamp(snum);
6523 SAFE_FREE(queue);
6524 return WERR_OK;
6527 switch (level) {
6528 case 1:
6529 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6530 set_enumjobs_timestamp(snum);
6531 return wret;
6532 case 2:
6533 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6534 set_enumjobs_timestamp(snum);
6535 return wret;
6536 default:
6537 SAFE_FREE(queue);
6538 *returned=0;
6539 return WERR_UNKNOWN_LEVEL;
6543 /****************************************************************************
6544 ****************************************************************************/
6546 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6548 return WERR_OK;
6551 /****************************************************************************
6552 ****************************************************************************/
6554 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6556 POLICY_HND *handle = &q_u->handle;
6557 uint32 jobid = q_u->jobid;
6558 uint32 command = q_u->command;
6560 struct current_user user;
6561 int snum;
6562 WERROR errcode = WERR_BADFUNC;
6564 if (!get_printer_snum(p, handle, &snum)) {
6565 return WERR_BADFID;
6568 if (!print_job_exists(snum, jobid)) {
6569 return WERR_INVALID_PRINTER_NAME;
6572 get_current_user(&user, p);
6574 switch (command) {
6575 case JOB_CONTROL_CANCEL:
6576 case JOB_CONTROL_DELETE:
6577 if (print_job_delete(&user, snum, jobid, &errcode)) {
6578 errcode = WERR_OK;
6580 break;
6581 case JOB_CONTROL_PAUSE:
6582 if (print_job_pause(&user, snum, jobid, &errcode)) {
6583 errcode = WERR_OK;
6585 break;
6586 case JOB_CONTROL_RESTART:
6587 case JOB_CONTROL_RESUME:
6588 if (print_job_resume(&user, snum, jobid, &errcode)) {
6589 errcode = WERR_OK;
6591 break;
6592 default:
6593 return WERR_UNKNOWN_LEVEL;
6596 return errcode;
6599 /****************************************************************************
6600 Enumerates all printer drivers at level 1.
6601 ****************************************************************************/
6603 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6605 int i;
6606 int ndrivers;
6607 uint32 version;
6608 fstring *list = NULL;
6610 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6611 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6613 *returned=0;
6615 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6616 list=NULL;
6617 ndrivers=get_ntdrivers(&list, architecture, version);
6618 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6620 if(ndrivers == -1)
6621 return WERR_NOMEM;
6623 if(ndrivers != 0) {
6624 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6625 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6626 SAFE_FREE(driver_info_1);
6627 SAFE_FREE(list);
6628 return WERR_NOMEM;
6630 else driver_info_1 = tdi1;
6633 for (i=0; i<ndrivers; i++) {
6634 WERROR status;
6635 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6636 ZERO_STRUCT(driver);
6637 status = get_a_printer_driver(&driver, 3, list[i],
6638 architecture, version);
6639 if (!W_ERROR_IS_OK(status)) {
6640 SAFE_FREE(list);
6641 return status;
6643 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6644 free_a_printer_driver(driver, 3);
6647 *returned+=ndrivers;
6648 SAFE_FREE(list);
6651 /* check the required size. */
6652 for (i=0; i<*returned; i++) {
6653 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6654 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6657 if (!alloc_buffer_size(buffer, *needed)) {
6658 SAFE_FREE(driver_info_1);
6659 return WERR_INSUFFICIENT_BUFFER;
6662 /* fill the buffer with the driver structures */
6663 for (i=0; i<*returned; i++) {
6664 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6665 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6668 SAFE_FREE(driver_info_1);
6670 if (*needed > offered) {
6671 *returned=0;
6672 return WERR_INSUFFICIENT_BUFFER;
6675 return WERR_OK;
6678 /****************************************************************************
6679 Enumerates all printer drivers at level 2.
6680 ****************************************************************************/
6682 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6684 int i;
6685 int ndrivers;
6686 uint32 version;
6687 fstring *list = NULL;
6689 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6690 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6692 *returned=0;
6694 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6695 list=NULL;
6696 ndrivers=get_ntdrivers(&list, architecture, version);
6697 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6699 if(ndrivers == -1)
6700 return WERR_NOMEM;
6702 if(ndrivers != 0) {
6703 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6704 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6705 SAFE_FREE(driver_info_2);
6706 SAFE_FREE(list);
6707 return WERR_NOMEM;
6709 else driver_info_2 = tdi2;
6712 for (i=0; i<ndrivers; i++) {
6713 WERROR status;
6715 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6716 ZERO_STRUCT(driver);
6717 status = get_a_printer_driver(&driver, 3, list[i],
6718 architecture, version);
6719 if (!W_ERROR_IS_OK(status)) {
6720 SAFE_FREE(list);
6721 return status;
6723 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6724 free_a_printer_driver(driver, 3);
6727 *returned+=ndrivers;
6728 SAFE_FREE(list);
6731 /* check the required size. */
6732 for (i=0; i<*returned; i++) {
6733 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6734 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6737 if (!alloc_buffer_size(buffer, *needed)) {
6738 SAFE_FREE(driver_info_2);
6739 return WERR_INSUFFICIENT_BUFFER;
6742 /* fill the buffer with the form structures */
6743 for (i=0; i<*returned; i++) {
6744 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6745 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6748 SAFE_FREE(driver_info_2);
6750 if (*needed > offered) {
6751 *returned=0;
6752 return WERR_INSUFFICIENT_BUFFER;
6755 return WERR_OK;
6758 /****************************************************************************
6759 Enumerates all printer drivers at level 3.
6760 ****************************************************************************/
6762 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6764 int i;
6765 int ndrivers;
6766 uint32 version;
6767 fstring *list = NULL;
6769 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6770 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6772 *returned=0;
6774 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6775 list=NULL;
6776 ndrivers=get_ntdrivers(&list, architecture, version);
6777 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6779 if(ndrivers == -1)
6780 return WERR_NOMEM;
6782 if(ndrivers != 0) {
6783 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6784 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6785 SAFE_FREE(driver_info_3);
6786 SAFE_FREE(list);
6787 return WERR_NOMEM;
6789 else driver_info_3 = tdi3;
6792 for (i=0; i<ndrivers; i++) {
6793 WERROR status;
6795 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6796 ZERO_STRUCT(driver);
6797 status = get_a_printer_driver(&driver, 3, list[i],
6798 architecture, version);
6799 if (!W_ERROR_IS_OK(status)) {
6800 SAFE_FREE(list);
6801 return status;
6803 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6804 free_a_printer_driver(driver, 3);
6807 *returned+=ndrivers;
6808 SAFE_FREE(list);
6811 /* check the required size. */
6812 for (i=0; i<*returned; i++) {
6813 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6814 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6817 if (!alloc_buffer_size(buffer, *needed)) {
6818 SAFE_FREE(driver_info_3);
6819 return WERR_INSUFFICIENT_BUFFER;
6822 /* fill the buffer with the driver structures */
6823 for (i=0; i<*returned; i++) {
6824 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6825 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6828 for (i=0; i<*returned; i++)
6829 SAFE_FREE(driver_info_3[i].dependentfiles);
6831 SAFE_FREE(driver_info_3);
6833 if (*needed > offered) {
6834 *returned=0;
6835 return WERR_INSUFFICIENT_BUFFER;
6838 return WERR_OK;
6841 /****************************************************************************
6842 Enumerates all printer drivers.
6843 ****************************************************************************/
6845 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6847 UNISTR2 *environment = &q_u->environment;
6848 uint32 level = q_u->level;
6849 NEW_BUFFER *buffer = NULL;
6850 uint32 offered = q_u->offered;
6851 uint32 *needed = &r_u->needed;
6852 uint32 *returned = &r_u->returned;
6854 fstring *list = NULL;
6855 fstring servername;
6856 fstring architecture;
6858 /* that's an [in out] buffer */
6859 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6860 buffer = r_u->buffer;
6862 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6863 fstrcpy(servername, get_called_name());
6864 *needed=0;
6865 *returned=0;
6867 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6869 switch (level) {
6870 case 1:
6871 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6872 case 2:
6873 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6874 case 3:
6875 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6876 default:
6877 *returned=0;
6878 SAFE_FREE(list);
6879 return WERR_UNKNOWN_LEVEL;
6883 /****************************************************************************
6884 ****************************************************************************/
6886 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6888 form->flag=list->flag;
6889 init_unistr(&form->name, list->name);
6890 form->width=list->width;
6891 form->length=list->length;
6892 form->left=list->left;
6893 form->top=list->top;
6894 form->right=list->right;
6895 form->bottom=list->bottom;
6898 /****************************************************************************
6899 ****************************************************************************/
6901 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6903 uint32 level = q_u->level;
6904 NEW_BUFFER *buffer = NULL;
6905 uint32 offered = q_u->offered;
6906 uint32 *needed = &r_u->needed;
6907 uint32 *numofforms = &r_u->numofforms;
6908 uint32 numbuiltinforms;
6910 nt_forms_struct *list=NULL;
6911 nt_forms_struct *builtinlist=NULL;
6912 FORM_1 *forms_1;
6913 int buffer_size=0;
6914 int i;
6916 /* that's an [in out] buffer */
6917 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6918 buffer = r_u->buffer;
6920 DEBUG(4,("_spoolss_enumforms\n"));
6921 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6922 DEBUGADD(5,("Info level [%d]\n", level));
6924 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6925 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6926 *numofforms = get_ntforms(&list);
6927 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6928 *numofforms += numbuiltinforms;
6930 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6932 switch (level) {
6933 case 1:
6934 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6935 *numofforms=0;
6936 return WERR_NOMEM;
6939 /* construct the list of form structures */
6940 for (i=0; i<numbuiltinforms; i++) {
6941 DEBUGADD(6,("Filling form number [%d]\n",i));
6942 fill_form_1(&forms_1[i], &builtinlist[i]);
6945 SAFE_FREE(builtinlist);
6947 for (; i<*numofforms; i++) {
6948 DEBUGADD(6,("Filling form number [%d]\n",i));
6949 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6952 SAFE_FREE(list);
6954 /* check the required size. */
6955 for (i=0; i<numbuiltinforms; i++) {
6956 DEBUGADD(6,("adding form [%d]'s size\n",i));
6957 buffer_size += spoolss_size_form_1(&forms_1[i]);
6959 for (; i<*numofforms; i++) {
6960 DEBUGADD(6,("adding form [%d]'s size\n",i));
6961 buffer_size += spoolss_size_form_1(&forms_1[i]);
6964 *needed=buffer_size;
6966 if (!alloc_buffer_size(buffer, buffer_size)){
6967 SAFE_FREE(forms_1);
6968 return WERR_INSUFFICIENT_BUFFER;
6971 /* fill the buffer with the form structures */
6972 for (i=0; i<numbuiltinforms; i++) {
6973 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6974 smb_io_form_1("", buffer, &forms_1[i], 0);
6976 for (; i<*numofforms; i++) {
6977 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6978 smb_io_form_1("", buffer, &forms_1[i], 0);
6981 SAFE_FREE(forms_1);
6983 if (*needed > offered) {
6984 *numofforms=0;
6985 return WERR_INSUFFICIENT_BUFFER;
6987 else
6988 return WERR_OK;
6990 default:
6991 SAFE_FREE(list);
6992 SAFE_FREE(builtinlist);
6993 return WERR_UNKNOWN_LEVEL;
6998 /****************************************************************************
6999 ****************************************************************************/
7001 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7003 uint32 level = q_u->level;
7004 UNISTR2 *uni_formname = &q_u->formname;
7005 NEW_BUFFER *buffer = NULL;
7006 uint32 offered = q_u->offered;
7007 uint32 *needed = &r_u->needed;
7009 nt_forms_struct *list=NULL;
7010 nt_forms_struct builtin_form;
7011 BOOL foundBuiltin;
7012 FORM_1 form_1;
7013 fstring form_name;
7014 int buffer_size=0;
7015 int numofforms=0, i=0;
7017 /* that's an [in out] buffer */
7018 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7019 buffer = r_u->buffer;
7021 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7023 DEBUG(4,("_spoolss_getform\n"));
7024 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7025 DEBUGADD(5,("Info level [%d]\n", level));
7027 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7028 if (!foundBuiltin) {
7029 numofforms = get_ntforms(&list);
7030 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7032 if (numofforms == 0)
7033 return WERR_BADFID;
7036 switch (level) {
7037 case 1:
7038 if (foundBuiltin) {
7039 fill_form_1(&form_1, &builtin_form);
7040 } else {
7042 /* Check if the requested name is in the list of form structures */
7043 for (i=0; i<numofforms; i++) {
7045 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7047 if (strequal(form_name, list[i].name)) {
7048 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7049 fill_form_1(&form_1, &list[i]);
7050 break;
7054 SAFE_FREE(list);
7055 if (i == numofforms) {
7056 return WERR_BADFID;
7059 /* check the required size. */
7061 *needed=spoolss_size_form_1(&form_1);
7063 if (!alloc_buffer_size(buffer, buffer_size)){
7064 return WERR_INSUFFICIENT_BUFFER;
7067 if (*needed > offered) {
7068 return WERR_INSUFFICIENT_BUFFER;
7071 /* fill the buffer with the form structures */
7072 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7073 smb_io_form_1("", buffer, &form_1, 0);
7075 return WERR_OK;
7077 default:
7078 SAFE_FREE(list);
7079 return WERR_UNKNOWN_LEVEL;
7083 /****************************************************************************
7084 ****************************************************************************/
7086 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7088 init_unistr(&port->port_name, name);
7091 /****************************************************************************
7092 ****************************************************************************/
7094 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7096 init_unistr(&port->port_name, name);
7097 init_unistr(&port->monitor_name, "Local Monitor");
7098 init_unistr(&port->description, "Local Port");
7099 port->port_type=PORT_TYPE_WRITE;
7100 port->reserved=0x0;
7103 /****************************************************************************
7104 enumports level 1.
7105 ****************************************************************************/
7107 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7109 PORT_INFO_1 *ports=NULL;
7110 int i=0;
7112 if (*lp_enumports_cmd()) {
7113 char *cmd = lp_enumports_cmd();
7114 char **qlines;
7115 pstring command;
7116 int numlines;
7117 int ret;
7118 int fd;
7120 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7122 DEBUG(10,("Running [%s]\n", command));
7123 ret = smbrun(command, &fd);
7124 DEBUG(10,("Returned [%d]\n", ret));
7125 if (ret != 0) {
7126 if (fd != -1)
7127 close(fd);
7128 /* Is this the best error to return here? */
7129 return WERR_ACCESS_DENIED;
7132 numlines = 0;
7133 qlines = fd_lines_load(fd, &numlines);
7134 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7135 close(fd);
7137 if(numlines) {
7138 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7139 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7140 dos_errstr(WERR_NOMEM)));
7141 file_lines_free(qlines);
7142 return WERR_NOMEM;
7145 for (i=0; i<numlines; i++) {
7146 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7147 fill_port_1(&ports[i], qlines[i]);
7150 file_lines_free(qlines);
7153 *returned = numlines;
7155 } else {
7156 *returned = 1; /* Sole Samba port returned. */
7158 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7159 return WERR_NOMEM;
7161 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7163 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7166 /* check the required size. */
7167 for (i=0; i<*returned; i++) {
7168 DEBUGADD(6,("adding port [%d]'s size\n", i));
7169 *needed += spoolss_size_port_info_1(&ports[i]);
7172 if (!alloc_buffer_size(buffer, *needed)) {
7173 SAFE_FREE(ports);
7174 return WERR_INSUFFICIENT_BUFFER;
7177 /* fill the buffer with the ports structures */
7178 for (i=0; i<*returned; i++) {
7179 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7180 smb_io_port_1("", buffer, &ports[i], 0);
7183 SAFE_FREE(ports);
7185 if (*needed > offered) {
7186 *returned=0;
7187 return WERR_INSUFFICIENT_BUFFER;
7190 return WERR_OK;
7193 /****************************************************************************
7194 enumports level 2.
7195 ****************************************************************************/
7197 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7199 PORT_INFO_2 *ports=NULL;
7200 int i=0;
7202 if (*lp_enumports_cmd()) {
7203 char *cmd = lp_enumports_cmd();
7204 char *path;
7205 char **qlines;
7206 pstring tmp_file;
7207 pstring command;
7208 int numlines;
7209 int ret;
7210 int fd;
7212 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7213 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7214 else
7215 path = lp_lockdir();
7217 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7218 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7220 unlink(tmp_file);
7221 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7222 ret = smbrun(command, &fd);
7223 DEBUGADD(10,("returned [%d]\n", ret));
7224 if (ret != 0) {
7225 if (fd != -1)
7226 close(fd);
7227 /* Is this the best error to return here? */
7228 return WERR_ACCESS_DENIED;
7231 numlines = 0;
7232 qlines = fd_lines_load(fd, &numlines);
7233 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7234 close(fd);
7236 if(numlines) {
7237 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7238 file_lines_free(qlines);
7239 return WERR_NOMEM;
7242 for (i=0; i<numlines; i++) {
7243 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7244 fill_port_2(&(ports[i]), qlines[i]);
7247 file_lines_free(qlines);
7250 *returned = numlines;
7252 } else {
7254 *returned = 1;
7256 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7257 return WERR_NOMEM;
7259 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7261 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7264 /* check the required size. */
7265 for (i=0; i<*returned; i++) {
7266 DEBUGADD(6,("adding port [%d]'s size\n", i));
7267 *needed += spoolss_size_port_info_2(&ports[i]);
7270 if (!alloc_buffer_size(buffer, *needed)) {
7271 SAFE_FREE(ports);
7272 return WERR_INSUFFICIENT_BUFFER;
7275 /* fill the buffer with the ports structures */
7276 for (i=0; i<*returned; i++) {
7277 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7278 smb_io_port_2("", buffer, &ports[i], 0);
7281 SAFE_FREE(ports);
7283 if (*needed > offered) {
7284 *returned=0;
7285 return WERR_INSUFFICIENT_BUFFER;
7288 return WERR_OK;
7291 /****************************************************************************
7292 enumports.
7293 ****************************************************************************/
7295 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7297 uint32 level = q_u->level;
7298 NEW_BUFFER *buffer = NULL;
7299 uint32 offered = q_u->offered;
7300 uint32 *needed = &r_u->needed;
7301 uint32 *returned = &r_u->returned;
7303 /* that's an [in out] buffer */
7304 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7305 buffer = r_u->buffer;
7307 DEBUG(4,("_spoolss_enumports\n"));
7309 *returned=0;
7310 *needed=0;
7312 switch (level) {
7313 case 1:
7314 return enumports_level_1(buffer, offered, needed, returned);
7315 case 2:
7316 return enumports_level_2(buffer, offered, needed, returned);
7317 default:
7318 return WERR_UNKNOWN_LEVEL;
7322 /****************************************************************************
7323 ****************************************************************************/
7325 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7326 const SPOOL_PRINTER_INFO_LEVEL *info,
7327 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7328 uint32 user_switch, const SPOOL_USER_CTR *user,
7329 POLICY_HND *handle)
7331 NT_PRINTER_INFO_LEVEL *printer = NULL;
7332 fstring name;
7333 int snum;
7334 WERROR err = WERR_OK;
7336 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7337 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7338 return WERR_NOMEM;
7341 ZERO_STRUCTP(printer);
7343 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7344 if (!convert_printer_info(info, printer, 2)) {
7345 free_a_printer(&printer, 2);
7346 return WERR_NOMEM;
7349 /* check to see if the printer already exists */
7351 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7352 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7353 printer->info_2->sharename));
7354 free_a_printer(&printer, 2);
7355 return WERR_PRINTER_ALREADY_EXISTS;
7358 /* FIXME!!! smbd should check to see if the driver is installed before
7359 trying to add a printer like this --jerry */
7361 if (*lp_addprinter_cmd() ) {
7362 if ( !add_printer_hook(printer) ) {
7363 free_a_printer(&printer,2);
7364 return WERR_ACCESS_DENIED;
7368 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7369 printer->info_2->sharename);
7372 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7373 free_a_printer(&printer,2);
7374 return WERR_ACCESS_DENIED;
7377 /* you must be a printer admin to add a new printer */
7378 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7379 free_a_printer(&printer,2);
7380 return WERR_ACCESS_DENIED;
7384 * Do sanity check on the requested changes for Samba.
7387 if (!check_printer_ok(printer->info_2, snum)) {
7388 free_a_printer(&printer,2);
7389 return WERR_INVALID_PARAM;
7393 * When a printer is created, the drivername bound to the printer is used
7394 * to lookup previously saved driver initialization info, which is then
7395 * bound to the new printer, simulating what happens in the Windows arch.
7398 if (!devmode)
7400 set_driver_init(printer, 2);
7402 else
7404 /* A valid devmode was included, convert and link it
7406 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7408 if (!convert_devicemode(printer->info_2->printername, devmode,
7409 &printer->info_2->devmode))
7410 return WERR_NOMEM;
7413 /* write the ASCII on disk */
7414 err = mod_a_printer(*printer, 2);
7415 if (!W_ERROR_IS_OK(err)) {
7416 free_a_printer(&printer,2);
7417 return err;
7420 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7421 /* Handle open failed - remove addition. */
7422 del_a_printer(printer->info_2->sharename);
7423 free_a_printer(&printer,2);
7424 return WERR_ACCESS_DENIED;
7427 update_c_setprinter(False);
7428 free_a_printer(&printer,2);
7430 return WERR_OK;
7433 /****************************************************************************
7434 ****************************************************************************/
7436 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7438 UNISTR2 *uni_srv_name = &q_u->server_name;
7439 uint32 level = q_u->level;
7440 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7441 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7442 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7443 uint32 user_switch = q_u->user_switch;
7444 SPOOL_USER_CTR *user = &q_u->user_ctr;
7445 POLICY_HND *handle = &r_u->handle;
7447 switch (level) {
7448 case 1:
7449 /* we don't handle yet */
7450 /* but I know what to do ... */
7451 return WERR_UNKNOWN_LEVEL;
7452 case 2:
7453 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7454 devmode, sdb,
7455 user_switch, user, handle);
7456 default:
7457 return WERR_UNKNOWN_LEVEL;
7461 /****************************************************************************
7462 ****************************************************************************/
7464 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7466 uint32 level = q_u->level;
7467 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7468 WERROR err = WERR_OK;
7469 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7470 struct current_user user;
7471 fstring driver_name;
7472 uint32 version;
7474 ZERO_STRUCT(driver);
7476 get_current_user(&user, p);
7478 if (!convert_printer_driver_info(info, &driver, level)) {
7479 err = WERR_NOMEM;
7480 goto done;
7483 DEBUG(5,("Cleaning driver's information\n"));
7484 err = clean_up_driver_struct(driver, level, &user);
7485 if (!W_ERROR_IS_OK(err))
7486 goto done;
7488 DEBUG(5,("Moving driver to final destination\n"));
7489 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7490 if (W_ERROR_IS_OK(err))
7491 err = WERR_ACCESS_DENIED;
7492 goto done;
7495 if (add_a_printer_driver(driver, level)!=0) {
7496 err = WERR_ACCESS_DENIED;
7497 goto done;
7500 /* BEGIN_ADMIN_LOG */
7501 switch(level) {
7502 case 3:
7503 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7504 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7505 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7506 break;
7507 case 6:
7508 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7509 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7510 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7511 break;
7513 /* END_ADMIN_LOG */
7516 * I think this is where he DrvUpgradePrinter() hook would be
7517 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7518 * server. Right now, we just need to send ourselves a message
7519 * to update each printer bound to this driver. --jerry
7522 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7523 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7524 driver_name));
7528 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7529 * decide if the driver init data should be deleted. The rules are:
7530 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7531 * 2) delete init data only if there is no 2k/Xp driver
7532 * 3) always delete init data
7533 * The generalized rule is always use init data from the highest order driver.
7534 * It is necessary to follow the driver install by an initialization step to
7535 * finish off this process.
7537 if (level == 3)
7538 version = driver.info_3->cversion;
7539 else if (level == 6)
7540 version = driver.info_6->version;
7541 else
7542 version = -1;
7543 switch (version) {
7545 * 9x printer driver - never delete init data
7547 case 0:
7548 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7549 driver_name));
7550 break;
7553 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7554 * there is no 2k/Xp driver init data for this driver name.
7556 case 2:
7558 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7560 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7562 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7564 if (!del_driver_init(driver_name))
7565 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7566 } else {
7568 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7570 free_a_printer_driver(driver1,3);
7571 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7572 driver_name));
7575 break;
7578 * 2k or Xp printer driver - always delete init data
7580 case 3:
7581 if (!del_driver_init(driver_name))
7582 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7583 break;
7585 default:
7586 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7587 break;
7591 done:
7592 free_a_printer_driver(driver, level);
7593 return err;
7596 /********************************************************************
7597 * spoolss_addprinterdriverex
7598 ********************************************************************/
7600 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7602 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7603 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7606 * we only support the semantics of AddPrinterDriver()
7607 * i.e. only copy files that are newer than existing ones
7610 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7611 return WERR_ACCESS_DENIED;
7613 ZERO_STRUCT(q_u_local);
7614 ZERO_STRUCT(r_u_local);
7616 /* just pass the information off to _spoolss_addprinterdriver() */
7617 q_u_local.server_name_ptr = q_u->server_name_ptr;
7618 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7619 q_u_local.level = q_u->level;
7620 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7622 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7625 /****************************************************************************
7626 ****************************************************************************/
7628 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7630 init_unistr(&info->name, name);
7633 /****************************************************************************
7634 ****************************************************************************/
7636 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7638 pstring path;
7639 pstring long_archi;
7640 const char *short_archi;
7641 DRIVER_DIRECTORY_1 *info=NULL;
7643 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7645 if (!(short_archi = get_short_archi(long_archi)))
7646 return WERR_INVALID_ENVIRONMENT;
7648 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7649 return WERR_NOMEM;
7651 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7653 DEBUG(4,("printer driver directory: [%s]\n", path));
7655 fill_driverdir_1(info, path);
7657 *needed += spoolss_size_driverdir_info_1(info);
7659 if (!alloc_buffer_size(buffer, *needed)) {
7660 SAFE_FREE(info);
7661 return WERR_INSUFFICIENT_BUFFER;
7664 smb_io_driverdir_1("", buffer, info, 0);
7666 SAFE_FREE(info);
7668 if (*needed > offered)
7669 return WERR_INSUFFICIENT_BUFFER;
7671 return WERR_OK;
7674 /****************************************************************************
7675 ****************************************************************************/
7677 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7679 UNISTR2 *name = &q_u->name;
7680 UNISTR2 *uni_environment = &q_u->environment;
7681 uint32 level = q_u->level;
7682 NEW_BUFFER *buffer = NULL;
7683 uint32 offered = q_u->offered;
7684 uint32 *needed = &r_u->needed;
7686 /* that's an [in out] buffer */
7687 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7688 buffer = r_u->buffer;
7690 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7692 *needed=0;
7694 switch(level) {
7695 case 1:
7696 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7697 default:
7698 return WERR_UNKNOWN_LEVEL;
7702 /****************************************************************************
7703 ****************************************************************************/
7705 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7707 POLICY_HND *handle = &q_u->handle;
7708 uint32 idx = q_u->index;
7709 uint32 in_value_len = q_u->valuesize;
7710 uint32 in_data_len = q_u->datasize;
7711 uint32 *out_max_value_len = &r_u->valuesize;
7712 uint16 **out_value = &r_u->value;
7713 uint32 *out_value_len = &r_u->realvaluesize;
7714 uint32 *out_type = &r_u->type;
7715 uint32 *out_max_data_len = &r_u->datasize;
7716 uint8 **data_out = &r_u->data;
7717 uint32 *out_data_len = &r_u->realdatasize;
7719 NT_PRINTER_INFO_LEVEL *printer = NULL;
7721 uint32 biggest_valuesize;
7722 uint32 biggest_datasize;
7723 uint32 data_len;
7724 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7725 int snum;
7726 WERROR result;
7727 REGISTRY_VALUE *val = NULL;
7728 NT_PRINTER_DATA *p_data;
7729 int i, key_index, num_values;
7730 int name_length;
7732 ZERO_STRUCT( printer );
7734 *out_type = 0;
7736 *out_max_data_len = 0;
7737 *data_out = NULL;
7738 *out_data_len = 0;
7740 DEBUG(5,("spoolss_enumprinterdata\n"));
7742 if (!Printer) {
7743 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7744 return WERR_BADFID;
7747 if (!get_printer_snum(p,handle, &snum))
7748 return WERR_BADFID;
7750 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7751 if (!W_ERROR_IS_OK(result))
7752 return result;
7754 p_data = &printer->info_2->data;
7755 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7757 result = WERR_OK;
7760 * The NT machine wants to know the biggest size of value and data
7762 * cf: MSDN EnumPrinterData remark section
7765 if ( !in_value_len && !in_data_len && (key_index != -1) )
7767 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7769 biggest_valuesize = 0;
7770 biggest_datasize = 0;
7772 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7774 for ( i=0; i<num_values; i++ )
7776 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7778 name_length = strlen(val->valuename);
7779 if ( strlen(val->valuename) > biggest_valuesize )
7780 biggest_valuesize = name_length;
7782 if ( val->size > biggest_datasize )
7783 biggest_datasize = val->size;
7785 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7786 biggest_datasize));
7789 /* the value is an UNICODE string but real_value_size is the length
7790 in bytes including the trailing 0 */
7792 *out_value_len = 2 * (1+biggest_valuesize);
7793 *out_data_len = biggest_datasize;
7795 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7797 goto done;
7801 * the value len is wrong in NT sp3
7802 * that's the number of bytes not the number of unicode chars
7805 if ( key_index != -1 )
7806 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7808 if ( !val )
7811 /* out_value should default to "" or else NT4 has
7812 problems unmarshalling the response */
7814 *out_max_value_len=(in_value_len/sizeof(uint16));
7816 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7818 result = WERR_NOMEM;
7819 goto done;
7822 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7824 /* the data is counted in bytes */
7826 *out_max_data_len = in_data_len;
7827 *out_data_len = in_data_len;
7829 /* only allocate when given a non-zero data_len */
7831 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7833 result = WERR_NOMEM;
7834 goto done;
7837 result = WERR_NO_MORE_ITEMS;
7839 else
7842 * the value is:
7843 * - counted in bytes in the request
7844 * - counted in UNICODE chars in the max reply
7845 * - counted in bytes in the real size
7847 * take a pause *before* coding not *during* coding
7850 /* name */
7851 *out_max_value_len=(in_value_len/sizeof(uint16));
7852 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7854 result = WERR_NOMEM;
7855 goto done;
7858 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7860 /* type */
7862 *out_type = regval_type( val );
7864 /* data - counted in bytes */
7866 *out_max_data_len = in_data_len;
7867 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7869 result = WERR_NOMEM;
7870 goto done;
7872 data_len = (size_t)regval_size(val);
7873 memcpy( *data_out, regval_data_p(val), data_len );
7874 *out_data_len = data_len;
7877 done:
7878 free_a_printer(&printer, 2);
7879 return result;
7882 /****************************************************************************
7883 ****************************************************************************/
7885 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7887 POLICY_HND *handle = &q_u->handle;
7888 UNISTR2 *value = &q_u->value;
7889 uint32 type = q_u->type;
7890 uint8 *data = q_u->data;
7891 uint32 real_len = q_u->real_len;
7893 NT_PRINTER_INFO_LEVEL *printer = NULL;
7894 int snum=0;
7895 WERROR status = WERR_OK;
7896 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7897 fstring valuename;
7899 DEBUG(5,("spoolss_setprinterdata\n"));
7901 if (!Printer) {
7902 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7903 return WERR_BADFID;
7906 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7907 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7908 return WERR_INVALID_PARAM;
7911 if (!get_printer_snum(p,handle, &snum))
7912 return WERR_BADFID;
7915 * Access check : NT returns "access denied" if you make a
7916 * SetPrinterData call without the necessary privildge.
7917 * we were originally returning OK if nothing changed
7918 * which made Win2k issue **a lot** of SetPrinterData
7919 * when connecting to a printer --jerry
7922 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7924 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7925 status = WERR_ACCESS_DENIED;
7926 goto done;
7929 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7930 if (!W_ERROR_IS_OK(status))
7931 return status;
7933 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7936 * When client side code sets a magic printer data key, detect it and save
7937 * the current printer data and the magic key's data (its the DEVMODE) for
7938 * future printer/driver initializations.
7940 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7942 /* Set devmode and printer initialization info */
7943 status = save_driver_init( printer, 2, data, real_len );
7945 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7947 else
7949 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7950 type, data, real_len );
7951 if ( W_ERROR_IS_OK(status) )
7952 status = mod_a_printer(*printer, 2);
7955 done:
7956 free_a_printer(&printer, 2);
7958 return status;
7961 /****************************************************************************
7962 ****************************************************************************/
7964 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7966 POLICY_HND *handle = &q_u->handle;
7967 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7968 int snum;
7970 DEBUG(5,("_spoolss_resetprinter\n"));
7973 * All we do is to check to see if the handle and queue is valid.
7974 * This call really doesn't mean anything to us because we only
7975 * support RAW printing. --jerry
7978 if (!Printer) {
7979 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7980 return WERR_BADFID;
7983 if (!get_printer_snum(p,handle, &snum))
7984 return WERR_BADFID;
7987 /* blindly return success */
7988 return WERR_OK;
7992 /****************************************************************************
7993 ****************************************************************************/
7995 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7997 POLICY_HND *handle = &q_u->handle;
7998 UNISTR2 *value = &q_u->valuename;
8000 NT_PRINTER_INFO_LEVEL *printer = NULL;
8001 int snum=0;
8002 WERROR status = WERR_OK;
8003 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8004 pstring valuename;
8006 DEBUG(5,("spoolss_deleteprinterdata\n"));
8008 if (!Printer) {
8009 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8010 return WERR_BADFID;
8013 if (!get_printer_snum(p, handle, &snum))
8014 return WERR_BADFID;
8016 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8017 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8018 return WERR_ACCESS_DENIED;
8021 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8022 if (!W_ERROR_IS_OK(status))
8023 return status;
8025 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8027 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8029 if ( W_ERROR_IS_OK(status) )
8030 mod_a_printer( *printer, 2 );
8032 free_a_printer(&printer, 2);
8034 return status;
8037 /****************************************************************************
8038 ****************************************************************************/
8040 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8042 POLICY_HND *handle = &q_u->handle;
8043 FORM *form = &q_u->form;
8044 nt_forms_struct tmpForm;
8045 int snum;
8046 WERROR status = WERR_OK;
8047 NT_PRINTER_INFO_LEVEL *printer = NULL;
8049 int count=0;
8050 nt_forms_struct *list=NULL;
8051 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8053 DEBUG(5,("spoolss_addform\n"));
8055 if (!Printer) {
8056 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8057 return WERR_BADFID;
8061 /* forms can be added on printer of on the print server handle */
8063 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8065 if (!get_printer_snum(p,handle, &snum))
8066 return WERR_BADFID;
8068 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8069 if (!W_ERROR_IS_OK(status))
8070 goto done;
8073 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8074 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8075 status = WERR_ACCESS_DENIED;
8076 goto done;
8079 /* can't add if builtin */
8081 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8082 status = WERR_ALREADY_EXISTS;
8083 goto done;
8086 count = get_ntforms(&list);
8088 if(!add_a_form(&list, form, &count)) {
8089 status = WERR_NOMEM;
8090 goto done;
8093 write_ntforms(&list, count);
8096 * ChangeID must always be set if this is a printer
8099 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8100 status = mod_a_printer(*printer, 2);
8102 done:
8103 if ( printer )
8104 free_a_printer(&printer, 2);
8105 SAFE_FREE(list);
8107 return status;
8110 /****************************************************************************
8111 ****************************************************************************/
8113 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8115 POLICY_HND *handle = &q_u->handle;
8116 UNISTR2 *form_name = &q_u->name;
8117 nt_forms_struct tmpForm;
8118 int count=0;
8119 nt_forms_struct *list=NULL;
8120 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8121 int snum;
8122 WERROR status = WERR_OK;
8123 NT_PRINTER_INFO_LEVEL *printer = NULL;
8125 DEBUG(5,("spoolss_deleteform\n"));
8127 if (!Printer) {
8128 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8129 return WERR_BADFID;
8132 /* forms can be deleted on printer of on the print server handle */
8134 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8136 if (!get_printer_snum(p,handle, &snum))
8137 return WERR_BADFID;
8139 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8140 if (!W_ERROR_IS_OK(status))
8141 goto done;
8144 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8145 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8146 status = WERR_ACCESS_DENIED;
8147 goto done;
8150 /* can't delete if builtin */
8152 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8153 status = WERR_INVALID_PARAM;
8154 goto done;
8157 count = get_ntforms(&list);
8159 if ( !delete_a_form(&list, form_name, &count, &status ))
8160 goto done;
8163 * ChangeID must always be set if this is a printer
8166 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8167 status = mod_a_printer(*printer, 2);
8169 done:
8170 if ( printer )
8171 free_a_printer(&printer, 2);
8172 SAFE_FREE(list);
8174 return status;
8177 /****************************************************************************
8178 ****************************************************************************/
8180 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8182 POLICY_HND *handle = &q_u->handle;
8183 FORM *form = &q_u->form;
8184 nt_forms_struct tmpForm;
8185 int snum;
8186 WERROR status = WERR_OK;
8187 NT_PRINTER_INFO_LEVEL *printer = NULL;
8189 int count=0;
8190 nt_forms_struct *list=NULL;
8191 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8193 DEBUG(5,("spoolss_setform\n"));
8195 if (!Printer) {
8196 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8197 return WERR_BADFID;
8200 /* forms can be modified on printer of on the print server handle */
8202 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8204 if (!get_printer_snum(p,handle, &snum))
8205 return WERR_BADFID;
8207 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8208 if (!W_ERROR_IS_OK(status))
8209 goto done;
8212 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8213 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8214 status = WERR_ACCESS_DENIED;
8215 goto done;
8218 /* can't set if builtin */
8219 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8220 status = WERR_INVALID_PARAM;
8221 goto done;
8224 count = get_ntforms(&list);
8225 update_a_form(&list, form, count);
8226 write_ntforms(&list, count);
8229 * ChangeID must always be set if this is a printer
8232 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8233 status = mod_a_printer(*printer, 2);
8236 done:
8237 if ( printer )
8238 free_a_printer(&printer, 2);
8239 SAFE_FREE(list);
8241 return status;
8244 /****************************************************************************
8245 enumprintprocessors level 1.
8246 ****************************************************************************/
8248 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8250 PRINTPROCESSOR_1 *info_1=NULL;
8252 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8253 return WERR_NOMEM;
8255 (*returned) = 0x1;
8257 init_unistr(&info_1->name, "winprint");
8259 *needed += spoolss_size_printprocessor_info_1(info_1);
8261 if (!alloc_buffer_size(buffer, *needed))
8262 return WERR_INSUFFICIENT_BUFFER;
8264 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8266 SAFE_FREE(info_1);
8268 if (*needed > offered) {
8269 *returned=0;
8270 return WERR_INSUFFICIENT_BUFFER;
8273 return WERR_OK;
8276 /****************************************************************************
8277 ****************************************************************************/
8279 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8281 uint32 level = q_u->level;
8282 NEW_BUFFER *buffer = NULL;
8283 uint32 offered = q_u->offered;
8284 uint32 *needed = &r_u->needed;
8285 uint32 *returned = &r_u->returned;
8287 /* that's an [in out] buffer */
8288 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8289 buffer = r_u->buffer;
8291 DEBUG(5,("spoolss_enumprintprocessors\n"));
8294 * Enumerate the print processors ...
8296 * Just reply with "winprint", to keep NT happy
8297 * and I can use my nice printer checker.
8300 *returned=0;
8301 *needed=0;
8303 switch (level) {
8304 case 1:
8305 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8306 default:
8307 return WERR_UNKNOWN_LEVEL;
8311 /****************************************************************************
8312 enumprintprocdatatypes level 1.
8313 ****************************************************************************/
8315 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8317 PRINTPROCDATATYPE_1 *info_1=NULL;
8319 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8320 return WERR_NOMEM;
8322 (*returned) = 0x1;
8324 init_unistr(&info_1->name, "RAW");
8326 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8328 if (!alloc_buffer_size(buffer, *needed))
8329 return WERR_INSUFFICIENT_BUFFER;
8331 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8333 SAFE_FREE(info_1);
8335 if (*needed > offered) {
8336 *returned=0;
8337 return WERR_INSUFFICIENT_BUFFER;
8340 return WERR_OK;
8343 /****************************************************************************
8344 ****************************************************************************/
8346 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8348 uint32 level = q_u->level;
8349 NEW_BUFFER *buffer = NULL;
8350 uint32 offered = q_u->offered;
8351 uint32 *needed = &r_u->needed;
8352 uint32 *returned = &r_u->returned;
8354 /* that's an [in out] buffer */
8355 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8356 buffer = r_u->buffer;
8358 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8360 *returned=0;
8361 *needed=0;
8363 switch (level) {
8364 case 1:
8365 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8366 default:
8367 return WERR_UNKNOWN_LEVEL;
8371 /****************************************************************************
8372 enumprintmonitors level 1.
8373 ****************************************************************************/
8375 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8377 PRINTMONITOR_1 *info_1=NULL;
8379 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8380 return WERR_NOMEM;
8382 (*returned) = 0x1;
8384 init_unistr(&info_1->name, "Local Port");
8386 *needed += spoolss_size_printmonitor_info_1(info_1);
8388 if (!alloc_buffer_size(buffer, *needed))
8389 return WERR_INSUFFICIENT_BUFFER;
8391 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8393 SAFE_FREE(info_1);
8395 if (*needed > offered) {
8396 *returned=0;
8397 return WERR_INSUFFICIENT_BUFFER;
8400 return WERR_OK;
8403 /****************************************************************************
8404 enumprintmonitors level 2.
8405 ****************************************************************************/
8407 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8409 PRINTMONITOR_2 *info_2=NULL;
8411 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8412 return WERR_NOMEM;
8414 (*returned) = 0x1;
8416 init_unistr(&info_2->name, "Local Port");
8417 init_unistr(&info_2->environment, "Windows NT X86");
8418 init_unistr(&info_2->dll_name, "localmon.dll");
8420 *needed += spoolss_size_printmonitor_info_2(info_2);
8422 if (!alloc_buffer_size(buffer, *needed))
8423 return WERR_INSUFFICIENT_BUFFER;
8425 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8427 SAFE_FREE(info_2);
8429 if (*needed > offered) {
8430 *returned=0;
8431 return WERR_INSUFFICIENT_BUFFER;
8434 return WERR_OK;
8437 /****************************************************************************
8438 ****************************************************************************/
8440 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8442 uint32 level = q_u->level;
8443 NEW_BUFFER *buffer = NULL;
8444 uint32 offered = q_u->offered;
8445 uint32 *needed = &r_u->needed;
8446 uint32 *returned = &r_u->returned;
8448 /* that's an [in out] buffer */
8449 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8450 buffer = r_u->buffer;
8452 DEBUG(5,("spoolss_enumprintmonitors\n"));
8455 * Enumerate the print monitors ...
8457 * Just reply with "Local Port", to keep NT happy
8458 * and I can use my nice printer checker.
8461 *returned=0;
8462 *needed=0;
8464 switch (level) {
8465 case 1:
8466 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8467 case 2:
8468 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8469 default:
8470 return WERR_UNKNOWN_LEVEL;
8474 /****************************************************************************
8475 ****************************************************************************/
8477 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8479 int i=0;
8480 BOOL found=False;
8481 JOB_INFO_1 *info_1=NULL;
8483 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8485 if (info_1 == NULL) {
8486 return WERR_NOMEM;
8489 for (i=0; i<count && found==False; i++) {
8490 if ((*queue)[i].job==(int)jobid)
8491 found=True;
8494 if (found==False) {
8495 SAFE_FREE(info_1);
8496 /* NT treats not found as bad param... yet another bad choice */
8497 return WERR_INVALID_PARAM;
8500 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8502 *needed += spoolss_size_job_info_1(info_1);
8504 if (!alloc_buffer_size(buffer, *needed)) {
8505 SAFE_FREE(info_1);
8506 return WERR_INSUFFICIENT_BUFFER;
8509 smb_io_job_info_1("", buffer, info_1, 0);
8511 SAFE_FREE(info_1);
8513 if (*needed > offered)
8514 return WERR_INSUFFICIENT_BUFFER;
8516 return WERR_OK;
8519 /****************************************************************************
8520 ****************************************************************************/
8522 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8524 int i = 0;
8525 BOOL found = False;
8526 JOB_INFO_2 *info_2;
8527 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8528 WERROR ret;
8529 DEVICEMODE *devmode = NULL;
8530 NT_DEVICEMODE *nt_devmode = NULL;
8532 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8534 ZERO_STRUCTP(info_2);
8536 if (info_2 == NULL) {
8537 ret = WERR_NOMEM;
8538 goto done;
8541 for ( i=0; i<count && found==False; i++ )
8543 if ((*queue)[i].job == (int)jobid)
8544 found = True;
8547 if ( !found )
8549 /* NT treats not found as bad param... yet another bad
8550 choice */
8551 ret = WERR_INVALID_PARAM;
8552 goto done;
8555 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8556 if (!W_ERROR_IS_OK(ret))
8557 goto done;
8560 * if the print job does not have a DEVMODE associated with it,
8561 * just use the one for the printer. A NULL devicemode is not
8562 * a failure condition
8565 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8566 devmode = construct_dev_mode(snum);
8567 else {
8568 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8569 ZERO_STRUCTP( devmode );
8570 convert_nt_devicemode( devmode, nt_devmode );
8574 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8576 *needed += spoolss_size_job_info_2(info_2);
8578 if (!alloc_buffer_size(buffer, *needed)) {
8579 ret = WERR_INSUFFICIENT_BUFFER;
8580 goto done;
8583 smb_io_job_info_2("", buffer, info_2, 0);
8585 if (*needed > offered) {
8586 ret = WERR_INSUFFICIENT_BUFFER;
8587 goto done;
8590 ret = WERR_OK;
8592 done:
8593 /* Cleanup allocated memory */
8595 free_job_info_2(info_2); /* Also frees devmode */
8596 SAFE_FREE(info_2);
8597 free_a_printer(&ntprinter, 2);
8599 return ret;
8602 /****************************************************************************
8603 ****************************************************************************/
8605 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8607 POLICY_HND *handle = &q_u->handle;
8608 uint32 jobid = q_u->jobid;
8609 uint32 level = q_u->level;
8610 NEW_BUFFER *buffer = NULL;
8611 uint32 offered = q_u->offered;
8612 uint32 *needed = &r_u->needed;
8613 WERROR wstatus = WERR_OK;
8615 int snum;
8616 int count;
8617 print_queue_struct *queue = NULL;
8618 print_status_struct prt_status;
8620 /* that's an [in out] buffer */
8621 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8622 buffer = r_u->buffer;
8624 DEBUG(5,("spoolss_getjob\n"));
8626 *needed = 0;
8628 if (!get_printer_snum(p, handle, &snum))
8629 return WERR_BADFID;
8631 count = print_queue_status(snum, &queue, &prt_status);
8633 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8634 count, prt_status.status, prt_status.message));
8636 switch ( level ) {
8637 case 1:
8638 wstatus = getjob_level_1(&queue, count, snum, jobid,
8639 buffer, offered, needed);
8640 break;
8641 case 2:
8642 wstatus = getjob_level_2(&queue, count, snum, jobid,
8643 buffer, offered, needed);
8644 break;
8645 default:
8646 wstatus = WERR_UNKNOWN_LEVEL;
8647 break;
8650 SAFE_FREE(queue);
8651 return wstatus;
8654 /********************************************************************
8655 spoolss_getprinterdataex
8657 From MSDN documentation of GetPrinterDataEx: pass request
8658 to GetPrinterData if key is "PrinterDriverData".
8659 ********************************************************************/
8661 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8663 POLICY_HND *handle = &q_u->handle;
8664 uint32 in_size = q_u->size;
8665 uint32 *type = &r_u->type;
8666 uint32 *out_size = &r_u->size;
8667 uint8 **data = &r_u->data;
8668 uint32 *needed = &r_u->needed;
8669 fstring keyname, valuename;
8671 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8673 NT_PRINTER_INFO_LEVEL *printer = NULL;
8674 int snum = 0;
8675 WERROR status = WERR_OK;
8677 DEBUG(4,("_spoolss_getprinterdataex\n"));
8679 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8680 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8682 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8683 keyname, valuename));
8685 /* in case of problem, return some default values */
8687 *needed = 0;
8688 *type = 0;
8689 *out_size = in_size;
8691 if (!Printer) {
8692 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8693 status = WERR_BADFID;
8694 goto done;
8697 /* Is the handle to a printer or to the server? */
8699 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8700 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8701 status = WERR_INVALID_PARAM;
8702 goto done;
8705 if ( !get_printer_snum(p,handle, &snum) )
8706 return WERR_BADFID;
8708 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8709 if ( !W_ERROR_IS_OK(status) )
8710 goto done;
8712 /* check to see if the keyname is valid */
8713 if ( !strlen(keyname) ) {
8714 status = WERR_INVALID_PARAM;
8715 goto done;
8718 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8719 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8720 free_a_printer( &printer, 2 );
8721 status = WERR_BADFILE;
8722 goto done;
8725 /* When given a new keyname, we should just create it */
8727 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8729 if (*needed > *out_size)
8730 status = WERR_MORE_DATA;
8732 done:
8733 if ( !W_ERROR_IS_OK(status) )
8735 DEBUG(5, ("error: allocating %d\n", *out_size));
8737 /* reply this param doesn't exist */
8739 if ( *out_size )
8741 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8742 status = WERR_NOMEM;
8743 goto done;
8746 else {
8747 *data = NULL;
8751 if ( printer )
8752 free_a_printer( &printer, 2 );
8754 return status;
8757 /********************************************************************
8758 * spoolss_setprinterdataex
8759 ********************************************************************/
8761 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8763 POLICY_HND *handle = &q_u->handle;
8764 uint32 type = q_u->type;
8765 uint8 *data = q_u->data;
8766 uint32 real_len = q_u->real_len;
8768 NT_PRINTER_INFO_LEVEL *printer = NULL;
8769 int snum = 0;
8770 WERROR status = WERR_OK;
8771 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8772 fstring valuename;
8773 fstring keyname;
8774 char *oid_string;
8776 DEBUG(4,("_spoolss_setprinterdataex\n"));
8778 /* From MSDN documentation of SetPrinterDataEx: pass request to
8779 SetPrinterData if key is "PrinterDriverData" */
8781 if (!Printer) {
8782 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8783 return WERR_BADFID;
8786 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8787 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8788 return WERR_INVALID_PARAM;
8791 if ( !get_printer_snum(p,handle, &snum) )
8792 return WERR_BADFID;
8795 * Access check : NT returns "access denied" if you make a
8796 * SetPrinterData call without the necessary privildge.
8797 * we were originally returning OK if nothing changed
8798 * which made Win2k issue **a lot** of SetPrinterData
8799 * when connecting to a printer --jerry
8802 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8804 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8805 return WERR_ACCESS_DENIED;
8808 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8809 if (!W_ERROR_IS_OK(status))
8810 return status;
8812 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8813 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8815 /* check for OID in valuename */
8817 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8819 *oid_string = '\0';
8820 oid_string++;
8823 /* save the registry data */
8825 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8827 if ( W_ERROR_IS_OK(status) )
8829 /* save the OID if one was specified */
8830 if ( oid_string ) {
8831 fstrcat( keyname, "\\" );
8832 fstrcat( keyname, SPOOL_OID_KEY );
8835 * I'm not checking the status here on purpose. Don't know
8836 * if this is right, but I'm returning the status from the
8837 * previous set_printer_dataex() call. I have no idea if
8838 * this is right. --jerry
8841 set_printer_dataex( printer, keyname, valuename,
8842 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8845 status = mod_a_printer(*printer, 2);
8848 free_a_printer(&printer, 2);
8850 return status;
8854 /********************************************************************
8855 * spoolss_deleteprinterdataex
8856 ********************************************************************/
8858 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8860 POLICY_HND *handle = &q_u->handle;
8861 UNISTR2 *value = &q_u->valuename;
8862 UNISTR2 *key = &q_u->keyname;
8864 NT_PRINTER_INFO_LEVEL *printer = NULL;
8865 int snum=0;
8866 WERROR status = WERR_OK;
8867 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8868 pstring valuename, keyname;
8870 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8872 if (!Printer) {
8873 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8874 return WERR_BADFID;
8877 if (!get_printer_snum(p, handle, &snum))
8878 return WERR_BADFID;
8880 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8881 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8882 return WERR_ACCESS_DENIED;
8885 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8886 if (!W_ERROR_IS_OK(status))
8887 return status;
8889 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8890 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8892 status = delete_printer_dataex( printer, keyname, valuename );
8894 if ( W_ERROR_IS_OK(status) )
8895 mod_a_printer( *printer, 2 );
8897 free_a_printer(&printer, 2);
8899 return status;
8902 /********************************************************************
8903 * spoolss_enumprinterkey
8904 ********************************************************************/
8907 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8909 fstring key;
8910 fstring *keynames = NULL;
8911 uint16 *enumkeys = NULL;
8912 int num_keys;
8913 int printerkey_len;
8914 POLICY_HND *handle = &q_u->handle;
8915 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8916 NT_PRINTER_DATA *data;
8917 NT_PRINTER_INFO_LEVEL *printer = NULL;
8918 int snum = 0;
8919 WERROR status = WERR_BADFILE;
8922 DEBUG(4,("_spoolss_enumprinterkey\n"));
8924 if (!Printer) {
8925 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8926 return WERR_BADFID;
8929 if ( !get_printer_snum(p,handle, &snum) )
8930 return WERR_BADFID;
8932 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8933 if (!W_ERROR_IS_OK(status))
8934 return status;
8936 /* get the list of subkey names */
8938 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8939 data = &printer->info_2->data;
8941 num_keys = get_printer_subkeys( data, key, &keynames );
8943 if ( num_keys == -1 ) {
8944 status = WERR_BADFILE;
8945 goto done;
8948 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8950 r_u->needed = printerkey_len*2;
8952 if ( q_u->size < r_u->needed ) {
8953 status = WERR_MORE_DATA;
8954 goto done;
8957 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8958 status = WERR_NOMEM;
8959 goto done;
8962 status = WERR_OK;
8964 if ( q_u->size < r_u->needed )
8965 status = WERR_MORE_DATA;
8967 done:
8968 free_a_printer( &printer, 2 );
8969 SAFE_FREE( keynames );
8971 return status;
8974 /********************************************************************
8975 * spoolss_deleteprinterkey
8976 ********************************************************************/
8978 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8980 POLICY_HND *handle = &q_u->handle;
8981 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8982 fstring key;
8983 NT_PRINTER_INFO_LEVEL *printer = NULL;
8984 int snum=0;
8985 WERROR status;
8987 DEBUG(5,("spoolss_deleteprinterkey\n"));
8989 if (!Printer) {
8990 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8991 return WERR_BADFID;
8994 /* if keyname == NULL, return error */
8996 if ( !q_u->keyname.buffer )
8997 return WERR_INVALID_PARAM;
8999 if (!get_printer_snum(p, handle, &snum))
9000 return WERR_BADFID;
9002 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9003 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9004 return WERR_ACCESS_DENIED;
9007 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9008 if (!W_ERROR_IS_OK(status))
9009 return status;
9011 /* delete the key and all subneys */
9013 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9015 status = delete_all_printer_data( printer->info_2, key );
9017 if ( W_ERROR_IS_OK(status) )
9018 status = mod_a_printer(*printer, 2);
9020 free_a_printer( &printer, 2 );
9022 return status;
9026 /********************************************************************
9027 * spoolss_enumprinterdataex
9028 ********************************************************************/
9030 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9032 POLICY_HND *handle = &q_u->handle;
9033 uint32 in_size = q_u->size;
9034 uint32 num_entries,
9035 needed;
9036 NT_PRINTER_INFO_LEVEL *printer = NULL;
9037 PRINTER_ENUM_VALUES *enum_values = NULL;
9038 NT_PRINTER_DATA *p_data;
9039 fstring key;
9040 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9041 int snum;
9042 WERROR result;
9043 int key_index;
9044 int i;
9045 REGISTRY_VALUE *val;
9046 char *value_name;
9047 int data_len;
9050 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9052 if (!Printer) {
9053 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9054 return WERR_BADFID;
9058 * first check for a keyname of NULL or "". Win2k seems to send
9059 * this a lot and we should send back WERR_INVALID_PARAM
9060 * no need to spend time looking up the printer in this case.
9061 * --jerry
9064 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9065 if ( !strlen(key) ) {
9066 result = WERR_INVALID_PARAM;
9067 goto done;
9070 /* get the printer off of disk */
9072 if (!get_printer_snum(p,handle, &snum))
9073 return WERR_BADFID;
9075 ZERO_STRUCT(printer);
9076 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9077 if (!W_ERROR_IS_OK(result))
9078 return result;
9080 /* now look for a match on the key name */
9082 p_data = &printer->info_2->data;
9084 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9085 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9087 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9088 result = WERR_INVALID_PARAM;
9089 goto done;
9092 result = WERR_OK;
9093 needed = 0;
9095 /* allocate the memory for the array of pointers -- if necessary */
9097 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9098 if ( num_entries )
9100 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9102 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9103 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9104 result = WERR_NOMEM;
9105 goto done;
9108 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9112 * loop through all params and build the array to pass
9113 * back to the client
9116 for ( i=0; i<num_entries; i++ )
9118 /* lookup the registry value */
9120 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9121 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9123 /* copy the data */
9125 value_name = regval_name( val );
9126 init_unistr( &enum_values[i].valuename, value_name );
9127 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9128 enum_values[i].type = regval_type( val );
9130 data_len = regval_size( val );
9131 if ( data_len ) {
9132 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9134 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9135 data_len ));
9136 result = WERR_NOMEM;
9137 goto done;
9140 enum_values[i].data_len = data_len;
9142 /* keep track of the size of the array in bytes */
9144 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9147 /* housekeeping information in the reply */
9149 r_u->needed = needed;
9150 r_u->returned = num_entries;
9152 if (needed > in_size) {
9153 result = WERR_MORE_DATA;
9154 goto done;
9157 /* copy data into the reply */
9159 r_u->ctr.size = r_u->needed;
9160 r_u->ctr.size_of_array = r_u->returned;
9161 r_u->ctr.values = enum_values;
9165 done:
9166 if ( printer )
9167 free_a_printer(&printer, 2);
9169 return result;
9172 /****************************************************************************
9173 ****************************************************************************/
9175 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9177 init_unistr(&info->name, name);
9180 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9181 UNISTR2 *environment,
9182 NEW_BUFFER *buffer,
9183 uint32 offered,
9184 uint32 *needed)
9186 pstring path;
9187 pstring long_archi;
9188 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9190 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9192 if (!get_short_archi(long_archi))
9193 return WERR_INVALID_ENVIRONMENT;
9195 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9196 return WERR_NOMEM;
9198 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9200 fill_printprocessordirectory_1(info, path);
9202 *needed += spoolss_size_printprocessordirectory_info_1(info);
9204 if (!alloc_buffer_size(buffer, *needed)) {
9205 safe_free(info);
9206 return WERR_INSUFFICIENT_BUFFER;
9209 smb_io_printprocessordirectory_1("", buffer, info, 0);
9211 safe_free(info);
9213 if (*needed > offered)
9214 return WERR_INSUFFICIENT_BUFFER;
9215 else
9216 return WERR_OK;
9219 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9221 uint32 level = q_u->level;
9222 NEW_BUFFER *buffer = NULL;
9223 uint32 offered = q_u->offered;
9224 uint32 *needed = &r_u->needed;
9225 WERROR result;
9227 /* that's an [in out] buffer */
9228 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9229 buffer = r_u->buffer;
9231 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9233 *needed=0;
9235 switch(level) {
9236 case 1:
9237 result = getprintprocessordirectory_level_1
9238 (&q_u->name, &q_u->environment, buffer, offered, needed);
9239 break;
9240 default:
9241 result = WERR_UNKNOWN_LEVEL;
9244 return result;
9247 #if 0
9249 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9250 SPOOL_R_REPLYOPENPRINTER *r_u)
9252 DEBUG(5,("_spoolss_replyopenprinter\n"));
9254 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9256 return WERR_OK;
9259 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9260 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9262 DEBUG(5,("_spoolss_replycloseprinter\n"));
9263 return WERR_OK;
9266 #endif