get rid of some sompiler warnings on IRIX
[Samba.git] / source3 / rpc_server / srv_spoolss_nt.c
blob725672da69d5a89c7420d6da2d287d5dee0c0fa7
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, msg->len);
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 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;
2602 if (!cli_negprot(the_cli)) {
2603 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2604 cli_shutdown(the_cli);
2605 return False;
2608 if (the_cli->protocol != PROTOCOL_NT1) {
2609 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2610 cli_shutdown(the_cli);
2611 return False;
2615 * Do an anonymous session setup.
2618 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2619 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2620 cli_shutdown(the_cli);
2621 return False;
2624 if (!(the_cli->sec_mode & 1)) {
2625 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2626 cli_shutdown(the_cli);
2627 return False;
2630 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2631 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) ));
2632 cli_shutdown(the_cli);
2633 return False;
2637 * Ok - we have an anonymous connection to the IPC$ share.
2638 * Now start the NT Domain stuff :-).
2641 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2642 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)));
2643 cli_nt_session_close(the_cli);
2644 cli_ulogoff(the_cli);
2645 cli_shutdown(the_cli);
2646 return False;
2649 return True;
2652 /***************************************************************************
2653 Connect to the client.
2654 ****************************************************************************/
2656 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2657 uint32 localprinter, uint32 type,
2658 POLICY_HND *handle, struct in_addr *client_ip)
2660 WERROR result;
2663 * If it's the first connection, contact the client
2664 * and connect to the IPC$ share anonymously
2666 if (smb_connections==0) {
2667 fstring unix_printer;
2669 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2671 if(!spoolss_connect_to_client(&notify_cli, client_ip, unix_printer))
2672 return False;
2674 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2675 /* Tell the connections db we're now interested in printer
2676 * notify messages. */
2677 register_message_flags( True, FLAG_MSG_PRINTING );
2681 * Tell the specific printing tdb we want messages for this printer
2682 * by registering our PID.
2685 if (!print_notify_register_pid(snum))
2686 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2688 smb_connections++;
2690 result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter,
2691 type, handle);
2693 if (!W_ERROR_IS_OK(result))
2694 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2695 dos_errstr(result)));
2697 return (W_ERROR_IS_OK(result));
2700 /********************************************************************
2701 * _spoolss_rffpcnex
2702 * ReplyFindFirstPrinterChangeNotifyEx
2704 * before replying OK: status=0 a rpc call is made to the workstation
2705 * asking ReplyOpenPrinter
2707 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2708 * called from api_spoolss_rffpcnex
2709 ********************************************************************/
2711 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2713 POLICY_HND *handle = &q_u->handle;
2714 uint32 flags = q_u->flags;
2715 uint32 options = q_u->options;
2716 UNISTR2 *localmachine = &q_u->localmachine;
2717 uint32 printerlocal = q_u->printerlocal;
2718 int snum = -1;
2719 SPOOL_NOTIFY_OPTION *option = q_u->option;
2720 struct in_addr client_ip;
2722 /* store the notify value in the printer struct */
2724 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2726 if (!Printer) {
2727 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2728 return WERR_BADFID;
2731 Printer->notify.flags=flags;
2732 Printer->notify.options=options;
2733 Printer->notify.printerlocal=printerlocal;
2735 if (Printer->notify.option)
2736 free_spool_notify_option(&Printer->notify.option);
2738 Printer->notify.option=dup_spool_notify_option(option);
2740 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2741 sizeof(Printer->notify.localmachine)-1);
2743 /* Connect to the client machine and send a ReplyOpenPrinter */
2745 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2746 snum = -1;
2747 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2748 !get_printer_snum(p, handle, &snum) )
2749 return WERR_BADFID;
2751 client_ip.s_addr = inet_addr(p->conn->client_address);
2753 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2754 Printer->notify.printerlocal, 1,
2755 &Printer->notify.client_hnd, &client_ip))
2756 return WERR_SERVER_UNAVAILABLE;
2758 Printer->notify.client_connected=True;
2760 return WERR_OK;
2763 /*******************************************************************
2764 * fill a notify_info_data with the servername
2765 ********************************************************************/
2767 void spoolss_notify_server_name(int snum,
2768 SPOOL_NOTIFY_INFO_DATA *data,
2769 print_queue_struct *queue,
2770 NT_PRINTER_INFO_LEVEL *printer,
2771 TALLOC_CTX *mem_ctx)
2773 pstring temp_name, temp;
2774 uint32 len;
2776 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
2778 len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
2780 data->notify_data.data.length = len;
2781 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2783 if (!data->notify_data.data.string) {
2784 data->notify_data.data.length = 0;
2785 return;
2788 memcpy(data->notify_data.data.string, temp, len);
2791 /*******************************************************************
2792 * fill a notify_info_data with the printername (not including the servername).
2793 ********************************************************************/
2795 void spoolss_notify_printer_name(int snum,
2796 SPOOL_NOTIFY_INFO_DATA *data,
2797 print_queue_struct *queue,
2798 NT_PRINTER_INFO_LEVEL *printer,
2799 TALLOC_CTX *mem_ctx)
2801 pstring temp;
2802 uint32 len;
2804 /* the notify name should not contain the \\server\ part */
2805 char *p = strrchr(printer->info_2->printername, '\\');
2807 if (!p) {
2808 p = printer->info_2->printername;
2809 } else {
2810 p++;
2813 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2815 data->notify_data.data.length = len;
2816 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2818 if (!data->notify_data.data.string) {
2819 data->notify_data.data.length = 0;
2820 return;
2823 memcpy(data->notify_data.data.string, temp, len);
2826 /*******************************************************************
2827 * fill a notify_info_data with the servicename
2828 ********************************************************************/
2830 void spoolss_notify_share_name(int snum,
2831 SPOOL_NOTIFY_INFO_DATA *data,
2832 print_queue_struct *queue,
2833 NT_PRINTER_INFO_LEVEL *printer,
2834 TALLOC_CTX *mem_ctx)
2836 pstring temp;
2837 uint32 len;
2839 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2841 data->notify_data.data.length = len;
2842 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2844 if (!data->notify_data.data.string) {
2845 data->notify_data.data.length = 0;
2846 return;
2849 memcpy(data->notify_data.data.string, temp, len);
2852 /*******************************************************************
2853 * fill a notify_info_data with the port name
2854 ********************************************************************/
2856 void spoolss_notify_port_name(int snum,
2857 SPOOL_NOTIFY_INFO_DATA *data,
2858 print_queue_struct *queue,
2859 NT_PRINTER_INFO_LEVEL *printer,
2860 TALLOC_CTX *mem_ctx)
2862 pstring temp;
2863 uint32 len;
2865 /* even if it's strange, that's consistant in all the code */
2867 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2869 data->notify_data.data.length = len;
2870 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2872 if (!data->notify_data.data.string) {
2873 data->notify_data.data.length = 0;
2874 return;
2877 memcpy(data->notify_data.data.string, temp, len);
2880 /*******************************************************************
2881 * fill a notify_info_data with the printername
2882 * but it doesn't exist, have to see what to do
2883 ********************************************************************/
2885 void spoolss_notify_driver_name(int snum,
2886 SPOOL_NOTIFY_INFO_DATA *data,
2887 print_queue_struct *queue,
2888 NT_PRINTER_INFO_LEVEL *printer,
2889 TALLOC_CTX *mem_ctx)
2891 pstring temp;
2892 uint32 len;
2894 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2896 data->notify_data.data.length = len;
2897 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2899 if (!data->notify_data.data.string) {
2900 data->notify_data.data.length = 0;
2901 return;
2904 memcpy(data->notify_data.data.string, temp, len);
2907 /*******************************************************************
2908 * fill a notify_info_data with the comment
2909 ********************************************************************/
2911 void spoolss_notify_comment(int snum,
2912 SPOOL_NOTIFY_INFO_DATA *data,
2913 print_queue_struct *queue,
2914 NT_PRINTER_INFO_LEVEL *printer,
2915 TALLOC_CTX *mem_ctx)
2917 pstring temp;
2918 uint32 len;
2920 if (*printer->info_2->comment == '\0')
2921 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2922 else
2923 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2925 data->notify_data.data.length = len;
2926 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2928 if (!data->notify_data.data.string) {
2929 data->notify_data.data.length = 0;
2930 return;
2933 memcpy(data->notify_data.data.string, temp, len);
2936 /*******************************************************************
2937 * fill a notify_info_data with the comment
2938 * location = "Room 1, floor 2, building 3"
2939 ********************************************************************/
2941 void spoolss_notify_location(int snum,
2942 SPOOL_NOTIFY_INFO_DATA *data,
2943 print_queue_struct *queue,
2944 NT_PRINTER_INFO_LEVEL *printer,
2945 TALLOC_CTX *mem_ctx)
2947 pstring temp;
2948 uint32 len;
2950 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2952 data->notify_data.data.length = len;
2953 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2955 if (!data->notify_data.data.string) {
2956 data->notify_data.data.length = 0;
2957 return;
2960 memcpy(data->notify_data.data.string, temp, len);
2963 /*******************************************************************
2964 * fill a notify_info_data with the device mode
2965 * jfm:xxxx don't to it for know but that's a real problem !!!
2966 ********************************************************************/
2968 static void spoolss_notify_devmode(int snum,
2969 SPOOL_NOTIFY_INFO_DATA *data,
2970 print_queue_struct *queue,
2971 NT_PRINTER_INFO_LEVEL *printer,
2972 TALLOC_CTX *mem_ctx)
2976 /*******************************************************************
2977 * fill a notify_info_data with the separator file name
2978 ********************************************************************/
2980 void spoolss_notify_sepfile(int snum,
2981 SPOOL_NOTIFY_INFO_DATA *data,
2982 print_queue_struct *queue,
2983 NT_PRINTER_INFO_LEVEL *printer,
2984 TALLOC_CTX *mem_ctx)
2986 pstring temp;
2987 uint32 len;
2989 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2991 data->notify_data.data.length = len;
2992 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2994 if (!data->notify_data.data.string) {
2995 data->notify_data.data.length = 0;
2996 return;
2999 memcpy(data->notify_data.data.string, temp, len);
3002 /*******************************************************************
3003 * fill a notify_info_data with the print processor
3004 * jfm:xxxx return always winprint to indicate we don't do anything to it
3005 ********************************************************************/
3007 void spoolss_notify_print_processor(int snum,
3008 SPOOL_NOTIFY_INFO_DATA *data,
3009 print_queue_struct *queue,
3010 NT_PRINTER_INFO_LEVEL *printer,
3011 TALLOC_CTX *mem_ctx)
3013 pstring temp;
3014 uint32 len;
3016 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3018 data->notify_data.data.length = len;
3019 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3021 if (!data->notify_data.data.string) {
3022 data->notify_data.data.length = 0;
3023 return;
3026 memcpy(data->notify_data.data.string, temp, len);
3029 /*******************************************************************
3030 * fill a notify_info_data with the print processor options
3031 * jfm:xxxx send an empty string
3032 ********************************************************************/
3034 void spoolss_notify_parameters(int snum,
3035 SPOOL_NOTIFY_INFO_DATA *data,
3036 print_queue_struct *queue,
3037 NT_PRINTER_INFO_LEVEL *printer,
3038 TALLOC_CTX *mem_ctx)
3040 pstring temp;
3041 uint32 len;
3043 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3045 data->notify_data.data.length = len;
3046 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3048 if (!data->notify_data.data.string) {
3049 data->notify_data.data.length = 0;
3050 return;
3053 memcpy(data->notify_data.data.string, temp, len);
3056 /*******************************************************************
3057 * fill a notify_info_data with the data type
3058 * jfm:xxxx always send RAW as data type
3059 ********************************************************************/
3061 void spoolss_notify_datatype(int snum,
3062 SPOOL_NOTIFY_INFO_DATA *data,
3063 print_queue_struct *queue,
3064 NT_PRINTER_INFO_LEVEL *printer,
3065 TALLOC_CTX *mem_ctx)
3067 pstring temp;
3068 uint32 len;
3070 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3072 data->notify_data.data.length = len;
3073 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3075 if (!data->notify_data.data.string) {
3076 data->notify_data.data.length = 0;
3077 return;
3080 memcpy(data->notify_data.data.string, temp, len);
3083 /*******************************************************************
3084 * fill a notify_info_data with the security descriptor
3085 * jfm:xxxx send an null pointer to say no security desc
3086 * have to implement security before !
3087 ********************************************************************/
3089 static void spoolss_notify_security_desc(int snum,
3090 SPOOL_NOTIFY_INFO_DATA *data,
3091 print_queue_struct *queue,
3092 NT_PRINTER_INFO_LEVEL *printer,
3093 TALLOC_CTX *mem_ctx)
3095 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3096 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3099 /*******************************************************************
3100 * fill a notify_info_data with the attributes
3101 * jfm:xxxx a samba printer is always shared
3102 ********************************************************************/
3104 void spoolss_notify_attributes(int snum,
3105 SPOOL_NOTIFY_INFO_DATA *data,
3106 print_queue_struct *queue,
3107 NT_PRINTER_INFO_LEVEL *printer,
3108 TALLOC_CTX *mem_ctx)
3110 data->notify_data.value[0] = printer->info_2->attributes;
3111 data->notify_data.value[1] = 0;
3114 /*******************************************************************
3115 * fill a notify_info_data with the priority
3116 ********************************************************************/
3118 static void spoolss_notify_priority(int snum,
3119 SPOOL_NOTIFY_INFO_DATA *data,
3120 print_queue_struct *queue,
3121 NT_PRINTER_INFO_LEVEL *printer,
3122 TALLOC_CTX *mem_ctx)
3124 data->notify_data.value[0] = printer->info_2->priority;
3125 data->notify_data.value[1] = 0;
3128 /*******************************************************************
3129 * fill a notify_info_data with the default priority
3130 ********************************************************************/
3132 static void spoolss_notify_default_priority(int snum,
3133 SPOOL_NOTIFY_INFO_DATA *data,
3134 print_queue_struct *queue,
3135 NT_PRINTER_INFO_LEVEL *printer,
3136 TALLOC_CTX *mem_ctx)
3138 data->notify_data.value[0] = printer->info_2->default_priority;
3139 data->notify_data.value[1] = 0;
3142 /*******************************************************************
3143 * fill a notify_info_data with the start time
3144 ********************************************************************/
3146 static void spoolss_notify_start_time(int snum,
3147 SPOOL_NOTIFY_INFO_DATA *data,
3148 print_queue_struct *queue,
3149 NT_PRINTER_INFO_LEVEL *printer,
3150 TALLOC_CTX *mem_ctx)
3152 data->notify_data.value[0] = printer->info_2->starttime;
3153 data->notify_data.value[1] = 0;
3156 /*******************************************************************
3157 * fill a notify_info_data with the until time
3158 ********************************************************************/
3160 static void spoolss_notify_until_time(int snum,
3161 SPOOL_NOTIFY_INFO_DATA *data,
3162 print_queue_struct *queue,
3163 NT_PRINTER_INFO_LEVEL *printer,
3164 TALLOC_CTX *mem_ctx)
3166 data->notify_data.value[0] = printer->info_2->untiltime;
3167 data->notify_data.value[1] = 0;
3170 /*******************************************************************
3171 * fill a notify_info_data with the status
3172 ********************************************************************/
3174 static void spoolss_notify_status(int snum,
3175 SPOOL_NOTIFY_INFO_DATA *data,
3176 print_queue_struct *queue,
3177 NT_PRINTER_INFO_LEVEL *printer,
3178 TALLOC_CTX *mem_ctx)
3180 print_status_struct status;
3182 print_queue_length(snum, &status);
3183 data->notify_data.value[0]=(uint32) status.status;
3184 data->notify_data.value[1] = 0;
3187 /*******************************************************************
3188 * fill a notify_info_data with the number of jobs queued
3189 ********************************************************************/
3191 void spoolss_notify_cjobs(int snum,
3192 SPOOL_NOTIFY_INFO_DATA *data,
3193 print_queue_struct *queue,
3194 NT_PRINTER_INFO_LEVEL *printer,
3195 TALLOC_CTX *mem_ctx)
3197 data->notify_data.value[0] = print_queue_length(snum, NULL);
3198 data->notify_data.value[1] = 0;
3201 /*******************************************************************
3202 * fill a notify_info_data with the average ppm
3203 ********************************************************************/
3205 static void spoolss_notify_average_ppm(int snum,
3206 SPOOL_NOTIFY_INFO_DATA *data,
3207 print_queue_struct *queue,
3208 NT_PRINTER_INFO_LEVEL *printer,
3209 TALLOC_CTX *mem_ctx)
3211 /* always respond 8 pages per minutes */
3212 /* a little hard ! */
3213 data->notify_data.value[0] = printer->info_2->averageppm;
3214 data->notify_data.value[1] = 0;
3217 /*******************************************************************
3218 * fill a notify_info_data with username
3219 ********************************************************************/
3221 static void spoolss_notify_username(int snum,
3222 SPOOL_NOTIFY_INFO_DATA *data,
3223 print_queue_struct *queue,
3224 NT_PRINTER_INFO_LEVEL *printer,
3225 TALLOC_CTX *mem_ctx)
3227 pstring temp;
3228 uint32 len;
3230 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3232 data->notify_data.data.length = len;
3233 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3235 if (!data->notify_data.data.string) {
3236 data->notify_data.data.length = 0;
3237 return;
3240 memcpy(data->notify_data.data.string, temp, len);
3243 /*******************************************************************
3244 * fill a notify_info_data with job status
3245 ********************************************************************/
3247 static void spoolss_notify_job_status(int snum,
3248 SPOOL_NOTIFY_INFO_DATA *data,
3249 print_queue_struct *queue,
3250 NT_PRINTER_INFO_LEVEL *printer,
3251 TALLOC_CTX *mem_ctx)
3253 data->notify_data.value[0]=nt_printj_status(queue->status);
3254 data->notify_data.value[1] = 0;
3257 /*******************************************************************
3258 * fill a notify_info_data with job name
3259 ********************************************************************/
3261 static void spoolss_notify_job_name(int snum,
3262 SPOOL_NOTIFY_INFO_DATA *data,
3263 print_queue_struct *queue,
3264 NT_PRINTER_INFO_LEVEL *printer,
3265 TALLOC_CTX *mem_ctx)
3267 pstring temp;
3268 uint32 len;
3270 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3272 data->notify_data.data.length = len;
3273 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3275 if (!data->notify_data.data.string) {
3276 data->notify_data.data.length = 0;
3277 return;
3280 memcpy(data->notify_data.data.string, temp, len);
3283 /*******************************************************************
3284 * fill a notify_info_data with job status
3285 ********************************************************************/
3287 static void spoolss_notify_job_status_string(int snum,
3288 SPOOL_NOTIFY_INFO_DATA *data,
3289 print_queue_struct *queue,
3290 NT_PRINTER_INFO_LEVEL *printer,
3291 TALLOC_CTX *mem_ctx)
3294 * Now we're returning job status codes we just return a "" here. JRA.
3297 const char *p = "";
3298 pstring temp;
3299 uint32 len;
3301 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3302 p = "unknown";
3304 switch (queue->status) {
3305 case LPQ_QUEUED:
3306 p = "Queued";
3307 break;
3308 case LPQ_PAUSED:
3309 p = ""; /* NT provides the paused string */
3310 break;
3311 case LPQ_SPOOLING:
3312 p = "Spooling";
3313 break;
3314 case LPQ_PRINTING:
3315 p = "Printing";
3316 break;
3318 #endif /* NO LONGER NEEDED. */
3320 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3322 data->notify_data.data.length = len;
3323 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3325 if (!data->notify_data.data.string) {
3326 data->notify_data.data.length = 0;
3327 return;
3330 memcpy(data->notify_data.data.string, temp, len);
3333 /*******************************************************************
3334 * fill a notify_info_data with job time
3335 ********************************************************************/
3337 static void spoolss_notify_job_time(int snum,
3338 SPOOL_NOTIFY_INFO_DATA *data,
3339 print_queue_struct *queue,
3340 NT_PRINTER_INFO_LEVEL *printer,
3341 TALLOC_CTX *mem_ctx)
3343 data->notify_data.value[0]=0x0;
3344 data->notify_data.value[1]=0;
3347 /*******************************************************************
3348 * fill a notify_info_data with job size
3349 ********************************************************************/
3351 static void spoolss_notify_job_size(int snum,
3352 SPOOL_NOTIFY_INFO_DATA *data,
3353 print_queue_struct *queue,
3354 NT_PRINTER_INFO_LEVEL *printer,
3355 TALLOC_CTX *mem_ctx)
3357 data->notify_data.value[0]=queue->size;
3358 data->notify_data.value[1]=0;
3361 /*******************************************************************
3362 * fill a notify_info_data with page info
3363 ********************************************************************/
3364 static void spoolss_notify_total_pages(int snum,
3365 SPOOL_NOTIFY_INFO_DATA *data,
3366 print_queue_struct *queue,
3367 NT_PRINTER_INFO_LEVEL *printer,
3368 TALLOC_CTX *mem_ctx)
3370 data->notify_data.value[0]=queue->page_count;
3371 data->notify_data.value[1]=0;
3374 /*******************************************************************
3375 * fill a notify_info_data with pages printed info.
3376 ********************************************************************/
3377 static void spoolss_notify_pages_printed(int snum,
3378 SPOOL_NOTIFY_INFO_DATA *data,
3379 print_queue_struct *queue,
3380 NT_PRINTER_INFO_LEVEL *printer,
3381 TALLOC_CTX *mem_ctx)
3383 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3384 data->notify_data.value[1]=0;
3387 /*******************************************************************
3388 Fill a notify_info_data with job position.
3389 ********************************************************************/
3391 static void spoolss_notify_job_position(int snum,
3392 SPOOL_NOTIFY_INFO_DATA *data,
3393 print_queue_struct *queue,
3394 NT_PRINTER_INFO_LEVEL *printer,
3395 TALLOC_CTX *mem_ctx)
3397 data->notify_data.value[0]=queue->job;
3398 data->notify_data.value[1]=0;
3401 /*******************************************************************
3402 Fill a notify_info_data with submitted time.
3403 ********************************************************************/
3405 static void spoolss_notify_submitted_time(int snum,
3406 SPOOL_NOTIFY_INFO_DATA *data,
3407 print_queue_struct *queue,
3408 NT_PRINTER_INFO_LEVEL *printer,
3409 TALLOC_CTX *mem_ctx)
3411 struct tm *t;
3412 uint32 len;
3413 SYSTEMTIME st;
3414 char *p;
3416 t=gmtime(&queue->time);
3418 len = sizeof(SYSTEMTIME);
3420 data->notify_data.data.length = len;
3421 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3423 if (!data->notify_data.data.string) {
3424 data->notify_data.data.length = 0;
3425 return;
3428 make_systemtime(&st, t);
3431 * Systemtime must be linearized as a set of UINT16's.
3432 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3435 p = (char *)data->notify_data.data.string;
3436 SSVAL(p, 0, st.year);
3437 SSVAL(p, 2, st.month);
3438 SSVAL(p, 4, st.dayofweek);
3439 SSVAL(p, 6, st.day);
3440 SSVAL(p, 8, st.hour);
3441 SSVAL(p, 10, st.minute);
3442 SSVAL(p, 12, st.second);
3443 SSVAL(p, 14, st.milliseconds);
3446 struct s_notify_info_data_table
3448 uint16 type;
3449 uint16 field;
3450 const char *name;
3451 uint32 size;
3452 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3453 print_queue_struct *queue,
3454 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3457 /* A table describing the various print notification constants and
3458 whether the notification data is a pointer to a variable sized
3459 buffer, a one value uint32 or a two value uint32. */
3461 static const struct s_notify_info_data_table notify_info_data_table[] =
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3485 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3486 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3487 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3488 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3508 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3509 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3510 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3511 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3514 /*******************************************************************
3515 Return the size of info_data structure.
3516 ********************************************************************/
3518 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3520 int i=0;
3522 for (i = 0; i < sizeof(notify_info_data_table); i++)
3524 if ( (notify_info_data_table[i].type == type)
3525 && (notify_info_data_table[i].field == field) )
3527 switch(notify_info_data_table[i].size)
3529 case NOTIFY_ONE_VALUE:
3530 case NOTIFY_TWO_VALUE:
3531 return 1;
3532 case NOTIFY_STRING:
3533 return 2;
3535 /* The only pointer notify data I have seen on
3536 the wire is the submitted time and this has
3537 the notify size set to 4. -tpot */
3539 case NOTIFY_POINTER:
3540 return 4;
3542 case NOTIFY_SECDESC:
3543 return 5;
3548 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3550 return 0;
3553 /*******************************************************************
3554 Return the type of notify_info_data.
3555 ********************************************************************/
3557 static int type_of_notify_info_data(uint16 type, uint16 field)
3559 int i=0;
3561 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3562 if (notify_info_data_table[i].type == type &&
3563 notify_info_data_table[i].field == field)
3564 return notify_info_data_table[i].size;
3567 return False;
3570 /****************************************************************************
3571 ****************************************************************************/
3573 static int search_notify(uint16 type, uint16 field, int *value)
3575 int i;
3577 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3578 if (notify_info_data_table[i].type == type &&
3579 notify_info_data_table[i].field == field &&
3580 notify_info_data_table[i].fn != NULL) {
3581 *value = i;
3582 return True;
3586 return False;
3589 /****************************************************************************
3590 ****************************************************************************/
3592 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3594 info_data->type = type;
3595 info_data->field = field;
3596 info_data->reserved = 0;
3598 info_data->size = size_of_notify_info_data(type, field);
3599 info_data->enc_type = type_of_notify_info_data(type, field);
3601 info_data->id = id;
3606 /*******************************************************************
3608 * fill a notify_info struct with info asked
3610 ********************************************************************/
3612 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3613 snum, SPOOL_NOTIFY_OPTION_TYPE
3614 *option_type, uint32 id,
3615 TALLOC_CTX *mem_ctx)
3617 int field_num,j;
3618 uint16 type;
3619 uint16 field;
3621 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3622 NT_PRINTER_INFO_LEVEL *printer = NULL;
3623 print_queue_struct *queue=NULL;
3625 type=option_type->type;
3627 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3628 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3629 option_type->count, lp_servicename(snum)));
3631 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3632 return False;
3634 for(field_num=0; field_num<option_type->count; field_num++) {
3635 field = option_type->fields[field_num];
3637 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3639 if (!search_notify(type, field, &j) )
3640 continue;
3642 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3643 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3644 return False;
3645 } else
3646 info->data = tid;
3648 current_data = &info->data[info->count];
3650 construct_info_data(current_data, type, field, id);
3652 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3653 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3655 notify_info_data_table[j].fn(snum, current_data, queue,
3656 printer, mem_ctx);
3658 info->count++;
3661 free_a_printer(&printer, 2);
3662 return True;
3665 /*******************************************************************
3667 * fill a notify_info struct with info asked
3669 ********************************************************************/
3671 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3672 SPOOL_NOTIFY_INFO *info,
3673 NT_PRINTER_INFO_LEVEL *printer,
3674 int snum, SPOOL_NOTIFY_OPTION_TYPE
3675 *option_type, uint32 id,
3676 TALLOC_CTX *mem_ctx)
3678 int field_num,j;
3679 uint16 type;
3680 uint16 field;
3682 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3684 DEBUG(4,("construct_notify_jobs_info\n"));
3686 type = option_type->type;
3688 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3689 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3690 option_type->count));
3692 for(field_num=0; field_num<option_type->count; field_num++) {
3693 field = option_type->fields[field_num];
3695 if (!search_notify(type, field, &j) )
3696 continue;
3698 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3699 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3700 return False;
3702 else info->data = tid;
3704 current_data=&(info->data[info->count]);
3706 construct_info_data(current_data, type, field, id);
3707 notify_info_data_table[j].fn(snum, current_data, queue,
3708 printer, mem_ctx);
3709 info->count++;
3712 return True;
3716 * JFM: The enumeration is not that simple, it's even non obvious.
3718 * let's take an example: I want to monitor the PRINTER SERVER for
3719 * the printer's name and the number of jobs currently queued.
3720 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3721 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3723 * I have 3 printers on the back of my server.
3725 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3726 * structures.
3727 * Number Data Id
3728 * 1 printer 1 name 1
3729 * 2 printer 1 cjob 1
3730 * 3 printer 2 name 2
3731 * 4 printer 2 cjob 2
3732 * 5 printer 3 name 3
3733 * 6 printer 3 name 3
3735 * that's the print server case, the printer case is even worse.
3738 /*******************************************************************
3740 * enumerate all printers on the printserver
3741 * fill a notify_info struct with info asked
3743 ********************************************************************/
3745 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3746 SPOOL_NOTIFY_INFO *info,
3747 TALLOC_CTX *mem_ctx)
3749 int snum;
3750 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3751 int n_services=lp_numservices();
3752 int i;
3753 SPOOL_NOTIFY_OPTION *option;
3754 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3756 DEBUG(4,("printserver_notify_info\n"));
3758 if (!Printer)
3759 return WERR_BADFID;
3761 option=Printer->notify.option;
3762 info->version=2;
3763 info->data=NULL;
3764 info->count=0;
3766 for (i=0; i<option->count; i++) {
3767 option_type=&(option->ctr.type[i]);
3769 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3770 continue;
3772 for (snum=0; snum<n_services; snum++)
3774 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3775 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3779 #if 0
3781 * Debugging information, don't delete.
3784 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3785 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3786 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3788 for (i=0; i<info->count; i++) {
3789 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3790 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3791 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3793 #endif
3795 return WERR_OK;
3798 /*******************************************************************
3800 * fill a notify_info struct with info asked
3802 ********************************************************************/
3804 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3805 TALLOC_CTX *mem_ctx)
3807 int snum;
3808 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3809 int i;
3810 uint32 id;
3811 SPOOL_NOTIFY_OPTION *option;
3812 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3813 int count,j;
3814 print_queue_struct *queue=NULL;
3815 print_status_struct status;
3817 DEBUG(4,("printer_notify_info\n"));
3819 if (!Printer)
3820 return WERR_BADFID;
3822 option=Printer->notify.option;
3823 id = 0x0;
3824 info->version=2;
3825 info->data=NULL;
3826 info->count=0;
3828 get_printer_snum(p, hnd, &snum);
3830 for (i=0; i<option->count; i++) {
3831 option_type=&option->ctr.type[i];
3833 switch ( option_type->type ) {
3834 case PRINTER_NOTIFY_TYPE:
3835 if(construct_notify_printer_info(Printer, info, snum,
3836 option_type, id,
3837 mem_ctx))
3838 id--;
3839 break;
3841 case JOB_NOTIFY_TYPE: {
3842 NT_PRINTER_INFO_LEVEL *printer = NULL;
3844 count = print_queue_status(snum, &queue, &status);
3846 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3847 goto done;
3849 for (j=0; j<count; j++) {
3850 construct_notify_jobs_info(&queue[j], info,
3851 printer, snum,
3852 option_type,
3853 queue[j].job,
3854 mem_ctx);
3857 free_a_printer(&printer, 2);
3859 done:
3860 SAFE_FREE(queue);
3861 break;
3867 * Debugging information, don't delete.
3870 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3871 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3872 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3874 for (i=0; i<info->count; i++) {
3875 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3876 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3877 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3880 return WERR_OK;
3883 /********************************************************************
3884 * spoolss_rfnpcnex
3885 ********************************************************************/
3887 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3889 POLICY_HND *handle = &q_u->handle;
3890 SPOOL_NOTIFY_INFO *info = &r_u->info;
3892 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3893 WERROR result = WERR_BADFID;
3895 /* we always have a NOTIFY_INFO struct */
3896 r_u->info_ptr=0x1;
3898 if (!Printer) {
3899 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3900 OUR_HANDLE(handle)));
3901 goto done;
3904 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3907 * We are now using the change value, and
3908 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3909 * I don't have a global notification system, I'm sending back all the
3910 * informations even when _NOTHING_ has changed.
3913 /* We need to keep track of the change value to send back in
3914 RRPCN replies otherwise our updates are ignored. */
3916 Printer->notify.fnpcn = True;
3918 if (Printer->notify.client_connected) {
3919 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3920 Printer->notify.change = q_u->change;
3923 /* just ignore the SPOOL_NOTIFY_OPTION */
3925 switch (Printer->printer_type) {
3926 case PRINTER_HANDLE_IS_PRINTSERVER:
3927 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3928 break;
3930 case PRINTER_HANDLE_IS_PRINTER:
3931 result = printer_notify_info(p, handle, info, p->mem_ctx);
3932 break;
3935 Printer->notify.fnpcn = False;
3937 done:
3938 return result;
3941 /********************************************************************
3942 * construct_printer_info_0
3943 * fill a printer_info_0 struct
3944 ********************************************************************/
3946 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3948 pstring chaine;
3949 int count;
3950 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3951 counter_printer_0 *session_counter;
3952 uint32 global_counter;
3953 struct tm *t;
3954 time_t setuptime;
3955 print_status_struct status;
3957 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3958 return False;
3960 count = print_queue_length(snum, &status);
3962 /* check if we already have a counter for this printer */
3963 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3965 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3966 if (session_counter->snum == snum)
3967 break;
3970 /* it's the first time, add it to the list */
3971 if (session_counter==NULL) {
3972 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3973 free_a_printer(&ntprinter, 2);
3974 return False;
3976 ZERO_STRUCTP(session_counter);
3977 session_counter->snum=snum;
3978 session_counter->counter=0;
3979 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3982 /* increment it */
3983 session_counter->counter++;
3985 /* JFM:
3986 * the global_counter should be stored in a TDB as it's common to all the clients
3987 * and should be zeroed on samba startup
3989 global_counter=session_counter->counter;
3991 pstrcpy(chaine,ntprinter->info_2->printername);
3993 init_unistr(&printer->printername, chaine);
3995 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3996 init_unistr(&printer->servername, chaine);
3998 printer->cjobs = count;
3999 printer->total_jobs = 0;
4000 printer->total_bytes = 0;
4002 setuptime = (time_t)ntprinter->info_2->setuptime;
4003 t=gmtime(&setuptime);
4005 printer->year = t->tm_year+1900;
4006 printer->month = t->tm_mon+1;
4007 printer->dayofweek = t->tm_wday;
4008 printer->day = t->tm_mday;
4009 printer->hour = t->tm_hour;
4010 printer->minute = t->tm_min;
4011 printer->second = t->tm_sec;
4012 printer->milliseconds = 0;
4014 printer->global_counter = global_counter;
4015 printer->total_pages = 0;
4017 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4018 printer->major_version = 0x0005; /* NT 5 */
4019 printer->build_version = 0x0893; /* build 2195 */
4021 printer->unknown7 = 0x1;
4022 printer->unknown8 = 0x0;
4023 printer->unknown9 = 0x0;
4024 printer->session_counter = session_counter->counter;
4025 printer->unknown11 = 0x0;
4026 printer->printer_errors = 0x0; /* number of print failure */
4027 printer->unknown13 = 0x0;
4028 printer->unknown14 = 0x1;
4029 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4030 printer->unknown16 = 0x0;
4031 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4032 printer->unknown18 = 0x0;
4033 printer->status = nt_printq_status(status.status);
4034 printer->unknown20 = 0x0;
4035 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4036 printer->unknown22 = 0x0;
4037 printer->unknown23 = 0x6; /* 6 ???*/
4038 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4039 printer->unknown25 = 0;
4040 printer->unknown26 = 0;
4041 printer->unknown27 = 0;
4042 printer->unknown28 = 0;
4043 printer->unknown29 = 0;
4045 free_a_printer(&ntprinter,2);
4046 return (True);
4049 /********************************************************************
4050 * construct_printer_info_1
4051 * fill a printer_info_1 struct
4052 ********************************************************************/
4053 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4055 pstring chaine;
4056 pstring chaine2;
4057 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4059 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4060 return False;
4062 printer->flags=flags;
4064 if (*ntprinter->info_2->comment == '\0') {
4065 init_unistr(&printer->comment, lp_comment(snum));
4066 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4067 ntprinter->info_2->drivername, lp_comment(snum));
4069 else {
4070 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4071 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4072 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4075 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4077 init_unistr(&printer->description, chaine);
4078 init_unistr(&printer->name, chaine2);
4080 free_a_printer(&ntprinter,2);
4082 return True;
4085 /****************************************************************************
4086 Free a DEVMODE struct.
4087 ****************************************************************************/
4089 static void free_dev_mode(DEVICEMODE *dev)
4091 if (dev == NULL)
4092 return;
4094 SAFE_FREE(dev->private);
4095 SAFE_FREE(dev);
4099 /****************************************************************************
4100 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4101 should be valid upon entry
4102 ****************************************************************************/
4104 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4106 if ( !devmode || !ntdevmode )
4107 return False;
4109 init_unistr(&devmode->devicename, ntdevmode->devicename);
4111 init_unistr(&devmode->formname, ntdevmode->formname);
4113 devmode->specversion = ntdevmode->specversion;
4114 devmode->driverversion = ntdevmode->driverversion;
4115 devmode->size = ntdevmode->size;
4116 devmode->driverextra = ntdevmode->driverextra;
4117 devmode->fields = ntdevmode->fields;
4119 devmode->orientation = ntdevmode->orientation;
4120 devmode->papersize = ntdevmode->papersize;
4121 devmode->paperlength = ntdevmode->paperlength;
4122 devmode->paperwidth = ntdevmode->paperwidth;
4123 devmode->scale = ntdevmode->scale;
4124 devmode->copies = ntdevmode->copies;
4125 devmode->defaultsource = ntdevmode->defaultsource;
4126 devmode->printquality = ntdevmode->printquality;
4127 devmode->color = ntdevmode->color;
4128 devmode->duplex = ntdevmode->duplex;
4129 devmode->yresolution = ntdevmode->yresolution;
4130 devmode->ttoption = ntdevmode->ttoption;
4131 devmode->collate = ntdevmode->collate;
4132 devmode->icmmethod = ntdevmode->icmmethod;
4133 devmode->icmintent = ntdevmode->icmintent;
4134 devmode->mediatype = ntdevmode->mediatype;
4135 devmode->dithertype = ntdevmode->dithertype;
4137 if (ntdevmode->private != NULL) {
4138 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4139 return False;
4142 return True;
4145 /****************************************************************************
4146 Create a DEVMODE struct. Returns malloced memory.
4147 ****************************************************************************/
4149 DEVICEMODE *construct_dev_mode(int snum)
4151 NT_PRINTER_INFO_LEVEL *printer = NULL;
4152 DEVICEMODE *devmode = NULL;
4154 DEBUG(7,("construct_dev_mode\n"));
4156 DEBUGADD(8,("getting printer characteristics\n"));
4158 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4159 return NULL;
4161 if ( !printer->info_2->devmode ) {
4162 DEBUG(5, ("BONG! There was no device mode!\n"));
4163 goto done;
4166 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4167 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4168 goto done;
4171 ZERO_STRUCTP(devmode);
4173 DEBUGADD(8,("loading DEVICEMODE\n"));
4175 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4176 free_dev_mode( devmode );
4177 devmode = NULL;
4180 done:
4181 free_a_printer(&printer,2);
4183 return devmode;
4186 /********************************************************************
4187 * construct_printer_info_2
4188 * fill a printer_info_2 struct
4189 ********************************************************************/
4191 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4193 int count;
4194 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4196 print_status_struct status;
4198 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4199 return False;
4201 count = print_queue_length(snum, &status);
4203 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4204 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4205 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4206 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4207 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4209 if (*ntprinter->info_2->comment == '\0')
4210 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4211 else
4212 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4214 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4215 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4216 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4217 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4218 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4220 printer->attributes = ntprinter->info_2->attributes;
4222 printer->priority = ntprinter->info_2->priority; /* priority */
4223 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4224 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4225 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4226 printer->status = nt_printq_status(status.status); /* status */
4227 printer->cjobs = count; /* jobs */
4228 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4230 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4231 DEBUG(8, ("Returning NULL Devicemode!\n"));
4234 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4235 /* steal the printer info sec_desc structure. [badly done]. */
4236 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4237 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4238 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4239 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4241 else {
4242 printer->secdesc = NULL;
4245 free_a_printer(&ntprinter, 2);
4246 return True;
4249 /********************************************************************
4250 * construct_printer_info_3
4251 * fill a printer_info_3 struct
4252 ********************************************************************/
4254 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4256 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4257 PRINTER_INFO_3 *printer = NULL;
4259 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4260 return False;
4262 *pp_printer = NULL;
4263 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4264 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4265 return False;
4268 ZERO_STRUCTP(printer);
4270 printer->flags = 4; /* These are the components of the SD we are returning. */
4271 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4272 /* steal the printer info sec_desc structure. [badly done]. */
4273 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4275 #if 0
4277 * Set the flags for the components we are returning.
4280 if (printer->secdesc->owner_sid)
4281 printer->flags |= OWNER_SECURITY_INFORMATION;
4283 if (printer->secdesc->grp_sid)
4284 printer->flags |= GROUP_SECURITY_INFORMATION;
4286 if (printer->secdesc->dacl)
4287 printer->flags |= DACL_SECURITY_INFORMATION;
4289 if (printer->secdesc->sacl)
4290 printer->flags |= SACL_SECURITY_INFORMATION;
4291 #endif
4293 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4294 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4295 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4298 free_a_printer(&ntprinter, 2);
4300 *pp_printer = printer;
4301 return True;
4304 /********************************************************************
4305 * construct_printer_info_4
4306 * fill a printer_info_4 struct
4307 ********************************************************************/
4309 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4311 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4313 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4314 return False;
4316 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4317 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4318 printer->attributes = ntprinter->info_2->attributes;
4320 free_a_printer(&ntprinter, 2);
4321 return True;
4324 /********************************************************************
4325 * construct_printer_info_5
4326 * fill a printer_info_5 struct
4327 ********************************************************************/
4329 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4331 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4333 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4334 return False;
4336 init_unistr(&printer->printername, ntprinter->info_2->printername);
4337 init_unistr(&printer->portname, ntprinter->info_2->portname);
4338 printer->attributes = ntprinter->info_2->attributes;
4340 /* these two are not used by NT+ according to MSDN */
4342 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4343 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4345 free_a_printer(&ntprinter, 2);
4347 return True;
4350 /********************************************************************
4351 * construct_printer_info_7
4352 * fill a printer_info_7 struct
4353 ********************************************************************/
4355 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4357 char *guid_str = NULL;
4358 GUID guid;
4360 if (is_printer_published(print_hnd, snum, &guid)) {
4361 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4362 strupper_m(guid_str);
4363 init_unistr(&printer->guid, guid_str);
4364 printer->action = SPOOL_DS_PUBLISH;
4365 } else {
4366 init_unistr(&printer->guid, "");
4367 printer->action = SPOOL_DS_UNPUBLISH;
4370 return True;
4373 /********************************************************************
4374 Spoolss_enumprinters.
4375 ********************************************************************/
4377 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4379 int snum;
4380 int i;
4381 int n_services=lp_numservices();
4382 PRINTER_INFO_1 *tp, *printers=NULL;
4383 PRINTER_INFO_1 current_prt;
4385 DEBUG(4,("enum_all_printers_info_1\n"));
4387 for (snum=0; snum<n_services; snum++) {
4388 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4389 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4391 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4392 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4393 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4394 SAFE_FREE(printers);
4395 *returned=0;
4396 return WERR_NOMEM;
4398 else printers = tp;
4399 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4401 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4402 (*returned)++;
4407 /* check the required size. */
4408 for (i=0; i<*returned; i++)
4409 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4411 if (!alloc_buffer_size(buffer, *needed))
4412 return WERR_INSUFFICIENT_BUFFER;
4414 /* fill the buffer with the structures */
4415 for (i=0; i<*returned; i++)
4416 smb_io_printer_info_1("", buffer, &printers[i], 0);
4418 /* clear memory */
4419 SAFE_FREE(printers);
4421 if (*needed > offered) {
4422 *returned=0;
4423 return WERR_INSUFFICIENT_BUFFER;
4425 else
4426 return WERR_OK;
4429 /********************************************************************
4430 enum_all_printers_info_1_local.
4431 *********************************************************************/
4433 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4435 DEBUG(4,("enum_all_printers_info_1_local\n"));
4437 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4440 /********************************************************************
4441 enum_all_printers_info_1_name.
4442 *********************************************************************/
4444 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4446 char *s = name;
4448 DEBUG(4,("enum_all_printers_info_1_name\n"));
4450 if ((name[0] == '\\') && (name[1] == '\\'))
4451 s = name + 2;
4453 if (is_myname_or_ipaddr(s)) {
4454 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4456 else
4457 return WERR_INVALID_NAME;
4460 /********************************************************************
4461 enum_all_printers_info_1_remote.
4462 *********************************************************************/
4464 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4466 PRINTER_INFO_1 *printer;
4467 fstring printername;
4468 fstring desc;
4469 fstring comment;
4470 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4472 /* JFM: currently it's more a place holder than anything else.
4473 * In the spooler world there is a notion of server registration.
4474 * the print servers are registring (sp ?) on the PDC (in the same domain)
4476 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4479 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4480 return WERR_NOMEM;
4482 *returned=1;
4484 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4485 slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4486 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4488 init_unistr(&printer->description, desc);
4489 init_unistr(&printer->name, printername);
4490 init_unistr(&printer->comment, comment);
4491 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4493 /* check the required size. */
4494 *needed += spoolss_size_printer_info_1(printer);
4496 if (!alloc_buffer_size(buffer, *needed)) {
4497 SAFE_FREE(printer);
4498 return WERR_INSUFFICIENT_BUFFER;
4501 /* fill the buffer with the structures */
4502 smb_io_printer_info_1("", buffer, printer, 0);
4504 /* clear memory */
4505 SAFE_FREE(printer);
4507 if (*needed > offered) {
4508 *returned=0;
4509 return WERR_INSUFFICIENT_BUFFER;
4511 else
4512 return WERR_OK;
4515 /********************************************************************
4516 enum_all_printers_info_1_network.
4517 *********************************************************************/
4519 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4521 char *s = name;
4523 DEBUG(4,("enum_all_printers_info_1_network\n"));
4525 /* If we respond to a enum_printers level 1 on our name with flags
4526 set to PRINTER_ENUM_REMOTE with a list of printers then these
4527 printers incorrectly appear in the APW browse list.
4528 Specifically the printers for the server appear at the workgroup
4529 level where all the other servers in the domain are
4530 listed. Windows responds to this call with a
4531 WERR_CAN_NOT_COMPLETE so we should do the same. */
4533 if (name[0] == '\\' && name[1] == '\\')
4534 s = name + 2;
4536 if (is_myname_or_ipaddr(s))
4537 return WERR_CAN_NOT_COMPLETE;
4539 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4542 /********************************************************************
4543 * api_spoolss_enumprinters
4545 * called from api_spoolss_enumprinters (see this to understand)
4546 ********************************************************************/
4548 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4550 int snum;
4551 int i;
4552 int n_services=lp_numservices();
4553 PRINTER_INFO_2 *tp, *printers=NULL;
4554 PRINTER_INFO_2 current_prt;
4556 for (snum=0; snum<n_services; snum++) {
4557 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4558 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4560 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4561 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4562 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4563 SAFE_FREE(printers);
4564 *returned = 0;
4565 return WERR_NOMEM;
4567 else printers = tp;
4568 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4569 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4570 (*returned)++;
4575 /* check the required size. */
4576 for (i=0; i<*returned; i++)
4577 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4579 if (!alloc_buffer_size(buffer, *needed)) {
4580 for (i=0; i<*returned; i++) {
4581 free_devmode(printers[i].devmode);
4583 SAFE_FREE(printers);
4584 return WERR_INSUFFICIENT_BUFFER;
4587 /* fill the buffer with the structures */
4588 for (i=0; i<*returned; i++)
4589 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4591 /* clear memory */
4592 for (i=0; i<*returned; i++) {
4593 free_devmode(printers[i].devmode);
4595 SAFE_FREE(printers);
4597 if (*needed > offered) {
4598 *returned=0;
4599 return WERR_INSUFFICIENT_BUFFER;
4601 else
4602 return WERR_OK;
4605 /********************************************************************
4606 * handle enumeration of printers at level 1
4607 ********************************************************************/
4609 static WERROR enumprinters_level1( uint32 flags, fstring name,
4610 NEW_BUFFER *buffer, uint32 offered,
4611 uint32 *needed, uint32 *returned)
4613 /* Not all the flags are equals */
4615 if (flags & PRINTER_ENUM_LOCAL)
4616 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4618 if (flags & PRINTER_ENUM_NAME)
4619 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4621 if (flags & PRINTER_ENUM_REMOTE)
4622 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4624 if (flags & PRINTER_ENUM_NETWORK)
4625 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4627 return WERR_OK; /* NT4sp5 does that */
4630 /********************************************************************
4631 * handle enumeration of printers at level 2
4632 ********************************************************************/
4634 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4635 NEW_BUFFER *buffer, uint32 offered,
4636 uint32 *needed, uint32 *returned)
4638 char *s = servername;
4640 if (flags & PRINTER_ENUM_LOCAL) {
4641 return enum_all_printers_info_2(buffer, offered, needed, returned);
4644 if (flags & PRINTER_ENUM_NAME) {
4645 if ((servername[0] == '\\') && (servername[1] == '\\'))
4646 s = servername + 2;
4647 if (is_myname_or_ipaddr(s))
4648 return enum_all_printers_info_2(buffer, offered, needed, returned);
4649 else
4650 return WERR_INVALID_NAME;
4653 if (flags & PRINTER_ENUM_REMOTE)
4654 return WERR_UNKNOWN_LEVEL;
4656 return WERR_OK;
4659 /********************************************************************
4660 * handle enumeration of printers at level 5
4661 ********************************************************************/
4663 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4664 NEW_BUFFER *buffer, uint32 offered,
4665 uint32 *needed, uint32 *returned)
4667 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4668 return WERR_OK;
4671 /********************************************************************
4672 * api_spoolss_enumprinters
4674 * called from api_spoolss_enumprinters (see this to understand)
4675 ********************************************************************/
4677 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4679 uint32 flags = q_u->flags;
4680 UNISTR2 *servername = &q_u->servername;
4681 uint32 level = q_u->level;
4682 NEW_BUFFER *buffer = NULL;
4683 uint32 offered = q_u->offered;
4684 uint32 *needed = &r_u->needed;
4685 uint32 *returned = &r_u->returned;
4687 fstring name;
4689 /* that's an [in out] buffer */
4690 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4691 buffer = r_u->buffer;
4693 DEBUG(4,("_spoolss_enumprinters\n"));
4695 *needed=0;
4696 *returned=0;
4699 * Level 1:
4700 * flags==PRINTER_ENUM_NAME
4701 * if name=="" then enumerates all printers
4702 * if name!="" then enumerate the printer
4703 * flags==PRINTER_ENUM_REMOTE
4704 * name is NULL, enumerate printers
4705 * Level 2: name!="" enumerates printers, name can't be NULL
4706 * Level 3: doesn't exist
4707 * Level 4: does a local registry lookup
4708 * Level 5: same as Level 2
4711 unistr2_to_ascii(name, servername, sizeof(name)-1);
4712 strupper_m(name);
4714 switch (level) {
4715 case 1:
4716 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4717 case 2:
4718 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4719 case 5:
4720 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4721 case 3:
4722 case 4:
4723 break;
4725 return WERR_UNKNOWN_LEVEL;
4728 /****************************************************************************
4729 ****************************************************************************/
4731 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4733 PRINTER_INFO_0 *printer=NULL;
4735 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4736 return WERR_NOMEM;
4738 construct_printer_info_0(print_hnd, printer, snum);
4740 /* check the required size. */
4741 *needed += spoolss_size_printer_info_0(printer);
4743 if (!alloc_buffer_size(buffer, *needed)) {
4744 SAFE_FREE(printer);
4745 return WERR_INSUFFICIENT_BUFFER;
4748 /* fill the buffer with the structures */
4749 smb_io_printer_info_0("", buffer, printer, 0);
4751 /* clear memory */
4752 SAFE_FREE(printer);
4754 if (*needed > offered) {
4755 return WERR_INSUFFICIENT_BUFFER;
4758 return WERR_OK;
4761 /****************************************************************************
4762 ****************************************************************************/
4764 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4766 PRINTER_INFO_1 *printer=NULL;
4768 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4769 return WERR_NOMEM;
4771 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4773 /* check the required size. */
4774 *needed += spoolss_size_printer_info_1(printer);
4776 if (!alloc_buffer_size(buffer, *needed)) {
4777 SAFE_FREE(printer);
4778 return WERR_INSUFFICIENT_BUFFER;
4781 /* fill the buffer with the structures */
4782 smb_io_printer_info_1("", buffer, printer, 0);
4784 /* clear memory */
4785 SAFE_FREE(printer);
4787 if (*needed > offered) {
4788 return WERR_INSUFFICIENT_BUFFER;
4791 return WERR_OK;
4794 /****************************************************************************
4795 ****************************************************************************/
4797 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4799 PRINTER_INFO_2 *printer=NULL;
4801 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4802 return WERR_NOMEM;
4804 construct_printer_info_2(print_hnd, printer, snum);
4806 /* check the required size. */
4807 *needed += spoolss_size_printer_info_2(printer);
4809 if (!alloc_buffer_size(buffer, *needed)) {
4810 free_printer_info_2(printer);
4811 return WERR_INSUFFICIENT_BUFFER;
4814 /* fill the buffer with the structures */
4815 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4816 free_printer_info_2(printer);
4817 return WERR_NOMEM;
4820 /* clear memory */
4821 free_printer_info_2(printer);
4823 if (*needed > offered) {
4824 return WERR_INSUFFICIENT_BUFFER;
4827 return WERR_OK;
4830 /****************************************************************************
4831 ****************************************************************************/
4833 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4835 PRINTER_INFO_3 *printer=NULL;
4837 if (!construct_printer_info_3(print_hnd, &printer, snum))
4838 return WERR_NOMEM;
4840 /* check the required size. */
4841 *needed += spoolss_size_printer_info_3(printer);
4843 if (!alloc_buffer_size(buffer, *needed)) {
4844 free_printer_info_3(printer);
4845 return WERR_INSUFFICIENT_BUFFER;
4848 /* fill the buffer with the structures */
4849 smb_io_printer_info_3("", buffer, printer, 0);
4851 /* clear memory */
4852 free_printer_info_3(printer);
4854 if (*needed > offered) {
4855 return WERR_INSUFFICIENT_BUFFER;
4858 return WERR_OK;
4861 /****************************************************************************
4862 ****************************************************************************/
4864 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4866 PRINTER_INFO_4 *printer=NULL;
4868 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4869 return WERR_NOMEM;
4871 if (!construct_printer_info_4(print_hnd, printer, snum))
4872 return WERR_NOMEM;
4874 /* check the required size. */
4875 *needed += spoolss_size_printer_info_4(printer);
4877 if (!alloc_buffer_size(buffer, *needed)) {
4878 free_printer_info_4(printer);
4879 return WERR_INSUFFICIENT_BUFFER;
4882 /* fill the buffer with the structures */
4883 smb_io_printer_info_4("", buffer, printer, 0);
4885 /* clear memory */
4886 free_printer_info_4(printer);
4888 if (*needed > offered) {
4889 return WERR_INSUFFICIENT_BUFFER;
4892 return WERR_OK;
4895 /****************************************************************************
4896 ****************************************************************************/
4898 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4900 PRINTER_INFO_5 *printer=NULL;
4902 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4903 return WERR_NOMEM;
4905 if (!construct_printer_info_5(print_hnd, printer, snum))
4906 return WERR_NOMEM;
4908 /* check the required size. */
4909 *needed += spoolss_size_printer_info_5(printer);
4911 if (!alloc_buffer_size(buffer, *needed)) {
4912 free_printer_info_5(printer);
4913 return WERR_INSUFFICIENT_BUFFER;
4916 /* fill the buffer with the structures */
4917 smb_io_printer_info_5("", buffer, printer, 0);
4919 /* clear memory */
4920 free_printer_info_5(printer);
4922 if (*needed > offered) {
4923 return WERR_INSUFFICIENT_BUFFER;
4926 return WERR_OK;
4929 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4931 PRINTER_INFO_7 *printer=NULL;
4933 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4934 return WERR_NOMEM;
4936 if (!construct_printer_info_7(print_hnd, printer, snum))
4937 return WERR_NOMEM;
4939 /* check the required size. */
4940 *needed += spoolss_size_printer_info_7(printer);
4942 if (!alloc_buffer_size(buffer, *needed)) {
4943 free_printer_info_7(printer);
4944 return WERR_INSUFFICIENT_BUFFER;
4947 /* fill the buffer with the structures */
4948 smb_io_printer_info_7("", buffer, printer, 0);
4950 /* clear memory */
4951 free_printer_info_7(printer);
4953 if (*needed > offered) {
4954 return WERR_INSUFFICIENT_BUFFER;
4957 return WERR_OK;
4960 /****************************************************************************
4961 ****************************************************************************/
4963 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4965 POLICY_HND *handle = &q_u->handle;
4966 uint32 level = q_u->level;
4967 NEW_BUFFER *buffer = NULL;
4968 uint32 offered = q_u->offered;
4969 uint32 *needed = &r_u->needed;
4970 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4972 int snum;
4974 /* that's an [in out] buffer */
4975 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4976 buffer = r_u->buffer;
4978 *needed=0;
4980 if (!get_printer_snum(p, handle, &snum))
4981 return WERR_BADFID;
4983 switch (level) {
4984 case 0:
4985 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4986 case 1:
4987 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4988 case 2:
4989 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4990 case 3:
4991 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4992 case 4:
4993 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4994 case 5:
4995 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4996 case 7:
4997 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4999 return WERR_UNKNOWN_LEVEL;
5002 /********************************************************************
5003 * fill a DRIVER_INFO_1 struct
5004 ********************************************************************/
5006 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5008 init_unistr( &info->name, driver.info_3->name);
5011 /********************************************************************
5012 * construct_printer_driver_info_1
5013 ********************************************************************/
5015 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5017 NT_PRINTER_INFO_LEVEL *printer = NULL;
5018 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5020 ZERO_STRUCT(driver);
5022 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5023 return WERR_INVALID_PRINTER_NAME;
5025 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5026 return WERR_UNKNOWN_PRINTER_DRIVER;
5028 fill_printer_driver_info_1(info, driver, servername, architecture);
5030 free_a_printer(&printer,2);
5032 return WERR_OK;
5035 /********************************************************************
5036 * construct_printer_driver_info_2
5037 * fill a printer_info_2 struct
5038 ********************************************************************/
5040 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5042 pstring temp;
5044 info->version=driver.info_3->cversion;
5046 init_unistr( &info->name, driver.info_3->name );
5047 init_unistr( &info->architecture, driver.info_3->environment );
5050 if (strlen(driver.info_3->driverpath)) {
5051 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5052 init_unistr( &info->driverpath, temp );
5053 } else
5054 init_unistr( &info->driverpath, "" );
5056 if (strlen(driver.info_3->datafile)) {
5057 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5058 init_unistr( &info->datafile, temp );
5059 } else
5060 init_unistr( &info->datafile, "" );
5062 if (strlen(driver.info_3->configfile)) {
5063 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5064 init_unistr( &info->configfile, temp );
5065 } else
5066 init_unistr( &info->configfile, "" );
5069 /********************************************************************
5070 * construct_printer_driver_info_2
5071 * fill a printer_info_2 struct
5072 ********************************************************************/
5074 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5076 NT_PRINTER_INFO_LEVEL *printer = NULL;
5077 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5079 ZERO_STRUCT(printer);
5080 ZERO_STRUCT(driver);
5082 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5083 return WERR_INVALID_PRINTER_NAME;
5085 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5086 return WERR_UNKNOWN_PRINTER_DRIVER;
5088 fill_printer_driver_info_2(info, driver, servername);
5090 free_a_printer(&printer,2);
5092 return WERR_OK;
5095 /********************************************************************
5096 * copy a strings array and convert to UNICODE
5098 * convert an array of ascii string to a UNICODE string
5099 ********************************************************************/
5101 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5103 int i=0;
5104 int j=0;
5105 const char *v;
5106 pstring line;
5107 uint16 *tuary;
5109 DEBUG(6,("init_unistr_array\n"));
5110 *uni_array=NULL;
5112 while (True)
5114 if ( !char_array )
5115 v = "";
5116 else
5118 v = char_array[i];
5119 if (!v)
5120 v = ""; /* hack to handle null lists */
5123 /* hack to allow this to be used in places other than when generating
5124 the list of dependent files */
5126 if ( servername )
5127 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5128 else
5129 pstrcpy( line, v );
5131 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5133 /* add one extra unit16 for the second terminating NULL */
5135 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5136 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5137 return 0;
5138 } else
5139 *uni_array = tuary;
5141 if ( !strlen(v) )
5142 break;
5144 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5145 i++;
5148 if (*uni_array) {
5149 /* special case for ""; we need to add both NULL's here */
5150 if (!j)
5151 (*uni_array)[j++]=0x0000;
5152 (*uni_array)[j]=0x0000;
5155 DEBUGADD(6,("last one:done\n"));
5157 /* return size of array in uint16's */
5159 return j+1;
5162 /********************************************************************
5163 * construct_printer_info_3
5164 * fill a printer_info_3 struct
5165 ********************************************************************/
5167 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5169 pstring temp;
5171 ZERO_STRUCTP(info);
5173 info->version=driver.info_3->cversion;
5175 init_unistr( &info->name, driver.info_3->name );
5176 init_unistr( &info->architecture, driver.info_3->environment );
5178 if (strlen(driver.info_3->driverpath)) {
5179 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5180 init_unistr( &info->driverpath, temp );
5181 } else
5182 init_unistr( &info->driverpath, "" );
5184 if (strlen(driver.info_3->datafile)) {
5185 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5186 init_unistr( &info->datafile, temp );
5187 } else
5188 init_unistr( &info->datafile, "" );
5190 if (strlen(driver.info_3->configfile)) {
5191 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5192 init_unistr( &info->configfile, temp );
5193 } else
5194 init_unistr( &info->configfile, "" );
5196 if (strlen(driver.info_3->helpfile)) {
5197 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5198 init_unistr( &info->helpfile, temp );
5199 } else
5200 init_unistr( &info->helpfile, "" );
5202 init_unistr( &info->monitorname, driver.info_3->monitorname );
5203 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5205 info->dependentfiles=NULL;
5206 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5209 /********************************************************************
5210 * construct_printer_info_3
5211 * fill a printer_info_3 struct
5212 ********************************************************************/
5214 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5216 NT_PRINTER_INFO_LEVEL *printer = NULL;
5217 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5218 WERROR status;
5219 ZERO_STRUCT(driver);
5221 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5222 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5223 if (!W_ERROR_IS_OK(status))
5224 return WERR_INVALID_PRINTER_NAME;
5226 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5227 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5229 #if 0 /* JERRY */
5232 * I put this code in during testing. Helpful when commenting out the
5233 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5234 * as win2k always queries the driver using an infor level of 6.
5235 * I've left it in (but ifdef'd out) because I'll probably
5236 * use it in experimentation again in the future. --jerry 22/01/2002
5239 if (!W_ERROR_IS_OK(status)) {
5241 * Is this a W2k client ?
5243 if (version == 3) {
5244 /* Yes - try again with a WinNT driver. */
5245 version = 2;
5246 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5247 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5249 #endif
5251 if (!W_ERROR_IS_OK(status)) {
5252 free_a_printer(&printer,2);
5253 return WERR_UNKNOWN_PRINTER_DRIVER;
5256 #if 0 /* JERRY */
5258 #endif
5261 fill_printer_driver_info_3(info, driver, servername);
5263 free_a_printer(&printer,2);
5265 return WERR_OK;
5268 /********************************************************************
5269 * construct_printer_info_6
5270 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5271 ********************************************************************/
5273 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5275 pstring temp;
5276 fstring nullstr;
5278 ZERO_STRUCTP(info);
5279 memset(&nullstr, '\0', sizeof(fstring));
5281 info->version=driver.info_3->cversion;
5283 init_unistr( &info->name, driver.info_3->name );
5284 init_unistr( &info->architecture, driver.info_3->environment );
5286 if (strlen(driver.info_3->driverpath)) {
5287 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5288 init_unistr( &info->driverpath, temp );
5289 } else
5290 init_unistr( &info->driverpath, "" );
5292 if (strlen(driver.info_3->datafile)) {
5293 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5294 init_unistr( &info->datafile, temp );
5295 } else
5296 init_unistr( &info->datafile, "" );
5298 if (strlen(driver.info_3->configfile)) {
5299 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5300 init_unistr( &info->configfile, temp );
5301 } else
5302 init_unistr( &info->configfile, "" );
5304 if (strlen(driver.info_3->helpfile)) {
5305 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5306 init_unistr( &info->helpfile, temp );
5307 } else
5308 init_unistr( &info->helpfile, "" );
5310 init_unistr( &info->monitorname, driver.info_3->monitorname );
5311 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5313 info->dependentfiles = NULL;
5314 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5316 info->previousdrivernames=NULL;
5317 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5319 info->driver_date.low=0;
5320 info->driver_date.high=0;
5322 info->padding=0;
5323 info->driver_version_low=0;
5324 info->driver_version_high=0;
5326 init_unistr( &info->mfgname, "");
5327 init_unistr( &info->oem_url, "");
5328 init_unistr( &info->hardware_id, "");
5329 init_unistr( &info->provider, "");
5332 /********************************************************************
5333 * construct_printer_info_6
5334 * fill a printer_info_6 struct
5335 ********************************************************************/
5337 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5338 fstring servername, fstring architecture, uint32 version)
5340 NT_PRINTER_INFO_LEVEL *printer = NULL;
5341 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5342 WERROR status;
5344 ZERO_STRUCT(driver);
5346 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5348 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5350 if (!W_ERROR_IS_OK(status))
5351 return WERR_INVALID_PRINTER_NAME;
5353 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5355 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5357 if (!W_ERROR_IS_OK(status))
5360 * Is this a W2k client ?
5363 if (version < 3) {
5364 free_a_printer(&printer,2);
5365 return WERR_UNKNOWN_PRINTER_DRIVER;
5368 /* Yes - try again with a WinNT driver. */
5369 version = 2;
5370 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5371 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5372 if (!W_ERROR_IS_OK(status)) {
5373 free_a_printer(&printer,2);
5374 return WERR_UNKNOWN_PRINTER_DRIVER;
5378 fill_printer_driver_info_6(info, driver, servername);
5380 free_a_printer(&printer,2);
5381 free_a_printer_driver(driver, 3);
5383 return WERR_OK;
5386 /****************************************************************************
5387 ****************************************************************************/
5389 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5391 SAFE_FREE(info->dependentfiles);
5394 /****************************************************************************
5395 ****************************************************************************/
5397 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5399 SAFE_FREE(info->dependentfiles);
5403 /****************************************************************************
5404 ****************************************************************************/
5406 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5408 DRIVER_INFO_1 *info=NULL;
5409 WERROR status;
5411 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5412 return WERR_NOMEM;
5414 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5415 if (!W_ERROR_IS_OK(status)) {
5416 SAFE_FREE(info);
5417 return status;
5420 /* check the required size. */
5421 *needed += spoolss_size_printer_driver_info_1(info);
5423 if (!alloc_buffer_size(buffer, *needed)) {
5424 SAFE_FREE(info);
5425 return WERR_INSUFFICIENT_BUFFER;
5428 /* fill the buffer with the structures */
5429 smb_io_printer_driver_info_1("", buffer, info, 0);
5431 /* clear memory */
5432 SAFE_FREE(info);
5434 if (*needed > offered)
5435 return WERR_INSUFFICIENT_BUFFER;
5437 return WERR_OK;
5440 /****************************************************************************
5441 ****************************************************************************/
5443 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5445 DRIVER_INFO_2 *info=NULL;
5446 WERROR status;
5448 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5449 return WERR_NOMEM;
5451 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5452 if (!W_ERROR_IS_OK(status)) {
5453 SAFE_FREE(info);
5454 return status;
5457 /* check the required size. */
5458 *needed += spoolss_size_printer_driver_info_2(info);
5460 if (!alloc_buffer_size(buffer, *needed)) {
5461 SAFE_FREE(info);
5462 return WERR_INSUFFICIENT_BUFFER;
5465 /* fill the buffer with the structures */
5466 smb_io_printer_driver_info_2("", buffer, info, 0);
5468 /* clear memory */
5469 SAFE_FREE(info);
5471 if (*needed > offered)
5472 return WERR_INSUFFICIENT_BUFFER;
5474 return WERR_OK;
5477 /****************************************************************************
5478 ****************************************************************************/
5480 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5482 DRIVER_INFO_3 info;
5483 WERROR status;
5485 ZERO_STRUCT(info);
5487 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5488 if (!W_ERROR_IS_OK(status)) {
5489 return status;
5492 /* check the required size. */
5493 *needed += spoolss_size_printer_driver_info_3(&info);
5495 if (!alloc_buffer_size(buffer, *needed)) {
5496 free_printer_driver_info_3(&info);
5497 return WERR_INSUFFICIENT_BUFFER;
5500 /* fill the buffer with the structures */
5501 smb_io_printer_driver_info_3("", buffer, &info, 0);
5503 free_printer_driver_info_3(&info);
5505 if (*needed > offered)
5506 return WERR_INSUFFICIENT_BUFFER;
5508 return WERR_OK;
5511 /****************************************************************************
5512 ****************************************************************************/
5514 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5516 DRIVER_INFO_6 info;
5517 WERROR status;
5519 ZERO_STRUCT(info);
5521 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5522 if (!W_ERROR_IS_OK(status)) {
5523 return status;
5526 /* check the required size. */
5527 *needed += spoolss_size_printer_driver_info_6(&info);
5529 if (!alloc_buffer_size(buffer, *needed)) {
5530 free_printer_driver_info_6(&info);
5531 return WERR_INSUFFICIENT_BUFFER;
5534 /* fill the buffer with the structures */
5535 smb_io_printer_driver_info_6("", buffer, &info, 0);
5537 free_printer_driver_info_6(&info);
5539 if (*needed > offered)
5540 return WERR_INSUFFICIENT_BUFFER;
5542 return WERR_OK;
5545 /****************************************************************************
5546 ****************************************************************************/
5548 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5550 POLICY_HND *handle = &q_u->handle;
5551 UNISTR2 *uni_arch = &q_u->architecture;
5552 uint32 level = q_u->level;
5553 uint32 clientmajorversion = q_u->clientmajorversion;
5554 NEW_BUFFER *buffer = NULL;
5555 uint32 offered = q_u->offered;
5556 uint32 *needed = &r_u->needed;
5557 uint32 *servermajorversion = &r_u->servermajorversion;
5558 uint32 *serverminorversion = &r_u->serverminorversion;
5560 fstring servername;
5561 fstring architecture;
5562 int snum;
5564 /* that's an [in out] buffer */
5565 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5566 buffer = r_u->buffer;
5568 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5570 *needed = 0;
5571 *servermajorversion = 0;
5572 *serverminorversion = 0;
5574 fstrcpy(servername, get_called_name());
5575 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5577 if (!get_printer_snum(p, handle, &snum))
5578 return WERR_BADFID;
5580 switch (level) {
5581 case 1:
5582 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5583 case 2:
5584 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5585 case 3:
5586 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5587 case 6:
5588 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5591 return WERR_UNKNOWN_LEVEL;
5594 /****************************************************************************
5595 ****************************************************************************/
5597 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5599 POLICY_HND *handle = &q_u->handle;
5601 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5603 if (!Printer) {
5604 DEBUG(3,("Error in startpageprinter printer handle\n"));
5605 return WERR_BADFID;
5608 Printer->page_started=True;
5609 return WERR_OK;
5612 /****************************************************************************
5613 ****************************************************************************/
5615 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5617 POLICY_HND *handle = &q_u->handle;
5618 int snum;
5620 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5622 if (!Printer) {
5623 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5624 return WERR_BADFID;
5627 if (!get_printer_snum(p, handle, &snum))
5628 return WERR_BADFID;
5630 Printer->page_started=False;
5631 print_job_endpage(snum, Printer->jobid);
5633 return WERR_OK;
5636 /********************************************************************
5637 * api_spoolss_getprinter
5638 * called from the spoolss dispatcher
5640 ********************************************************************/
5642 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5644 POLICY_HND *handle = &q_u->handle;
5645 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5646 uint32 *jobid = &r_u->jobid;
5648 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5649 int snum;
5650 pstring jobname;
5651 fstring datatype;
5652 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5653 struct current_user user;
5655 if (!Printer) {
5656 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5657 return WERR_BADFID;
5660 get_current_user(&user, p);
5663 * a nice thing with NT is it doesn't listen to what you tell it.
5664 * when asked to send _only_ RAW datas, it tries to send datas
5665 * in EMF format.
5667 * So I add checks like in NT Server ...
5670 if (info_1->p_datatype != 0) {
5671 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5672 if (strcmp(datatype, "RAW") != 0) {
5673 (*jobid)=0;
5674 return WERR_INVALID_DATATYPE;
5678 /* get the share number of the printer */
5679 if (!get_printer_snum(p, handle, &snum)) {
5680 return WERR_BADFID;
5683 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5685 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5687 /* An error occured in print_job_start() so return an appropriate
5688 NT error code. */
5690 if (Printer->jobid == -1) {
5691 return map_werror_from_unix(errno);
5694 Printer->document_started=True;
5695 (*jobid) = Printer->jobid;
5697 return WERR_OK;
5700 /********************************************************************
5701 * api_spoolss_getprinter
5702 * called from the spoolss dispatcher
5704 ********************************************************************/
5706 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5708 POLICY_HND *handle = &q_u->handle;
5710 return _spoolss_enddocprinter_internal(p, handle);
5713 /****************************************************************************
5714 ****************************************************************************/
5716 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5718 POLICY_HND *handle = &q_u->handle;
5719 uint32 buffer_size = q_u->buffer_size;
5720 uint8 *buffer = q_u->buffer;
5721 uint32 *buffer_written = &q_u->buffer_size2;
5722 int snum;
5723 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5725 if (!Printer) {
5726 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5727 r_u->buffer_written = q_u->buffer_size2;
5728 return WERR_BADFID;
5731 if (!get_printer_snum(p, handle, &snum))
5732 return WERR_BADFID;
5734 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5735 if (*buffer_written == -1) {
5736 r_u->buffer_written = 0;
5737 if (errno == ENOSPC)
5738 return WERR_NO_SPOOL_SPACE;
5739 else
5740 return WERR_ACCESS_DENIED;
5743 r_u->buffer_written = q_u->buffer_size2;
5745 return WERR_OK;
5748 /********************************************************************
5749 * api_spoolss_getprinter
5750 * called from the spoolss dispatcher
5752 ********************************************************************/
5754 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5755 pipes_struct *p)
5757 struct current_user user;
5758 int snum;
5759 WERROR errcode = WERR_BADFUNC;
5760 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5762 get_current_user(&user, p);
5764 if (!Printer) {
5765 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5766 return WERR_BADFID;
5769 if (!get_printer_snum(p, handle, &snum))
5770 return WERR_BADFID;
5772 switch (command) {
5773 case PRINTER_CONTROL_PAUSE:
5774 if (print_queue_pause(&user, snum, &errcode)) {
5775 errcode = WERR_OK;
5777 break;
5778 case PRINTER_CONTROL_RESUME:
5779 case PRINTER_CONTROL_UNPAUSE:
5780 if (print_queue_resume(&user, snum, &errcode)) {
5781 errcode = WERR_OK;
5783 break;
5784 case PRINTER_CONTROL_PURGE:
5785 if (print_queue_purge(&user, snum, &errcode)) {
5786 errcode = WERR_OK;
5788 break;
5789 default:
5790 return WERR_UNKNOWN_LEVEL;
5793 return errcode;
5796 /********************************************************************
5797 * api_spoolss_abortprinter
5798 * From MSDN: "Deletes printer's spool file if printer is configured
5799 * for spooling"
5800 ********************************************************************/
5802 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5804 POLICY_HND *handle = &q_u->handle;
5805 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5806 int snum;
5807 struct current_user user;
5808 WERROR errcode = WERR_OK;
5810 if (!Printer) {
5811 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5812 return WERR_BADFID;
5815 if (!get_printer_snum(p, handle, &snum))
5816 return WERR_BADFID;
5818 get_current_user( &user, p );
5820 print_job_delete( &user, snum, Printer->jobid, &errcode );
5822 return errcode;
5825 /********************************************************************
5826 * called by spoolss_api_setprinter
5827 * when updating a printer description
5828 ********************************************************************/
5830 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5831 const SPOOL_PRINTER_INFO_LEVEL *info,
5832 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5834 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5835 struct current_user user;
5836 WERROR result;
5837 int snum;
5839 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5841 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5842 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5843 OUR_HANDLE(handle)));
5845 result = WERR_BADFID;
5846 goto done;
5849 /* NT seems to like setting the security descriptor even though
5850 nothing may have actually changed. This causes annoying
5851 dialog boxes when the user doesn't have permission to change
5852 the security descriptor. */
5854 nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5856 if (DEBUGLEVEL >= 10) {
5857 SEC_ACL *the_acl;
5858 int i;
5860 the_acl = old_secdesc_ctr->sec->dacl;
5861 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5862 PRINTERNAME(snum), the_acl->num_aces));
5864 for (i = 0; i < the_acl->num_aces; i++) {
5865 fstring sid_str;
5867 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5869 DEBUG(10, ("%s 0x%08x\n", sid_str,
5870 the_acl->ace[i].info.mask));
5873 the_acl = secdesc_ctr->sec->dacl;
5875 if (the_acl) {
5876 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5877 PRINTERNAME(snum), the_acl->num_aces));
5879 for (i = 0; i < the_acl->num_aces; i++) {
5880 fstring sid_str;
5882 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5884 DEBUG(10, ("%s 0x%08x\n", sid_str,
5885 the_acl->ace[i].info.mask));
5887 } else {
5888 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5892 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5894 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5895 result = WERR_OK;
5896 goto done;
5899 /* Work out which user is performing the operation */
5901 get_current_user(&user, p);
5903 /* Check the user has permissions to change the security
5904 descriptor. By experimentation with two NT machines, the user
5905 requires Full Access to the printer to change security
5906 information. */
5908 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5909 result = WERR_ACCESS_DENIED;
5910 goto done;
5913 result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5915 done:
5917 return result;
5920 /********************************************************************
5921 Do Samba sanity checks on a printer info struct.
5922 this has changed purpose: it now "canonicalises" printer
5923 info from a client rather than just checking it is correct
5924 ********************************************************************/
5926 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5928 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5929 info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5931 /* we force some elements to "correct" values */
5932 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5933 fstrcpy(info->sharename, lp_servicename(snum));
5934 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5935 get_called_name(), info->sharename);
5936 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5939 return True;
5942 /****************************************************************************
5943 ****************************************************************************/
5945 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5947 extern userdom_struct current_user_info;
5948 char *cmd = lp_addprinter_cmd();
5949 char **qlines;
5950 pstring command;
5951 int numlines;
5952 int ret;
5953 int fd;
5954 fstring remote_machine = "%m";
5956 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5958 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5959 cmd, printer->info_2->printername, printer->info_2->sharename,
5960 printer->info_2->portname, printer->info_2->drivername,
5961 printer->info_2->location, printer->info_2->comment, remote_machine);
5963 DEBUG(10,("Running [%s]\n", command));
5964 ret = smbrun(command, &fd);
5965 DEBUGADD(10,("returned [%d]\n", ret));
5967 if ( ret != 0 ) {
5968 if (fd != -1)
5969 close(fd);
5970 return False;
5973 numlines = 0;
5974 /* Get lines and convert them back to dos-codepage */
5975 qlines = fd_lines_load(fd, &numlines);
5976 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5977 close(fd);
5979 if(numlines) {
5980 /* Set the portname to what the script says the portname should be. */
5981 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5982 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5984 /* Send SIGHUP to process group... is there a better way? */
5985 kill(0, SIGHUP);
5987 /* reload our services immediately */
5988 reload_services( False );
5991 file_lines_free(qlines);
5992 return True;
5995 /********************************************************************
5996 * Called by spoolss_api_setprinter
5997 * when updating a printer description.
5998 ********************************************************************/
6000 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6001 const SPOOL_PRINTER_INFO_LEVEL *info,
6002 DEVICEMODE *devmode)
6004 int snum;
6005 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6006 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6007 WERROR result;
6008 UNISTR2 buffer;
6009 fstring asc_buffer;
6011 DEBUG(8,("update_printer\n"));
6013 result = WERR_OK;
6015 if (!Printer) {
6016 result = WERR_BADFID;
6017 goto done;
6020 if (!get_printer_snum(p, handle, &snum)) {
6021 result = WERR_BADFID;
6022 goto done;
6025 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6026 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6027 result = WERR_BADFID;
6028 goto done;
6031 DEBUGADD(8,("Converting info_2 struct\n"));
6034 * convert_printer_info converts the incoming
6035 * info from the client and overwrites the info
6036 * just read from the tdb in the pointer 'printer'.
6039 if (!convert_printer_info(info, printer, level)) {
6040 result = WERR_NOMEM;
6041 goto done;
6044 if (devmode) {
6045 /* we have a valid devmode
6046 convert it and link it*/
6048 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6049 if (!convert_devicemode(printer->info_2->printername, devmode,
6050 &printer->info_2->devmode)) {
6051 result = WERR_NOMEM;
6052 goto done;
6056 /* Do sanity check on the requested changes for Samba */
6058 if (!check_printer_ok(printer->info_2, snum)) {
6059 result = WERR_INVALID_PARAM;
6060 goto done;
6063 /* FIXME!!! If the driver has changed we really should verify that
6064 it is installed before doing much else --jerry */
6066 /* Check calling user has permission to update printer description */
6068 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6069 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6070 result = WERR_ACCESS_DENIED;
6071 goto done;
6074 /* Call addprinter hook */
6075 /* Check changes to see if this is really needed */
6077 if ( *lp_addprinter_cmd()
6078 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6079 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6080 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6081 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6083 if ( !add_printer_hook(printer) ) {
6084 result = WERR_ACCESS_DENIED;
6085 goto done;
6089 * make sure we actually reload the services after
6090 * this as smb.conf could have a new section in it
6091 * .... shouldn't .... but could
6093 reload_services(False);
6097 * When a *new* driver is bound to a printer, the drivername is used to
6098 * lookup previously saved driver initialization info, which is then
6099 * bound to the printer, simulating what happens in the Windows arch.
6101 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6103 if (!set_driver_init(printer, 2))
6105 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6106 printer->info_2->drivername));
6109 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6110 printer->info_2->drivername));
6112 notify_printer_driver(snum, printer->info_2->drivername);
6116 * flag which changes actually occured. This is a small subset of
6117 * all the possible changes. We also have to update things in the
6118 * DsSpooler key.
6121 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6122 init_unistr2( &buffer, printer->info_2->comment, strlen(printer->info_2->comment)+1 );
6123 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6124 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6126 notify_printer_comment(snum, printer->info_2->comment);
6129 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6130 init_unistr2( &buffer, printer->info_2->sharename, strlen(printer->info_2->sharename)+1 );
6131 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6132 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6133 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6134 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6136 notify_printer_sharename(snum, printer->info_2->sharename);
6139 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6140 init_unistr2( &buffer, printer->info_2->portname, strlen(printer->info_2->portname)+1 );
6141 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6142 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6144 notify_printer_port(snum, printer->info_2->portname);
6147 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6148 init_unistr2( &buffer, printer->info_2->location, strlen(printer->info_2->location)+1 );
6149 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6150 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6152 notify_printer_location(snum, printer->info_2->location);
6155 /* here we need to update some more DsSpooler keys */
6156 /* uNCName, serverName, shortServerName */
6158 init_unistr2( &buffer, global_myname(), strlen(global_myname())+1 );
6159 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6160 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6161 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6162 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6164 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6165 global_myname(), printer->info_2->sharename );
6166 init_unistr2( &buffer, asc_buffer, strlen(asc_buffer)+1 );
6167 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6168 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6170 /* Update printer info */
6171 result = mod_a_printer(*printer, 2);
6173 done:
6174 free_a_printer(&printer, 2);
6175 free_a_printer(&old_printer, 2);
6178 return result;
6181 /****************************************************************************
6182 ****************************************************************************/
6183 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6184 const SPOOL_PRINTER_INFO_LEVEL *info)
6186 #ifdef HAVE_ADS
6187 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6188 int snum;
6189 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6191 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6193 if (!Printer)
6194 return WERR_BADFID;
6196 if (!get_printer_snum(p, handle, &snum))
6197 return WERR_BADFID;
6199 nt_printer_publish(Printer, snum, info7->action);
6201 return WERR_OK;
6202 #else
6203 return WERR_UNKNOWN_LEVEL;
6204 #endif
6206 /****************************************************************************
6207 ****************************************************************************/
6209 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6211 POLICY_HND *handle = &q_u->handle;
6212 uint32 level = q_u->level;
6213 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6214 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6215 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6216 uint32 command = q_u->command;
6218 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6220 if (!Printer) {
6221 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6222 return WERR_BADFID;
6225 /* check the level */
6226 switch (level) {
6227 case 0:
6228 return control_printer(handle, command, p);
6229 case 2:
6230 return update_printer(p, handle, level, info, devmode_ctr.devmode);
6231 case 3:
6232 return update_printer_sec(handle, level, info, p,
6233 secdesc_ctr);
6234 case 7:
6235 return publish_or_unpublish_printer(p, handle, info);
6236 default:
6237 return WERR_UNKNOWN_LEVEL;
6241 /****************************************************************************
6242 ****************************************************************************/
6244 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6246 POLICY_HND *handle = &q_u->handle;
6247 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6249 if (!Printer) {
6250 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6251 return WERR_BADFID;
6254 if (Printer->notify.client_connected==True) {
6255 int snum = -1;
6257 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6258 snum = -1;
6259 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6260 !get_printer_snum(p, handle, &snum) )
6261 return WERR_BADFID;
6263 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6266 Printer->notify.flags=0;
6267 Printer->notify.options=0;
6268 Printer->notify.localmachine[0]='\0';
6269 Printer->notify.printerlocal=0;
6270 if (Printer->notify.option)
6271 free_spool_notify_option(&Printer->notify.option);
6272 Printer->notify.client_connected=False;
6274 return WERR_OK;
6277 /****************************************************************************
6278 ****************************************************************************/
6280 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6282 /* that's an [in out] buffer (despite appearences to the contrary) */
6283 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6285 r_u->needed = 0;
6286 return WERR_INVALID_PARAM; /* this is what a NT server
6287 returns for AddJob. AddJob
6288 must fail on non-local
6289 printers */
6292 /****************************************************************************
6293 ****************************************************************************/
6295 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6296 int position, int snum)
6298 pstring temp_name;
6300 struct tm *t;
6302 t=gmtime(&queue->time);
6303 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6305 job_info->jobid=queue->job;
6306 init_unistr(&job_info->printername, lp_servicename(snum));
6307 init_unistr(&job_info->machinename, temp_name);
6308 init_unistr(&job_info->username, queue->fs_user);
6309 init_unistr(&job_info->document, queue->fs_file);
6310 init_unistr(&job_info->datatype, "RAW");
6311 init_unistr(&job_info->text_status, "");
6312 job_info->status=nt_printj_status(queue->status);
6313 job_info->priority=queue->priority;
6314 job_info->position=position;
6315 job_info->totalpages=queue->page_count;
6316 job_info->pagesprinted=0;
6318 make_systemtime(&job_info->submitted, t);
6321 /****************************************************************************
6322 ****************************************************************************/
6324 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6325 int position, int snum,
6326 NT_PRINTER_INFO_LEVEL *ntprinter,
6327 DEVICEMODE *devmode)
6329 pstring temp_name;
6330 struct tm *t;
6332 t=gmtime(&queue->time);
6333 slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6335 job_info->jobid=queue->job;
6337 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6339 init_unistr(&job_info->machinename, temp_name);
6340 init_unistr(&job_info->username, queue->fs_user);
6341 init_unistr(&job_info->document, queue->fs_file);
6342 init_unistr(&job_info->notifyname, queue->fs_user);
6343 init_unistr(&job_info->datatype, "RAW");
6344 init_unistr(&job_info->printprocessor, "winprint");
6345 init_unistr(&job_info->parameters, "");
6346 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6347 init_unistr(&job_info->text_status, "");
6349 /* and here the security descriptor */
6351 job_info->status=nt_printj_status(queue->status);
6352 job_info->priority=queue->priority;
6353 job_info->position=position;
6354 job_info->starttime=0;
6355 job_info->untiltime=0;
6356 job_info->totalpages=queue->page_count;
6357 job_info->size=queue->size;
6358 make_systemtime(&(job_info->submitted), t);
6359 job_info->timeelapsed=0;
6360 job_info->pagesprinted=0;
6362 job_info->devmode = devmode;
6364 return (True);
6367 /****************************************************************************
6368 Enumjobs at level 1.
6369 ****************************************************************************/
6371 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6372 NEW_BUFFER *buffer, uint32 offered,
6373 uint32 *needed, uint32 *returned)
6375 JOB_INFO_1 *info;
6376 int i;
6378 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6379 if (info==NULL) {
6380 SAFE_FREE(queue);
6381 *returned=0;
6382 return WERR_NOMEM;
6385 for (i=0; i<*returned; i++)
6386 fill_job_info_1(&info[i], &queue[i], i, snum);
6388 SAFE_FREE(queue);
6390 /* check the required size. */
6391 for (i=0; i<*returned; i++)
6392 (*needed) += spoolss_size_job_info_1(&info[i]);
6394 if (!alloc_buffer_size(buffer, *needed)) {
6395 SAFE_FREE(info);
6396 return WERR_INSUFFICIENT_BUFFER;
6399 /* fill the buffer with the structures */
6400 for (i=0; i<*returned; i++)
6401 smb_io_job_info_1("", buffer, &info[i], 0);
6403 /* clear memory */
6404 SAFE_FREE(info);
6406 if (*needed > offered) {
6407 *returned=0;
6408 return WERR_INSUFFICIENT_BUFFER;
6411 return WERR_OK;
6414 /****************************************************************************
6415 Enumjobs at level 2.
6416 ****************************************************************************/
6418 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6419 NEW_BUFFER *buffer, uint32 offered,
6420 uint32 *needed, uint32 *returned)
6422 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6423 JOB_INFO_2 *info = NULL;
6424 int i;
6425 WERROR result;
6426 DEVICEMODE *devmode = NULL;
6428 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6429 if (info==NULL) {
6430 *returned=0;
6431 result = WERR_NOMEM;
6432 goto done;
6435 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6436 if (!W_ERROR_IS_OK(result)) {
6437 *returned = 0;
6438 goto done;
6441 /* this should not be a failure condition if the devmode is NULL */
6443 devmode = construct_dev_mode(snum);
6445 for (i=0; i<*returned; i++)
6446 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6447 devmode);
6449 free_a_printer(&ntprinter, 2);
6450 SAFE_FREE(queue);
6452 /* check the required size. */
6453 for (i=0; i<*returned; i++)
6454 (*needed) += spoolss_size_job_info_2(&info[i]);
6456 if (*needed > offered) {
6457 *returned=0;
6458 result = WERR_INSUFFICIENT_BUFFER;
6459 goto done;
6462 if (!alloc_buffer_size(buffer, *needed)) {
6463 SAFE_FREE(info);
6464 result = WERR_INSUFFICIENT_BUFFER;
6465 goto done;
6468 /* fill the buffer with the structures */
6469 for (i=0; i<*returned; i++)
6470 smb_io_job_info_2("", buffer, &info[i], 0);
6472 result = WERR_OK;
6474 done:
6475 free_a_printer(&ntprinter, 2);
6476 free_devmode(devmode);
6477 SAFE_FREE(queue);
6478 SAFE_FREE(info);
6480 return result;
6484 /****************************************************************************
6485 Enumjobs.
6486 ****************************************************************************/
6488 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6490 POLICY_HND *handle = &q_u->handle;
6491 uint32 level = q_u->level;
6492 NEW_BUFFER *buffer = NULL;
6493 uint32 offered = q_u->offered;
6494 uint32 *needed = &r_u->needed;
6495 uint32 *returned = &r_u->returned;
6496 WERROR wret;
6498 int snum;
6499 print_status_struct prt_status;
6500 print_queue_struct *queue=NULL;
6502 /* that's an [in out] buffer */
6503 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6504 buffer = r_u->buffer;
6506 DEBUG(4,("_spoolss_enumjobs\n"));
6508 *needed=0;
6509 *returned=0;
6511 if (!get_printer_snum(p, handle, &snum))
6512 return WERR_BADFID;
6514 *returned = print_queue_status(snum, &queue, &prt_status);
6515 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6517 if (*returned == 0) {
6518 set_enumjobs_timestamp(snum);
6519 SAFE_FREE(queue);
6520 return WERR_OK;
6523 switch (level) {
6524 case 1:
6525 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6526 set_enumjobs_timestamp(snum);
6527 return wret;
6528 case 2:
6529 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6530 set_enumjobs_timestamp(snum);
6531 return wret;
6532 default:
6533 SAFE_FREE(queue);
6534 *returned=0;
6535 return WERR_UNKNOWN_LEVEL;
6539 /****************************************************************************
6540 ****************************************************************************/
6542 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6544 return WERR_OK;
6547 /****************************************************************************
6548 ****************************************************************************/
6550 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6552 POLICY_HND *handle = &q_u->handle;
6553 uint32 jobid = q_u->jobid;
6554 uint32 command = q_u->command;
6556 struct current_user user;
6557 int snum;
6558 WERROR errcode = WERR_BADFUNC;
6560 if (!get_printer_snum(p, handle, &snum)) {
6561 return WERR_BADFID;
6564 if (!print_job_exists(snum, jobid)) {
6565 return WERR_INVALID_PRINTER_NAME;
6568 get_current_user(&user, p);
6570 switch (command) {
6571 case JOB_CONTROL_CANCEL:
6572 case JOB_CONTROL_DELETE:
6573 if (print_job_delete(&user, snum, jobid, &errcode)) {
6574 errcode = WERR_OK;
6576 break;
6577 case JOB_CONTROL_PAUSE:
6578 if (print_job_pause(&user, snum, jobid, &errcode)) {
6579 errcode = WERR_OK;
6581 break;
6582 case JOB_CONTROL_RESTART:
6583 case JOB_CONTROL_RESUME:
6584 if (print_job_resume(&user, snum, jobid, &errcode)) {
6585 errcode = WERR_OK;
6587 break;
6588 default:
6589 return WERR_UNKNOWN_LEVEL;
6592 return errcode;
6595 /****************************************************************************
6596 Enumerates all printer drivers at level 1.
6597 ****************************************************************************/
6599 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6601 int i;
6602 int ndrivers;
6603 uint32 version;
6604 fstring *list = NULL;
6606 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6607 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6609 *returned=0;
6611 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6612 list=NULL;
6613 ndrivers=get_ntdrivers(&list, architecture, version);
6614 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6616 if(ndrivers == -1)
6617 return WERR_NOMEM;
6619 if(ndrivers != 0) {
6620 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6621 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6622 SAFE_FREE(driver_info_1);
6623 SAFE_FREE(list);
6624 return WERR_NOMEM;
6626 else driver_info_1 = tdi1;
6629 for (i=0; i<ndrivers; i++) {
6630 WERROR status;
6631 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6632 ZERO_STRUCT(driver);
6633 status = get_a_printer_driver(&driver, 3, list[i],
6634 architecture, version);
6635 if (!W_ERROR_IS_OK(status)) {
6636 SAFE_FREE(list);
6637 return status;
6639 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6640 free_a_printer_driver(driver, 3);
6643 *returned+=ndrivers;
6644 SAFE_FREE(list);
6647 /* check the required size. */
6648 for (i=0; i<*returned; i++) {
6649 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6650 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6653 if (!alloc_buffer_size(buffer, *needed)) {
6654 SAFE_FREE(driver_info_1);
6655 return WERR_INSUFFICIENT_BUFFER;
6658 /* fill the buffer with the driver structures */
6659 for (i=0; i<*returned; i++) {
6660 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6661 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6664 SAFE_FREE(driver_info_1);
6666 if (*needed > offered) {
6667 *returned=0;
6668 return WERR_INSUFFICIENT_BUFFER;
6671 return WERR_OK;
6674 /****************************************************************************
6675 Enumerates all printer drivers at level 2.
6676 ****************************************************************************/
6678 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6680 int i;
6681 int ndrivers;
6682 uint32 version;
6683 fstring *list = NULL;
6685 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6686 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6688 *returned=0;
6690 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6691 list=NULL;
6692 ndrivers=get_ntdrivers(&list, architecture, version);
6693 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6695 if(ndrivers == -1)
6696 return WERR_NOMEM;
6698 if(ndrivers != 0) {
6699 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6700 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6701 SAFE_FREE(driver_info_2);
6702 SAFE_FREE(list);
6703 return WERR_NOMEM;
6705 else driver_info_2 = tdi2;
6708 for (i=0; i<ndrivers; i++) {
6709 WERROR status;
6711 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6712 ZERO_STRUCT(driver);
6713 status = get_a_printer_driver(&driver, 3, list[i],
6714 architecture, version);
6715 if (!W_ERROR_IS_OK(status)) {
6716 SAFE_FREE(list);
6717 return status;
6719 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6720 free_a_printer_driver(driver, 3);
6723 *returned+=ndrivers;
6724 SAFE_FREE(list);
6727 /* check the required size. */
6728 for (i=0; i<*returned; i++) {
6729 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6730 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6733 if (!alloc_buffer_size(buffer, *needed)) {
6734 SAFE_FREE(driver_info_2);
6735 return WERR_INSUFFICIENT_BUFFER;
6738 /* fill the buffer with the form structures */
6739 for (i=0; i<*returned; i++) {
6740 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6741 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6744 SAFE_FREE(driver_info_2);
6746 if (*needed > offered) {
6747 *returned=0;
6748 return WERR_INSUFFICIENT_BUFFER;
6751 return WERR_OK;
6754 /****************************************************************************
6755 Enumerates all printer drivers at level 3.
6756 ****************************************************************************/
6758 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6760 int i;
6761 int ndrivers;
6762 uint32 version;
6763 fstring *list = NULL;
6765 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6766 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6768 *returned=0;
6770 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6771 list=NULL;
6772 ndrivers=get_ntdrivers(&list, architecture, version);
6773 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6775 if(ndrivers == -1)
6776 return WERR_NOMEM;
6778 if(ndrivers != 0) {
6779 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6780 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6781 SAFE_FREE(driver_info_3);
6782 SAFE_FREE(list);
6783 return WERR_NOMEM;
6785 else driver_info_3 = tdi3;
6788 for (i=0; i<ndrivers; i++) {
6789 WERROR status;
6791 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6792 ZERO_STRUCT(driver);
6793 status = get_a_printer_driver(&driver, 3, list[i],
6794 architecture, version);
6795 if (!W_ERROR_IS_OK(status)) {
6796 SAFE_FREE(list);
6797 return status;
6799 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6800 free_a_printer_driver(driver, 3);
6803 *returned+=ndrivers;
6804 SAFE_FREE(list);
6807 /* check the required size. */
6808 for (i=0; i<*returned; i++) {
6809 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6810 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6813 if (!alloc_buffer_size(buffer, *needed)) {
6814 SAFE_FREE(driver_info_3);
6815 return WERR_INSUFFICIENT_BUFFER;
6818 /* fill the buffer with the driver structures */
6819 for (i=0; i<*returned; i++) {
6820 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6821 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6824 for (i=0; i<*returned; i++)
6825 SAFE_FREE(driver_info_3[i].dependentfiles);
6827 SAFE_FREE(driver_info_3);
6829 if (*needed > offered) {
6830 *returned=0;
6831 return WERR_INSUFFICIENT_BUFFER;
6834 return WERR_OK;
6837 /****************************************************************************
6838 Enumerates all printer drivers.
6839 ****************************************************************************/
6841 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6843 UNISTR2 *environment = &q_u->environment;
6844 uint32 level = q_u->level;
6845 NEW_BUFFER *buffer = NULL;
6846 uint32 offered = q_u->offered;
6847 uint32 *needed = &r_u->needed;
6848 uint32 *returned = &r_u->returned;
6850 fstring *list = NULL;
6851 fstring servername;
6852 fstring architecture;
6854 /* that's an [in out] buffer */
6855 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6856 buffer = r_u->buffer;
6858 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6859 fstrcpy(servername, get_called_name());
6860 *needed=0;
6861 *returned=0;
6863 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6865 switch (level) {
6866 case 1:
6867 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6868 case 2:
6869 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6870 case 3:
6871 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6872 default:
6873 *returned=0;
6874 SAFE_FREE(list);
6875 return WERR_UNKNOWN_LEVEL;
6879 /****************************************************************************
6880 ****************************************************************************/
6882 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6884 form->flag=list->flag;
6885 init_unistr(&form->name, list->name);
6886 form->width=list->width;
6887 form->length=list->length;
6888 form->left=list->left;
6889 form->top=list->top;
6890 form->right=list->right;
6891 form->bottom=list->bottom;
6894 /****************************************************************************
6895 ****************************************************************************/
6897 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6899 uint32 level = q_u->level;
6900 NEW_BUFFER *buffer = NULL;
6901 uint32 offered = q_u->offered;
6902 uint32 *needed = &r_u->needed;
6903 uint32 *numofforms = &r_u->numofforms;
6904 uint32 numbuiltinforms;
6906 nt_forms_struct *list=NULL;
6907 nt_forms_struct *builtinlist=NULL;
6908 FORM_1 *forms_1;
6909 int buffer_size=0;
6910 int i;
6912 /* that's an [in out] buffer */
6913 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6914 buffer = r_u->buffer;
6916 DEBUG(4,("_spoolss_enumforms\n"));
6917 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6918 DEBUGADD(5,("Info level [%d]\n", level));
6920 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6921 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6922 *numofforms = get_ntforms(&list);
6923 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6924 *numofforms += numbuiltinforms;
6926 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6928 switch (level) {
6929 case 1:
6930 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6931 *numofforms=0;
6932 return WERR_NOMEM;
6935 /* construct the list of form structures */
6936 for (i=0; i<numbuiltinforms; i++) {
6937 DEBUGADD(6,("Filling form number [%d]\n",i));
6938 fill_form_1(&forms_1[i], &builtinlist[i]);
6941 SAFE_FREE(builtinlist);
6943 for (; i<*numofforms; i++) {
6944 DEBUGADD(6,("Filling form number [%d]\n",i));
6945 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6948 SAFE_FREE(list);
6950 /* check the required size. */
6951 for (i=0; i<numbuiltinforms; i++) {
6952 DEBUGADD(6,("adding form [%d]'s size\n",i));
6953 buffer_size += spoolss_size_form_1(&forms_1[i]);
6955 for (; i<*numofforms; i++) {
6956 DEBUGADD(6,("adding form [%d]'s size\n",i));
6957 buffer_size += spoolss_size_form_1(&forms_1[i]);
6960 *needed=buffer_size;
6962 if (!alloc_buffer_size(buffer, buffer_size)){
6963 SAFE_FREE(forms_1);
6964 return WERR_INSUFFICIENT_BUFFER;
6967 /* fill the buffer with the form structures */
6968 for (i=0; i<numbuiltinforms; i++) {
6969 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6970 smb_io_form_1("", buffer, &forms_1[i], 0);
6972 for (; i<*numofforms; i++) {
6973 DEBUGADD(6,("adding form [%d] to buffer\n",i));
6974 smb_io_form_1("", buffer, &forms_1[i], 0);
6977 SAFE_FREE(forms_1);
6979 if (*needed > offered) {
6980 *numofforms=0;
6981 return WERR_INSUFFICIENT_BUFFER;
6983 else
6984 return WERR_OK;
6986 default:
6987 SAFE_FREE(list);
6988 SAFE_FREE(builtinlist);
6989 return WERR_UNKNOWN_LEVEL;
6994 /****************************************************************************
6995 ****************************************************************************/
6997 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6999 uint32 level = q_u->level;
7000 UNISTR2 *uni_formname = &q_u->formname;
7001 NEW_BUFFER *buffer = NULL;
7002 uint32 offered = q_u->offered;
7003 uint32 *needed = &r_u->needed;
7005 nt_forms_struct *list=NULL;
7006 nt_forms_struct builtin_form;
7007 BOOL foundBuiltin;
7008 FORM_1 form_1;
7009 fstring form_name;
7010 int buffer_size=0;
7011 int numofforms=0, i=0;
7013 /* that's an [in out] buffer */
7014 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7015 buffer = r_u->buffer;
7017 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7019 DEBUG(4,("_spoolss_getform\n"));
7020 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7021 DEBUGADD(5,("Info level [%d]\n", level));
7023 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7024 if (!foundBuiltin) {
7025 numofforms = get_ntforms(&list);
7026 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7028 if (numofforms == 0)
7029 return WERR_BADFID;
7032 switch (level) {
7033 case 1:
7034 if (foundBuiltin) {
7035 fill_form_1(&form_1, &builtin_form);
7036 } else {
7038 /* Check if the requested name is in the list of form structures */
7039 for (i=0; i<numofforms; i++) {
7041 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7043 if (strequal(form_name, list[i].name)) {
7044 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7045 fill_form_1(&form_1, &list[i]);
7046 break;
7050 SAFE_FREE(list);
7051 if (i == numofforms) {
7052 return WERR_BADFID;
7055 /* check the required size. */
7057 *needed=spoolss_size_form_1(&form_1);
7059 if (!alloc_buffer_size(buffer, buffer_size)){
7060 return WERR_INSUFFICIENT_BUFFER;
7063 if (*needed > offered) {
7064 return WERR_INSUFFICIENT_BUFFER;
7067 /* fill the buffer with the form structures */
7068 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7069 smb_io_form_1("", buffer, &form_1, 0);
7071 return WERR_OK;
7073 default:
7074 SAFE_FREE(list);
7075 return WERR_UNKNOWN_LEVEL;
7079 /****************************************************************************
7080 ****************************************************************************/
7082 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7084 init_unistr(&port->port_name, name);
7087 /****************************************************************************
7088 ****************************************************************************/
7090 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7092 init_unistr(&port->port_name, name);
7093 init_unistr(&port->monitor_name, "Local Monitor");
7094 init_unistr(&port->description, "Local Port");
7095 port->port_type=PORT_TYPE_WRITE;
7096 port->reserved=0x0;
7099 /****************************************************************************
7100 enumports level 1.
7101 ****************************************************************************/
7103 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7105 PORT_INFO_1 *ports=NULL;
7106 int i=0;
7108 if (*lp_enumports_cmd()) {
7109 char *cmd = lp_enumports_cmd();
7110 char **qlines;
7111 pstring command;
7112 int numlines;
7113 int ret;
7114 int fd;
7116 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7118 DEBUG(10,("Running [%s]\n", command));
7119 ret = smbrun(command, &fd);
7120 DEBUG(10,("Returned [%d]\n", ret));
7121 if (ret != 0) {
7122 if (fd != -1)
7123 close(fd);
7124 /* Is this the best error to return here? */
7125 return WERR_ACCESS_DENIED;
7128 numlines = 0;
7129 qlines = fd_lines_load(fd, &numlines);
7130 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7131 close(fd);
7133 if(numlines) {
7134 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7135 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7136 dos_errstr(WERR_NOMEM)));
7137 file_lines_free(qlines);
7138 return WERR_NOMEM;
7141 for (i=0; i<numlines; i++) {
7142 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7143 fill_port_1(&ports[i], qlines[i]);
7146 file_lines_free(qlines);
7149 *returned = numlines;
7151 } else {
7152 *returned = 1; /* Sole Samba port returned. */
7154 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7155 return WERR_NOMEM;
7157 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7159 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7162 /* check the required size. */
7163 for (i=0; i<*returned; i++) {
7164 DEBUGADD(6,("adding port [%d]'s size\n", i));
7165 *needed += spoolss_size_port_info_1(&ports[i]);
7168 if (!alloc_buffer_size(buffer, *needed)) {
7169 SAFE_FREE(ports);
7170 return WERR_INSUFFICIENT_BUFFER;
7173 /* fill the buffer with the ports structures */
7174 for (i=0; i<*returned; i++) {
7175 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7176 smb_io_port_1("", buffer, &ports[i], 0);
7179 SAFE_FREE(ports);
7181 if (*needed > offered) {
7182 *returned=0;
7183 return WERR_INSUFFICIENT_BUFFER;
7186 return WERR_OK;
7189 /****************************************************************************
7190 enumports level 2.
7191 ****************************************************************************/
7193 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7195 PORT_INFO_2 *ports=NULL;
7196 int i=0;
7198 if (*lp_enumports_cmd()) {
7199 char *cmd = lp_enumports_cmd();
7200 char *path;
7201 char **qlines;
7202 pstring tmp_file;
7203 pstring command;
7204 int numlines;
7205 int ret;
7206 int fd;
7208 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7209 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7210 else
7211 path = lp_lockdir();
7213 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7214 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7216 unlink(tmp_file);
7217 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7218 ret = smbrun(command, &fd);
7219 DEBUGADD(10,("returned [%d]\n", ret));
7220 if (ret != 0) {
7221 if (fd != -1)
7222 close(fd);
7223 /* Is this the best error to return here? */
7224 return WERR_ACCESS_DENIED;
7227 numlines = 0;
7228 qlines = fd_lines_load(fd, &numlines);
7229 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7230 close(fd);
7232 if(numlines) {
7233 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7234 file_lines_free(qlines);
7235 return WERR_NOMEM;
7238 for (i=0; i<numlines; i++) {
7239 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7240 fill_port_2(&(ports[i]), qlines[i]);
7243 file_lines_free(qlines);
7246 *returned = numlines;
7248 } else {
7250 *returned = 1;
7252 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7253 return WERR_NOMEM;
7255 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7257 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7260 /* check the required size. */
7261 for (i=0; i<*returned; i++) {
7262 DEBUGADD(6,("adding port [%d]'s size\n", i));
7263 *needed += spoolss_size_port_info_2(&ports[i]);
7266 if (!alloc_buffer_size(buffer, *needed)) {
7267 SAFE_FREE(ports);
7268 return WERR_INSUFFICIENT_BUFFER;
7271 /* fill the buffer with the ports structures */
7272 for (i=0; i<*returned; i++) {
7273 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7274 smb_io_port_2("", buffer, &ports[i], 0);
7277 SAFE_FREE(ports);
7279 if (*needed > offered) {
7280 *returned=0;
7281 return WERR_INSUFFICIENT_BUFFER;
7284 return WERR_OK;
7287 /****************************************************************************
7288 enumports.
7289 ****************************************************************************/
7291 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7293 uint32 level = q_u->level;
7294 NEW_BUFFER *buffer = NULL;
7295 uint32 offered = q_u->offered;
7296 uint32 *needed = &r_u->needed;
7297 uint32 *returned = &r_u->returned;
7299 /* that's an [in out] buffer */
7300 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7301 buffer = r_u->buffer;
7303 DEBUG(4,("_spoolss_enumports\n"));
7305 *returned=0;
7306 *needed=0;
7308 switch (level) {
7309 case 1:
7310 return enumports_level_1(buffer, offered, needed, returned);
7311 case 2:
7312 return enumports_level_2(buffer, offered, needed, returned);
7313 default:
7314 return WERR_UNKNOWN_LEVEL;
7318 /****************************************************************************
7319 ****************************************************************************/
7321 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7322 const SPOOL_PRINTER_INFO_LEVEL *info,
7323 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7324 uint32 user_switch, const SPOOL_USER_CTR *user,
7325 POLICY_HND *handle)
7327 NT_PRINTER_INFO_LEVEL *printer = NULL;
7328 fstring name;
7329 int snum;
7330 WERROR err = WERR_OK;
7332 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7333 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7334 return WERR_NOMEM;
7337 ZERO_STRUCTP(printer);
7339 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7340 if (!convert_printer_info(info, printer, 2)) {
7341 free_a_printer(&printer, 2);
7342 return WERR_NOMEM;
7345 /* check to see if the printer already exists */
7347 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7348 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7349 printer->info_2->sharename));
7350 free_a_printer(&printer, 2);
7351 return WERR_PRINTER_ALREADY_EXISTS;
7354 /* FIXME!!! smbd should check to see if the driver is installed before
7355 trying to add a printer like this --jerry */
7357 if (*lp_addprinter_cmd() ) {
7358 if ( !add_printer_hook(printer) ) {
7359 free_a_printer(&printer,2);
7360 return WERR_ACCESS_DENIED;
7364 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7365 printer->info_2->sharename);
7368 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7369 free_a_printer(&printer,2);
7370 return WERR_ACCESS_DENIED;
7373 /* you must be a printer admin to add a new printer */
7374 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7375 free_a_printer(&printer,2);
7376 return WERR_ACCESS_DENIED;
7380 * Do sanity check on the requested changes for Samba.
7383 if (!check_printer_ok(printer->info_2, snum)) {
7384 free_a_printer(&printer,2);
7385 return WERR_INVALID_PARAM;
7389 * When a printer is created, the drivername bound to the printer is used
7390 * to lookup previously saved driver initialization info, which is then
7391 * bound to the new printer, simulating what happens in the Windows arch.
7394 if (!devmode)
7396 set_driver_init(printer, 2);
7398 else
7400 /* A valid devmode was included, convert and link it
7402 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7404 if (!convert_devicemode(printer->info_2->printername, devmode,
7405 &printer->info_2->devmode))
7406 return WERR_NOMEM;
7409 /* write the ASCII on disk */
7410 err = mod_a_printer(*printer, 2);
7411 if (!W_ERROR_IS_OK(err)) {
7412 free_a_printer(&printer,2);
7413 return err;
7416 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7417 /* Handle open failed - remove addition. */
7418 del_a_printer(printer->info_2->sharename);
7419 free_a_printer(&printer,2);
7420 return WERR_ACCESS_DENIED;
7423 update_c_setprinter(False);
7424 free_a_printer(&printer,2);
7426 return WERR_OK;
7429 /****************************************************************************
7430 ****************************************************************************/
7432 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7434 UNISTR2 *uni_srv_name = &q_u->server_name;
7435 uint32 level = q_u->level;
7436 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7437 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7438 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7439 uint32 user_switch = q_u->user_switch;
7440 SPOOL_USER_CTR *user = &q_u->user_ctr;
7441 POLICY_HND *handle = &r_u->handle;
7443 switch (level) {
7444 case 1:
7445 /* we don't handle yet */
7446 /* but I know what to do ... */
7447 return WERR_UNKNOWN_LEVEL;
7448 case 2:
7449 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7450 devmode, sdb,
7451 user_switch, user, handle);
7452 default:
7453 return WERR_UNKNOWN_LEVEL;
7457 /****************************************************************************
7458 ****************************************************************************/
7460 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7462 uint32 level = q_u->level;
7463 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7464 WERROR err = WERR_OK;
7465 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7466 struct current_user user;
7467 fstring driver_name;
7468 uint32 version;
7470 ZERO_STRUCT(driver);
7472 get_current_user(&user, p);
7474 if (!convert_printer_driver_info(info, &driver, level)) {
7475 err = WERR_NOMEM;
7476 goto done;
7479 DEBUG(5,("Cleaning driver's information\n"));
7480 err = clean_up_driver_struct(driver, level, &user);
7481 if (!W_ERROR_IS_OK(err))
7482 goto done;
7484 DEBUG(5,("Moving driver to final destination\n"));
7485 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7486 if (W_ERROR_IS_OK(err))
7487 err = WERR_ACCESS_DENIED;
7488 goto done;
7491 if (add_a_printer_driver(driver, level)!=0) {
7492 err = WERR_ACCESS_DENIED;
7493 goto done;
7496 /* BEGIN_ADMIN_LOG */
7497 switch(level) {
7498 case 3:
7499 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7500 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7501 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7502 break;
7503 case 6:
7504 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7505 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7506 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7507 break;
7509 /* END_ADMIN_LOG */
7512 * I think this is where he DrvUpgradePrinter() hook would be
7513 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7514 * server. Right now, we just need to send ourselves a message
7515 * to update each printer bound to this driver. --jerry
7518 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7519 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7520 driver_name));
7524 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7525 * decide if the driver init data should be deleted. The rules are:
7526 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7527 * 2) delete init data only if there is no 2k/Xp driver
7528 * 3) always delete init data
7529 * The generalized rule is always use init data from the highest order driver.
7530 * It is necessary to follow the driver install by an initialization step to
7531 * finish off this process.
7533 if (level == 3)
7534 version = driver.info_3->cversion;
7535 else if (level == 6)
7536 version = driver.info_6->version;
7537 else
7538 version = -1;
7539 switch (version) {
7541 * 9x printer driver - never delete init data
7543 case 0:
7544 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7545 driver_name));
7546 break;
7549 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7550 * there is no 2k/Xp driver init data for this driver name.
7552 case 2:
7554 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7556 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7558 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7560 if (!del_driver_init(driver_name))
7561 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7562 } else {
7564 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7566 free_a_printer_driver(driver1,3);
7567 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7568 driver_name));
7571 break;
7574 * 2k or Xp printer driver - always delete init data
7576 case 3:
7577 if (!del_driver_init(driver_name))
7578 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7579 break;
7581 default:
7582 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7583 break;
7587 done:
7588 free_a_printer_driver(driver, level);
7589 return err;
7592 /********************************************************************
7593 * spoolss_addprinterdriverex
7594 ********************************************************************/
7596 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7598 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7599 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7602 * we only support the semantics of AddPrinterDriver()
7603 * i.e. only copy files that are newer than existing ones
7606 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7607 return WERR_ACCESS_DENIED;
7609 ZERO_STRUCT(q_u_local);
7610 ZERO_STRUCT(r_u_local);
7612 /* just pass the information off to _spoolss_addprinterdriver() */
7613 q_u_local.server_name_ptr = q_u->server_name_ptr;
7614 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7615 q_u_local.level = q_u->level;
7616 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7618 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7621 /****************************************************************************
7622 ****************************************************************************/
7624 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7626 init_unistr(&info->name, name);
7629 /****************************************************************************
7630 ****************************************************************************/
7632 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7634 pstring path;
7635 pstring long_archi;
7636 const char *short_archi;
7637 DRIVER_DIRECTORY_1 *info=NULL;
7639 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7641 if (!(short_archi = get_short_archi(long_archi)))
7642 return WERR_INVALID_ENVIRONMENT;
7644 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7645 return WERR_NOMEM;
7647 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7649 DEBUG(4,("printer driver directory: [%s]\n", path));
7651 fill_driverdir_1(info, path);
7653 *needed += spoolss_size_driverdir_info_1(info);
7655 if (!alloc_buffer_size(buffer, *needed)) {
7656 SAFE_FREE(info);
7657 return WERR_INSUFFICIENT_BUFFER;
7660 smb_io_driverdir_1("", buffer, info, 0);
7662 SAFE_FREE(info);
7664 if (*needed > offered)
7665 return WERR_INSUFFICIENT_BUFFER;
7667 return WERR_OK;
7670 /****************************************************************************
7671 ****************************************************************************/
7673 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7675 UNISTR2 *name = &q_u->name;
7676 UNISTR2 *uni_environment = &q_u->environment;
7677 uint32 level = q_u->level;
7678 NEW_BUFFER *buffer = NULL;
7679 uint32 offered = q_u->offered;
7680 uint32 *needed = &r_u->needed;
7682 /* that's an [in out] buffer */
7683 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7684 buffer = r_u->buffer;
7686 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7688 *needed=0;
7690 switch(level) {
7691 case 1:
7692 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7693 default:
7694 return WERR_UNKNOWN_LEVEL;
7698 /****************************************************************************
7699 ****************************************************************************/
7701 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7703 POLICY_HND *handle = &q_u->handle;
7704 uint32 idx = q_u->index;
7705 uint32 in_value_len = q_u->valuesize;
7706 uint32 in_data_len = q_u->datasize;
7707 uint32 *out_max_value_len = &r_u->valuesize;
7708 uint16 **out_value = &r_u->value;
7709 uint32 *out_value_len = &r_u->realvaluesize;
7710 uint32 *out_type = &r_u->type;
7711 uint32 *out_max_data_len = &r_u->datasize;
7712 uint8 **data_out = &r_u->data;
7713 uint32 *out_data_len = &r_u->realdatasize;
7715 NT_PRINTER_INFO_LEVEL *printer = NULL;
7717 uint32 biggest_valuesize;
7718 uint32 biggest_datasize;
7719 uint32 data_len;
7720 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7721 int snum;
7722 WERROR result;
7723 REGISTRY_VALUE *val = NULL;
7724 NT_PRINTER_DATA *p_data;
7725 int i, key_index, num_values;
7726 int name_length;
7728 ZERO_STRUCT( printer );
7730 *out_type = 0;
7732 *out_max_data_len = 0;
7733 *data_out = NULL;
7734 *out_data_len = 0;
7736 DEBUG(5,("spoolss_enumprinterdata\n"));
7738 if (!Printer) {
7739 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7740 return WERR_BADFID;
7743 if (!get_printer_snum(p,handle, &snum))
7744 return WERR_BADFID;
7746 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7747 if (!W_ERROR_IS_OK(result))
7748 return result;
7750 p_data = &printer->info_2->data;
7751 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7753 result = WERR_OK;
7756 * The NT machine wants to know the biggest size of value and data
7758 * cf: MSDN EnumPrinterData remark section
7761 if ( !in_value_len && !in_data_len && (key_index != -1) )
7763 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7765 biggest_valuesize = 0;
7766 biggest_datasize = 0;
7768 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7770 for ( i=0; i<num_values; i++ )
7772 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7774 name_length = strlen(val->valuename);
7775 if ( strlen(val->valuename) > biggest_valuesize )
7776 biggest_valuesize = name_length;
7778 if ( val->size > biggest_datasize )
7779 biggest_datasize = val->size;
7781 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7782 biggest_datasize));
7785 /* the value is an UNICODE string but real_value_size is the length
7786 in bytes including the trailing 0 */
7788 *out_value_len = 2 * (1+biggest_valuesize);
7789 *out_data_len = biggest_datasize;
7791 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7793 goto done;
7797 * the value len is wrong in NT sp3
7798 * that's the number of bytes not the number of unicode chars
7801 if ( key_index != -1 )
7802 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7804 if ( !val )
7807 /* out_value should default to "" or else NT4 has
7808 problems unmarshalling the response */
7810 *out_max_value_len=(in_value_len/sizeof(uint16));
7812 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7814 result = WERR_NOMEM;
7815 goto done;
7818 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7820 /* the data is counted in bytes */
7822 *out_max_data_len = in_data_len;
7823 *out_data_len = in_data_len;
7825 /* only allocate when given a non-zero data_len */
7827 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7829 result = WERR_NOMEM;
7830 goto done;
7833 result = WERR_NO_MORE_ITEMS;
7835 else
7838 * the value is:
7839 * - counted in bytes in the request
7840 * - counted in UNICODE chars in the max reply
7841 * - counted in bytes in the real size
7843 * take a pause *before* coding not *during* coding
7846 /* name */
7847 *out_max_value_len=(in_value_len/sizeof(uint16));
7848 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7850 result = WERR_NOMEM;
7851 goto done;
7854 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7856 /* type */
7858 *out_type = regval_type( val );
7860 /* data - counted in bytes */
7862 *out_max_data_len = in_data_len;
7863 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7865 result = WERR_NOMEM;
7866 goto done;
7868 data_len = (size_t)regval_size(val);
7869 memcpy( *data_out, regval_data_p(val), data_len );
7870 *out_data_len = data_len;
7873 done:
7874 free_a_printer(&printer, 2);
7875 return result;
7878 /****************************************************************************
7879 ****************************************************************************/
7881 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7883 POLICY_HND *handle = &q_u->handle;
7884 UNISTR2 *value = &q_u->value;
7885 uint32 type = q_u->type;
7886 uint8 *data = q_u->data;
7887 uint32 real_len = q_u->real_len;
7889 NT_PRINTER_INFO_LEVEL *printer = NULL;
7890 int snum=0;
7891 WERROR status = WERR_OK;
7892 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7893 fstring valuename;
7895 DEBUG(5,("spoolss_setprinterdata\n"));
7897 if (!Printer) {
7898 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7899 return WERR_BADFID;
7902 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7903 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7904 return WERR_INVALID_PARAM;
7907 if (!get_printer_snum(p,handle, &snum))
7908 return WERR_BADFID;
7911 * Access check : NT returns "access denied" if you make a
7912 * SetPrinterData call without the necessary privildge.
7913 * we were originally returning OK if nothing changed
7914 * which made Win2k issue **a lot** of SetPrinterData
7915 * when connecting to a printer --jerry
7918 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7920 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7921 status = WERR_ACCESS_DENIED;
7922 goto done;
7925 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7926 if (!W_ERROR_IS_OK(status))
7927 return status;
7929 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7932 * When client side code sets a magic printer data key, detect it and save
7933 * the current printer data and the magic key's data (its the DEVMODE) for
7934 * future printer/driver initializations.
7936 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
7938 /* Set devmode and printer initialization info */
7939 status = save_driver_init( printer, 2, data, real_len );
7941 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7943 else
7945 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
7946 type, data, real_len );
7947 if ( W_ERROR_IS_OK(status) )
7948 status = mod_a_printer(*printer, 2);
7951 done:
7952 free_a_printer(&printer, 2);
7954 return status;
7957 /****************************************************************************
7958 ****************************************************************************/
7960 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7962 POLICY_HND *handle = &q_u->handle;
7963 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7964 int snum;
7966 DEBUG(5,("_spoolss_resetprinter\n"));
7969 * All we do is to check to see if the handle and queue is valid.
7970 * This call really doesn't mean anything to us because we only
7971 * support RAW printing. --jerry
7974 if (!Printer) {
7975 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7976 return WERR_BADFID;
7979 if (!get_printer_snum(p,handle, &snum))
7980 return WERR_BADFID;
7983 /* blindly return success */
7984 return WERR_OK;
7988 /****************************************************************************
7989 ****************************************************************************/
7991 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7993 POLICY_HND *handle = &q_u->handle;
7994 UNISTR2 *value = &q_u->valuename;
7996 NT_PRINTER_INFO_LEVEL *printer = NULL;
7997 int snum=0;
7998 WERROR status = WERR_OK;
7999 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8000 pstring valuename;
8002 DEBUG(5,("spoolss_deleteprinterdata\n"));
8004 if (!Printer) {
8005 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8006 return WERR_BADFID;
8009 if (!get_printer_snum(p, handle, &snum))
8010 return WERR_BADFID;
8012 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8013 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8014 return WERR_ACCESS_DENIED;
8017 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8018 if (!W_ERROR_IS_OK(status))
8019 return status;
8021 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8023 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8025 free_a_printer(&printer, 2);
8027 return status;
8030 /****************************************************************************
8031 ****************************************************************************/
8033 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8035 POLICY_HND *handle = &q_u->handle;
8036 FORM *form = &q_u->form;
8037 nt_forms_struct tmpForm;
8038 int snum;
8039 WERROR status = WERR_OK;
8040 NT_PRINTER_INFO_LEVEL *printer = NULL;
8042 int count=0;
8043 nt_forms_struct *list=NULL;
8044 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8046 DEBUG(5,("spoolss_addform\n"));
8048 if (!Printer) {
8049 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8050 return WERR_BADFID;
8054 /* forms can be added on printer of on the print server handle */
8056 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8058 if (!get_printer_snum(p,handle, &snum))
8059 return WERR_BADFID;
8061 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8062 if (!W_ERROR_IS_OK(status))
8063 goto done;
8066 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8067 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8068 status = WERR_ACCESS_DENIED;
8069 goto done;
8072 /* can't add if builtin */
8074 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8075 status = WERR_ALREADY_EXISTS;
8076 goto done;
8079 count = get_ntforms(&list);
8081 if(!add_a_form(&list, form, &count)) {
8082 status = WERR_NOMEM;
8083 goto done;
8086 write_ntforms(&list, count);
8089 * ChangeID must always be set if this is a printer
8092 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8093 status = mod_a_printer(*printer, 2);
8095 done:
8096 if ( printer )
8097 free_a_printer(&printer, 2);
8098 SAFE_FREE(list);
8100 return status;
8103 /****************************************************************************
8104 ****************************************************************************/
8106 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8108 POLICY_HND *handle = &q_u->handle;
8109 UNISTR2 *form_name = &q_u->name;
8110 nt_forms_struct tmpForm;
8111 int count=0;
8112 nt_forms_struct *list=NULL;
8113 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8114 int snum;
8115 WERROR status = WERR_OK;
8116 NT_PRINTER_INFO_LEVEL *printer = NULL;
8118 DEBUG(5,("spoolss_deleteform\n"));
8120 if (!Printer) {
8121 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8122 return WERR_BADFID;
8125 /* forms can be deleted on printer of on the print server handle */
8127 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8129 if (!get_printer_snum(p,handle, &snum))
8130 return WERR_BADFID;
8132 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8133 if (!W_ERROR_IS_OK(status))
8134 goto done;
8137 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8138 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8139 status = WERR_ACCESS_DENIED;
8140 goto done;
8143 /* can't delete if builtin */
8145 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8146 status = WERR_INVALID_PARAM;
8147 goto done;
8150 count = get_ntforms(&list);
8152 if ( !delete_a_form(&list, form_name, &count, &status ))
8153 goto done;
8156 * ChangeID must always be set if this is a printer
8159 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8160 status = mod_a_printer(*printer, 2);
8162 done:
8163 if ( printer )
8164 free_a_printer(&printer, 2);
8165 SAFE_FREE(list);
8167 return status;
8170 /****************************************************************************
8171 ****************************************************************************/
8173 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8175 POLICY_HND *handle = &q_u->handle;
8176 FORM *form = &q_u->form;
8177 nt_forms_struct tmpForm;
8178 int snum;
8179 WERROR status = WERR_OK;
8180 NT_PRINTER_INFO_LEVEL *printer = NULL;
8182 int count=0;
8183 nt_forms_struct *list=NULL;
8184 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8186 DEBUG(5,("spoolss_setform\n"));
8188 if (!Printer) {
8189 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8190 return WERR_BADFID;
8193 /* forms can be modified on printer of on the print server handle */
8195 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8197 if (!get_printer_snum(p,handle, &snum))
8198 return WERR_BADFID;
8200 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8201 if (!W_ERROR_IS_OK(status))
8202 goto done;
8205 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8206 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8207 status = WERR_ACCESS_DENIED;
8208 goto done;
8211 /* can't set if builtin */
8212 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8213 status = WERR_INVALID_PARAM;
8214 goto done;
8217 count = get_ntforms(&list);
8218 update_a_form(&list, form, count);
8219 write_ntforms(&list, count);
8222 * ChangeID must always be set if this is a printer
8225 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8226 status = mod_a_printer(*printer, 2);
8229 done:
8230 if ( printer )
8231 free_a_printer(&printer, 2);
8232 SAFE_FREE(list);
8234 return status;
8237 /****************************************************************************
8238 enumprintprocessors level 1.
8239 ****************************************************************************/
8241 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8243 PRINTPROCESSOR_1 *info_1=NULL;
8245 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8246 return WERR_NOMEM;
8248 (*returned) = 0x1;
8250 init_unistr(&info_1->name, "winprint");
8252 *needed += spoolss_size_printprocessor_info_1(info_1);
8254 if (!alloc_buffer_size(buffer, *needed))
8255 return WERR_INSUFFICIENT_BUFFER;
8257 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8259 SAFE_FREE(info_1);
8261 if (*needed > offered) {
8262 *returned=0;
8263 return WERR_INSUFFICIENT_BUFFER;
8266 return WERR_OK;
8269 /****************************************************************************
8270 ****************************************************************************/
8272 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8274 uint32 level = q_u->level;
8275 NEW_BUFFER *buffer = NULL;
8276 uint32 offered = q_u->offered;
8277 uint32 *needed = &r_u->needed;
8278 uint32 *returned = &r_u->returned;
8280 /* that's an [in out] buffer */
8281 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8282 buffer = r_u->buffer;
8284 DEBUG(5,("spoolss_enumprintprocessors\n"));
8287 * Enumerate the print processors ...
8289 * Just reply with "winprint", to keep NT happy
8290 * and I can use my nice printer checker.
8293 *returned=0;
8294 *needed=0;
8296 switch (level) {
8297 case 1:
8298 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8299 default:
8300 return WERR_UNKNOWN_LEVEL;
8304 /****************************************************************************
8305 enumprintprocdatatypes level 1.
8306 ****************************************************************************/
8308 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8310 PRINTPROCDATATYPE_1 *info_1=NULL;
8312 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8313 return WERR_NOMEM;
8315 (*returned) = 0x1;
8317 init_unistr(&info_1->name, "RAW");
8319 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8321 if (!alloc_buffer_size(buffer, *needed))
8322 return WERR_INSUFFICIENT_BUFFER;
8324 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8326 SAFE_FREE(info_1);
8328 if (*needed > offered) {
8329 *returned=0;
8330 return WERR_INSUFFICIENT_BUFFER;
8333 return WERR_OK;
8336 /****************************************************************************
8337 ****************************************************************************/
8339 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8341 uint32 level = q_u->level;
8342 NEW_BUFFER *buffer = NULL;
8343 uint32 offered = q_u->offered;
8344 uint32 *needed = &r_u->needed;
8345 uint32 *returned = &r_u->returned;
8347 /* that's an [in out] buffer */
8348 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8349 buffer = r_u->buffer;
8351 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8353 *returned=0;
8354 *needed=0;
8356 switch (level) {
8357 case 1:
8358 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8359 default:
8360 return WERR_UNKNOWN_LEVEL;
8364 /****************************************************************************
8365 enumprintmonitors level 1.
8366 ****************************************************************************/
8368 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8370 PRINTMONITOR_1 *info_1=NULL;
8372 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8373 return WERR_NOMEM;
8375 (*returned) = 0x1;
8377 init_unistr(&info_1->name, "Local Port");
8379 *needed += spoolss_size_printmonitor_info_1(info_1);
8381 if (!alloc_buffer_size(buffer, *needed))
8382 return WERR_INSUFFICIENT_BUFFER;
8384 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8386 SAFE_FREE(info_1);
8388 if (*needed > offered) {
8389 *returned=0;
8390 return WERR_INSUFFICIENT_BUFFER;
8393 return WERR_OK;
8396 /****************************************************************************
8397 enumprintmonitors level 2.
8398 ****************************************************************************/
8400 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8402 PRINTMONITOR_2 *info_2=NULL;
8404 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8405 return WERR_NOMEM;
8407 (*returned) = 0x1;
8409 init_unistr(&info_2->name, "Local Port");
8410 init_unistr(&info_2->environment, "Windows NT X86");
8411 init_unistr(&info_2->dll_name, "localmon.dll");
8413 *needed += spoolss_size_printmonitor_info_2(info_2);
8415 if (!alloc_buffer_size(buffer, *needed))
8416 return WERR_INSUFFICIENT_BUFFER;
8418 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8420 SAFE_FREE(info_2);
8422 if (*needed > offered) {
8423 *returned=0;
8424 return WERR_INSUFFICIENT_BUFFER;
8427 return WERR_OK;
8430 /****************************************************************************
8431 ****************************************************************************/
8433 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8435 uint32 level = q_u->level;
8436 NEW_BUFFER *buffer = NULL;
8437 uint32 offered = q_u->offered;
8438 uint32 *needed = &r_u->needed;
8439 uint32 *returned = &r_u->returned;
8441 /* that's an [in out] buffer */
8442 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8443 buffer = r_u->buffer;
8445 DEBUG(5,("spoolss_enumprintmonitors\n"));
8448 * Enumerate the print monitors ...
8450 * Just reply with "Local Port", to keep NT happy
8451 * and I can use my nice printer checker.
8454 *returned=0;
8455 *needed=0;
8457 switch (level) {
8458 case 1:
8459 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8460 case 2:
8461 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8462 default:
8463 return WERR_UNKNOWN_LEVEL;
8467 /****************************************************************************
8468 ****************************************************************************/
8470 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8472 int i=0;
8473 BOOL found=False;
8474 JOB_INFO_1 *info_1=NULL;
8476 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8478 if (info_1 == NULL) {
8479 return WERR_NOMEM;
8482 for (i=0; i<count && found==False; i++) {
8483 if ((*queue)[i].job==(int)jobid)
8484 found=True;
8487 if (found==False) {
8488 SAFE_FREE(info_1);
8489 /* NT treats not found as bad param... yet another bad choice */
8490 return WERR_INVALID_PARAM;
8493 fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8495 *needed += spoolss_size_job_info_1(info_1);
8497 if (!alloc_buffer_size(buffer, *needed)) {
8498 SAFE_FREE(info_1);
8499 return WERR_INSUFFICIENT_BUFFER;
8502 smb_io_job_info_1("", buffer, info_1, 0);
8504 SAFE_FREE(info_1);
8506 if (*needed > offered)
8507 return WERR_INSUFFICIENT_BUFFER;
8509 return WERR_OK;
8512 /****************************************************************************
8513 ****************************************************************************/
8515 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8517 int i = 0;
8518 BOOL found = False;
8519 JOB_INFO_2 *info_2;
8520 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8521 WERROR ret;
8522 DEVICEMODE *devmode = NULL;
8523 NT_DEVICEMODE *nt_devmode = NULL;
8525 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8527 ZERO_STRUCTP(info_2);
8529 if (info_2 == NULL) {
8530 ret = WERR_NOMEM;
8531 goto done;
8534 for ( i=0; i<count && found==False; i++ )
8536 if ((*queue)[i].job == (int)jobid)
8537 found = True;
8540 if ( !found )
8542 /* NT treats not found as bad param... yet another bad
8543 choice */
8544 ret = WERR_INVALID_PARAM;
8545 goto done;
8548 ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8549 if (!W_ERROR_IS_OK(ret))
8550 goto done;
8553 * if the print job does not have a DEVMODE associated with it,
8554 * just use the one for the printer. A NULL devicemode is not
8555 * a failure condition
8558 if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8559 devmode = construct_dev_mode(snum);
8560 else {
8561 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8562 ZERO_STRUCTP( devmode );
8563 convert_nt_devicemode( devmode, nt_devmode );
8567 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8569 *needed += spoolss_size_job_info_2(info_2);
8571 if (!alloc_buffer_size(buffer, *needed)) {
8572 ret = WERR_INSUFFICIENT_BUFFER;
8573 goto done;
8576 smb_io_job_info_2("", buffer, info_2, 0);
8578 if (*needed > offered) {
8579 ret = WERR_INSUFFICIENT_BUFFER;
8580 goto done;
8583 ret = WERR_OK;
8585 done:
8586 /* Cleanup allocated memory */
8588 free_job_info_2(info_2); /* Also frees devmode */
8589 SAFE_FREE(info_2);
8590 free_a_printer(&ntprinter, 2);
8592 return ret;
8595 /****************************************************************************
8596 ****************************************************************************/
8598 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8600 POLICY_HND *handle = &q_u->handle;
8601 uint32 jobid = q_u->jobid;
8602 uint32 level = q_u->level;
8603 NEW_BUFFER *buffer = NULL;
8604 uint32 offered = q_u->offered;
8605 uint32 *needed = &r_u->needed;
8606 WERROR wstatus = WERR_OK;
8608 int snum;
8609 int count;
8610 print_queue_struct *queue = NULL;
8611 print_status_struct prt_status;
8613 /* that's an [in out] buffer */
8614 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8615 buffer = r_u->buffer;
8617 DEBUG(5,("spoolss_getjob\n"));
8619 *needed = 0;
8621 if (!get_printer_snum(p, handle, &snum))
8622 return WERR_BADFID;
8624 count = print_queue_status(snum, &queue, &prt_status);
8626 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8627 count, prt_status.status, prt_status.message));
8629 switch ( level ) {
8630 case 1:
8631 wstatus = getjob_level_1(&queue, count, snum, jobid,
8632 buffer, offered, needed);
8633 break;
8634 case 2:
8635 wstatus = getjob_level_2(&queue, count, snum, jobid,
8636 buffer, offered, needed);
8637 break;
8638 default:
8639 wstatus = WERR_UNKNOWN_LEVEL;
8640 break;
8643 SAFE_FREE(queue);
8644 return wstatus;
8647 /********************************************************************
8648 spoolss_getprinterdataex
8650 From MSDN documentation of GetPrinterDataEx: pass request
8651 to GetPrinterData if key is "PrinterDriverData".
8652 ********************************************************************/
8654 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8656 POLICY_HND *handle = &q_u->handle;
8657 uint32 in_size = q_u->size;
8658 uint32 *type = &r_u->type;
8659 uint32 *out_size = &r_u->size;
8660 uint8 **data = &r_u->data;
8661 uint32 *needed = &r_u->needed;
8662 fstring keyname, valuename;
8664 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8666 NT_PRINTER_INFO_LEVEL *printer = NULL;
8667 int snum = 0;
8668 WERROR status = WERR_OK;
8670 DEBUG(4,("_spoolss_getprinterdataex\n"));
8672 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8673 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8675 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8676 keyname, valuename));
8678 /* in case of problem, return some default values */
8680 *needed = 0;
8681 *type = 0;
8682 *out_size = in_size;
8684 if (!Printer) {
8685 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8686 status = WERR_BADFID;
8687 goto done;
8690 /* Is the handle to a printer or to the server? */
8692 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8693 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8694 status = WERR_INVALID_PARAM;
8695 goto done;
8698 if ( !get_printer_snum(p,handle, &snum) )
8699 return WERR_BADFID;
8701 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8702 if ( !W_ERROR_IS_OK(status) )
8703 goto done;
8705 /* check to see if the keyname is valid */
8706 if ( !strlen(keyname) ) {
8707 status = WERR_INVALID_PARAM;
8708 goto done;
8711 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8712 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8713 free_a_printer( &printer, 2 );
8714 status = WERR_BADFILE;
8715 goto done;
8718 /* When given a new keyname, we should just create it */
8720 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8722 if (*needed > *out_size)
8723 status = WERR_MORE_DATA;
8725 done:
8726 if ( !W_ERROR_IS_OK(status) )
8728 DEBUG(5, ("error: allocating %d\n", *out_size));
8730 /* reply this param doesn't exist */
8732 if ( *out_size )
8734 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8735 status = WERR_NOMEM;
8736 goto done;
8739 else {
8740 *data = NULL;
8744 if ( printer )
8745 free_a_printer( &printer, 2 );
8747 return status;
8750 /********************************************************************
8751 * spoolss_setprinterdataex
8752 ********************************************************************/
8754 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8756 POLICY_HND *handle = &q_u->handle;
8757 uint32 type = q_u->type;
8758 uint8 *data = q_u->data;
8759 uint32 real_len = q_u->real_len;
8761 NT_PRINTER_INFO_LEVEL *printer = NULL;
8762 int snum = 0;
8763 WERROR status = WERR_OK;
8764 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8765 fstring valuename;
8766 fstring keyname;
8767 char *oid_string;
8769 DEBUG(4,("_spoolss_setprinterdataex\n"));
8771 /* From MSDN documentation of SetPrinterDataEx: pass request to
8772 SetPrinterData if key is "PrinterDriverData" */
8774 if (!Printer) {
8775 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8776 return WERR_BADFID;
8779 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8780 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8781 return WERR_INVALID_PARAM;
8784 if ( !get_printer_snum(p,handle, &snum) )
8785 return WERR_BADFID;
8788 * Access check : NT returns "access denied" if you make a
8789 * SetPrinterData call without the necessary privildge.
8790 * we were originally returning OK if nothing changed
8791 * which made Win2k issue **a lot** of SetPrinterData
8792 * when connecting to a printer --jerry
8795 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8797 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8798 return WERR_ACCESS_DENIED;
8801 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8802 if (!W_ERROR_IS_OK(status))
8803 return status;
8805 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8806 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8808 /* check for OID in valuename */
8810 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8812 *oid_string = '\0';
8813 oid_string++;
8816 /* save the registry data */
8818 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8820 if ( W_ERROR_IS_OK(status) )
8822 /* save the OID if one was specified */
8823 if ( oid_string ) {
8824 fstrcat( keyname, "\\" );
8825 fstrcat( keyname, SPOOL_OID_KEY );
8828 * I'm not checking the status here on purpose. Don't know
8829 * if this is right, but I'm returning the status from the
8830 * previous set_printer_dataex() call. I have no idea if
8831 * this is right. --jerry
8834 set_printer_dataex( printer, keyname, valuename,
8835 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8838 status = mod_a_printer(*printer, 2);
8841 free_a_printer(&printer, 2);
8843 return status;
8847 /********************************************************************
8848 * spoolss_deleteprinterdataex
8849 ********************************************************************/
8851 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8853 POLICY_HND *handle = &q_u->handle;
8854 UNISTR2 *value = &q_u->valuename;
8855 UNISTR2 *key = &q_u->keyname;
8857 NT_PRINTER_INFO_LEVEL *printer = NULL;
8858 int snum=0;
8859 WERROR status = WERR_OK;
8860 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8861 pstring valuename, keyname;
8863 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8865 if (!Printer) {
8866 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8867 return WERR_BADFID;
8870 if (!get_printer_snum(p, handle, &snum))
8871 return WERR_BADFID;
8873 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8874 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8875 return WERR_ACCESS_DENIED;
8878 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8879 if (!W_ERROR_IS_OK(status))
8880 return status;
8882 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8883 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8885 status = delete_printer_dataex( printer, keyname, valuename );
8887 free_a_printer(&printer, 2);
8889 return status;
8892 /********************************************************************
8893 * spoolss_enumprinterkey
8894 ********************************************************************/
8897 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8899 fstring key;
8900 fstring *keynames = NULL;
8901 uint16 *enumkeys = NULL;
8902 int num_keys;
8903 int printerkey_len;
8904 POLICY_HND *handle = &q_u->handle;
8905 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8906 NT_PRINTER_DATA *data;
8907 NT_PRINTER_INFO_LEVEL *printer = NULL;
8908 int snum = 0;
8909 WERROR status = WERR_BADFILE;
8912 DEBUG(4,("_spoolss_enumprinterkey\n"));
8914 if (!Printer) {
8915 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8916 return WERR_BADFID;
8919 if ( !get_printer_snum(p,handle, &snum) )
8920 return WERR_BADFID;
8922 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8923 if (!W_ERROR_IS_OK(status))
8924 return status;
8926 /* get the list of subkey names */
8928 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8929 data = &printer->info_2->data;
8931 num_keys = get_printer_subkeys( data, key, &keynames );
8933 if ( num_keys == -1 ) {
8934 status = WERR_BADFILE;
8935 goto done;
8938 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
8940 r_u->needed = printerkey_len*2;
8942 if ( q_u->size < r_u->needed ) {
8943 status = WERR_MORE_DATA;
8944 goto done;
8947 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8948 status = WERR_NOMEM;
8949 goto done;
8952 status = WERR_OK;
8954 if ( q_u->size < r_u->needed )
8955 status = WERR_MORE_DATA;
8957 done:
8958 free_a_printer( &printer, 2 );
8959 SAFE_FREE( keynames );
8961 return status;
8964 /********************************************************************
8965 * spoolss_deleteprinterkey
8966 ********************************************************************/
8968 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8970 POLICY_HND *handle = &q_u->handle;
8971 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8972 fstring key;
8973 NT_PRINTER_INFO_LEVEL *printer = NULL;
8974 int snum=0;
8975 WERROR status;
8977 DEBUG(5,("spoolss_deleteprinterkey\n"));
8979 if (!Printer) {
8980 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8981 return WERR_BADFID;
8984 /* if keyname == NULL, return error */
8986 if ( !q_u->keyname.buffer )
8987 return WERR_INVALID_PARAM;
8989 if (!get_printer_snum(p, handle, &snum))
8990 return WERR_BADFID;
8992 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8993 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8994 return WERR_ACCESS_DENIED;
8997 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8998 if (!W_ERROR_IS_OK(status))
8999 return status;
9001 /* delete the key and all subneys */
9003 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9005 status = delete_all_printer_data( printer->info_2, key );
9007 if ( W_ERROR_IS_OK(status) )
9008 status = mod_a_printer(*printer, 2);
9010 free_a_printer( &printer, 2 );
9012 return status;
9016 /********************************************************************
9017 * spoolss_enumprinterdataex
9018 ********************************************************************/
9020 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9022 POLICY_HND *handle = &q_u->handle;
9023 uint32 in_size = q_u->size;
9024 uint32 num_entries,
9025 needed;
9026 NT_PRINTER_INFO_LEVEL *printer = NULL;
9027 PRINTER_ENUM_VALUES *enum_values = NULL;
9028 NT_PRINTER_DATA *p_data;
9029 fstring key;
9030 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9031 int snum;
9032 WERROR result;
9033 int key_index;
9034 int i;
9035 REGISTRY_VALUE *val;
9036 char *value_name;
9037 int data_len;
9040 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9042 if (!Printer) {
9043 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9044 return WERR_BADFID;
9048 * first check for a keyname of NULL or "". Win2k seems to send
9049 * this a lot and we should send back WERR_INVALID_PARAM
9050 * no need to spend time looking up the printer in this case.
9051 * --jerry
9054 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9055 if ( !strlen(key) ) {
9056 result = WERR_INVALID_PARAM;
9057 goto done;
9060 /* get the printer off of disk */
9062 if (!get_printer_snum(p,handle, &snum))
9063 return WERR_BADFID;
9065 ZERO_STRUCT(printer);
9066 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9067 if (!W_ERROR_IS_OK(result))
9068 return result;
9070 /* now look for a match on the key name */
9072 p_data = &printer->info_2->data;
9074 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9075 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9077 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9078 result = WERR_INVALID_PARAM;
9079 goto done;
9082 result = WERR_OK;
9083 needed = 0;
9085 /* allocate the memory for the array of pointers -- if necessary */
9087 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9088 if ( num_entries )
9090 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9092 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9093 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9094 result = WERR_NOMEM;
9095 goto done;
9098 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9102 * loop through all params and build the array to pass
9103 * back to the client
9106 for ( i=0; i<num_entries; i++ )
9108 /* lookup the registry value */
9110 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9111 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9113 /* copy the data */
9115 value_name = regval_name( val );
9116 init_unistr( &enum_values[i].valuename, value_name );
9117 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9118 enum_values[i].type = regval_type( val );
9120 data_len = regval_size( val );
9121 if ( data_len ) {
9122 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9124 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9125 data_len ));
9126 result = WERR_NOMEM;
9127 goto done;
9130 enum_values[i].data_len = data_len;
9132 /* keep track of the size of the array in bytes */
9134 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9137 /* housekeeping information in the reply */
9139 r_u->needed = needed;
9140 r_u->returned = num_entries;
9142 if (needed > in_size) {
9143 result = WERR_MORE_DATA;
9144 goto done;
9147 /* copy data into the reply */
9149 r_u->ctr.size = r_u->needed;
9150 r_u->ctr.size_of_array = r_u->returned;
9151 r_u->ctr.values = enum_values;
9155 done:
9156 if ( printer )
9157 free_a_printer(&printer, 2);
9159 return result;
9162 /****************************************************************************
9163 ****************************************************************************/
9165 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9167 init_unistr(&info->name, name);
9170 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9171 UNISTR2 *environment,
9172 NEW_BUFFER *buffer,
9173 uint32 offered,
9174 uint32 *needed)
9176 pstring path;
9177 pstring long_archi;
9178 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9180 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9182 if (!get_short_archi(long_archi))
9183 return WERR_INVALID_ENVIRONMENT;
9185 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9186 return WERR_NOMEM;
9188 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9190 fill_printprocessordirectory_1(info, path);
9192 *needed += spoolss_size_printprocessordirectory_info_1(info);
9194 if (!alloc_buffer_size(buffer, *needed)) {
9195 safe_free(info);
9196 return WERR_INSUFFICIENT_BUFFER;
9199 smb_io_printprocessordirectory_1("", buffer, info, 0);
9201 safe_free(info);
9203 if (*needed > offered)
9204 return WERR_INSUFFICIENT_BUFFER;
9205 else
9206 return WERR_OK;
9209 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9211 uint32 level = q_u->level;
9212 NEW_BUFFER *buffer = NULL;
9213 uint32 offered = q_u->offered;
9214 uint32 *needed = &r_u->needed;
9215 WERROR result;
9217 /* that's an [in out] buffer */
9218 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9219 buffer = r_u->buffer;
9221 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9223 *needed=0;
9225 switch(level) {
9226 case 1:
9227 result = getprintprocessordirectory_level_1
9228 (&q_u->name, &q_u->environment, buffer, offered, needed);
9229 break;
9230 default:
9231 result = WERR_UNKNOWN_LEVEL;
9234 return result;
9237 #if 0
9239 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9240 SPOOL_R_REPLYOPENPRINTER *r_u)
9242 DEBUG(5,("_spoolss_replyopenprinter\n"));
9244 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9246 return WERR_OK;
9249 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9250 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9252 DEBUG(5,("_spoolss_replycloseprinter\n"));
9253 return WERR_OK;
9256 #endif