tiny simplification
[Samba/gebeck_regimport.git] / source3 / rpc_server / srv_spoolss_nt.c
blob3758c8fd63ed9cbaeb2198f913599198e71af486
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 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, see <http://www.gnu.org/licenses/>.
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26 up, all the errors returned are DOS errors, not NT status codes. */
28 #include "includes.h"
30 extern userdom_struct current_user_info;
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42 struct table_node {
43 const char *long_archi;
44 const char *short_archi;
45 int version;
48 static Printer_entry *printers_list;
50 typedef struct _counter_printer_0 {
51 struct _counter_printer_0 *next;
52 struct _counter_printer_0 *prev;
54 int snum;
55 uint32 counter;
56 } counter_printer_0;
58 static counter_printer_0 *counter_list;
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
64 /* in printing/nt_printing.c */
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
68 /* API table for Xcv Monitor functions */
70 struct xcv_api_table {
71 const char *name;
72 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
76 /* translate between internal status numbers and NT status numbers */
77 static int nt_printj_status(int v)
79 switch (v) {
80 case LPQ_QUEUED:
81 return 0;
82 case LPQ_PAUSED:
83 return JOB_STATUS_PAUSED;
84 case LPQ_SPOOLING:
85 return JOB_STATUS_SPOOLING;
86 case LPQ_PRINTING:
87 return JOB_STATUS_PRINTING;
88 case LPQ_ERROR:
89 return JOB_STATUS_ERROR;
90 case LPQ_DELETING:
91 return JOB_STATUS_DELETING;
92 case LPQ_OFFLINE:
93 return JOB_STATUS_OFFLINE;
94 case LPQ_PAPEROUT:
95 return JOB_STATUS_PAPEROUT;
96 case LPQ_PRINTED:
97 return JOB_STATUS_PRINTED;
98 case LPQ_DELETED:
99 return JOB_STATUS_DELETED;
100 case LPQ_BLOCKED:
101 return JOB_STATUS_BLOCKED;
102 case LPQ_USER_INTERVENTION:
103 return JOB_STATUS_USER_INTERVENTION;
105 return 0;
108 static int nt_printq_status(int v)
110 switch (v) {
111 case LPQ_PAUSED:
112 return PRINTER_STATUS_PAUSED;
113 case LPQ_QUEUED:
114 case LPQ_SPOOLING:
115 case LPQ_PRINTING:
116 return 0;
118 return 0;
121 /****************************************************************************
122 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
123 ****************************************************************************/
125 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
127 if (*pp == NULL)
128 return;
130 SAFE_FREE((*pp)->ctr.type);
131 SAFE_FREE(*pp);
134 /***************************************************************************
135 Disconnect from the client
136 ****************************************************************************/
138 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
140 WERROR result;
143 * Tell the specific printing tdb we no longer want messages for this printer
144 * by deregistering our PID.
147 if (!print_notify_deregister_pid(snum))
148 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
150 /* weird if the test succeds !!! */
151 if (smb_connections==0) {
152 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
153 return;
156 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe,
157 talloc_tos(),
158 handle);
160 if (!W_ERROR_IS_OK(result))
161 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
162 dos_errstr(result)));
164 /* if it's the last connection, deconnect the IPC$ share */
165 if (smb_connections==1) {
167 cli_shutdown( notify_cli_pipe->cli );
168 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
170 messaging_deregister(smbd_messaging_context(),
171 MSG_PRINTER_NOTIFY2, NULL);
173 /* Tell the connections db we're no longer interested in
174 * printer notify messages. */
176 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
179 smb_connections--;
182 /****************************************************************************
183 Functions to free a printer entry datastruct.
184 ****************************************************************************/
186 static void free_printer_entry(void *ptr)
188 Printer_entry *Printer = (Printer_entry *)ptr;
190 if (Printer->notify.client_connected==True) {
191 int snum = -1;
193 if ( Printer->printer_type == SPLHND_SERVER) {
194 snum = -1;
195 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
196 } else if (Printer->printer_type == SPLHND_PRINTER) {
197 snum = print_queue_snum(Printer->sharename);
198 if (snum != -1)
199 srv_spoolss_replycloseprinter(snum,
200 &Printer->notify.client_hnd);
204 Printer->notify.flags=0;
205 Printer->notify.options=0;
206 Printer->notify.localmachine[0]='\0';
207 Printer->notify.printerlocal=0;
208 free_spool_notify_option(&Printer->notify.option);
209 Printer->notify.option=NULL;
210 Printer->notify.client_connected=False;
212 free_nt_devicemode( &Printer->nt_devmode );
213 free_a_printer( &Printer->printer_info, 2 );
215 talloc_destroy( Printer->ctx );
217 /* Remove from the internal list. */
218 DLIST_REMOVE(printers_list, Printer);
220 SAFE_FREE(Printer);
223 /****************************************************************************
224 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
225 ****************************************************************************/
227 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
229 SPOOL_NOTIFY_OPTION *new_sp = NULL;
231 if (!sp)
232 return NULL;
234 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
235 if (!new_sp)
236 return NULL;
238 *new_sp = *sp;
240 if (sp->ctr.count) {
241 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
243 if (!new_sp->ctr.type) {
244 SAFE_FREE(new_sp);
245 return NULL;
249 return new_sp;
252 /****************************************************************************
253 find printer index by handle
254 ****************************************************************************/
256 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
258 Printer_entry *find_printer = NULL;
260 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
261 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
262 return NULL;
265 return find_printer;
268 /****************************************************************************
269 Close printer index by handle.
270 ****************************************************************************/
272 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
274 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
276 if (!Printer) {
277 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
278 return False;
281 close_policy_hnd(p, hnd);
283 return True;
286 /****************************************************************************
287 Delete a printer given a handle.
288 ****************************************************************************/
290 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
292 char *cmd = lp_deleteprinter_cmd();
293 char *command = NULL;
294 int ret;
295 SE_PRIV se_printop = SE_PRINT_OPERATOR;
296 bool is_print_op = False;
298 /* can't fail if we don't try */
300 if ( !*cmd )
301 return WERR_OK;
303 command = talloc_asprintf(ctx,
304 "%s \"%s\"",
305 cmd, sharename);
306 if (!command) {
307 return WERR_NOMEM;
309 if ( token )
310 is_print_op = user_has_privileges( token, &se_printop );
312 DEBUG(10,("Running [%s]\n", command));
314 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
316 if ( is_print_op )
317 become_root();
319 if ( (ret = smbrun(command, NULL)) == 0 ) {
320 /* Tell everyone we updated smb.conf. */
321 message_send_all(smbd_messaging_context(),
322 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
325 if ( is_print_op )
326 unbecome_root();
328 /********** END SePrintOperatorPrivlege BLOCK **********/
330 DEBUGADD(10,("returned [%d]\n", ret));
332 TALLOC_FREE(command);
334 if (ret != 0)
335 return WERR_BADFID; /* What to return here? */
337 /* go ahead and re-read the services immediately */
338 reload_services( False );
340 if ( lp_servicenumber( sharename ) < 0 )
341 return WERR_ACCESS_DENIED;
343 return WERR_OK;
346 /****************************************************************************
347 Delete a printer given a handle.
348 ****************************************************************************/
350 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
352 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
354 if (!Printer) {
355 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
356 return WERR_BADFID;
360 * It turns out that Windows allows delete printer on a handle
361 * opened by an admin user, then used on a pipe handle created
362 * by an anonymous user..... but they're working on security.... riiight !
363 * JRA.
366 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
367 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
368 return WERR_ACCESS_DENIED;
371 /* this does not need a become root since the access check has been
372 done on the handle already */
374 if (del_a_printer( Printer->sharename ) != 0) {
375 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
376 return WERR_BADFID;
379 return delete_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, Printer->sharename );
382 /****************************************************************************
383 Return the snum of a printer corresponding to an handle.
384 ****************************************************************************/
386 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
387 struct share_params **params)
389 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
391 if (!Printer) {
392 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
393 return False;
396 switch (Printer->printer_type) {
397 case SPLHND_PRINTER:
398 DEBUG(4,("short name:%s\n", Printer->sharename));
399 *number = print_queue_snum(Printer->sharename);
400 return (*number != -1);
401 case SPLHND_SERVER:
402 return False;
403 default:
404 return False;
408 /****************************************************************************
409 Set printer handle type.
410 Check if it's \\server or \\server\printer
411 ****************************************************************************/
413 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
415 DEBUG(3,("Setting printer type=%s\n", handlename));
417 if ( strlen(handlename) < 3 ) {
418 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
419 return False;
422 /* it's a print server */
423 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
424 DEBUGADD(4,("Printer is a print server\n"));
425 Printer->printer_type = SPLHND_SERVER;
427 /* it's a printer (set_printer_hnd_name() will handle port monitors */
428 else {
429 DEBUGADD(4,("Printer is a printer\n"));
430 Printer->printer_type = SPLHND_PRINTER;
433 return True;
436 /****************************************************************************
437 Set printer handle name.. Accept names like \\server, \\server\printer,
438 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
439 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
440 XcvDataPort() interface.
441 ****************************************************************************/
443 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
445 int snum;
446 int n_services=lp_numservices();
447 char *aprinter, *printername;
448 const char *servername;
449 fstring sname;
450 bool found=False;
451 NT_PRINTER_INFO_LEVEL *printer = NULL;
452 WERROR result;
454 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
456 aprinter = handlename;
457 if ( *handlename == '\\' ) {
458 servername = handlename + 2;
459 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
460 *aprinter = '\0';
461 aprinter++;
464 else {
465 servername = "";
468 /* save the servername to fill in replies on this handle */
470 if ( !is_myname_or_ipaddr( servername ) )
471 return False;
473 fstrcpy( Printer->servername, servername );
475 if ( Printer->printer_type == SPLHND_SERVER )
476 return True;
478 if ( Printer->printer_type != SPLHND_PRINTER )
479 return False;
481 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
483 /* check for the Port Monitor Interface */
485 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
486 Printer->printer_type = SPLHND_PORTMON_TCP;
487 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
488 found = True;
490 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
491 Printer->printer_type = SPLHND_PORTMON_LOCAL;
492 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
493 found = True;
496 /* Search all sharenames first as this is easier than pulling
497 the printer_info_2 off of disk. Don't use find_service() since
498 that calls out to map_username() */
500 /* do another loop to look for printernames */
502 for (snum=0; !found && snum<n_services; snum++) {
504 /* no point going on if this is not a printer */
506 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
507 continue;
509 fstrcpy(sname, lp_servicename(snum));
510 if ( strequal( aprinter, sname ) ) {
511 found = True;
512 break;
515 /* no point looking up the printer object if
516 we aren't allowing printername != sharename */
518 if ( lp_force_printername(snum) )
519 continue;
521 fstrcpy(sname, lp_servicename(snum));
523 printer = NULL;
524 result = get_a_printer( NULL, &printer, 2, sname );
525 if ( !W_ERROR_IS_OK(result) ) {
526 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
527 sname, dos_errstr(result)));
528 continue;
531 /* printername is always returned as \\server\printername */
532 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
533 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
534 printer->info_2->printername));
535 free_a_printer( &printer, 2);
536 continue;
539 printername++;
541 if ( strequal(printername, aprinter) ) {
542 free_a_printer( &printer, 2);
543 found = True;
544 break;
547 DEBUGADD(10, ("printername: %s\n", printername));
549 free_a_printer( &printer, 2);
552 free_a_printer( &printer, 2);
554 if ( !found ) {
555 DEBUGADD(4,("Printer not found\n"));
556 return False;
559 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
561 fstrcpy(Printer->sharename, sname);
563 return True;
566 /****************************************************************************
567 Find first available printer slot. creates a printer handle for you.
568 ****************************************************************************/
570 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
572 Printer_entry *new_printer;
574 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
576 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
577 return False;
579 ZERO_STRUCTP(new_printer);
581 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
582 SAFE_FREE(new_printer);
583 return False;
586 /* Add to the internal list. */
587 DLIST_ADD(printers_list, new_printer);
589 new_printer->notify.option=NULL;
591 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
592 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
593 close_printer_handle(p, hnd);
594 return False;
597 if (!set_printer_hnd_printertype(new_printer, name)) {
598 close_printer_handle(p, hnd);
599 return False;
602 if (!set_printer_hnd_name(new_printer, name)) {
603 close_printer_handle(p, hnd);
604 return False;
607 new_printer->access_granted = access_granted;
609 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
611 return True;
614 /***************************************************************************
615 check to see if the client motify handle is monitoring the notification
616 given by (notify_type, notify_field).
617 **************************************************************************/
619 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
620 uint16 notify_field)
622 return True;
625 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
626 uint16 notify_field)
628 SPOOL_NOTIFY_OPTION *option = p->notify.option;
629 uint32 i, j;
632 * Flags should always be zero when the change notify
633 * is registered by the client's spooler. A user Win32 app
634 * might use the flags though instead of the NOTIFY_OPTION_INFO
635 * --jerry
638 if (!option) {
639 return False;
642 if (p->notify.flags)
643 return is_monitoring_event_flags(
644 p->notify.flags, notify_type, notify_field);
646 for (i = 0; i < option->count; i++) {
648 /* Check match for notify_type */
650 if (option->ctr.type[i].type != notify_type)
651 continue;
653 /* Check match for field */
655 for (j = 0; j < option->ctr.type[i].count; j++) {
656 if (option->ctr.type[i].fields[j] == notify_field) {
657 return True;
662 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
663 p->servername, p->sharename, notify_type, notify_field));
665 return False;
668 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
670 static void notify_one_value(struct spoolss_notify_msg *msg,
671 SPOOL_NOTIFY_INFO_DATA *data,
672 TALLOC_CTX *mem_ctx)
674 data->notify_data.value[0] = msg->notify.value[0];
675 data->notify_data.value[1] = 0;
678 static void notify_string(struct spoolss_notify_msg *msg,
679 SPOOL_NOTIFY_INFO_DATA *data,
680 TALLOC_CTX *mem_ctx)
682 UNISTR2 unistr;
684 /* The length of the message includes the trailing \0 */
686 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
688 data->notify_data.data.length = msg->len * 2;
689 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
691 if (!data->notify_data.data.string) {
692 data->notify_data.data.length = 0;
693 return;
696 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
699 static void notify_system_time(struct spoolss_notify_msg *msg,
700 SPOOL_NOTIFY_INFO_DATA *data,
701 TALLOC_CTX *mem_ctx)
703 SYSTEMTIME systime;
704 prs_struct ps;
706 if (msg->len != sizeof(time_t)) {
707 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
708 msg->len));
709 return;
712 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
713 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
714 return;
717 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
718 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
719 prs_mem_free(&ps);
720 return;
723 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
724 prs_mem_free(&ps);
725 return;
728 data->notify_data.data.length = prs_offset(&ps);
729 if (prs_offset(&ps)) {
730 data->notify_data.data.string = (uint16 *)
731 TALLOC(mem_ctx, prs_offset(&ps));
732 if (!data->notify_data.data.string) {
733 prs_mem_free(&ps);
734 return;
736 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
737 } else {
738 data->notify_data.data.string = NULL;
741 prs_mem_free(&ps);
744 struct notify2_message_table {
745 const char *name;
746 void (*fn)(struct spoolss_notify_msg *msg,
747 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
750 static struct notify2_message_table printer_notify_table[] = {
751 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
752 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
753 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
754 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
755 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
756 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
757 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
758 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
759 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
760 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
761 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
762 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
763 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
764 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
765 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
766 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
767 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
768 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
769 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
772 static struct notify2_message_table job_notify_table[] = {
773 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
774 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
775 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
776 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
777 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
778 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
779 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
780 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
781 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
782 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
783 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
784 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
785 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
786 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
787 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
788 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
789 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
790 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
791 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
792 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
793 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
794 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
795 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
796 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
800 /***********************************************************************
801 Allocate talloc context for container object
802 **********************************************************************/
804 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
806 if ( !ctr )
807 return;
809 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
811 return;
814 /***********************************************************************
815 release all allocated memory and zero out structure
816 **********************************************************************/
818 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
820 if ( !ctr )
821 return;
823 if ( ctr->ctx )
824 talloc_destroy(ctr->ctx);
826 ZERO_STRUCTP(ctr);
828 return;
831 /***********************************************************************
832 **********************************************************************/
834 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
836 if ( !ctr )
837 return NULL;
839 return ctr->ctx;
842 /***********************************************************************
843 **********************************************************************/
845 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
847 if ( !ctr || !ctr->msg_groups )
848 return NULL;
850 if ( idx >= ctr->num_groups )
851 return NULL;
853 return &ctr->msg_groups[idx];
857 /***********************************************************************
858 How many groups of change messages do we have ?
859 **********************************************************************/
861 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
863 if ( !ctr )
864 return 0;
866 return ctr->num_groups;
869 /***********************************************************************
870 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
871 **********************************************************************/
873 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
875 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
876 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
877 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
878 int i, new_slot;
880 if ( !ctr || !msg )
881 return 0;
883 /* loop over all groups looking for a matching printer name */
885 for ( i=0; i<ctr->num_groups; i++ ) {
886 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
887 break;
890 /* add a new group? */
892 if ( i == ctr->num_groups ) {
893 ctr->num_groups++;
895 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
896 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
897 return 0;
899 ctr->msg_groups = groups;
901 /* clear the new entry and set the printer name */
903 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
904 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
907 /* add the change messages; 'i' is the correct index now regardless */
909 msg_grp = &ctr->msg_groups[i];
911 msg_grp->num_msgs++;
913 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
914 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
915 return 0;
917 msg_grp->msgs = msg_list;
919 new_slot = msg_grp->num_msgs-1;
920 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
922 /* need to allocate own copy of data */
924 if ( msg->len != 0 )
925 msg_grp->msgs[new_slot].notify.data = (char *)
926 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
928 return ctr->num_groups;
931 /***********************************************************************
932 Send a change notication message on all handles which have a call
933 back registered
934 **********************************************************************/
936 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
938 Printer_entry *p;
939 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
940 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
941 SPOOLSS_NOTIFY_MSG *messages;
942 int sending_msg_count;
944 if ( !msg_group ) {
945 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
946 return;
949 messages = msg_group->msgs;
951 if ( !messages ) {
952 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
953 return;
956 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
958 /* loop over all printers */
960 for (p = printers_list; p; p = p->next) {
961 SPOOL_NOTIFY_INFO_DATA *data;
962 uint32 data_len = 0;
963 uint32 id;
964 int i;
966 /* Is there notification on this handle? */
968 if ( !p->notify.client_connected )
969 continue;
971 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
973 /* For this printer? Print servers always receive
974 notifications. */
976 if ( ( p->printer_type == SPLHND_PRINTER ) &&
977 ( !strequal(msg_group->printername, p->sharename) ) )
978 continue;
980 DEBUG(10,("Our printer\n"));
982 /* allocate the max entries possible */
984 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
985 if (!data) {
986 return;
989 ZERO_STRUCTP(data);
991 /* build the array of change notifications */
993 sending_msg_count = 0;
995 for ( i=0; i<msg_group->num_msgs; i++ ) {
996 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
998 /* Are we monitoring this event? */
1000 if (!is_monitoring_event(p, msg->type, msg->field))
1001 continue;
1003 sending_msg_count++;
1006 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1007 msg->type, msg->field, p->sharename));
1010 * if the is a printer notification handle and not a job notification
1011 * type, then set the id to 0. Other wise just use what was specified
1012 * in the message.
1014 * When registering change notification on a print server handle
1015 * we always need to send back the id (snum) matching the printer
1016 * for which the change took place. For change notify registered
1017 * on a printer handle, this does not matter and the id should be 0.
1019 * --jerry
1022 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1023 id = 0;
1024 else
1025 id = msg->id;
1028 /* Convert unix jobid to smb jobid */
1030 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1031 id = sysjob_to_jobid(msg->id);
1033 if (id == -1) {
1034 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1035 goto done;
1039 construct_info_data( &data[data_len], msg->type, msg->field, id );
1041 switch(msg->type) {
1042 case PRINTER_NOTIFY_TYPE:
1043 if ( printer_notify_table[msg->field].fn )
1044 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1045 break;
1047 case JOB_NOTIFY_TYPE:
1048 if ( job_notify_table[msg->field].fn )
1049 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1050 break;
1052 default:
1053 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1054 goto done;
1057 data_len++;
1060 if ( sending_msg_count ) {
1061 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1062 data_len, data, p->notify.change, 0 );
1066 done:
1067 DEBUG(8,("send_notify2_changes: Exit...\n"));
1068 return;
1071 /***********************************************************************
1072 **********************************************************************/
1074 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1077 uint32 tv_sec, tv_usec;
1078 size_t offset = 0;
1080 /* Unpack message */
1082 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1083 msg->printer);
1085 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1086 &tv_sec, &tv_usec,
1087 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1089 if (msg->len == 0)
1090 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1091 &msg->notify.value[0], &msg->notify.value[1]);
1092 else
1093 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1094 &msg->len, &msg->notify.data);
1096 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1097 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1099 tv->tv_sec = tv_sec;
1100 tv->tv_usec = tv_usec;
1102 if (msg->len == 0)
1103 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1104 msg->notify.value[1]));
1105 else
1106 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1108 return True;
1111 /********************************************************************
1112 Receive a notify2 message list
1113 ********************************************************************/
1115 static void receive_notify2_message_list(struct messaging_context *msg,
1116 void *private_data,
1117 uint32_t msg_type,
1118 struct server_id server_id,
1119 DATA_BLOB *data)
1121 size_t msg_count, i;
1122 char *buf = (char *)data->data;
1123 char *msg_ptr;
1124 size_t msg_len;
1125 SPOOLSS_NOTIFY_MSG notify;
1126 SPOOLSS_NOTIFY_MSG_CTR messages;
1127 int num_groups;
1129 if (data->length < 4) {
1130 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1131 return;
1134 msg_count = IVAL(buf, 0);
1135 msg_ptr = buf + 4;
1137 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1139 if (msg_count == 0) {
1140 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1141 return;
1144 /* initialize the container */
1146 ZERO_STRUCT( messages );
1147 notify_msg_ctr_init( &messages );
1150 * build message groups for each printer identified
1151 * in a change_notify msg. Remember that a PCN message
1152 * includes the handle returned for the srv_spoolss_replyopenprinter()
1153 * call. Therefore messages are grouped according to printer handle.
1156 for ( i=0; i<msg_count; i++ ) {
1157 struct timeval msg_tv;
1159 if (msg_ptr + 4 - buf > data->length) {
1160 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1161 return;
1164 msg_len = IVAL(msg_ptr,0);
1165 msg_ptr += 4;
1167 if (msg_ptr + msg_len - buf > data->length) {
1168 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1169 return;
1172 /* unpack messages */
1174 ZERO_STRUCT( notify );
1175 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1176 msg_ptr += msg_len;
1178 /* add to correct list in container */
1180 notify_msg_ctr_addmsg( &messages, &notify );
1182 /* free memory that might have been allocated by notify2_unpack_msg() */
1184 if ( notify.len != 0 )
1185 SAFE_FREE( notify.notify.data );
1188 /* process each group of messages */
1190 num_groups = notify_msg_ctr_numgroups( &messages );
1191 for ( i=0; i<num_groups; i++ )
1192 send_notify2_changes( &messages, i );
1195 /* cleanup */
1197 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1199 notify_msg_ctr_destroy( &messages );
1201 return;
1204 /********************************************************************
1205 Send a message to ourself about new driver being installed
1206 so we can upgrade the information for each printer bound to this
1207 driver
1208 ********************************************************************/
1210 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1212 int len = strlen(drivername);
1214 if (!len)
1215 return False;
1217 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1218 drivername));
1220 messaging_send_buf(smbd_messaging_context(), procid_self(),
1221 MSG_PRINTER_DRVUPGRADE,
1222 (uint8 *)drivername, len+1);
1224 return True;
1227 /**********************************************************************
1228 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1229 over all printers, upgrading ones as necessary
1230 **********************************************************************/
1232 void do_drv_upgrade_printer(struct messaging_context *msg,
1233 void *private_data,
1234 uint32_t msg_type,
1235 struct server_id server_id,
1236 DATA_BLOB *data)
1238 fstring drivername;
1239 int snum;
1240 int n_services = lp_numservices();
1241 size_t len;
1243 len = MIN(data->length,sizeof(drivername)-1);
1244 strncpy(drivername, (const char *)data->data, len);
1246 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1248 /* Iterate the printer list */
1250 for (snum=0; snum<n_services; snum++)
1252 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1254 WERROR result;
1255 NT_PRINTER_INFO_LEVEL *printer = NULL;
1257 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1258 if (!W_ERROR_IS_OK(result))
1259 continue;
1261 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1263 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1265 /* all we care about currently is the change_id */
1267 result = mod_a_printer(printer, 2);
1268 if (!W_ERROR_IS_OK(result)) {
1269 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1270 dos_errstr(result)));
1274 free_a_printer(&printer, 2);
1278 /* all done */
1281 /********************************************************************
1282 Update the cache for all printq's with a registered client
1283 connection
1284 ********************************************************************/
1286 void update_monitored_printq_cache( void )
1288 Printer_entry *printer = printers_list;
1289 int snum;
1291 /* loop through all printers and update the cache where
1292 client_connected == True */
1293 while ( printer )
1295 if ( (printer->printer_type == SPLHND_PRINTER)
1296 && printer->notify.client_connected )
1298 snum = print_queue_snum(printer->sharename);
1299 print_queue_status( snum, NULL, NULL );
1302 printer = printer->next;
1305 return;
1307 /********************************************************************
1308 Send a message to ourself about new driver being installed
1309 so we can upgrade the information for each printer bound to this
1310 driver
1311 ********************************************************************/
1313 static bool srv_spoolss_reset_printerdata(char* drivername)
1315 int len = strlen(drivername);
1317 if (!len)
1318 return False;
1320 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1321 drivername));
1323 messaging_send_buf(smbd_messaging_context(), procid_self(),
1324 MSG_PRINTERDATA_INIT_RESET,
1325 (uint8 *)drivername, len+1);
1327 return True;
1330 /**********************************************************************
1331 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1332 over all printers, resetting printer data as neessary
1333 **********************************************************************/
1335 void reset_all_printerdata(struct messaging_context *msg,
1336 void *private_data,
1337 uint32_t msg_type,
1338 struct server_id server_id,
1339 DATA_BLOB *data)
1341 fstring drivername;
1342 int snum;
1343 int n_services = lp_numservices();
1344 size_t len;
1346 len = MIN( data->length, sizeof(drivername)-1 );
1347 strncpy( drivername, (const char *)data->data, len );
1349 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1351 /* Iterate the printer list */
1353 for ( snum=0; snum<n_services; snum++ )
1355 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1357 WERROR result;
1358 NT_PRINTER_INFO_LEVEL *printer = NULL;
1360 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1361 if ( !W_ERROR_IS_OK(result) )
1362 continue;
1365 * if the printer is bound to the driver,
1366 * then reset to the new driver initdata
1369 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1371 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1373 if ( !set_driver_init(printer, 2) ) {
1374 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1375 printer->info_2->printername, printer->info_2->drivername));
1378 result = mod_a_printer( printer, 2 );
1379 if ( !W_ERROR_IS_OK(result) ) {
1380 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1381 get_dos_error_msg(result)));
1385 free_a_printer( &printer, 2 );
1389 /* all done */
1391 return;
1394 /********************************************************************
1395 Copy routines used by convert_to_openprinterex()
1396 *******************************************************************/
1398 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1400 DEVICEMODE *d;
1401 int len;
1403 if (!devmode)
1404 return NULL;
1406 DEBUG (8,("dup_devmode\n"));
1408 /* bulk copy first */
1410 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1411 if (!d)
1412 return NULL;
1414 /* dup the pointer members separately */
1416 len = unistrlen(devmode->devicename.buffer);
1417 if (len != -1) {
1418 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1419 if (!d->devicename.buffer) {
1420 return NULL;
1422 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1423 return NULL;
1427 len = unistrlen(devmode->formname.buffer);
1428 if (len != -1) {
1429 d->formname.buffer = TALLOC_ARRAY(ctx, uint16, len);
1430 if (!d->formname.buffer) {
1431 return NULL;
1433 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1434 return NULL;
1437 if (devmode->driverextra) {
1438 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1439 devmode->driverextra);
1440 if (!d->dev_private) {
1441 return NULL;
1443 } else {
1444 d->dev_private = NULL;
1446 return d;
1449 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1451 if (!new_ctr || !ctr)
1452 return;
1454 DEBUG(8,("copy_devmode_ctr\n"));
1456 new_ctr->size = ctr->size;
1457 new_ctr->devmode_ptr = ctr->devmode_ptr;
1459 if(ctr->devmode_ptr)
1460 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1463 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1465 if (!new_def || !def)
1466 return;
1468 DEBUG(8,("copy_printer_defaults\n"));
1470 new_def->datatype_ptr = def->datatype_ptr;
1472 if (def->datatype_ptr)
1473 copy_unistr2(&new_def->datatype, &def->datatype);
1475 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1477 new_def->access_required = def->access_required;
1480 /********************************************************************
1481 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1482 * SPOOL_Q_OPEN_PRINTER_EX structure
1483 ********************************************************************/
1485 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1487 if (!q_u_ex || !q_u)
1488 return WERR_OK;
1490 DEBUG(8,("convert_to_openprinterex\n"));
1492 if ( q_u->printername ) {
1493 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1494 if (q_u_ex->printername == NULL)
1495 return WERR_NOMEM;
1496 copy_unistr2(q_u_ex->printername, q_u->printername);
1499 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1501 return WERR_OK;
1504 /********************************************************************
1505 * spoolss_open_printer
1507 * called from the spoolss dispatcher
1508 ********************************************************************/
1510 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1512 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1513 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1515 if (!q_u || !r_u)
1516 return WERR_NOMEM;
1518 ZERO_STRUCT(q_u_ex);
1519 ZERO_STRUCT(r_u_ex);
1521 /* convert the OpenPrinter() call to OpenPrinterEx() */
1523 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1524 if (!W_ERROR_IS_OK(r_u_ex.status))
1525 return r_u_ex.status;
1527 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1529 /* convert back to OpenPrinter() */
1531 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1533 if (W_ERROR_EQUAL(r_u->status, WERR_INVALID_PARAM)) {
1534 /* OpenPrinterEx returns this for a bad
1535 * printer name. We must return WERR_INVALID_PRINTER_NAME
1536 * instead.
1538 r_u->status = WERR_INVALID_PRINTER_NAME;
1540 return r_u->status;
1543 /********************************************************************
1544 ********************************************************************/
1546 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1548 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1549 POLICY_HND *handle = &r_u->handle;
1551 fstring name;
1552 int snum;
1553 Printer_entry *Printer=NULL;
1555 if (!q_u->printername) {
1556 return WERR_INVALID_PARAM;
1559 /* some sanity check because you can open a printer or a print server */
1560 /* aka: \\server\printer or \\server */
1562 unistr2_to_ascii(name, q_u->printername, sizeof(name));
1564 DEBUGADD(3,("checking name: %s\n",name));
1566 if (!open_printer_hnd(p, handle, name, 0)) {
1567 return WERR_INVALID_PARAM;
1570 Printer=find_printer_index_by_hnd(p, handle);
1571 if ( !Printer ) {
1572 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1573 "handle we created for printer %s\n", name ));
1574 close_printer_handle(p,handle);
1575 return WERR_INVALID_PARAM;
1579 * First case: the user is opening the print server:
1581 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1582 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1584 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1585 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1586 * or if the user is listed in the smb.conf printer admin parameter.
1588 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1589 * client view printer folder, but does not show the MSAPW.
1591 * Note: this test needs code to check access rights here too. Jeremy
1592 * could you look at this?
1594 * Second case: the user is opening a printer:
1595 * NT doesn't let us connect to a printer if the connecting user
1596 * doesn't have print permission.
1598 * Third case: user is opening a Port Monitor
1599 * access checks same as opening a handle to the print server.
1602 switch (Printer->printer_type )
1604 case SPLHND_SERVER:
1605 case SPLHND_PORTMON_TCP:
1606 case SPLHND_PORTMON_LOCAL:
1607 /* Printserver handles use global struct... */
1609 snum = -1;
1611 /* Map standard access rights to object specific access rights */
1613 se_map_standard(&printer_default->access_required,
1614 &printserver_std_mapping);
1616 /* Deny any object specific bits that don't apply to print
1617 servers (i.e printer and job specific bits) */
1619 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1621 if (printer_default->access_required &
1622 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1623 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1624 close_printer_handle(p, handle);
1625 return WERR_ACCESS_DENIED;
1628 /* Allow admin access */
1630 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1632 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1634 if (!lp_ms_add_printer_wizard()) {
1635 close_printer_handle(p, handle);
1636 return WERR_ACCESS_DENIED;
1639 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1640 and not a printer admin, then fail */
1642 if ((p->pipe_user.ut.uid != 0) &&
1643 !user_has_privileges(p->pipe_user.nt_user_token,
1644 &se_printop ) &&
1645 !token_contains_name_in_list(
1646 uidtoname(p->pipe_user.ut.uid), NULL,
1647 p->pipe_user.nt_user_token,
1648 lp_printer_admin(snum))) {
1649 close_printer_handle(p, handle);
1650 return WERR_ACCESS_DENIED;
1653 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1655 else
1657 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1660 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1661 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1663 /* We fall through to return WERR_OK */
1664 break;
1666 case SPLHND_PRINTER:
1667 /* NT doesn't let us connect to a printer if the connecting user
1668 doesn't have print permission. */
1670 if (!get_printer_snum(p, handle, &snum, NULL)) {
1671 close_printer_handle(p, handle);
1672 return WERR_BADFID;
1675 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1677 /* map an empty access mask to the minimum access mask */
1678 if (printer_default->access_required == 0x0)
1679 printer_default->access_required = PRINTER_ACCESS_USE;
1682 * If we are not serving the printer driver for this printer,
1683 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1684 * will keep NT clients happy --jerry
1687 if (lp_use_client_driver(snum)
1688 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1690 printer_default->access_required = PRINTER_ACCESS_USE;
1693 /* check smb.conf parameters and the the sec_desc */
1695 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1696 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1697 return WERR_ACCESS_DENIED;
1700 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1701 p->pipe_user.nt_user_token, snum) ||
1702 !print_access_check(&p->pipe_user, snum,
1703 printer_default->access_required)) {
1704 DEBUG(3, ("access DENIED for printer open\n"));
1705 close_printer_handle(p, handle);
1706 return WERR_ACCESS_DENIED;
1709 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1710 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1711 close_printer_handle(p, handle);
1712 return WERR_ACCESS_DENIED;
1715 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1716 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1717 else
1718 printer_default->access_required = PRINTER_ACCESS_USE;
1720 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1721 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1723 break;
1725 default:
1726 /* sanity check to prevent programmer error */
1727 return WERR_BADFID;
1730 Printer->access_granted = printer_default->access_required;
1733 * If the client sent a devmode in the OpenPrinter() call, then
1734 * save it here in case we get a job submission on this handle
1737 if ( (Printer->printer_type != SPLHND_SERVER)
1738 && q_u->printer_default.devmode_cont.devmode_ptr )
1740 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1741 &Printer->nt_devmode );
1744 #if 0 /* JERRY -- I'm doubtful this is really effective */
1745 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1746 optimization in Windows 2000 clients --jerry */
1748 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1749 && (RA_WIN2K == get_remote_arch()) )
1751 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1752 sys_usleep( 500000 );
1754 #endif
1756 return WERR_OK;
1759 /****************************************************************************
1760 ****************************************************************************/
1762 static bool convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1763 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1765 bool ret;
1767 switch (level) {
1768 case 2:
1769 /* allocate memory if needed. Messy because
1770 convert_printer_info is used to update an existing
1771 printer or build a new one */
1773 if ( !printer->info_2 ) {
1774 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1775 if ( !printer->info_2 ) {
1776 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1777 return False;
1781 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1782 printer->info_2->setuptime = time(NULL);
1784 return ret;
1787 return False;
1790 static bool convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1791 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1793 bool result = True;
1795 switch (level) {
1796 case 3:
1797 printer->info_3=NULL;
1798 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1799 result = False;
1800 break;
1801 case 6:
1802 printer->info_6=NULL;
1803 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1804 result = False;
1805 break;
1806 default:
1807 break;
1810 return result;
1813 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1814 NT_DEVICEMODE **pp_nt_devmode)
1816 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1819 * Ensure nt_devmode is a valid pointer
1820 * as we will be overwriting it.
1823 if (nt_devmode == NULL) {
1824 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1825 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1826 return False;
1829 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1830 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1832 nt_devmode->specversion=devmode->specversion;
1833 nt_devmode->driverversion=devmode->driverversion;
1834 nt_devmode->size=devmode->size;
1835 nt_devmode->fields=devmode->fields;
1836 nt_devmode->orientation=devmode->orientation;
1837 nt_devmode->papersize=devmode->papersize;
1838 nt_devmode->paperlength=devmode->paperlength;
1839 nt_devmode->paperwidth=devmode->paperwidth;
1840 nt_devmode->scale=devmode->scale;
1841 nt_devmode->copies=devmode->copies;
1842 nt_devmode->defaultsource=devmode->defaultsource;
1843 nt_devmode->printquality=devmode->printquality;
1844 nt_devmode->color=devmode->color;
1845 nt_devmode->duplex=devmode->duplex;
1846 nt_devmode->yresolution=devmode->yresolution;
1847 nt_devmode->ttoption=devmode->ttoption;
1848 nt_devmode->collate=devmode->collate;
1850 nt_devmode->logpixels=devmode->logpixels;
1851 nt_devmode->bitsperpel=devmode->bitsperpel;
1852 nt_devmode->pelswidth=devmode->pelswidth;
1853 nt_devmode->pelsheight=devmode->pelsheight;
1854 nt_devmode->displayflags=devmode->displayflags;
1855 nt_devmode->displayfrequency=devmode->displayfrequency;
1856 nt_devmode->icmmethod=devmode->icmmethod;
1857 nt_devmode->icmintent=devmode->icmintent;
1858 nt_devmode->mediatype=devmode->mediatype;
1859 nt_devmode->dithertype=devmode->dithertype;
1860 nt_devmode->reserved1=devmode->reserved1;
1861 nt_devmode->reserved2=devmode->reserved2;
1862 nt_devmode->panningwidth=devmode->panningwidth;
1863 nt_devmode->panningheight=devmode->panningheight;
1866 * Only change private and driverextra if the incoming devmode
1867 * has a new one. JRA.
1870 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1871 SAFE_FREE(nt_devmode->nt_dev_private);
1872 nt_devmode->driverextra=devmode->driverextra;
1873 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1874 return False;
1875 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1878 *pp_nt_devmode = nt_devmode;
1880 return True;
1883 /********************************************************************
1884 * _spoolss_enddocprinter_internal.
1885 ********************************************************************/
1887 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1889 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1890 int snum;
1892 if (!Printer) {
1893 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1894 return WERR_BADFID;
1897 if (!get_printer_snum(p, handle, &snum, NULL))
1898 return WERR_BADFID;
1900 Printer->document_started=False;
1901 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1902 /* error codes unhandled so far ... */
1904 return WERR_OK;
1907 /********************************************************************
1908 * api_spoolss_closeprinter
1909 ********************************************************************/
1911 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1913 POLICY_HND *handle = &q_u->handle;
1915 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1917 if (Printer && Printer->document_started)
1918 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1920 if (!close_printer_handle(p, handle))
1921 return WERR_BADFID;
1923 /* clear the returned printer handle. Observed behavior
1924 from Win2k server. Don't think this really matters.
1925 Previous code just copied the value of the closed
1926 handle. --jerry */
1928 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1930 return WERR_OK;
1933 /********************************************************************
1934 * api_spoolss_deleteprinter
1936 ********************************************************************/
1938 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1940 POLICY_HND *handle = &q_u->handle;
1941 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1942 WERROR result;
1944 if (Printer && Printer->document_started)
1945 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1947 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1949 result = delete_printer_handle(p, handle);
1951 update_c_setprinter(False);
1953 return result;
1956 /*******************************************************************
1957 * static function to lookup the version id corresponding to an
1958 * long architecture string
1959 ******************************************************************/
1961 static int get_version_id (char * arch)
1963 int i;
1964 struct table_node archi_table[]= {
1966 {"Windows 4.0", "WIN40", 0 },
1967 {"Windows NT x86", "W32X86", 2 },
1968 {"Windows NT R4000", "W32MIPS", 2 },
1969 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1970 {"Windows NT PowerPC", "W32PPC", 2 },
1971 {"Windows IA64", "IA64", 3 },
1972 {"Windows x64", "x64", 3 },
1973 {NULL, "", -1 }
1976 for (i=0; archi_table[i].long_archi != NULL; i++)
1978 if (strcmp(arch, archi_table[i].long_archi) == 0)
1979 return (archi_table[i].version);
1982 return -1;
1985 /********************************************************************
1986 * _spoolss_deleteprinterdriver
1987 ********************************************************************/
1989 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1991 fstring driver;
1992 fstring arch;
1993 NT_PRINTER_DRIVER_INFO_LEVEL info;
1994 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1995 int version;
1996 WERROR status;
1997 WERROR status_win2k = WERR_ACCESS_DENIED;
1998 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2000 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2001 and not a printer admin, then fail */
2003 if ( (p->pipe_user.ut.uid != 0)
2004 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2005 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2006 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2008 return WERR_ACCESS_DENIED;
2011 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2012 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2014 /* check that we have a valid driver name first */
2016 if ((version=get_version_id(arch)) == -1)
2017 return WERR_INVALID_ENVIRONMENT;
2019 ZERO_STRUCT(info);
2020 ZERO_STRUCT(info_win2k);
2022 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2024 /* try for Win2k driver if "Windows NT x86" */
2026 if ( version == 2 ) {
2027 version = 3;
2028 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2029 status = WERR_UNKNOWN_PRINTER_DRIVER;
2030 goto done;
2033 /* otherwise it was a failure */
2034 else {
2035 status = WERR_UNKNOWN_PRINTER_DRIVER;
2036 goto done;
2041 if (printer_driver_in_use(info.info_3)) {
2042 status = WERR_PRINTER_DRIVER_IN_USE;
2043 goto done;
2046 if ( version == 2 )
2048 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2050 /* if we get to here, we now have 2 driver info structures to remove */
2051 /* remove the Win2k driver first*/
2053 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2054 free_a_printer_driver( info_win2k, 3 );
2056 /* this should not have failed---if it did, report to client */
2057 if ( !W_ERROR_IS_OK(status_win2k) )
2059 status = status_win2k;
2060 goto done;
2065 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2067 /* if at least one of the deletes succeeded return OK */
2069 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2070 status = WERR_OK;
2072 done:
2073 free_a_printer_driver( info, 3 );
2075 return status;
2078 /********************************************************************
2079 * spoolss_deleteprinterdriverex
2080 ********************************************************************/
2082 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2084 fstring driver;
2085 fstring arch;
2086 NT_PRINTER_DRIVER_INFO_LEVEL info;
2087 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2088 int version;
2089 uint32 flags = q_u->delete_flags;
2090 bool delete_files;
2091 WERROR status;
2092 WERROR status_win2k = WERR_ACCESS_DENIED;
2093 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2095 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2096 and not a printer admin, then fail */
2098 if ( (p->pipe_user.ut.uid != 0)
2099 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2100 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2101 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2103 return WERR_ACCESS_DENIED;
2106 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2107 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2109 /* check that we have a valid driver name first */
2110 if ((version=get_version_id(arch)) == -1) {
2111 /* this is what NT returns */
2112 return WERR_INVALID_ENVIRONMENT;
2115 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2116 version = q_u->version;
2118 ZERO_STRUCT(info);
2119 ZERO_STRUCT(info_win2k);
2121 status = get_a_printer_driver(&info, 3, driver, arch, version);
2123 if ( !W_ERROR_IS_OK(status) )
2126 * if the client asked for a specific version,
2127 * or this is something other than Windows NT x86,
2128 * then we've failed
2131 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2132 goto done;
2134 /* try for Win2k driver if "Windows NT x86" */
2136 version = 3;
2137 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2138 status = WERR_UNKNOWN_PRINTER_DRIVER;
2139 goto done;
2143 if ( printer_driver_in_use(info.info_3) ) {
2144 status = WERR_PRINTER_DRIVER_IN_USE;
2145 goto done;
2149 * we have a couple of cases to consider.
2150 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2151 * then the delete should fail if **any** files overlap with
2152 * other drivers
2153 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2154 * non-overlapping files
2155 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2156 * is set, the do not delete any files
2157 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2160 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2162 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2164 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2165 /* no idea of the correct error here */
2166 status = WERR_ACCESS_DENIED;
2167 goto done;
2171 /* also check for W32X86/3 if necessary; maybe we already have? */
2173 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2174 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2177 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2178 /* no idea of the correct error here */
2179 free_a_printer_driver( info_win2k, 3 );
2180 status = WERR_ACCESS_DENIED;
2181 goto done;
2184 /* if we get to here, we now have 2 driver info structures to remove */
2185 /* remove the Win2k driver first*/
2187 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2188 free_a_printer_driver( info_win2k, 3 );
2190 /* this should not have failed---if it did, report to client */
2192 if ( !W_ERROR_IS_OK(status_win2k) )
2193 goto done;
2197 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2199 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2200 status = WERR_OK;
2201 done:
2202 free_a_printer_driver( info, 3 );
2204 return status;
2208 /****************************************************************************
2209 Internal routine for retreiving printerdata
2210 ***************************************************************************/
2212 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2213 const char *key, const char *value, uint32 *type, uint8 **data,
2214 uint32 *needed, uint32 in_size )
2216 REGISTRY_VALUE *val;
2217 uint32 size;
2218 int data_len;
2220 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2221 return WERR_BADFILE;
2223 *type = regval_type( val );
2225 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2227 size = regval_size( val );
2229 /* copy the min(in_size, len) */
2231 if ( in_size ) {
2232 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2234 /* special case for 0 length values */
2235 if ( data_len ) {
2236 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2237 return WERR_NOMEM;
2239 else {
2240 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2241 return WERR_NOMEM;
2244 else
2245 *data = NULL;
2247 *needed = size;
2249 DEBUG(5,("get_printer_dataex: copy done\n"));
2251 return WERR_OK;
2254 /****************************************************************************
2255 Internal routine for removing printerdata
2256 ***************************************************************************/
2258 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2260 return delete_printer_data( printer->info_2, key, value );
2263 /****************************************************************************
2264 Internal routine for storing printerdata
2265 ***************************************************************************/
2267 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2268 uint32 type, uint8 *data, int real_len )
2270 /* the registry objects enforce uniqueness based on value name */
2272 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2275 /********************************************************************
2276 GetPrinterData on a printer server Handle.
2277 ********************************************************************/
2279 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2281 int i;
2283 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2285 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2286 *type = REG_DWORD;
2287 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2288 return WERR_NOMEM;
2289 SIVAL(*data, 0, 0x00);
2290 *needed = 0x4;
2291 return WERR_OK;
2294 if (!StrCaseCmp(value, "BeepEnabled")) {
2295 *type = REG_DWORD;
2296 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2297 return WERR_NOMEM;
2298 SIVAL(*data, 0, 0x00);
2299 *needed = 0x4;
2300 return WERR_OK;
2303 if (!StrCaseCmp(value, "EventLog")) {
2304 *type = REG_DWORD;
2305 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2306 return WERR_NOMEM;
2307 /* formally was 0x1b */
2308 SIVAL(*data, 0, 0x0);
2309 *needed = 0x4;
2310 return WERR_OK;
2313 if (!StrCaseCmp(value, "NetPopup")) {
2314 *type = REG_DWORD;
2315 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2316 return WERR_NOMEM;
2317 SIVAL(*data, 0, 0x00);
2318 *needed = 0x4;
2319 return WERR_OK;
2322 if (!StrCaseCmp(value, "MajorVersion")) {
2323 *type = REG_DWORD;
2324 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2325 return WERR_NOMEM;
2327 /* Windows NT 4.0 seems to not allow uploading of drivers
2328 to a server that reports 0x3 as the MajorVersion.
2329 need to investigate more how Win2k gets around this .
2330 -- jerry */
2332 if ( RA_WINNT == get_remote_arch() )
2333 SIVAL(*data, 0, 2);
2334 else
2335 SIVAL(*data, 0, 3);
2337 *needed = 0x4;
2338 return WERR_OK;
2341 if (!StrCaseCmp(value, "MinorVersion")) {
2342 *type = REG_DWORD;
2343 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2344 return WERR_NOMEM;
2345 SIVAL(*data, 0, 0);
2346 *needed = 0x4;
2347 return WERR_OK;
2350 /* REG_BINARY
2351 * uint32 size = 0x114
2352 * uint32 major = 5
2353 * uint32 minor = [0|1]
2354 * uint32 build = [2195|2600]
2355 * extra unicode string = e.g. "Service Pack 3"
2357 if (!StrCaseCmp(value, "OSVersion")) {
2358 *type = REG_BINARY;
2359 *needed = 0x114;
2361 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2362 return WERR_NOMEM;
2364 SIVAL(*data, 0, *needed); /* size */
2365 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2366 SIVAL(*data, 8, 0);
2367 SIVAL(*data, 12, 2195); /* build */
2369 /* leave extra string empty */
2371 return WERR_OK;
2375 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2376 const char *string="C:\\PRINTERS";
2377 *type = REG_SZ;
2378 *needed = 2*(strlen(string)+1);
2379 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2380 return WERR_NOMEM;
2381 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2383 /* it's done by hand ready to go on the wire */
2384 for (i=0; i<strlen(string); i++) {
2385 (*data)[2*i]=string[i];
2386 (*data)[2*i+1]='\0';
2388 return WERR_OK;
2391 if (!StrCaseCmp(value, "Architecture")) {
2392 const char *string="Windows NT x86";
2393 *type = REG_SZ;
2394 *needed = 2*(strlen(string)+1);
2395 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2396 return WERR_NOMEM;
2397 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2398 for (i=0; i<strlen(string); i++) {
2399 (*data)[2*i]=string[i];
2400 (*data)[2*i+1]='\0';
2402 return WERR_OK;
2405 if (!StrCaseCmp(value, "DsPresent")) {
2406 *type = REG_DWORD;
2407 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2408 return WERR_NOMEM;
2410 /* only show the publish check box if we are a
2411 memeber of a AD domain */
2413 if ( lp_security() == SEC_ADS )
2414 SIVAL(*data, 0, 0x01);
2415 else
2416 SIVAL(*data, 0, 0x00);
2418 *needed = 0x4;
2419 return WERR_OK;
2422 if (!StrCaseCmp(value, "DNSMachineName")) {
2423 const char *hostname = get_mydnsfullname();
2425 if (!hostname)
2426 return WERR_BADFILE;
2427 *type = REG_SZ;
2428 *needed = 2*(strlen(hostname)+1);
2429 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2430 return WERR_NOMEM;
2431 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2432 for (i=0; i<strlen(hostname); i++) {
2433 (*data)[2*i]=hostname[i];
2434 (*data)[2*i+1]='\0';
2436 return WERR_OK;
2440 return WERR_BADFILE;
2443 /********************************************************************
2444 * spoolss_getprinterdata
2445 ********************************************************************/
2447 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2449 POLICY_HND *handle = &q_u->handle;
2450 UNISTR2 *valuename = &q_u->valuename;
2451 uint32 in_size = q_u->size;
2452 uint32 *type = &r_u->type;
2453 uint32 *out_size = &r_u->size;
2454 uint8 **data = &r_u->data;
2455 uint32 *needed = &r_u->needed;
2456 WERROR status;
2457 fstring value;
2458 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2459 NT_PRINTER_INFO_LEVEL *printer = NULL;
2460 int snum = 0;
2463 * Reminder: when it's a string, the length is in BYTES
2464 * even if UNICODE is negociated.
2466 * JFM, 4/19/1999
2469 *out_size = in_size;
2471 /* in case of problem, return some default values */
2473 *needed = 0;
2474 *type = 0;
2476 DEBUG(4,("_spoolss_getprinterdata\n"));
2478 if ( !Printer ) {
2479 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2480 status = WERR_BADFID;
2481 goto done;
2484 unistr2_to_ascii(value, valuename, sizeof(value));
2486 if ( Printer->printer_type == SPLHND_SERVER )
2487 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2488 else
2490 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2491 status = WERR_BADFID;
2492 goto done;
2495 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2496 if ( !W_ERROR_IS_OK(status) )
2497 goto done;
2499 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2501 if ( strequal(value, "ChangeId") ) {
2502 *type = REG_DWORD;
2503 *needed = sizeof(uint32);
2504 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2505 status = WERR_NOMEM;
2506 goto done;
2508 SIVAL( *data, 0, printer->info_2->changeid );
2509 status = WERR_OK;
2511 else
2512 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2515 if (*needed > *out_size)
2516 status = WERR_MORE_DATA;
2518 done:
2519 if ( !W_ERROR_IS_OK(status) )
2521 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2523 /* reply this param doesn't exist */
2525 if ( *out_size ) {
2526 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2527 if ( printer )
2528 free_a_printer( &printer, 2 );
2529 return WERR_NOMEM;
2531 } else {
2532 *data = NULL;
2536 /* cleanup & exit */
2538 if ( printer )
2539 free_a_printer( &printer, 2 );
2541 return status;
2544 /*********************************************************
2545 Connect to the client machine.
2546 **********************************************************/
2548 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2549 struct sockaddr_storage *client_ss, const char *remote_machine)
2551 NTSTATUS ret;
2552 struct cli_state *the_cli;
2553 struct sockaddr_storage rm_addr;
2555 if ( is_zero_addr(client_ss) ) {
2556 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2557 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2558 return False;
2561 if (ismyaddr(&rm_addr)) {
2562 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2563 return False;
2565 } else {
2566 char addr[INET6_ADDRSTRLEN];
2567 rm_addr = *client_ss;
2568 print_sockaddr(addr, sizeof(addr), &rm_addr);
2569 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2570 addr));
2573 /* setup the connection */
2575 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2576 &rm_addr, 0, "IPC$", "IPC",
2577 "", /* username */
2578 "", /* domain */
2579 "", /* password */
2580 0, lp_client_signing(), NULL );
2582 if ( !NT_STATUS_IS_OK( ret ) ) {
2583 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2584 remote_machine ));
2585 return False;
2588 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2589 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2590 cli_shutdown(the_cli);
2591 return False;
2595 * Ok - we have an anonymous connection to the IPC$ share.
2596 * Now start the NT Domain stuff :-).
2599 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2600 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2601 remote_machine, nt_errstr(ret)));
2602 cli_shutdown(the_cli);
2603 return False;
2606 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2608 (*pp_pipe)->cli = the_cli;
2610 return True;
2613 /***************************************************************************
2614 Connect to the client.
2615 ****************************************************************************/
2617 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2618 uint32 localprinter, uint32 type,
2619 POLICY_HND *handle, struct sockaddr_storage *client_ss)
2621 WERROR result;
2624 * If it's the first connection, contact the client
2625 * and connect to the IPC$ share anonymously
2627 if (smb_connections==0) {
2628 fstring unix_printer;
2630 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2632 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2633 return False;
2635 messaging_register(smbd_messaging_context(), NULL,
2636 MSG_PRINTER_NOTIFY2,
2637 receive_notify2_message_list);
2638 /* Tell the connections db we're now interested in printer
2639 * notify messages. */
2640 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2644 * Tell the specific printing tdb we want messages for this printer
2645 * by registering our PID.
2648 if (!print_notify_register_pid(snum))
2649 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2651 smb_connections++;
2653 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe,
2654 talloc_tos(),
2655 printer,
2656 localprinter,
2657 type,
2658 handle);
2660 if (!W_ERROR_IS_OK(result))
2661 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2662 dos_errstr(result)));
2664 return (W_ERROR_IS_OK(result));
2667 /********************************************************************
2668 * _spoolss_rffpcnex
2669 * ReplyFindFirstPrinterChangeNotifyEx
2671 * before replying OK: status=0 a rpc call is made to the workstation
2672 * asking ReplyOpenPrinter
2674 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2675 * called from api_spoolss_rffpcnex
2676 ********************************************************************/
2678 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2680 POLICY_HND *handle = &q_u->handle;
2681 uint32 flags = q_u->flags;
2682 uint32 options = q_u->options;
2683 UNISTR2 *localmachine = &q_u->localmachine;
2684 uint32 printerlocal = q_u->printerlocal;
2685 int snum = -1;
2686 SPOOL_NOTIFY_OPTION *option = q_u->option;
2687 struct sockaddr_storage client_ss;
2689 /* store the notify value in the printer struct */
2691 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2693 if (!Printer) {
2694 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2695 return WERR_BADFID;
2698 Printer->notify.flags=flags;
2699 Printer->notify.options=options;
2700 Printer->notify.printerlocal=printerlocal;
2702 if (Printer->notify.option)
2703 free_spool_notify_option(&Printer->notify.option);
2705 Printer->notify.option=dup_spool_notify_option(option);
2707 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2708 sizeof(Printer->notify.localmachine));
2710 /* Connect to the client machine and send a ReplyOpenPrinter */
2712 if ( Printer->printer_type == SPLHND_SERVER)
2713 snum = -1;
2714 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2715 !get_printer_snum(p, handle, &snum, NULL) )
2716 return WERR_BADFID;
2718 if (!interpret_string_addr(&client_ss,
2719 p->conn->client_address,
2720 AI_NUMERICHOST)) {
2721 return WERR_SERVER_UNAVAILABLE;
2724 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2725 Printer->notify.printerlocal, 1,
2726 &Printer->notify.client_hnd, &client_ss))
2727 return WERR_SERVER_UNAVAILABLE;
2729 Printer->notify.client_connected=True;
2731 return WERR_OK;
2734 /*******************************************************************
2735 * fill a notify_info_data with the servername
2736 ********************************************************************/
2738 void spoolss_notify_server_name(int snum,
2739 SPOOL_NOTIFY_INFO_DATA *data,
2740 print_queue_struct *queue,
2741 NT_PRINTER_INFO_LEVEL *printer,
2742 TALLOC_CTX *mem_ctx)
2744 smb_ucs2_t *temp = NULL;
2745 uint32 len;
2747 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
2748 if (len == (uint32)-1) {
2749 len = 0;
2752 data->notify_data.data.length = len;
2753 if (len) {
2754 data->notify_data.data.string = (uint16 *)temp;
2755 } else {
2756 data->notify_data.data.string = NULL;
2760 /*******************************************************************
2761 * fill a notify_info_data with the printername (not including the servername).
2762 ********************************************************************/
2764 void spoolss_notify_printer_name(int snum,
2765 SPOOL_NOTIFY_INFO_DATA *data,
2766 print_queue_struct *queue,
2767 NT_PRINTER_INFO_LEVEL *printer,
2768 TALLOC_CTX *mem_ctx)
2770 smb_ucs2_t *temp = NULL;
2771 uint32 len;
2773 /* the notify name should not contain the \\server\ part */
2774 char *p = strrchr(printer->info_2->printername, '\\');
2776 if (!p) {
2777 p = printer->info_2->printername;
2778 } else {
2779 p++;
2782 len = rpcstr_push_talloc(mem_ctx, &temp, p);
2783 if (len == (uint32)-1) {
2784 len = 0;
2787 data->notify_data.data.length = len;
2788 if (len) {
2789 data->notify_data.data.string = (uint16 *)temp;
2790 } else {
2791 data->notify_data.data.string = NULL;
2795 /*******************************************************************
2796 * fill a notify_info_data with the servicename
2797 ********************************************************************/
2799 void spoolss_notify_share_name(int snum,
2800 SPOOL_NOTIFY_INFO_DATA *data,
2801 print_queue_struct *queue,
2802 NT_PRINTER_INFO_LEVEL *printer,
2803 TALLOC_CTX *mem_ctx)
2805 smb_ucs2_t *temp = NULL;
2806 uint32 len;
2808 len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
2809 if (len == (uint32)-1) {
2810 len = 0;
2813 data->notify_data.data.length = len;
2814 if (len) {
2815 data->notify_data.data.string = (uint16 *)temp;
2816 } else {
2817 data->notify_data.data.string = NULL;
2822 /*******************************************************************
2823 * fill a notify_info_data with the port name
2824 ********************************************************************/
2826 void spoolss_notify_port_name(int snum,
2827 SPOOL_NOTIFY_INFO_DATA *data,
2828 print_queue_struct *queue,
2829 NT_PRINTER_INFO_LEVEL *printer,
2830 TALLOC_CTX *mem_ctx)
2832 smb_ucs2_t *temp = NULL;
2833 uint32 len;
2835 /* even if it's strange, that's consistant in all the code */
2837 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
2838 if (len == (uint32)-1) {
2839 len = 0;
2842 data->notify_data.data.length = len;
2843 if (len) {
2844 data->notify_data.data.string = (uint16 *)temp;
2845 } else {
2846 data->notify_data.data.string = NULL;
2850 /*******************************************************************
2851 * fill a notify_info_data with the printername
2852 * but it doesn't exist, have to see what to do
2853 ********************************************************************/
2855 void spoolss_notify_driver_name(int snum,
2856 SPOOL_NOTIFY_INFO_DATA *data,
2857 print_queue_struct *queue,
2858 NT_PRINTER_INFO_LEVEL *printer,
2859 TALLOC_CTX *mem_ctx)
2861 smb_ucs2_t *temp = NULL;
2862 uint32 len;
2864 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
2865 if (len == (uint32)-1) {
2866 len = 0;
2869 data->notify_data.data.length = len;
2870 if (len) {
2871 data->notify_data.data.string = (uint16 *)temp;
2872 } else {
2873 data->notify_data.data.string = NULL;
2877 /*******************************************************************
2878 * fill a notify_info_data with the comment
2879 ********************************************************************/
2881 void spoolss_notify_comment(int snum,
2882 SPOOL_NOTIFY_INFO_DATA *data,
2883 print_queue_struct *queue,
2884 NT_PRINTER_INFO_LEVEL *printer,
2885 TALLOC_CTX *mem_ctx)
2887 smb_ucs2_t *temp = NULL;
2888 uint32 len;
2890 if (*printer->info_2->comment == '\0')
2891 len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
2892 else
2893 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
2895 if (len == (uint32)-1) {
2896 len = 0;
2898 data->notify_data.data.length = len;
2899 if (len) {
2900 data->notify_data.data.string = (uint16 *)temp;
2901 } else {
2902 data->notify_data.data.string = NULL;
2906 /*******************************************************************
2907 * fill a notify_info_data with the comment
2908 * location = "Room 1, floor 2, building 3"
2909 ********************************************************************/
2911 void spoolss_notify_location(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 smb_ucs2_t *temp = NULL;
2918 uint32 len;
2920 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
2921 if (len == (uint32)-1) {
2922 len = 0;
2925 data->notify_data.data.length = len;
2926 if (len) {
2927 data->notify_data.data.string = (uint16 *)temp;
2928 } else {
2929 data->notify_data.data.string = NULL;
2933 /*******************************************************************
2934 * fill a notify_info_data with the device mode
2935 * jfm:xxxx don't to it for know but that's a real problem !!!
2936 ********************************************************************/
2938 static void spoolss_notify_devmode(int snum,
2939 SPOOL_NOTIFY_INFO_DATA *data,
2940 print_queue_struct *queue,
2941 NT_PRINTER_INFO_LEVEL *printer,
2942 TALLOC_CTX *mem_ctx)
2944 /* for a dummy implementation we have to zero the fields */
2945 data->notify_data.data.length = 0;
2946 data->notify_data.data.string = NULL;
2949 /*******************************************************************
2950 * fill a notify_info_data with the separator file name
2951 ********************************************************************/
2953 void spoolss_notify_sepfile(int snum,
2954 SPOOL_NOTIFY_INFO_DATA *data,
2955 print_queue_struct *queue,
2956 NT_PRINTER_INFO_LEVEL *printer,
2957 TALLOC_CTX *mem_ctx)
2959 smb_ucs2_t *temp = NULL;
2960 uint32 len;
2962 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
2963 if (len == (uint32)-1) {
2964 len = 0;
2967 data->notify_data.data.length = len;
2968 if (len) {
2969 data->notify_data.data.string = (uint16 *)temp;
2970 } else {
2971 data->notify_data.data.string = NULL;
2975 /*******************************************************************
2976 * fill a notify_info_data with the print processor
2977 * jfm:xxxx return always winprint to indicate we don't do anything to it
2978 ********************************************************************/
2980 void spoolss_notify_print_processor(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 smb_ucs2_t *temp = NULL;
2987 uint32 len;
2989 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
2990 if (len == (uint32)-1) {
2991 len = 0;
2994 data->notify_data.data.length = len;
2995 if (len) {
2996 data->notify_data.data.string = (uint16 *)temp;
2997 } else {
2998 data->notify_data.data.string = NULL;
3002 /*******************************************************************
3003 * fill a notify_info_data with the print processor options
3004 * jfm:xxxx send an empty string
3005 ********************************************************************/
3007 void spoolss_notify_parameters(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 smb_ucs2_t *temp = NULL;
3014 uint32 len;
3016 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
3017 if (len == (uint32)-1) {
3018 len = 0;
3021 data->notify_data.data.length = len;
3022 if (len) {
3023 data->notify_data.data.string = (uint16 *)temp;
3024 } else {
3025 data->notify_data.data.string = NULL;
3029 /*******************************************************************
3030 * fill a notify_info_data with the data type
3031 * jfm:xxxx always send RAW as data type
3032 ********************************************************************/
3034 void spoolss_notify_datatype(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 smb_ucs2_t *temp = NULL;
3041 uint32 len;
3043 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
3044 if (len == (uint32)-1) {
3045 len = 0;
3048 data->notify_data.data.length = len;
3049 if (len) {
3050 data->notify_data.data.string = (uint16 *)temp;
3051 } else {
3052 data->notify_data.data.string = NULL;
3056 /*******************************************************************
3057 * fill a notify_info_data with the security descriptor
3058 * jfm:xxxx send an null pointer to say no security desc
3059 * have to implement security before !
3060 ********************************************************************/
3062 static void spoolss_notify_security_desc(int snum,
3063 SPOOL_NOTIFY_INFO_DATA *data,
3064 print_queue_struct *queue,
3065 NT_PRINTER_INFO_LEVEL *printer,
3066 TALLOC_CTX *mem_ctx)
3068 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3069 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3072 /*******************************************************************
3073 * fill a notify_info_data with the attributes
3074 * jfm:xxxx a samba printer is always shared
3075 ********************************************************************/
3077 void spoolss_notify_attributes(int snum,
3078 SPOOL_NOTIFY_INFO_DATA *data,
3079 print_queue_struct *queue,
3080 NT_PRINTER_INFO_LEVEL *printer,
3081 TALLOC_CTX *mem_ctx)
3083 data->notify_data.value[0] = printer->info_2->attributes;
3084 data->notify_data.value[1] = 0;
3087 /*******************************************************************
3088 * fill a notify_info_data with the priority
3089 ********************************************************************/
3091 static void spoolss_notify_priority(int snum,
3092 SPOOL_NOTIFY_INFO_DATA *data,
3093 print_queue_struct *queue,
3094 NT_PRINTER_INFO_LEVEL *printer,
3095 TALLOC_CTX *mem_ctx)
3097 data->notify_data.value[0] = printer->info_2->priority;
3098 data->notify_data.value[1] = 0;
3101 /*******************************************************************
3102 * fill a notify_info_data with the default priority
3103 ********************************************************************/
3105 static void spoolss_notify_default_priority(int snum,
3106 SPOOL_NOTIFY_INFO_DATA *data,
3107 print_queue_struct *queue,
3108 NT_PRINTER_INFO_LEVEL *printer,
3109 TALLOC_CTX *mem_ctx)
3111 data->notify_data.value[0] = printer->info_2->default_priority;
3112 data->notify_data.value[1] = 0;
3115 /*******************************************************************
3116 * fill a notify_info_data with the start time
3117 ********************************************************************/
3119 static void spoolss_notify_start_time(int snum,
3120 SPOOL_NOTIFY_INFO_DATA *data,
3121 print_queue_struct *queue,
3122 NT_PRINTER_INFO_LEVEL *printer,
3123 TALLOC_CTX *mem_ctx)
3125 data->notify_data.value[0] = printer->info_2->starttime;
3126 data->notify_data.value[1] = 0;
3129 /*******************************************************************
3130 * fill a notify_info_data with the until time
3131 ********************************************************************/
3133 static void spoolss_notify_until_time(int snum,
3134 SPOOL_NOTIFY_INFO_DATA *data,
3135 print_queue_struct *queue,
3136 NT_PRINTER_INFO_LEVEL *printer,
3137 TALLOC_CTX *mem_ctx)
3139 data->notify_data.value[0] = printer->info_2->untiltime;
3140 data->notify_data.value[1] = 0;
3143 /*******************************************************************
3144 * fill a notify_info_data with the status
3145 ********************************************************************/
3147 static void spoolss_notify_status(int snum,
3148 SPOOL_NOTIFY_INFO_DATA *data,
3149 print_queue_struct *queue,
3150 NT_PRINTER_INFO_LEVEL *printer,
3151 TALLOC_CTX *mem_ctx)
3153 print_status_struct status;
3155 print_queue_length(snum, &status);
3156 data->notify_data.value[0]=(uint32) status.status;
3157 data->notify_data.value[1] = 0;
3160 /*******************************************************************
3161 * fill a notify_info_data with the number of jobs queued
3162 ********************************************************************/
3164 void spoolss_notify_cjobs(int snum,
3165 SPOOL_NOTIFY_INFO_DATA *data,
3166 print_queue_struct *queue,
3167 NT_PRINTER_INFO_LEVEL *printer,
3168 TALLOC_CTX *mem_ctx)
3170 data->notify_data.value[0] = print_queue_length(snum, NULL);
3171 data->notify_data.value[1] = 0;
3174 /*******************************************************************
3175 * fill a notify_info_data with the average ppm
3176 ********************************************************************/
3178 static void spoolss_notify_average_ppm(int snum,
3179 SPOOL_NOTIFY_INFO_DATA *data,
3180 print_queue_struct *queue,
3181 NT_PRINTER_INFO_LEVEL *printer,
3182 TALLOC_CTX *mem_ctx)
3184 /* always respond 8 pages per minutes */
3185 /* a little hard ! */
3186 data->notify_data.value[0] = printer->info_2->averageppm;
3187 data->notify_data.value[1] = 0;
3190 /*******************************************************************
3191 * fill a notify_info_data with username
3192 ********************************************************************/
3194 static void spoolss_notify_username(int snum,
3195 SPOOL_NOTIFY_INFO_DATA *data,
3196 print_queue_struct *queue,
3197 NT_PRINTER_INFO_LEVEL *printer,
3198 TALLOC_CTX *mem_ctx)
3200 smb_ucs2_t *temp = NULL;
3201 uint32 len;
3203 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
3204 if (len == (uint32)-1) {
3205 len = 0;
3208 data->notify_data.data.length = len;
3209 if (len) {
3210 data->notify_data.data.string = (uint16 *)temp;
3211 } else {
3212 data->notify_data.data.string = NULL;
3216 /*******************************************************************
3217 * fill a notify_info_data with job status
3218 ********************************************************************/
3220 static void spoolss_notify_job_status(int snum,
3221 SPOOL_NOTIFY_INFO_DATA *data,
3222 print_queue_struct *queue,
3223 NT_PRINTER_INFO_LEVEL *printer,
3224 TALLOC_CTX *mem_ctx)
3226 data->notify_data.value[0]=nt_printj_status(queue->status);
3227 data->notify_data.value[1] = 0;
3230 /*******************************************************************
3231 * fill a notify_info_data with job name
3232 ********************************************************************/
3234 static void spoolss_notify_job_name(int snum,
3235 SPOOL_NOTIFY_INFO_DATA *data,
3236 print_queue_struct *queue,
3237 NT_PRINTER_INFO_LEVEL *printer,
3238 TALLOC_CTX *mem_ctx)
3240 smb_ucs2_t *temp = NULL;
3241 uint32 len;
3243 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
3244 if (len == (uint32)-1) {
3245 len = 0;
3248 data->notify_data.data.length = len;
3249 if (len) {
3250 data->notify_data.data.string = (uint16 *)temp;
3251 } else {
3252 data->notify_data.data.string = NULL;
3256 /*******************************************************************
3257 * fill a notify_info_data with job status
3258 ********************************************************************/
3260 static void spoolss_notify_job_status_string(int snum,
3261 SPOOL_NOTIFY_INFO_DATA *data,
3262 print_queue_struct *queue,
3263 NT_PRINTER_INFO_LEVEL *printer,
3264 TALLOC_CTX *mem_ctx)
3267 * Now we're returning job status codes we just return a "" here. JRA.
3270 const char *p = "";
3271 smb_ucs2_t *temp = NULL;
3272 uint32 len;
3274 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3275 p = "unknown";
3277 switch (queue->status) {
3278 case LPQ_QUEUED:
3279 p = "Queued";
3280 break;
3281 case LPQ_PAUSED:
3282 p = ""; /* NT provides the paused string */
3283 break;
3284 case LPQ_SPOOLING:
3285 p = "Spooling";
3286 break;
3287 case LPQ_PRINTING:
3288 p = "Printing";
3289 break;
3291 #endif /* NO LONGER NEEDED. */
3293 len = rpcstr_push_talloc(mem_ctx, &temp, p);
3294 if (len == (uint32)-1) {
3295 len = 0;
3298 data->notify_data.data.length = len;
3299 if (len) {
3300 data->notify_data.data.string = (uint16 *)temp;
3301 } else {
3302 data->notify_data.data.string = NULL;
3306 /*******************************************************************
3307 * fill a notify_info_data with job time
3308 ********************************************************************/
3310 static void spoolss_notify_job_time(int snum,
3311 SPOOL_NOTIFY_INFO_DATA *data,
3312 print_queue_struct *queue,
3313 NT_PRINTER_INFO_LEVEL *printer,
3314 TALLOC_CTX *mem_ctx)
3316 data->notify_data.value[0]=0x0;
3317 data->notify_data.value[1]=0;
3320 /*******************************************************************
3321 * fill a notify_info_data with job size
3322 ********************************************************************/
3324 static void spoolss_notify_job_size(int snum,
3325 SPOOL_NOTIFY_INFO_DATA *data,
3326 print_queue_struct *queue,
3327 NT_PRINTER_INFO_LEVEL *printer,
3328 TALLOC_CTX *mem_ctx)
3330 data->notify_data.value[0]=queue->size;
3331 data->notify_data.value[1]=0;
3334 /*******************************************************************
3335 * fill a notify_info_data with page info
3336 ********************************************************************/
3337 static void spoolss_notify_total_pages(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]=queue->page_count;
3344 data->notify_data.value[1]=0;
3347 /*******************************************************************
3348 * fill a notify_info_data with pages printed info.
3349 ********************************************************************/
3350 static void spoolss_notify_pages_printed(int snum,
3351 SPOOL_NOTIFY_INFO_DATA *data,
3352 print_queue_struct *queue,
3353 NT_PRINTER_INFO_LEVEL *printer,
3354 TALLOC_CTX *mem_ctx)
3356 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3357 data->notify_data.value[1]=0;
3360 /*******************************************************************
3361 Fill a notify_info_data with job position.
3362 ********************************************************************/
3364 static void spoolss_notify_job_position(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->job;
3371 data->notify_data.value[1]=0;
3374 /*******************************************************************
3375 Fill a notify_info_data with submitted time.
3376 ********************************************************************/
3378 static void spoolss_notify_submitted_time(int snum,
3379 SPOOL_NOTIFY_INFO_DATA *data,
3380 print_queue_struct *queue,
3381 NT_PRINTER_INFO_LEVEL *printer,
3382 TALLOC_CTX *mem_ctx)
3384 struct tm *t;
3385 uint32 len;
3386 SYSTEMTIME st;
3387 char *p;
3389 t=gmtime(&queue->time);
3391 len = sizeof(SYSTEMTIME);
3393 data->notify_data.data.length = len;
3394 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3396 if (!data->notify_data.data.string) {
3397 data->notify_data.data.length = 0;
3398 return;
3401 make_systemtime(&st, t);
3404 * Systemtime must be linearized as a set of UINT16's.
3405 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3408 p = (char *)data->notify_data.data.string;
3409 SSVAL(p, 0, st.year);
3410 SSVAL(p, 2, st.month);
3411 SSVAL(p, 4, st.dayofweek);
3412 SSVAL(p, 6, st.day);
3413 SSVAL(p, 8, st.hour);
3414 SSVAL(p, 10, st.minute);
3415 SSVAL(p, 12, st.second);
3416 SSVAL(p, 14, st.milliseconds);
3419 struct s_notify_info_data_table
3421 uint16 type;
3422 uint16 field;
3423 const char *name;
3424 uint32 size;
3425 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3426 print_queue_struct *queue,
3427 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3430 /* A table describing the various print notification constants and
3431 whether the notification data is a pointer to a variable sized
3432 buffer, a one value uint32 or a two value uint32. */
3434 static const struct s_notify_info_data_table notify_info_data_table[] =
3436 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3437 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3438 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3439 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3440 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3441 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3462 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3463 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3464 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3465 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3466 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3467 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3485 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3488 /*******************************************************************
3489 Return the size of info_data structure.
3490 ********************************************************************/
3492 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3494 int i=0;
3496 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3497 if ( (notify_info_data_table[i].type == type)
3498 && (notify_info_data_table[i].field == field) ) {
3499 switch(notify_info_data_table[i].size) {
3500 case NOTIFY_ONE_VALUE:
3501 case NOTIFY_TWO_VALUE:
3502 return 1;
3503 case NOTIFY_STRING:
3504 return 2;
3506 /* The only pointer notify data I have seen on
3507 the wire is the submitted time and this has
3508 the notify size set to 4. -tpot */
3510 case NOTIFY_POINTER:
3511 return 4;
3513 case NOTIFY_SECDESC:
3514 return 5;
3519 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3521 return 0;
3524 /*******************************************************************
3525 Return the type of notify_info_data.
3526 ********************************************************************/
3528 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3530 uint32 i=0;
3532 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3533 if (notify_info_data_table[i].type == type &&
3534 notify_info_data_table[i].field == field)
3535 return notify_info_data_table[i].size;
3538 return 0;
3541 /****************************************************************************
3542 ****************************************************************************/
3544 static bool search_notify(uint16 type, uint16 field, int *value)
3546 int i;
3548 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3549 if (notify_info_data_table[i].type == type &&
3550 notify_info_data_table[i].field == field &&
3551 notify_info_data_table[i].fn != NULL) {
3552 *value = i;
3553 return True;
3557 return False;
3560 /****************************************************************************
3561 ****************************************************************************/
3563 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3565 info_data->type = type;
3566 info_data->field = field;
3567 info_data->reserved = 0;
3569 info_data->size = size_of_notify_info_data(type, field);
3570 info_data->enc_type = type_of_notify_info_data(type, field);
3572 info_data->id = id;
3575 /*******************************************************************
3577 * fill a notify_info struct with info asked
3579 ********************************************************************/
3581 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3582 snum, SPOOL_NOTIFY_OPTION_TYPE
3583 *option_type, uint32 id,
3584 TALLOC_CTX *mem_ctx)
3586 int field_num,j;
3587 uint16 type;
3588 uint16 field;
3590 SPOOL_NOTIFY_INFO_DATA *current_data;
3591 NT_PRINTER_INFO_LEVEL *printer = NULL;
3592 print_queue_struct *queue=NULL;
3594 type=option_type->type;
3596 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3597 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3598 option_type->count, lp_servicename(snum)));
3600 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3601 return False;
3603 for(field_num=0; field_num<option_type->count; field_num++) {
3604 field = option_type->fields[field_num];
3606 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3608 if (!search_notify(type, field, &j) )
3609 continue;
3611 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3612 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3613 free_a_printer(&printer, 2);
3614 return False;
3617 current_data = &info->data[info->count];
3619 construct_info_data(current_data, type, field, id);
3621 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3622 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3624 notify_info_data_table[j].fn(snum, current_data, queue,
3625 printer, mem_ctx);
3627 info->count++;
3630 free_a_printer(&printer, 2);
3631 return True;
3634 /*******************************************************************
3636 * fill a notify_info struct with info asked
3638 ********************************************************************/
3640 static bool construct_notify_jobs_info(print_queue_struct *queue,
3641 SPOOL_NOTIFY_INFO *info,
3642 NT_PRINTER_INFO_LEVEL *printer,
3643 int snum, SPOOL_NOTIFY_OPTION_TYPE
3644 *option_type, uint32 id,
3645 TALLOC_CTX *mem_ctx)
3647 int field_num,j;
3648 uint16 type;
3649 uint16 field;
3651 SPOOL_NOTIFY_INFO_DATA *current_data;
3653 DEBUG(4,("construct_notify_jobs_info\n"));
3655 type = option_type->type;
3657 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3658 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3659 option_type->count));
3661 for(field_num=0; field_num<option_type->count; field_num++) {
3662 field = option_type->fields[field_num];
3664 if (!search_notify(type, field, &j) )
3665 continue;
3667 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3668 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3669 return False;
3672 current_data=&(info->data[info->count]);
3674 construct_info_data(current_data, type, field, id);
3675 notify_info_data_table[j].fn(snum, current_data, queue,
3676 printer, mem_ctx);
3677 info->count++;
3680 return True;
3684 * JFM: The enumeration is not that simple, it's even non obvious.
3686 * let's take an example: I want to monitor the PRINTER SERVER for
3687 * the printer's name and the number of jobs currently queued.
3688 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3689 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3691 * I have 3 printers on the back of my server.
3693 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3694 * structures.
3695 * Number Data Id
3696 * 1 printer 1 name 1
3697 * 2 printer 1 cjob 1
3698 * 3 printer 2 name 2
3699 * 4 printer 2 cjob 2
3700 * 5 printer 3 name 3
3701 * 6 printer 3 name 3
3703 * that's the print server case, the printer case is even worse.
3706 /*******************************************************************
3708 * enumerate all printers on the printserver
3709 * fill a notify_info struct with info asked
3711 ********************************************************************/
3713 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3714 SPOOL_NOTIFY_INFO *info,
3715 TALLOC_CTX *mem_ctx)
3717 int snum;
3718 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3719 int n_services=lp_numservices();
3720 int i;
3721 SPOOL_NOTIFY_OPTION *option;
3722 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3724 DEBUG(4,("printserver_notify_info\n"));
3726 if (!Printer)
3727 return WERR_BADFID;
3729 option=Printer->notify.option;
3730 info->version=2;
3731 info->data=NULL;
3732 info->count=0;
3734 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3735 sending a ffpcn() request first */
3737 if ( !option )
3738 return WERR_BADFID;
3740 for (i=0; i<option->count; i++) {
3741 option_type=&(option->ctr.type[i]);
3743 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3744 continue;
3746 for (snum=0; snum<n_services; snum++)
3748 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3749 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3753 #if 0
3755 * Debugging information, don't delete.
3758 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3759 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3760 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3762 for (i=0; i<info->count; i++) {
3763 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3764 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3765 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3767 #endif
3769 return WERR_OK;
3772 /*******************************************************************
3774 * fill a notify_info struct with info asked
3776 ********************************************************************/
3778 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3779 TALLOC_CTX *mem_ctx)
3781 int snum;
3782 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3783 int i;
3784 uint32 id;
3785 SPOOL_NOTIFY_OPTION *option;
3786 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3787 int count,j;
3788 print_queue_struct *queue=NULL;
3789 print_status_struct status;
3791 DEBUG(4,("printer_notify_info\n"));
3793 if (!Printer)
3794 return WERR_BADFID;
3796 option=Printer->notify.option;
3797 id = 0x0;
3798 info->version=2;
3799 info->data=NULL;
3800 info->count=0;
3802 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3803 sending a ffpcn() request first */
3805 if ( !option )
3806 return WERR_BADFID;
3808 get_printer_snum(p, hnd, &snum, NULL);
3810 for (i=0; i<option->count; i++) {
3811 option_type=&option->ctr.type[i];
3813 switch ( option_type->type ) {
3814 case PRINTER_NOTIFY_TYPE:
3815 if(construct_notify_printer_info(Printer, info, snum,
3816 option_type, id,
3817 mem_ctx))
3818 id--;
3819 break;
3821 case JOB_NOTIFY_TYPE: {
3822 NT_PRINTER_INFO_LEVEL *printer = NULL;
3824 count = print_queue_status(snum, &queue, &status);
3826 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3827 goto done;
3829 for (j=0; j<count; j++) {
3830 construct_notify_jobs_info(&queue[j], info,
3831 printer, snum,
3832 option_type,
3833 queue[j].job,
3834 mem_ctx);
3837 free_a_printer(&printer, 2);
3839 done:
3840 SAFE_FREE(queue);
3841 break;
3847 * Debugging information, don't delete.
3850 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3851 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3852 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3854 for (i=0; i<info->count; i++) {
3855 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3856 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3857 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3860 return WERR_OK;
3863 /********************************************************************
3864 * spoolss_rfnpcnex
3865 ********************************************************************/
3867 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3869 POLICY_HND *handle = &q_u->handle;
3870 SPOOL_NOTIFY_INFO *info = &r_u->info;
3872 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3873 WERROR result = WERR_BADFID;
3875 /* we always have a NOTIFY_INFO struct */
3876 r_u->info_ptr=0x1;
3878 if (!Printer) {
3879 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3880 OUR_HANDLE(handle)));
3881 goto done;
3884 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3887 * We are now using the change value, and
3888 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3889 * I don't have a global notification system, I'm sending back all the
3890 * informations even when _NOTHING_ has changed.
3893 /* We need to keep track of the change value to send back in
3894 RRPCN replies otherwise our updates are ignored. */
3896 Printer->notify.fnpcn = True;
3898 if (Printer->notify.client_connected) {
3899 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3900 Printer->notify.change = q_u->change;
3903 /* just ignore the SPOOL_NOTIFY_OPTION */
3905 switch (Printer->printer_type) {
3906 case SPLHND_SERVER:
3907 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3908 break;
3910 case SPLHND_PRINTER:
3911 result = printer_notify_info(p, handle, info, p->mem_ctx);
3912 break;
3915 Printer->notify.fnpcn = False;
3917 done:
3918 return result;
3921 /********************************************************************
3922 * construct_printer_info_0
3923 * fill a printer_info_0 struct
3924 ********************************************************************/
3926 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3928 char *chaine = NULL;
3929 int count;
3930 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3931 counter_printer_0 *session_counter;
3932 uint32 global_counter;
3933 struct tm *t;
3934 time_t setuptime;
3935 print_status_struct status;
3936 TALLOC_CTX *ctx = talloc_tos();
3938 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3939 return False;
3941 init_unistr(&printer->printername, ntprinter->info_2->printername);
3943 chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3944 if (!chaine) {
3945 free_a_printer(&ntprinter,2);
3946 return false;
3949 count = print_queue_length(snum, &status);
3951 /* check if we already have a counter for this printer */
3952 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3953 if (session_counter->snum == snum)
3954 break;
3957 init_unistr(&printer->servername, chaine);
3959 /* it's the first time, add it to the list */
3960 if (session_counter==NULL) {
3961 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3962 free_a_printer(&ntprinter, 2);
3963 return False;
3965 ZERO_STRUCTP(session_counter);
3966 session_counter->snum=snum;
3967 session_counter->counter=0;
3968 DLIST_ADD(counter_list, session_counter);
3971 /* increment it */
3972 session_counter->counter++;
3974 /* JFM:
3975 * the global_counter should be stored in a TDB as it's common to all the clients
3976 * and should be zeroed on samba startup
3978 global_counter=session_counter->counter;
3979 printer->cjobs = count;
3980 printer->total_jobs = 0;
3981 printer->total_bytes = 0;
3983 setuptime = (time_t)ntprinter->info_2->setuptime;
3984 t=gmtime(&setuptime);
3986 printer->year = t->tm_year+1900;
3987 printer->month = t->tm_mon+1;
3988 printer->dayofweek = t->tm_wday;
3989 printer->day = t->tm_mday;
3990 printer->hour = t->tm_hour;
3991 printer->minute = t->tm_min;
3992 printer->second = t->tm_sec;
3993 printer->milliseconds = 0;
3995 printer->global_counter = global_counter;
3996 printer->total_pages = 0;
3998 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3999 printer->major_version = 0x0005; /* NT 5 */
4000 printer->build_version = 0x0893; /* build 2195 */
4002 printer->unknown7 = 0x1;
4003 printer->unknown8 = 0x0;
4004 printer->unknown9 = 0x0;
4005 printer->session_counter = session_counter->counter;
4006 printer->unknown11 = 0x0;
4007 printer->printer_errors = 0x0; /* number of print failure */
4008 printer->unknown13 = 0x0;
4009 printer->unknown14 = 0x1;
4010 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4011 printer->unknown16 = 0x0;
4012 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4013 printer->unknown18 = 0x0;
4014 printer->status = nt_printq_status(status.status);
4015 printer->unknown20 = 0x0;
4016 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4017 printer->unknown22 = 0x0;
4018 printer->unknown23 = 0x6; /* 6 ???*/
4019 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4020 printer->unknown25 = 0;
4021 printer->unknown26 = 0;
4022 printer->unknown27 = 0;
4023 printer->unknown28 = 0;
4024 printer->unknown29 = 0;
4026 free_a_printer(&ntprinter,2);
4027 return (True);
4030 /********************************************************************
4031 * construct_printer_info_1
4032 * fill a printer_info_1 struct
4033 ********************************************************************/
4034 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4036 char *chaine = NULL;
4037 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4038 TALLOC_CTX *ctx = talloc_tos();
4040 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4041 return false;
4043 printer->flags=flags;
4045 if (*ntprinter->info_2->comment == '\0') {
4046 init_unistr(&printer->comment, lp_comment(snum));
4047 chaine = talloc_asprintf(ctx,
4048 "%s,%s,%s", ntprinter->info_2->printername,
4049 ntprinter->info_2->drivername, lp_comment(snum));
4051 else {
4052 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4053 chaine = talloc_asprintf(ctx,
4054 "%s,%s,%s", ntprinter->info_2->printername,
4055 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4058 if (!chaine) {
4059 free_a_printer(&ntprinter,2);
4060 return false;
4063 init_unistr(&printer->description, chaine);
4064 init_unistr(&printer->name, ntprinter->info_2->printername);
4066 free_a_printer(&ntprinter,2);
4068 return True;
4071 /****************************************************************************
4072 Free a DEVMODE struct.
4073 ****************************************************************************/
4075 static void free_dev_mode(DEVICEMODE *dev)
4077 if (dev == NULL)
4078 return;
4080 SAFE_FREE(dev->dev_private);
4081 SAFE_FREE(dev);
4085 /****************************************************************************
4086 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4087 should be valid upon entry
4088 ****************************************************************************/
4090 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4092 if ( !devmode || !ntdevmode )
4093 return False;
4095 init_unistr(&devmode->devicename, ntdevmode->devicename);
4097 init_unistr(&devmode->formname, ntdevmode->formname);
4099 devmode->specversion = ntdevmode->specversion;
4100 devmode->driverversion = ntdevmode->driverversion;
4101 devmode->size = ntdevmode->size;
4102 devmode->driverextra = ntdevmode->driverextra;
4103 devmode->fields = ntdevmode->fields;
4105 devmode->orientation = ntdevmode->orientation;
4106 devmode->papersize = ntdevmode->papersize;
4107 devmode->paperlength = ntdevmode->paperlength;
4108 devmode->paperwidth = ntdevmode->paperwidth;
4109 devmode->scale = ntdevmode->scale;
4110 devmode->copies = ntdevmode->copies;
4111 devmode->defaultsource = ntdevmode->defaultsource;
4112 devmode->printquality = ntdevmode->printquality;
4113 devmode->color = ntdevmode->color;
4114 devmode->duplex = ntdevmode->duplex;
4115 devmode->yresolution = ntdevmode->yresolution;
4116 devmode->ttoption = ntdevmode->ttoption;
4117 devmode->collate = ntdevmode->collate;
4118 devmode->icmmethod = ntdevmode->icmmethod;
4119 devmode->icmintent = ntdevmode->icmintent;
4120 devmode->mediatype = ntdevmode->mediatype;
4121 devmode->dithertype = ntdevmode->dithertype;
4123 if (ntdevmode->nt_dev_private != NULL) {
4124 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4125 return False;
4128 return True;
4131 /****************************************************************************
4132 Create a DEVMODE struct. Returns malloced memory.
4133 ****************************************************************************/
4135 DEVICEMODE *construct_dev_mode(const char *servicename)
4137 NT_PRINTER_INFO_LEVEL *printer = NULL;
4138 DEVICEMODE *devmode = NULL;
4140 DEBUG(7,("construct_dev_mode\n"));
4142 DEBUGADD(8,("getting printer characteristics\n"));
4144 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4145 return NULL;
4147 if ( !printer->info_2->devmode ) {
4148 DEBUG(5, ("BONG! There was no device mode!\n"));
4149 goto done;
4152 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4153 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4154 goto done;
4157 ZERO_STRUCTP(devmode);
4159 DEBUGADD(8,("loading DEVICEMODE\n"));
4161 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4162 free_dev_mode( devmode );
4163 devmode = NULL;
4166 done:
4167 free_a_printer(&printer,2);
4169 return devmode;
4172 /********************************************************************
4173 * construct_printer_info_2
4174 * fill a printer_info_2 struct
4175 ********************************************************************/
4177 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4179 int count;
4180 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4182 print_status_struct status;
4184 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4185 return False;
4187 count = print_queue_length(snum, &status);
4189 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4190 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4191 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4192 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4193 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4195 if (*ntprinter->info_2->comment == '\0')
4196 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4197 else
4198 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4200 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4201 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4202 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4203 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4204 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4206 printer->attributes = ntprinter->info_2->attributes;
4208 printer->priority = ntprinter->info_2->priority; /* priority */
4209 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4210 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4211 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4212 printer->status = nt_printq_status(status.status); /* status */
4213 printer->cjobs = count; /* jobs */
4214 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4216 if ( !(printer->devmode = construct_dev_mode(
4217 lp_const_servicename(snum))) )
4218 DEBUG(8, ("Returning NULL Devicemode!\n"));
4220 printer->secdesc = NULL;
4222 if ( ntprinter->info_2->secdesc_buf
4223 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4225 /* don't use talloc_steal() here unless you do a deep steal of all
4226 the SEC_DESC members */
4228 printer->secdesc = dup_sec_desc( talloc_tos(),
4229 ntprinter->info_2->secdesc_buf->sd );
4232 free_a_printer(&ntprinter, 2);
4234 return True;
4237 /********************************************************************
4238 * construct_printer_info_3
4239 * fill a printer_info_3 struct
4240 ********************************************************************/
4242 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4244 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4245 PRINTER_INFO_3 *printer = NULL;
4247 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4248 return False;
4250 *pp_printer = NULL;
4251 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4252 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4253 free_a_printer(&ntprinter, 2);
4254 return False;
4257 ZERO_STRUCTP(printer);
4259 /* These are the components of the SD we are returning. */
4261 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4262 /* don't use talloc_steal() here unless you do a deep steal of all
4263 the SEC_DESC members */
4265 printer->secdesc = dup_sec_desc( talloc_tos(),
4266 ntprinter->info_2->secdesc_buf->sd );
4269 free_a_printer(&ntprinter, 2);
4271 *pp_printer = printer;
4272 return True;
4275 /********************************************************************
4276 * construct_printer_info_4
4277 * fill a printer_info_4 struct
4278 ********************************************************************/
4280 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4282 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4284 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4285 return False;
4287 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4288 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4289 printer->attributes = ntprinter->info_2->attributes;
4291 free_a_printer(&ntprinter, 2);
4292 return True;
4295 /********************************************************************
4296 * construct_printer_info_5
4297 * fill a printer_info_5 struct
4298 ********************************************************************/
4300 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4302 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4304 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4305 return False;
4307 init_unistr(&printer->printername, ntprinter->info_2->printername);
4308 init_unistr(&printer->portname, ntprinter->info_2->portname);
4309 printer->attributes = ntprinter->info_2->attributes;
4311 /* these two are not used by NT+ according to MSDN */
4313 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4314 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4316 free_a_printer(&ntprinter, 2);
4318 return True;
4321 /********************************************************************
4322 * construct_printer_info_6
4323 * fill a printer_info_6 struct
4324 ********************************************************************/
4326 static bool construct_printer_info_6(Printer_entry *print_hnd,
4327 PRINTER_INFO_6 *printer,
4328 int snum)
4330 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4331 int count;
4332 print_status_struct status;
4334 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4335 lp_const_servicename(snum))))
4336 return False;
4338 count = print_queue_length(snum, &status);
4340 printer->status = nt_printq_status(status.status);
4342 free_a_printer(&ntprinter, 2);
4344 return True;
4347 /********************************************************************
4348 * construct_printer_info_7
4349 * fill a printer_info_7 struct
4350 ********************************************************************/
4352 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4354 char *guid_str = NULL;
4355 struct GUID guid;
4357 if (is_printer_published(print_hnd, snum, &guid)) {
4358 asprintf(&guid_str, "{%s}",
4359 smb_uuid_string(talloc_tos(), guid));
4360 strupper_m(guid_str);
4361 init_unistr(&printer->guid, guid_str);
4362 printer->action = SPOOL_DS_PUBLISH;
4363 } else {
4364 init_unistr(&printer->guid, "");
4365 printer->action = SPOOL_DS_UNPUBLISH;
4368 return True;
4371 /********************************************************************
4372 Spoolss_enumprinters.
4373 ********************************************************************/
4375 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4377 int snum;
4378 int i;
4379 int n_services=lp_numservices();
4380 PRINTER_INFO_1 *printers=NULL;
4381 PRINTER_INFO_1 current_prt;
4382 WERROR result = WERR_OK;
4384 DEBUG(4,("enum_all_printers_info_1\n"));
4386 for (snum=0; snum<n_services; snum++) {
4387 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4388 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4390 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4391 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4392 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4393 *returned=0;
4394 return WERR_NOMEM;
4396 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4398 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4399 (*returned)++;
4404 /* check the required size. */
4405 for (i=0; i<*returned; i++)
4406 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4408 if (*needed > offered) {
4409 result = WERR_INSUFFICIENT_BUFFER;
4410 goto out;
4413 if (!rpcbuf_alloc_size(buffer, *needed)) {
4414 result = WERR_NOMEM;
4415 goto out;
4418 /* fill the buffer with the structures */
4419 for (i=0; i<*returned; i++)
4420 smb_io_printer_info_1("", buffer, &printers[i], 0);
4422 out:
4423 /* clear memory */
4425 SAFE_FREE(printers);
4427 if ( !W_ERROR_IS_OK(result) )
4428 *returned = 0;
4430 return result;
4433 /********************************************************************
4434 enum_all_printers_info_1_local.
4435 *********************************************************************/
4437 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4439 DEBUG(4,("enum_all_printers_info_1_local\n"));
4441 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4444 /********************************************************************
4445 enum_all_printers_info_1_name.
4446 *********************************************************************/
4448 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4450 char *s = name;
4452 DEBUG(4,("enum_all_printers_info_1_name\n"));
4454 if ((name[0] == '\\') && (name[1] == '\\'))
4455 s = name + 2;
4457 if (is_myname_or_ipaddr(s)) {
4458 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4460 else
4461 return WERR_INVALID_NAME;
4464 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4465 /********************************************************************
4466 enum_all_printers_info_1_remote.
4467 *********************************************************************/
4469 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4471 PRINTER_INFO_1 *printer;
4472 fstring printername;
4473 fstring desc;
4474 fstring comment;
4475 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4476 WERROR result = WERR_OK;
4478 /* JFM: currently it's more a place holder than anything else.
4479 * In the spooler world there is a notion of server registration.
4480 * the print servers are registered on the PDC (in the same domain)
4482 * We should have a TDB here. The registration is done thru an
4483 * undocumented RPC call.
4486 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4487 return WERR_NOMEM;
4489 *returned=1;
4491 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4492 slprintf(desc, sizeof(desc)-1,"%s", name);
4493 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4495 init_unistr(&printer->description, desc);
4496 init_unistr(&printer->name, printername);
4497 init_unistr(&printer->comment, comment);
4498 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4500 /* check the required size. */
4501 *needed += spoolss_size_printer_info_1(printer);
4503 if (*needed > offered) {
4504 result = WERR_INSUFFICIENT_BUFFER;
4505 goto out;
4508 if (!rpcbuf_alloc_size(buffer, *needed)) {
4509 result = WERR_NOMEM;
4510 goto out;
4513 /* fill the buffer with the structures */
4514 smb_io_printer_info_1("", buffer, printer, 0);
4516 out:
4517 /* clear memory */
4518 SAFE_FREE(printer);
4520 if ( !W_ERROR_IS_OK(result) )
4521 *returned = 0;
4523 return result;
4526 #endif
4528 /********************************************************************
4529 enum_all_printers_info_1_network.
4530 *********************************************************************/
4532 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4534 char *s = name;
4536 DEBUG(4,("enum_all_printers_info_1_network\n"));
4538 /* If we respond to a enum_printers level 1 on our name with flags
4539 set to PRINTER_ENUM_REMOTE with a list of printers then these
4540 printers incorrectly appear in the APW browse list.
4541 Specifically the printers for the server appear at the workgroup
4542 level where all the other servers in the domain are
4543 listed. Windows responds to this call with a
4544 WERR_CAN_NOT_COMPLETE so we should do the same. */
4546 if (name[0] == '\\' && name[1] == '\\')
4547 s = name + 2;
4549 if (is_myname_or_ipaddr(s))
4550 return WERR_CAN_NOT_COMPLETE;
4552 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4555 /********************************************************************
4556 * api_spoolss_enumprinters
4558 * called from api_spoolss_enumprinters (see this to understand)
4559 ********************************************************************/
4561 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4563 int snum;
4564 int i;
4565 int n_services=lp_numservices();
4566 PRINTER_INFO_2 *printers=NULL;
4567 PRINTER_INFO_2 current_prt;
4568 WERROR result = WERR_OK;
4570 *returned = 0;
4572 for (snum=0; snum<n_services; snum++) {
4573 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4574 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4576 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4577 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4578 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4579 *returned = 0;
4580 return WERR_NOMEM;
4583 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4585 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4587 (*returned)++;
4592 /* check the required size. */
4593 for (i=0; i<*returned; i++)
4594 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4596 if (*needed > offered) {
4597 result = WERR_INSUFFICIENT_BUFFER;
4598 goto out;
4601 if (!rpcbuf_alloc_size(buffer, *needed)) {
4602 result = WERR_NOMEM;
4603 goto out;
4606 /* fill the buffer with the structures */
4607 for (i=0; i<*returned; i++)
4608 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4610 out:
4611 /* clear memory */
4613 for (i=0; i<*returned; i++)
4614 free_devmode(printers[i].devmode);
4616 SAFE_FREE(printers);
4618 if ( !W_ERROR_IS_OK(result) )
4619 *returned = 0;
4621 return result;
4624 /********************************************************************
4625 * handle enumeration of printers at level 1
4626 ********************************************************************/
4628 static WERROR enumprinters_level1( uint32 flags, fstring name,
4629 RPC_BUFFER *buffer, uint32 offered,
4630 uint32 *needed, uint32 *returned)
4632 /* Not all the flags are equals */
4634 if (flags & PRINTER_ENUM_LOCAL)
4635 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4637 if (flags & PRINTER_ENUM_NAME)
4638 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4640 #if 0 /* JERRY - disabled for now */
4641 if (flags & PRINTER_ENUM_REMOTE)
4642 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4643 #endif
4645 if (flags & PRINTER_ENUM_NETWORK)
4646 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4648 return WERR_OK; /* NT4sp5 does that */
4651 /********************************************************************
4652 * handle enumeration of printers at level 2
4653 ********************************************************************/
4655 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4656 RPC_BUFFER *buffer, uint32 offered,
4657 uint32 *needed, uint32 *returned)
4659 char *s = servername;
4661 if (flags & PRINTER_ENUM_LOCAL) {
4662 return enum_all_printers_info_2(buffer, offered, needed, returned);
4665 if (flags & PRINTER_ENUM_NAME) {
4666 if ((servername[0] == '\\') && (servername[1] == '\\'))
4667 s = servername + 2;
4668 if (is_myname_or_ipaddr(s))
4669 return enum_all_printers_info_2(buffer, offered, needed, returned);
4670 else
4671 return WERR_INVALID_NAME;
4674 if (flags & PRINTER_ENUM_REMOTE)
4675 return WERR_UNKNOWN_LEVEL;
4677 return WERR_OK;
4680 /********************************************************************
4681 * handle enumeration of printers at level 5
4682 ********************************************************************/
4684 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4685 RPC_BUFFER *buffer, uint32 offered,
4686 uint32 *needed, uint32 *returned)
4688 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4689 return WERR_OK;
4692 /********************************************************************
4693 * api_spoolss_enumprinters
4695 * called from api_spoolss_enumprinters (see this to understand)
4696 ********************************************************************/
4698 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4700 uint32 flags = q_u->flags;
4701 UNISTR2 *servername = &q_u->servername;
4702 uint32 level = q_u->level;
4703 RPC_BUFFER *buffer = NULL;
4704 uint32 offered = q_u->offered;
4705 uint32 *needed = &r_u->needed;
4706 uint32 *returned = &r_u->returned;
4708 fstring name;
4710 /* that's an [in out] buffer */
4712 if (!q_u->buffer && (offered!=0)) {
4713 return WERR_INVALID_PARAM;
4716 rpcbuf_move(q_u->buffer, &r_u->buffer);
4717 buffer = r_u->buffer;
4719 DEBUG(4,("_spoolss_enumprinters\n"));
4721 *needed=0;
4722 *returned=0;
4725 * Level 1:
4726 * flags==PRINTER_ENUM_NAME
4727 * if name=="" then enumerates all printers
4728 * if name!="" then enumerate the printer
4729 * flags==PRINTER_ENUM_REMOTE
4730 * name is NULL, enumerate printers
4731 * Level 2: name!="" enumerates printers, name can't be NULL
4732 * Level 3: doesn't exist
4733 * Level 4: does a local registry lookup
4734 * Level 5: same as Level 2
4737 unistr2_to_ascii(name, servername, sizeof(name));
4738 strupper_m(name);
4740 switch (level) {
4741 case 1:
4742 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4743 case 2:
4744 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4745 case 5:
4746 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4747 case 3:
4748 case 4:
4749 break;
4751 return WERR_UNKNOWN_LEVEL;
4754 /****************************************************************************
4755 ****************************************************************************/
4757 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4759 PRINTER_INFO_0 *printer=NULL;
4760 WERROR result = WERR_OK;
4762 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4763 return WERR_NOMEM;
4765 construct_printer_info_0(print_hnd, printer, snum);
4767 /* check the required size. */
4768 *needed += spoolss_size_printer_info_0(printer);
4770 if (*needed > offered) {
4771 result = WERR_INSUFFICIENT_BUFFER;
4772 goto out;
4775 if (!rpcbuf_alloc_size(buffer, *needed)) {
4776 result = WERR_NOMEM;
4777 goto out;
4780 /* fill the buffer with the structures */
4781 smb_io_printer_info_0("", buffer, printer, 0);
4783 out:
4784 /* clear memory */
4786 SAFE_FREE(printer);
4788 return result;
4791 /****************************************************************************
4792 ****************************************************************************/
4794 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4796 PRINTER_INFO_1 *printer=NULL;
4797 WERROR result = WERR_OK;
4799 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4800 return WERR_NOMEM;
4802 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4804 /* check the required size. */
4805 *needed += spoolss_size_printer_info_1(printer);
4807 if (*needed > offered) {
4808 result = WERR_INSUFFICIENT_BUFFER;
4809 goto out;
4812 if (!rpcbuf_alloc_size(buffer, *needed)) {
4813 result = WERR_NOMEM;
4814 goto out;
4817 /* fill the buffer with the structures */
4818 smb_io_printer_info_1("", buffer, printer, 0);
4820 out:
4821 /* clear memory */
4822 SAFE_FREE(printer);
4824 return result;
4827 /****************************************************************************
4828 ****************************************************************************/
4830 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4832 PRINTER_INFO_2 *printer=NULL;
4833 WERROR result = WERR_OK;
4835 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4836 return WERR_NOMEM;
4838 construct_printer_info_2(print_hnd, printer, snum);
4840 /* check the required size. */
4841 *needed += spoolss_size_printer_info_2(printer);
4843 if (*needed > offered) {
4844 result = WERR_INSUFFICIENT_BUFFER;
4845 goto out;
4848 if (!rpcbuf_alloc_size(buffer, *needed)) {
4849 result = WERR_NOMEM;
4850 goto out;
4853 /* fill the buffer with the structures */
4854 if (!smb_io_printer_info_2("", buffer, printer, 0))
4855 result = WERR_NOMEM;
4857 out:
4858 /* clear memory */
4859 free_printer_info_2(printer);
4861 return result;
4864 /****************************************************************************
4865 ****************************************************************************/
4867 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4869 PRINTER_INFO_3 *printer=NULL;
4870 WERROR result = WERR_OK;
4872 if (!construct_printer_info_3(print_hnd, &printer, snum))
4873 return WERR_NOMEM;
4875 /* check the required size. */
4876 *needed += spoolss_size_printer_info_3(printer);
4878 if (*needed > offered) {
4879 result = WERR_INSUFFICIENT_BUFFER;
4880 goto out;
4883 if (!rpcbuf_alloc_size(buffer, *needed)) {
4884 result = WERR_NOMEM;
4885 goto out;
4888 /* fill the buffer with the structures */
4889 smb_io_printer_info_3("", buffer, printer, 0);
4891 out:
4892 /* clear memory */
4893 free_printer_info_3(printer);
4895 return result;
4898 /****************************************************************************
4899 ****************************************************************************/
4901 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4903 PRINTER_INFO_4 *printer=NULL;
4904 WERROR result = WERR_OK;
4906 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4907 return WERR_NOMEM;
4909 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4910 SAFE_FREE(printer);
4911 return WERR_NOMEM;
4914 /* check the required size. */
4915 *needed += spoolss_size_printer_info_4(printer);
4917 if (*needed > offered) {
4918 result = WERR_INSUFFICIENT_BUFFER;
4919 goto out;
4922 if (!rpcbuf_alloc_size(buffer, *needed)) {
4923 result = WERR_NOMEM;
4924 goto out;
4927 /* fill the buffer with the structures */
4928 smb_io_printer_info_4("", buffer, printer, 0);
4930 out:
4931 /* clear memory */
4932 free_printer_info_4(printer);
4934 return result;
4937 /****************************************************************************
4938 ****************************************************************************/
4940 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4942 PRINTER_INFO_5 *printer=NULL;
4943 WERROR result = WERR_OK;
4945 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4946 return WERR_NOMEM;
4948 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4949 free_printer_info_5(printer);
4950 return WERR_NOMEM;
4953 /* check the required size. */
4954 *needed += spoolss_size_printer_info_5(printer);
4956 if (*needed > offered) {
4957 result = WERR_INSUFFICIENT_BUFFER;
4958 goto out;
4961 if (!rpcbuf_alloc_size(buffer, *needed)) {
4962 result = WERR_NOMEM;
4963 goto out;
4966 /* fill the buffer with the structures */
4967 smb_io_printer_info_5("", buffer, printer, 0);
4969 out:
4970 /* clear memory */
4971 free_printer_info_5(printer);
4973 return result;
4976 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4977 int snum,
4978 RPC_BUFFER *buffer, uint32 offered,
4979 uint32 *needed)
4981 PRINTER_INFO_6 *printer;
4982 WERROR result = WERR_OK;
4984 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4985 return WERR_NOMEM;
4988 if (!construct_printer_info_6(print_hnd, printer, snum)) {
4989 free_printer_info_6(printer);
4990 return WERR_NOMEM;
4993 /* check the required size. */
4994 *needed += spoolss_size_printer_info_6(printer);
4996 if (*needed > offered) {
4997 result = WERR_INSUFFICIENT_BUFFER;
4998 goto out;
5001 if (!rpcbuf_alloc_size(buffer, *needed)) {
5002 result = WERR_NOMEM;
5003 goto out;
5006 /* fill the buffer with the structures */
5007 smb_io_printer_info_6("", buffer, printer, 0);
5009 out:
5010 /* clear memory */
5011 free_printer_info_6(printer);
5013 return result;
5016 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5018 PRINTER_INFO_7 *printer=NULL;
5019 WERROR result = WERR_OK;
5021 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5022 return WERR_NOMEM;
5024 if (!construct_printer_info_7(print_hnd, printer, snum))
5025 return WERR_NOMEM;
5027 /* check the required size. */
5028 *needed += spoolss_size_printer_info_7(printer);
5030 if (*needed > offered) {
5031 result = WERR_INSUFFICIENT_BUFFER;
5032 goto out;
5035 if (!rpcbuf_alloc_size(buffer, *needed)) {
5036 result = WERR_NOMEM;
5037 goto out;
5041 /* fill the buffer with the structures */
5042 smb_io_printer_info_7("", buffer, printer, 0);
5044 out:
5045 /* clear memory */
5046 free_printer_info_7(printer);
5048 return result;
5051 /****************************************************************************
5052 ****************************************************************************/
5054 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5056 POLICY_HND *handle = &q_u->handle;
5057 uint32 level = q_u->level;
5058 RPC_BUFFER *buffer = NULL;
5059 uint32 offered = q_u->offered;
5060 uint32 *needed = &r_u->needed;
5061 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5063 int snum;
5065 /* that's an [in out] buffer */
5067 if (!q_u->buffer && (offered!=0)) {
5068 return WERR_INVALID_PARAM;
5071 rpcbuf_move(q_u->buffer, &r_u->buffer);
5072 buffer = r_u->buffer;
5074 *needed=0;
5076 if (!get_printer_snum(p, handle, &snum, NULL))
5077 return WERR_BADFID;
5079 switch (level) {
5080 case 0:
5081 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5082 case 1:
5083 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5084 case 2:
5085 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5086 case 3:
5087 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5088 case 4:
5089 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5090 case 5:
5091 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5092 case 6:
5093 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5094 case 7:
5095 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5097 return WERR_UNKNOWN_LEVEL;
5100 /********************************************************************
5101 * fill a DRIVER_INFO_1 struct
5102 ********************************************************************/
5104 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5106 init_unistr( &info->name, driver.info_3->name);
5109 /********************************************************************
5110 * construct_printer_driver_info_1
5111 ********************************************************************/
5113 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5115 NT_PRINTER_INFO_LEVEL *printer = NULL;
5116 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5118 ZERO_STRUCT(driver);
5120 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5121 return WERR_INVALID_PRINTER_NAME;
5123 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5124 free_a_printer(&printer, 2);
5125 return WERR_UNKNOWN_PRINTER_DRIVER;
5128 fill_printer_driver_info_1(info, driver, servername, architecture);
5130 free_a_printer(&printer,2);
5132 return WERR_OK;
5135 /********************************************************************
5136 * construct_printer_driver_info_2
5137 * fill a printer_info_2 struct
5138 ********************************************************************/
5140 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5142 TALLOC_CTX *ctx = talloc_tos();
5143 char *temp = NULL;
5145 info->version=driver.info_3->cversion;
5147 init_unistr( &info->name, driver.info_3->name );
5148 init_unistr( &info->architecture, driver.info_3->environment );
5151 if (strlen(driver.info_3->driverpath)) {
5152 temp = talloc_asprintf(ctx,
5153 "\\\\%s%s",
5154 servername,
5155 driver.info_3->driverpath);
5156 init_unistr( &info->driverpath, temp );
5157 } else {
5158 init_unistr( &info->driverpath, "" );
5161 TALLOC_FREE(temp);
5162 if (strlen(driver.info_3->datafile)) {
5163 temp = talloc_asprintf(ctx,
5164 "\\\\%s%s",
5165 servername,
5166 driver.info_3->datafile);
5167 init_unistr( &info->datafile, temp );
5168 } else
5169 init_unistr( &info->datafile, "" );
5171 TALLOC_FREE(temp);
5172 if (strlen(driver.info_3->configfile)) {
5173 temp = talloc_asprintf(ctx,
5174 "\\\\%s%s",
5175 servername,
5176 driver.info_3->configfile);
5177 init_unistr( &info->configfile, temp );
5178 } else
5179 init_unistr( &info->configfile, "" );
5182 /********************************************************************
5183 * construct_printer_driver_info_2
5184 * fill a printer_info_2 struct
5185 ********************************************************************/
5187 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5189 NT_PRINTER_INFO_LEVEL *printer = NULL;
5190 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5192 ZERO_STRUCT(printer);
5193 ZERO_STRUCT(driver);
5195 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5196 return WERR_INVALID_PRINTER_NAME;
5198 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5199 free_a_printer(&printer, 2);
5200 return WERR_UNKNOWN_PRINTER_DRIVER;
5203 fill_printer_driver_info_2(info, driver, servername);
5205 free_a_printer(&printer,2);
5207 return WERR_OK;
5210 /********************************************************************
5211 * copy a strings array and convert to UNICODE
5213 * convert an array of ascii string to a UNICODE string
5214 ********************************************************************/
5216 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5218 int i=0;
5219 int j=0;
5220 const char *v;
5221 char *line = NULL;
5222 TALLOC_CTX *ctx = talloc_tos();
5224 DEBUG(6,("init_unistr_array\n"));
5225 *uni_array=NULL;
5227 while (true) {
5228 if ( !char_array ) {
5229 v = "";
5230 } else {
5231 v = char_array[i];
5232 if (!v)
5233 v = ""; /* hack to handle null lists */
5236 /* hack to allow this to be used in places other than when generating
5237 the list of dependent files */
5239 TALLOC_FREE(line);
5240 if ( servername ) {
5241 line = talloc_asprintf(ctx,
5242 "\\\\%s%s",
5243 servername,
5245 } else {
5246 line = talloc_strdup(ctx, v);
5249 if (!line) {
5250 SAFE_FREE(*uni_array);
5251 return 0;
5253 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5255 /* add one extra unit16 for the second terminating NULL */
5257 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5258 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5259 return 0;
5262 if ( !strlen(v) )
5263 break;
5265 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5266 i++;
5269 if (*uni_array) {
5270 /* special case for ""; we need to add both NULL's here */
5271 if (!j)
5272 (*uni_array)[j++]=0x0000;
5273 (*uni_array)[j]=0x0000;
5276 DEBUGADD(6,("last one:done\n"));
5278 /* return size of array in uint16's */
5280 return j+1;
5283 /********************************************************************
5284 * construct_printer_info_3
5285 * fill a printer_info_3 struct
5286 ********************************************************************/
5288 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5290 char *temp = NULL;
5291 TALLOC_CTX *ctx = talloc_tos();
5293 ZERO_STRUCTP(info);
5295 info->version=driver.info_3->cversion;
5297 init_unistr( &info->name, driver.info_3->name );
5298 init_unistr( &info->architecture, driver.info_3->environment );
5300 if (strlen(driver.info_3->driverpath)) {
5301 temp = talloc_asprintf(ctx,
5302 "\\\\%s%s",
5303 servername,
5304 driver.info_3->driverpath);
5305 init_unistr( &info->driverpath, temp );
5306 } else
5307 init_unistr( &info->driverpath, "" );
5309 TALLOC_FREE(temp);
5310 if (strlen(driver.info_3->datafile)) {
5311 temp = talloc_asprintf(ctx,
5312 "\\\\%s%s",
5313 servername,
5314 driver.info_3->datafile);
5315 init_unistr( &info->datafile, temp );
5316 } else
5317 init_unistr( &info->datafile, "" );
5319 TALLOC_FREE(temp);
5320 if (strlen(driver.info_3->configfile)) {
5321 temp = talloc_asprintf(ctx,
5322 "\\\\%s%s",
5323 servername,
5324 driver.info_3->configfile);
5325 init_unistr( &info->configfile, temp );
5326 } else
5327 init_unistr( &info->configfile, "" );
5329 TALLOC_FREE(temp);
5330 if (strlen(driver.info_3->helpfile)) {
5331 temp = talloc_asprintf(ctx,
5332 "\\\\%s%s",
5333 servername,
5334 driver.info_3->helpfile);
5335 init_unistr( &info->helpfile, temp );
5336 } else
5337 init_unistr( &info->helpfile, "" );
5339 TALLOC_FREE(temp);
5340 init_unistr( &info->monitorname, driver.info_3->monitorname );
5341 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5343 info->dependentfiles=NULL;
5344 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5347 /********************************************************************
5348 * construct_printer_info_3
5349 * fill a printer_info_3 struct
5350 ********************************************************************/
5352 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5354 NT_PRINTER_INFO_LEVEL *printer = NULL;
5355 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5356 WERROR status;
5357 ZERO_STRUCT(driver);
5359 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5360 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5361 if (!W_ERROR_IS_OK(status))
5362 return WERR_INVALID_PRINTER_NAME;
5364 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5365 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5367 #if 0 /* JERRY */
5370 * I put this code in during testing. Helpful when commenting out the
5371 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5372 * as win2k always queries the driver using an infor level of 6.
5373 * I've left it in (but ifdef'd out) because I'll probably
5374 * use it in experimentation again in the future. --jerry 22/01/2002
5377 if (!W_ERROR_IS_OK(status)) {
5379 * Is this a W2k client ?
5381 if (version == 3) {
5382 /* Yes - try again with a WinNT driver. */
5383 version = 2;
5384 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5385 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5387 #endif
5389 if (!W_ERROR_IS_OK(status)) {
5390 free_a_printer(&printer,2);
5391 return WERR_UNKNOWN_PRINTER_DRIVER;
5394 #if 0 /* JERRY */
5396 #endif
5399 fill_printer_driver_info_3(info, driver, servername);
5401 free_a_printer(&printer,2);
5403 return WERR_OK;
5406 /********************************************************************
5407 * construct_printer_info_6
5408 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5409 ********************************************************************/
5411 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5413 char *temp = NULL;
5414 fstring nullstr;
5415 TALLOC_CTX *ctx = talloc_tos();
5417 ZERO_STRUCTP(info);
5418 memset(&nullstr, '\0', sizeof(fstring));
5420 info->version=driver.info_3->cversion;
5422 init_unistr( &info->name, driver.info_3->name );
5423 init_unistr( &info->architecture, driver.info_3->environment );
5425 if (strlen(driver.info_3->driverpath)) {
5426 temp = talloc_asprintf(ctx,
5427 "\\\\%s%s",
5428 servername,
5429 driver.info_3->driverpath);
5430 init_unistr( &info->driverpath, temp );
5431 } else
5432 init_unistr( &info->driverpath, "" );
5434 TALLOC_FREE(temp);
5435 if (strlen(driver.info_3->datafile)) {
5436 temp = talloc_asprintf(ctx,
5437 "\\\\%s%s",
5438 servername,
5439 driver.info_3->datafile);
5440 init_unistr( &info->datafile, temp );
5441 } else
5442 init_unistr( &info->datafile, "" );
5444 TALLOC_FREE(temp);
5445 if (strlen(driver.info_3->configfile)) {
5446 temp = talloc_asprintf(ctx,
5447 "\\\\%s%s",
5448 servername,
5449 driver.info_3->configfile);
5450 init_unistr( &info->configfile, temp );
5451 } else
5452 init_unistr( &info->configfile, "" );
5454 TALLOC_FREE(temp);
5455 if (strlen(driver.info_3->helpfile)) {
5456 temp = talloc_asprintf(ctx,
5457 "\\\\%s%s",
5458 servername,
5459 driver.info_3->helpfile);
5460 init_unistr( &info->helpfile, temp );
5461 } else
5462 init_unistr( &info->helpfile, "" );
5464 TALLOC_FREE(temp);
5465 init_unistr( &info->monitorname, driver.info_3->monitorname );
5466 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5468 info->dependentfiles = NULL;
5469 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5471 info->previousdrivernames=NULL;
5472 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5474 info->driver_date=0;
5476 info->padding=0;
5477 info->driver_version_low=0;
5478 info->driver_version_high=0;
5480 init_unistr( &info->mfgname, "");
5481 init_unistr( &info->oem_url, "");
5482 init_unistr( &info->hardware_id, "");
5483 init_unistr( &info->provider, "");
5486 /********************************************************************
5487 * construct_printer_info_6
5488 * fill a printer_info_6 struct
5489 ********************************************************************/
5491 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5492 fstring servername, fstring architecture, uint32 version)
5494 NT_PRINTER_INFO_LEVEL *printer = NULL;
5495 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5496 WERROR status;
5498 ZERO_STRUCT(driver);
5500 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5502 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5504 if (!W_ERROR_IS_OK(status))
5505 return WERR_INVALID_PRINTER_NAME;
5507 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5509 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5511 if (!W_ERROR_IS_OK(status))
5514 * Is this a W2k client ?
5517 if (version < 3) {
5518 free_a_printer(&printer,2);
5519 return WERR_UNKNOWN_PRINTER_DRIVER;
5522 /* Yes - try again with a WinNT driver. */
5523 version = 2;
5524 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5525 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5526 if (!W_ERROR_IS_OK(status)) {
5527 free_a_printer(&printer,2);
5528 return WERR_UNKNOWN_PRINTER_DRIVER;
5532 fill_printer_driver_info_6(info, driver, servername);
5534 free_a_printer(&printer,2);
5535 free_a_printer_driver(driver, 3);
5537 return WERR_OK;
5540 /****************************************************************************
5541 ****************************************************************************/
5543 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5545 SAFE_FREE(info->dependentfiles);
5548 /****************************************************************************
5549 ****************************************************************************/
5551 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5553 SAFE_FREE(info->dependentfiles);
5556 /****************************************************************************
5557 ****************************************************************************/
5559 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5561 DRIVER_INFO_1 *info=NULL;
5562 WERROR result;
5564 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5565 return WERR_NOMEM;
5567 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5568 if (!W_ERROR_IS_OK(result))
5569 goto out;
5571 /* check the required size. */
5572 *needed += spoolss_size_printer_driver_info_1(info);
5574 if (*needed > offered) {
5575 result = WERR_INSUFFICIENT_BUFFER;
5576 goto out;
5579 if (!rpcbuf_alloc_size(buffer, *needed)) {
5580 result = WERR_NOMEM;
5581 goto out;
5584 /* fill the buffer with the structures */
5585 smb_io_printer_driver_info_1("", buffer, info, 0);
5587 out:
5588 /* clear memory */
5589 SAFE_FREE(info);
5591 return result;
5594 /****************************************************************************
5595 ****************************************************************************/
5597 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5599 DRIVER_INFO_2 *info=NULL;
5600 WERROR result;
5602 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5603 return WERR_NOMEM;
5605 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5606 if (!W_ERROR_IS_OK(result))
5607 goto out;
5609 /* check the required size. */
5610 *needed += spoolss_size_printer_driver_info_2(info);
5612 if (*needed > offered) {
5613 result = WERR_INSUFFICIENT_BUFFER;
5614 goto out;
5617 if (!rpcbuf_alloc_size(buffer, *needed)) {
5618 result = WERR_NOMEM;
5619 goto out;
5622 /* fill the buffer with the structures */
5623 smb_io_printer_driver_info_2("", buffer, info, 0);
5625 out:
5626 /* clear memory */
5627 SAFE_FREE(info);
5629 return result;
5632 /****************************************************************************
5633 ****************************************************************************/
5635 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5637 DRIVER_INFO_3 info;
5638 WERROR result;
5640 ZERO_STRUCT(info);
5642 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5643 if (!W_ERROR_IS_OK(result))
5644 goto out;
5646 /* check the required size. */
5647 *needed += spoolss_size_printer_driver_info_3(&info);
5649 if (*needed > offered) {
5650 result = WERR_INSUFFICIENT_BUFFER;
5651 goto out;
5654 if (!rpcbuf_alloc_size(buffer, *needed)) {
5655 result = WERR_NOMEM;
5656 goto out;
5659 /* fill the buffer with the structures */
5660 smb_io_printer_driver_info_3("", buffer, &info, 0);
5662 out:
5663 free_printer_driver_info_3(&info);
5665 return result;
5668 /****************************************************************************
5669 ****************************************************************************/
5671 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5673 DRIVER_INFO_6 info;
5674 WERROR result;
5676 ZERO_STRUCT(info);
5678 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5679 if (!W_ERROR_IS_OK(result))
5680 goto out;
5682 /* check the required size. */
5683 *needed += spoolss_size_printer_driver_info_6(&info);
5685 if (*needed > offered) {
5686 result = WERR_INSUFFICIENT_BUFFER;
5687 goto out;
5690 if (!rpcbuf_alloc_size(buffer, *needed)) {
5691 result = WERR_NOMEM;
5692 goto out;
5695 /* fill the buffer with the structures */
5696 smb_io_printer_driver_info_6("", buffer, &info, 0);
5698 out:
5699 free_printer_driver_info_6(&info);
5701 return result;
5704 /****************************************************************************
5705 ****************************************************************************/
5707 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5709 POLICY_HND *handle = &q_u->handle;
5710 UNISTR2 *uni_arch = &q_u->architecture;
5711 uint32 level = q_u->level;
5712 uint32 clientmajorversion = q_u->clientmajorversion;
5713 RPC_BUFFER *buffer = NULL;
5714 uint32 offered = q_u->offered;
5715 uint32 *needed = &r_u->needed;
5716 uint32 *servermajorversion = &r_u->servermajorversion;
5717 uint32 *serverminorversion = &r_u->serverminorversion;
5718 Printer_entry *printer;
5720 fstring servername;
5721 fstring architecture;
5722 int snum;
5724 /* that's an [in out] buffer */
5726 if (!q_u->buffer && (offered!=0)) {
5727 return WERR_INVALID_PARAM;
5730 rpcbuf_move(q_u->buffer, &r_u->buffer);
5731 buffer = r_u->buffer;
5733 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5735 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5736 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5737 return WERR_INVALID_PRINTER_NAME;
5740 *needed = 0;
5741 *servermajorversion = 0;
5742 *serverminorversion = 0;
5744 fstrcpy(servername, get_server_name( printer ));
5745 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5747 if (!get_printer_snum(p, handle, &snum, NULL))
5748 return WERR_BADFID;
5750 switch (level) {
5751 case 1:
5752 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5753 case 2:
5754 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5755 case 3:
5756 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5757 case 6:
5758 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5759 #if 0 /* JERRY */
5760 case 101:
5761 /* apparently this call is the equivalent of
5762 EnumPrinterDataEx() for the DsDriver key */
5763 break;
5764 #endif
5767 return WERR_UNKNOWN_LEVEL;
5770 /****************************************************************************
5771 ****************************************************************************/
5773 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5775 POLICY_HND *handle = &q_u->handle;
5777 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5779 if (!Printer) {
5780 DEBUG(3,("Error in startpageprinter printer handle\n"));
5781 return WERR_BADFID;
5784 Printer->page_started=True;
5785 return WERR_OK;
5788 /****************************************************************************
5789 ****************************************************************************/
5791 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5793 POLICY_HND *handle = &q_u->handle;
5794 int snum;
5796 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5798 if (!Printer) {
5799 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5800 return WERR_BADFID;
5803 if (!get_printer_snum(p, handle, &snum, NULL))
5804 return WERR_BADFID;
5806 Printer->page_started=False;
5807 print_job_endpage(snum, Printer->jobid);
5809 return WERR_OK;
5812 /********************************************************************
5813 * api_spoolss_getprinter
5814 * called from the spoolss dispatcher
5816 ********************************************************************/
5818 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5820 POLICY_HND *handle = &q_u->handle;
5821 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5822 uint32 *jobid = &r_u->jobid;
5823 TALLOC_CTX *ctx = p->mem_ctx;
5824 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5825 int snum;
5826 char *jobname = NULL;
5827 fstring datatype;
5828 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5830 if (!Printer) {
5831 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5832 return WERR_BADFID;
5836 * a nice thing with NT is it doesn't listen to what you tell it.
5837 * when asked to send _only_ RAW datas, it tries to send datas
5838 * in EMF format.
5840 * So I add checks like in NT Server ...
5843 if (info_1->p_datatype != 0) {
5844 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5845 if (strcmp(datatype, "RAW") != 0) {
5846 (*jobid)=0;
5847 return WERR_INVALID_DATATYPE;
5851 /* get the share number of the printer */
5852 if (!get_printer_snum(p, handle, &snum, NULL)) {
5853 return WERR_BADFID;
5856 jobname = unistr2_to_ascii_talloc(ctx, &info_1->docname);
5858 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5860 /* An error occured in print_job_start() so return an appropriate
5861 NT error code. */
5863 if (Printer->jobid == -1) {
5864 return map_werror_from_unix(errno);
5867 Printer->document_started=True;
5868 (*jobid) = Printer->jobid;
5870 return WERR_OK;
5873 /********************************************************************
5874 * api_spoolss_getprinter
5875 * called from the spoolss dispatcher
5877 ********************************************************************/
5879 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5881 POLICY_HND *handle = &q_u->handle;
5883 return _spoolss_enddocprinter_internal(p, handle);
5886 /****************************************************************************
5887 ****************************************************************************/
5889 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5891 POLICY_HND *handle = &q_u->handle;
5892 uint32 buffer_size = q_u->buffer_size;
5893 uint8 *buffer = q_u->buffer;
5894 uint32 *buffer_written = &q_u->buffer_size2;
5895 int snum;
5896 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5898 if (!Printer) {
5899 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5900 r_u->buffer_written = q_u->buffer_size2;
5901 return WERR_BADFID;
5904 if (!get_printer_snum(p, handle, &snum, NULL))
5905 return WERR_BADFID;
5907 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5908 (SMB_OFF_T)-1, (size_t)buffer_size);
5909 if (*buffer_written == (uint32)-1) {
5910 r_u->buffer_written = 0;
5911 if (errno == ENOSPC)
5912 return WERR_NO_SPOOL_SPACE;
5913 else
5914 return WERR_ACCESS_DENIED;
5917 r_u->buffer_written = q_u->buffer_size2;
5919 return WERR_OK;
5922 /********************************************************************
5923 * api_spoolss_getprinter
5924 * called from the spoolss dispatcher
5926 ********************************************************************/
5928 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5929 pipes_struct *p)
5931 int snum;
5932 WERROR errcode = WERR_BADFUNC;
5933 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5935 if (!Printer) {
5936 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5937 return WERR_BADFID;
5940 if (!get_printer_snum(p, handle, &snum, NULL))
5941 return WERR_BADFID;
5943 switch (command) {
5944 case PRINTER_CONTROL_PAUSE:
5945 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5946 errcode = WERR_OK;
5948 break;
5949 case PRINTER_CONTROL_RESUME:
5950 case PRINTER_CONTROL_UNPAUSE:
5951 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5952 errcode = WERR_OK;
5954 break;
5955 case PRINTER_CONTROL_PURGE:
5956 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5957 errcode = WERR_OK;
5959 break;
5960 default:
5961 return WERR_UNKNOWN_LEVEL;
5964 return errcode;
5967 /********************************************************************
5968 * api_spoolss_abortprinter
5969 * From MSDN: "Deletes printer's spool file if printer is configured
5970 * for spooling"
5971 ********************************************************************/
5973 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5975 POLICY_HND *handle = &q_u->handle;
5976 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5977 int snum;
5978 WERROR errcode = WERR_OK;
5980 if (!Printer) {
5981 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5982 return WERR_BADFID;
5985 if (!get_printer_snum(p, handle, &snum, NULL))
5986 return WERR_BADFID;
5988 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5990 return errcode;
5993 /********************************************************************
5994 * called by spoolss_api_setprinter
5995 * when updating a printer description
5996 ********************************************************************/
5998 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5999 const SPOOL_PRINTER_INFO_LEVEL *info,
6000 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6002 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6003 WERROR result;
6004 int snum;
6006 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6008 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6009 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6010 OUR_HANDLE(handle)));
6012 result = WERR_BADFID;
6013 goto done;
6016 if (!secdesc_ctr) {
6017 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6018 result = WERR_INVALID_PARAM;
6019 goto done;
6022 /* Check the user has permissions to change the security
6023 descriptor. By experimentation with two NT machines, the user
6024 requires Full Access to the printer to change security
6025 information. */
6027 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6028 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6029 result = WERR_ACCESS_DENIED;
6030 goto done;
6033 /* NT seems to like setting the security descriptor even though
6034 nothing may have actually changed. */
6036 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
6038 if (DEBUGLEVEL >= 10) {
6039 SEC_ACL *the_acl;
6040 int i;
6042 the_acl = old_secdesc_ctr->sd->dacl;
6043 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6044 PRINTERNAME(snum), the_acl->num_aces));
6046 for (i = 0; i < the_acl->num_aces; i++) {
6047 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6048 &the_acl->aces[i].trustee),
6049 the_acl->aces[i].access_mask));
6052 the_acl = secdesc_ctr->sd->dacl;
6054 if (the_acl) {
6055 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6056 PRINTERNAME(snum), the_acl->num_aces));
6058 for (i = 0; i < the_acl->num_aces; i++) {
6059 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6060 &the_acl->aces[i].trustee),
6061 the_acl->aces[i].access_mask));
6063 } else {
6064 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6068 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6069 if (!new_secdesc_ctr) {
6070 result = WERR_NOMEM;
6071 goto done;
6074 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6075 result = WERR_OK;
6076 goto done;
6079 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6081 done:
6083 return result;
6086 /********************************************************************
6087 Canonicalize printer info from a client
6089 ATTN: It does not matter what we set the servername to hear
6090 since we do the necessary work in get_a_printer() to set it to
6091 the correct value based on what the client sent in the
6092 _spoolss_open_printer_ex().
6093 ********************************************************************/
6095 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6097 fstring printername;
6098 const char *p;
6100 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6101 "portname=%s drivername=%s comment=%s location=%s\n",
6102 info->servername, info->printername, info->sharename,
6103 info->portname, info->drivername, info->comment, info->location));
6105 /* we force some elements to "correct" values */
6106 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6107 fstrcpy(info->sharename, lp_servicename(snum));
6109 /* check to see if we allow printername != sharename */
6111 if ( lp_force_printername(snum) ) {
6112 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6113 global_myname(), info->sharename );
6114 } else {
6116 /* make sure printername is in \\server\printername format */
6118 fstrcpy( printername, info->printername );
6119 p = printername;
6120 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6121 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6122 p++;
6125 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6126 global_myname(), p );
6129 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6130 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6134 return True;
6137 /****************************************************************************
6138 ****************************************************************************/
6140 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6142 char *cmd = lp_addport_cmd();
6143 char *command = NULL;
6144 int ret;
6145 int fd;
6146 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6147 bool is_print_op = False;
6149 if ( !*cmd ) {
6150 return WERR_ACCESS_DENIED;
6153 command = talloc_asprintf(ctx,
6154 "%s \"%s\" \"%s\"", cmd, portname, uri );
6155 if (!command) {
6156 return WERR_NOMEM;
6159 if ( token )
6160 is_print_op = user_has_privileges( token, &se_printop );
6162 DEBUG(10,("Running [%s]\n", command));
6164 /********* BEGIN SePrintOperatorPrivilege **********/
6166 if ( is_print_op )
6167 become_root();
6169 ret = smbrun(command, &fd);
6171 if ( is_print_op )
6172 unbecome_root();
6174 /********* END SePrintOperatorPrivilege **********/
6176 DEBUGADD(10,("returned [%d]\n", ret));
6178 TALLOC_FREE(command);
6180 if ( ret != 0 ) {
6181 if (fd != -1)
6182 close(fd);
6183 return WERR_ACCESS_DENIED;
6186 return WERR_OK;
6189 /****************************************************************************
6190 ****************************************************************************/
6192 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6194 char *cmd = lp_addprinter_cmd();
6195 char **qlines;
6196 char *command = NULL;
6197 int numlines;
6198 int ret;
6199 int fd;
6200 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6201 bool is_print_op = False;
6202 char *remote_machine = talloc_strdup(ctx, "%m");
6204 if (!remote_machine) {
6205 return false;
6207 remote_machine = talloc_sub_basic(ctx,
6208 current_user_info.smb_name,
6209 current_user_info.domain,
6210 remote_machine);
6211 if (!remote_machine) {
6212 return false;
6215 command = talloc_asprintf(ctx,
6216 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6217 cmd, printer->info_2->printername, printer->info_2->sharename,
6218 printer->info_2->portname, printer->info_2->drivername,
6219 printer->info_2->location, printer->info_2->comment, remote_machine);
6220 if (!command) {
6221 return false;
6224 if ( token )
6225 is_print_op = user_has_privileges( token, &se_printop );
6227 DEBUG(10,("Running [%s]\n", command));
6229 /********* BEGIN SePrintOperatorPrivilege **********/
6231 if ( is_print_op )
6232 become_root();
6234 if ( (ret = smbrun(command, &fd)) == 0 ) {
6235 /* Tell everyone we updated smb.conf. */
6236 message_send_all(smbd_messaging_context(),
6237 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6240 if ( is_print_op )
6241 unbecome_root();
6243 /********* END SePrintOperatorPrivilege **********/
6245 DEBUGADD(10,("returned [%d]\n", ret));
6247 TALLOC_FREE(command);
6248 TALLOC_FREE(remote_machine);
6250 if ( ret != 0 ) {
6251 if (fd != -1)
6252 close(fd);
6253 return False;
6256 /* reload our services immediately */
6257 reload_services( False );
6259 numlines = 0;
6260 /* Get lines and convert them back to dos-codepage */
6261 qlines = fd_lines_load(fd, &numlines, 0);
6262 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6263 close(fd);
6265 /* Set the portname to what the script says the portname should be. */
6266 /* but don't require anything to be return from the script exit a good error code */
6268 if (numlines) {
6269 /* Set the portname to what the script says the portname should be. */
6270 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6271 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6274 file_lines_free(qlines);
6275 return True;
6279 /********************************************************************
6280 * Called by spoolss_api_setprinter
6281 * when updating a printer description.
6282 ********************************************************************/
6284 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6285 const SPOOL_PRINTER_INFO_LEVEL *info,
6286 DEVICEMODE *devmode)
6288 int snum;
6289 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6290 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6291 WERROR result;
6292 UNISTR2 buffer;
6293 fstring asc_buffer;
6295 DEBUG(8,("update_printer\n"));
6297 result = WERR_OK;
6299 if (!Printer) {
6300 result = WERR_BADFID;
6301 goto done;
6304 if (!get_printer_snum(p, handle, &snum, NULL)) {
6305 result = WERR_BADFID;
6306 goto done;
6309 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6310 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6311 result = WERR_BADFID;
6312 goto done;
6315 DEBUGADD(8,("Converting info_2 struct\n"));
6318 * convert_printer_info converts the incoming
6319 * info from the client and overwrites the info
6320 * just read from the tdb in the pointer 'printer'.
6323 if (!convert_printer_info(info, printer, level)) {
6324 result = WERR_NOMEM;
6325 goto done;
6328 if (devmode) {
6329 /* we have a valid devmode
6330 convert it and link it*/
6332 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6333 if (!convert_devicemode(printer->info_2->printername, devmode,
6334 &printer->info_2->devmode)) {
6335 result = WERR_NOMEM;
6336 goto done;
6340 /* Do sanity check on the requested changes for Samba */
6342 if (!check_printer_ok(printer->info_2, snum)) {
6343 result = WERR_INVALID_PARAM;
6344 goto done;
6347 /* FIXME!!! If the driver has changed we really should verify that
6348 it is installed before doing much else --jerry */
6350 /* Check calling user has permission to update printer description */
6352 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6353 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6354 result = WERR_ACCESS_DENIED;
6355 goto done;
6358 /* Call addprinter hook */
6359 /* Check changes to see if this is really needed */
6361 if ( *lp_addprinter_cmd()
6362 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6363 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6364 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6365 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6367 /* add_printer_hook() will call reload_services() */
6369 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
6370 result = WERR_ACCESS_DENIED;
6371 goto done;
6376 * When a *new* driver is bound to a printer, the drivername is used to
6377 * lookup previously saved driver initialization info, which is then
6378 * bound to the printer, simulating what happens in the Windows arch.
6380 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6382 if (!set_driver_init(printer, 2))
6384 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6385 printer->info_2->drivername));
6388 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6389 printer->info_2->drivername));
6391 notify_printer_driver(snum, printer->info_2->drivername);
6395 * flag which changes actually occured. This is a small subset of
6396 * all the possible changes. We also have to update things in the
6397 * DsSpooler key.
6400 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6401 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6402 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6403 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6405 notify_printer_comment(snum, printer->info_2->comment);
6408 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6409 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6410 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6411 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6413 notify_printer_sharename(snum, printer->info_2->sharename);
6416 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6417 char *pname;
6419 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6420 pname++;
6421 else
6422 pname = printer->info_2->printername;
6425 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6426 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6427 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6429 notify_printer_printername( snum, pname );
6432 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6433 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6434 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6435 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6437 notify_printer_port(snum, printer->info_2->portname);
6440 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6441 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6442 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6443 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6445 notify_printer_location(snum, printer->info_2->location);
6448 /* here we need to update some more DsSpooler keys */
6449 /* uNCName, serverName, shortServerName */
6451 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6452 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6453 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6454 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6455 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6457 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6458 global_myname(), printer->info_2->sharename );
6459 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6460 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6461 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6463 /* Update printer info */
6464 result = mod_a_printer(printer, 2);
6466 done:
6467 free_a_printer(&printer, 2);
6468 free_a_printer(&old_printer, 2);
6471 return result;
6474 /****************************************************************************
6475 ****************************************************************************/
6476 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6477 const SPOOL_PRINTER_INFO_LEVEL *info)
6479 #ifdef HAVE_ADS
6480 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6481 int snum;
6482 Printer_entry *Printer;
6484 if ( lp_security() != SEC_ADS ) {
6485 return WERR_UNKNOWN_LEVEL;
6488 Printer = find_printer_index_by_hnd(p, handle);
6490 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6492 if (!Printer)
6493 return WERR_BADFID;
6495 if (!get_printer_snum(p, handle, &snum, NULL))
6496 return WERR_BADFID;
6498 nt_printer_publish(Printer, snum, info7->action);
6500 return WERR_OK;
6501 #else
6502 return WERR_UNKNOWN_LEVEL;
6503 #endif
6505 /****************************************************************************
6506 ****************************************************************************/
6508 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6510 POLICY_HND *handle = &q_u->handle;
6511 uint32 level = q_u->level;
6512 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6513 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6514 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6515 uint32 command = q_u->command;
6516 WERROR result;
6518 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6520 if (!Printer) {
6521 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6522 return WERR_BADFID;
6525 /* check the level */
6526 switch (level) {
6527 case 0:
6528 return control_printer(handle, command, p);
6529 case 2:
6530 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6531 if (!W_ERROR_IS_OK(result))
6532 return result;
6533 if (secdesc_ctr)
6534 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6535 return result;
6536 case 3:
6537 return update_printer_sec(handle, level, info, p,
6538 secdesc_ctr);
6539 case 7:
6540 return publish_or_unpublish_printer(p, handle, info);
6541 default:
6542 return WERR_UNKNOWN_LEVEL;
6546 /****************************************************************************
6547 ****************************************************************************/
6549 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6551 POLICY_HND *handle = &q_u->handle;
6552 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6554 if (!Printer) {
6555 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6556 return WERR_BADFID;
6559 if (Printer->notify.client_connected==True) {
6560 int snum = -1;
6562 if ( Printer->printer_type == SPLHND_SERVER)
6563 snum = -1;
6564 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6565 !get_printer_snum(p, handle, &snum, NULL) )
6566 return WERR_BADFID;
6568 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6571 Printer->notify.flags=0;
6572 Printer->notify.options=0;
6573 Printer->notify.localmachine[0]='\0';
6574 Printer->notify.printerlocal=0;
6575 if (Printer->notify.option)
6576 free_spool_notify_option(&Printer->notify.option);
6577 Printer->notify.client_connected=False;
6579 return WERR_OK;
6582 /****************************************************************************
6583 ****************************************************************************/
6585 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6587 /* that's an [in out] buffer */
6589 if (!q_u->buffer && (q_u->offered!=0)) {
6590 return WERR_INVALID_PARAM;
6593 rpcbuf_move(q_u->buffer, &r_u->buffer);
6595 r_u->needed = 0;
6596 return WERR_INVALID_PARAM; /* this is what a NT server
6597 returns for AddJob. AddJob
6598 must fail on non-local
6599 printers */
6602 /****************************************************************************
6603 ****************************************************************************/
6605 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6606 int position, int snum,
6607 const NT_PRINTER_INFO_LEVEL *ntprinter)
6609 struct tm *t;
6611 t=gmtime(&queue->time);
6613 job_info->jobid=queue->job;
6614 init_unistr(&job_info->printername, lp_servicename(snum));
6615 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6616 init_unistr(&job_info->username, queue->fs_user);
6617 init_unistr(&job_info->document, queue->fs_file);
6618 init_unistr(&job_info->datatype, "RAW");
6619 init_unistr(&job_info->text_status, "");
6620 job_info->status=nt_printj_status(queue->status);
6621 job_info->priority=queue->priority;
6622 job_info->position=position;
6623 job_info->totalpages=queue->page_count;
6624 job_info->pagesprinted=0;
6626 make_systemtime(&job_info->submitted, t);
6629 /****************************************************************************
6630 ****************************************************************************/
6632 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6633 int position, int snum,
6634 const NT_PRINTER_INFO_LEVEL *ntprinter,
6635 DEVICEMODE *devmode)
6637 struct tm *t;
6639 t=gmtime(&queue->time);
6641 job_info->jobid=queue->job;
6643 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6645 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6646 init_unistr(&job_info->username, queue->fs_user);
6647 init_unistr(&job_info->document, queue->fs_file);
6648 init_unistr(&job_info->notifyname, queue->fs_user);
6649 init_unistr(&job_info->datatype, "RAW");
6650 init_unistr(&job_info->printprocessor, "winprint");
6651 init_unistr(&job_info->parameters, "");
6652 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6653 init_unistr(&job_info->text_status, "");
6655 /* and here the security descriptor */
6657 job_info->status=nt_printj_status(queue->status);
6658 job_info->priority=queue->priority;
6659 job_info->position=position;
6660 job_info->starttime=0;
6661 job_info->untiltime=0;
6662 job_info->totalpages=queue->page_count;
6663 job_info->size=queue->size;
6664 make_systemtime(&(job_info->submitted), t);
6665 job_info->timeelapsed=0;
6666 job_info->pagesprinted=0;
6668 job_info->devmode = devmode;
6670 return (True);
6673 /****************************************************************************
6674 Enumjobs at level 1.
6675 ****************************************************************************/
6677 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6678 const NT_PRINTER_INFO_LEVEL *ntprinter,
6679 RPC_BUFFER *buffer, uint32 offered,
6680 uint32 *needed, uint32 *returned)
6682 JOB_INFO_1 *info;
6683 int i;
6684 WERROR result = WERR_OK;
6686 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6687 if (info==NULL) {
6688 *returned=0;
6689 return WERR_NOMEM;
6692 for (i=0; i<*returned; i++)
6693 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6695 /* check the required size. */
6696 for (i=0; i<*returned; i++)
6697 (*needed) += spoolss_size_job_info_1(&info[i]);
6699 if (*needed > offered) {
6700 result = WERR_INSUFFICIENT_BUFFER;
6701 goto out;
6704 if (!rpcbuf_alloc_size(buffer, *needed)) {
6705 result = WERR_NOMEM;
6706 goto out;
6709 /* fill the buffer with the structures */
6710 for (i=0; i<*returned; i++)
6711 smb_io_job_info_1("", buffer, &info[i], 0);
6713 out:
6714 /* clear memory */
6715 SAFE_FREE(info);
6717 if ( !W_ERROR_IS_OK(result) )
6718 *returned = 0;
6720 return result;
6723 /****************************************************************************
6724 Enumjobs at level 2.
6725 ****************************************************************************/
6727 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6728 const NT_PRINTER_INFO_LEVEL *ntprinter,
6729 RPC_BUFFER *buffer, uint32 offered,
6730 uint32 *needed, uint32 *returned)
6732 JOB_INFO_2 *info = NULL;
6733 int i;
6734 WERROR result = WERR_OK;
6735 DEVICEMODE *devmode = NULL;
6737 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6738 *returned=0;
6739 return WERR_NOMEM;
6742 /* this should not be a failure condition if the devmode is NULL */
6744 devmode = construct_dev_mode(lp_const_servicename(snum));
6746 for (i=0; i<*returned; i++)
6747 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6749 /* check the required size. */
6750 for (i=0; i<*returned; i++)
6751 (*needed) += spoolss_size_job_info_2(&info[i]);
6753 if (*needed > offered) {
6754 result = WERR_INSUFFICIENT_BUFFER;
6755 goto out;
6758 if (!rpcbuf_alloc_size(buffer, *needed)) {
6759 result = WERR_NOMEM;
6760 goto out;
6763 /* fill the buffer with the structures */
6764 for (i=0; i<*returned; i++)
6765 smb_io_job_info_2("", buffer, &info[i], 0);
6767 out:
6768 free_devmode(devmode);
6769 SAFE_FREE(info);
6771 if ( !W_ERROR_IS_OK(result) )
6772 *returned = 0;
6774 return result;
6778 /****************************************************************************
6779 Enumjobs.
6780 ****************************************************************************/
6782 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6784 POLICY_HND *handle = &q_u->handle;
6785 uint32 level = q_u->level;
6786 RPC_BUFFER *buffer = NULL;
6787 uint32 offered = q_u->offered;
6788 uint32 *needed = &r_u->needed;
6789 uint32 *returned = &r_u->returned;
6790 WERROR wret;
6791 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6792 int snum;
6793 print_status_struct prt_status;
6794 print_queue_struct *queue=NULL;
6796 /* that's an [in out] buffer */
6798 if (!q_u->buffer && (offered!=0)) {
6799 return WERR_INVALID_PARAM;
6802 rpcbuf_move(q_u->buffer, &r_u->buffer);
6803 buffer = r_u->buffer;
6805 DEBUG(4,("_spoolss_enumjobs\n"));
6807 *needed=0;
6808 *returned=0;
6810 /* lookup the printer snum and tdb entry */
6812 if (!get_printer_snum(p, handle, &snum, NULL))
6813 return WERR_BADFID;
6815 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6816 if ( !W_ERROR_IS_OK(wret) )
6817 return wret;
6819 *returned = print_queue_status(snum, &queue, &prt_status);
6820 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6822 if (*returned == 0) {
6823 SAFE_FREE(queue);
6824 free_a_printer(&ntprinter, 2);
6825 return WERR_OK;
6828 switch (level) {
6829 case 1:
6830 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6831 break;
6832 case 2:
6833 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6834 break;
6835 default:
6836 *returned=0;
6837 wret = WERR_UNKNOWN_LEVEL;
6838 break;
6841 SAFE_FREE(queue);
6842 free_a_printer( &ntprinter, 2 );
6843 return wret;
6846 /****************************************************************************
6847 ****************************************************************************/
6849 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6851 return WERR_OK;
6854 /****************************************************************************
6855 ****************************************************************************/
6857 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6859 POLICY_HND *handle = &q_u->handle;
6860 uint32 jobid = q_u->jobid;
6861 uint32 command = q_u->command;
6863 int snum;
6864 WERROR errcode = WERR_BADFUNC;
6866 if (!get_printer_snum(p, handle, &snum, NULL)) {
6867 return WERR_BADFID;
6870 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6871 return WERR_INVALID_PRINTER_NAME;
6874 switch (command) {
6875 case JOB_CONTROL_CANCEL:
6876 case JOB_CONTROL_DELETE:
6877 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6878 errcode = WERR_OK;
6880 break;
6881 case JOB_CONTROL_PAUSE:
6882 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6883 errcode = WERR_OK;
6885 break;
6886 case JOB_CONTROL_RESTART:
6887 case JOB_CONTROL_RESUME:
6888 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6889 errcode = WERR_OK;
6891 break;
6892 default:
6893 return WERR_UNKNOWN_LEVEL;
6896 return errcode;
6899 /****************************************************************************
6900 Enumerates all printer drivers at level 1.
6901 ****************************************************************************/
6903 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6905 int i;
6906 int ndrivers;
6907 uint32 version;
6908 fstring *list = NULL;
6909 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6910 DRIVER_INFO_1 *driver_info_1=NULL;
6911 WERROR result = WERR_OK;
6913 *returned=0;
6915 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6916 list=NULL;
6917 ndrivers=get_ntdrivers(&list, architecture, version);
6918 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6920 if(ndrivers == -1) {
6921 SAFE_FREE(driver_info_1);
6922 return WERR_NOMEM;
6925 if(ndrivers != 0) {
6926 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6927 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6928 SAFE_FREE(list);
6929 return WERR_NOMEM;
6933 for (i=0; i<ndrivers; i++) {
6934 WERROR status;
6935 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6936 ZERO_STRUCT(driver);
6937 status = get_a_printer_driver(&driver, 3, list[i],
6938 architecture, version);
6939 if (!W_ERROR_IS_OK(status)) {
6940 SAFE_FREE(list);
6941 SAFE_FREE(driver_info_1);
6942 return status;
6944 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6945 free_a_printer_driver(driver, 3);
6948 *returned+=ndrivers;
6949 SAFE_FREE(list);
6952 /* check the required size. */
6953 for (i=0; i<*returned; i++) {
6954 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6955 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6958 if (*needed > offered) {
6959 result = WERR_INSUFFICIENT_BUFFER;
6960 goto out;
6963 if (!rpcbuf_alloc_size(buffer, *needed)) {
6964 result = WERR_NOMEM;
6965 goto out;
6968 /* fill the buffer with the driver structures */
6969 for (i=0; i<*returned; i++) {
6970 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6971 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6974 out:
6975 SAFE_FREE(driver_info_1);
6977 if ( !W_ERROR_IS_OK(result) )
6978 *returned = 0;
6980 return result;
6983 /****************************************************************************
6984 Enumerates all printer drivers at level 2.
6985 ****************************************************************************/
6987 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6989 int i;
6990 int ndrivers;
6991 uint32 version;
6992 fstring *list = NULL;
6993 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6994 DRIVER_INFO_2 *driver_info_2=NULL;
6995 WERROR result = WERR_OK;
6997 *returned=0;
6999 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7000 list=NULL;
7001 ndrivers=get_ntdrivers(&list, architecture, version);
7002 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7004 if(ndrivers == -1) {
7005 SAFE_FREE(driver_info_2);
7006 return WERR_NOMEM;
7009 if(ndrivers != 0) {
7010 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7011 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7012 SAFE_FREE(list);
7013 return WERR_NOMEM;
7017 for (i=0; i<ndrivers; i++) {
7018 WERROR status;
7020 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7021 ZERO_STRUCT(driver);
7022 status = get_a_printer_driver(&driver, 3, list[i],
7023 architecture, version);
7024 if (!W_ERROR_IS_OK(status)) {
7025 SAFE_FREE(list);
7026 SAFE_FREE(driver_info_2);
7027 return status;
7029 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7030 free_a_printer_driver(driver, 3);
7033 *returned+=ndrivers;
7034 SAFE_FREE(list);
7037 /* check the required size. */
7038 for (i=0; i<*returned; i++) {
7039 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7040 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7043 if (*needed > offered) {
7044 result = WERR_INSUFFICIENT_BUFFER;
7045 goto out;
7048 if (!rpcbuf_alloc_size(buffer, *needed)) {
7049 result = WERR_NOMEM;
7050 goto out;
7053 /* fill the buffer with the form structures */
7054 for (i=0; i<*returned; i++) {
7055 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7056 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7059 out:
7060 SAFE_FREE(driver_info_2);
7062 if ( !W_ERROR_IS_OK(result) )
7063 *returned = 0;
7065 return result;
7068 /****************************************************************************
7069 Enumerates all printer drivers at level 3.
7070 ****************************************************************************/
7072 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7074 int i;
7075 int ndrivers;
7076 uint32 version;
7077 fstring *list = NULL;
7078 DRIVER_INFO_3 *driver_info_3=NULL;
7079 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7080 WERROR result = WERR_OK;
7082 *returned=0;
7084 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7085 list=NULL;
7086 ndrivers=get_ntdrivers(&list, architecture, version);
7087 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7089 if(ndrivers == -1) {
7090 SAFE_FREE(driver_info_3);
7091 return WERR_NOMEM;
7094 if(ndrivers != 0) {
7095 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7096 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7097 SAFE_FREE(list);
7098 return WERR_NOMEM;
7102 for (i=0; i<ndrivers; i++) {
7103 WERROR status;
7105 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7106 ZERO_STRUCT(driver);
7107 status = get_a_printer_driver(&driver, 3, list[i],
7108 architecture, version);
7109 if (!W_ERROR_IS_OK(status)) {
7110 SAFE_FREE(list);
7111 SAFE_FREE(driver_info_3);
7112 return status;
7114 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7115 free_a_printer_driver(driver, 3);
7118 *returned+=ndrivers;
7119 SAFE_FREE(list);
7122 /* check the required size. */
7123 for (i=0; i<*returned; i++) {
7124 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7125 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7128 if (*needed > offered) {
7129 result = WERR_INSUFFICIENT_BUFFER;
7130 goto out;
7133 if (!rpcbuf_alloc_size(buffer, *needed)) {
7134 result = WERR_NOMEM;
7135 goto out;
7138 /* fill the buffer with the driver structures */
7139 for (i=0; i<*returned; i++) {
7140 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7141 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7144 out:
7145 for (i=0; i<*returned; i++) {
7146 SAFE_FREE(driver_info_3[i].dependentfiles);
7149 SAFE_FREE(driver_info_3);
7151 if ( !W_ERROR_IS_OK(result) )
7152 *returned = 0;
7154 return result;
7157 /****************************************************************************
7158 Enumerates all printer drivers.
7159 ****************************************************************************/
7161 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7163 uint32 level = q_u->level;
7164 RPC_BUFFER *buffer = NULL;
7165 uint32 offered = q_u->offered;
7166 uint32 *needed = &r_u->needed;
7167 uint32 *returned = &r_u->returned;
7169 fstring servername;
7170 fstring architecture;
7172 /* that's an [in out] buffer */
7174 if (!q_u->buffer && (offered!=0)) {
7175 return WERR_INVALID_PARAM;
7178 rpcbuf_move(q_u->buffer, &r_u->buffer);
7179 buffer = r_u->buffer;
7181 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7183 *needed = 0;
7184 *returned = 0;
7186 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7187 unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7189 if ( !is_myname_or_ipaddr( servername ) )
7190 return WERR_UNKNOWN_PRINTER_DRIVER;
7192 switch (level) {
7193 case 1:
7194 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7195 case 2:
7196 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7197 case 3:
7198 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7199 default:
7200 return WERR_UNKNOWN_LEVEL;
7204 /****************************************************************************
7205 ****************************************************************************/
7207 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7209 form->flag=list->flag;
7210 init_unistr(&form->name, list->name);
7211 form->width=list->width;
7212 form->length=list->length;
7213 form->left=list->left;
7214 form->top=list->top;
7215 form->right=list->right;
7216 form->bottom=list->bottom;
7219 /****************************************************************************
7220 ****************************************************************************/
7222 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7224 uint32 level = q_u->level;
7225 RPC_BUFFER *buffer = NULL;
7226 uint32 offered = q_u->offered;
7227 uint32 *needed = &r_u->needed;
7228 uint32 *numofforms = &r_u->numofforms;
7229 uint32 numbuiltinforms;
7231 nt_forms_struct *list=NULL;
7232 nt_forms_struct *builtinlist=NULL;
7233 FORM_1 *forms_1;
7234 int buffer_size=0;
7235 int i;
7237 /* that's an [in out] buffer */
7239 if (!q_u->buffer && (offered!=0) ) {
7240 return WERR_INVALID_PARAM;
7243 rpcbuf_move(q_u->buffer, &r_u->buffer);
7244 buffer = r_u->buffer;
7246 DEBUG(4,("_spoolss_enumforms\n"));
7247 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7248 DEBUGADD(5,("Info level [%d]\n", level));
7250 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7251 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7252 *numofforms = get_ntforms(&list);
7253 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7254 *numofforms += numbuiltinforms;
7256 if (*numofforms == 0) {
7257 SAFE_FREE(builtinlist);
7258 SAFE_FREE(list);
7259 return WERR_NO_MORE_ITEMS;
7262 switch (level) {
7263 case 1:
7264 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7265 SAFE_FREE(builtinlist);
7266 SAFE_FREE(list);
7267 *numofforms=0;
7268 return WERR_NOMEM;
7271 /* construct the list of form structures */
7272 for (i=0; i<numbuiltinforms; i++) {
7273 DEBUGADD(6,("Filling form number [%d]\n",i));
7274 fill_form_1(&forms_1[i], &builtinlist[i]);
7277 SAFE_FREE(builtinlist);
7279 for (; i<*numofforms; i++) {
7280 DEBUGADD(6,("Filling form number [%d]\n",i));
7281 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7284 SAFE_FREE(list);
7286 /* check the required size. */
7287 for (i=0; i<numbuiltinforms; i++) {
7288 DEBUGADD(6,("adding form [%d]'s size\n",i));
7289 buffer_size += spoolss_size_form_1(&forms_1[i]);
7291 for (; i<*numofforms; i++) {
7292 DEBUGADD(6,("adding form [%d]'s size\n",i));
7293 buffer_size += spoolss_size_form_1(&forms_1[i]);
7296 *needed=buffer_size;
7298 if (*needed > offered) {
7299 SAFE_FREE(forms_1);
7300 *numofforms=0;
7301 return WERR_INSUFFICIENT_BUFFER;
7304 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7305 SAFE_FREE(forms_1);
7306 *numofforms=0;
7307 return WERR_NOMEM;
7310 /* fill the buffer with the form structures */
7311 for (i=0; i<numbuiltinforms; i++) {
7312 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7313 smb_io_form_1("", buffer, &forms_1[i], 0);
7315 for (; i<*numofforms; i++) {
7316 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7317 smb_io_form_1("", buffer, &forms_1[i], 0);
7320 SAFE_FREE(forms_1);
7322 return WERR_OK;
7324 default:
7325 SAFE_FREE(list);
7326 SAFE_FREE(builtinlist);
7327 return WERR_UNKNOWN_LEVEL;
7331 /****************************************************************************
7332 ****************************************************************************/
7334 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7336 uint32 level = q_u->level;
7337 UNISTR2 *uni_formname = &q_u->formname;
7338 RPC_BUFFER *buffer = NULL;
7339 uint32 offered = q_u->offered;
7340 uint32 *needed = &r_u->needed;
7342 nt_forms_struct *list=NULL;
7343 nt_forms_struct builtin_form;
7344 bool foundBuiltin;
7345 FORM_1 form_1;
7346 fstring form_name;
7347 int buffer_size=0;
7348 int numofforms=0, i=0;
7350 /* that's an [in out] buffer */
7352 if (!q_u->buffer && (offered!=0)) {
7353 return WERR_INVALID_PARAM;
7356 rpcbuf_move(q_u->buffer, &r_u->buffer);
7357 buffer = r_u->buffer;
7359 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
7361 DEBUG(4,("_spoolss_getform\n"));
7362 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7363 DEBUGADD(5,("Info level [%d]\n", level));
7365 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7366 if (!foundBuiltin) {
7367 numofforms = get_ntforms(&list);
7368 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7370 if (numofforms == 0)
7371 return WERR_BADFID;
7374 switch (level) {
7375 case 1:
7376 if (foundBuiltin) {
7377 fill_form_1(&form_1, &builtin_form);
7378 } else {
7380 /* Check if the requested name is in the list of form structures */
7381 for (i=0; i<numofforms; i++) {
7383 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7385 if (strequal(form_name, list[i].name)) {
7386 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7387 fill_form_1(&form_1, &list[i]);
7388 break;
7392 SAFE_FREE(list);
7393 if (i == numofforms) {
7394 return WERR_BADFID;
7397 /* check the required size. */
7399 *needed=spoolss_size_form_1(&form_1);
7401 if (*needed > offered)
7402 return WERR_INSUFFICIENT_BUFFER;
7404 if (!rpcbuf_alloc_size(buffer, buffer_size))
7405 return WERR_NOMEM;
7407 /* fill the buffer with the form structures */
7408 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7409 smb_io_form_1("", buffer, &form_1, 0);
7411 return WERR_OK;
7413 default:
7414 SAFE_FREE(list);
7415 return WERR_UNKNOWN_LEVEL;
7419 /****************************************************************************
7420 ****************************************************************************/
7422 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7424 init_unistr(&port->port_name, name);
7427 /****************************************************************************
7428 TODO: This probably needs distinguish between TCP/IP and Local ports
7429 somehow.
7430 ****************************************************************************/
7432 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7434 init_unistr(&port->port_name, name);
7435 init_unistr(&port->monitor_name, "Local Monitor");
7436 init_unistr(&port->description, SPL_LOCAL_PORT );
7437 port->port_type=PORT_TYPE_WRITE;
7438 port->reserved=0x0;
7442 /****************************************************************************
7443 wrapper around the enumer ports command
7444 ****************************************************************************/
7446 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7448 char *cmd = lp_enumports_cmd();
7449 char **qlines = NULL;
7450 char *command = NULL;
7451 int numlines;
7452 int ret;
7453 int fd;
7455 *count = 0;
7456 *lines = NULL;
7458 /* if no hook then just fill in the default port */
7460 if ( !*cmd ) {
7461 if (!(qlines = SMB_MALLOC_ARRAY( char*, 2 ))) {
7462 return WERR_NOMEM;
7464 if (!(qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME ))) {
7465 SAFE_FREE(qlines);
7466 return WERR_NOMEM;
7468 qlines[1] = NULL;
7469 numlines = 1;
7471 else {
7472 /* we have a valid enumport command */
7474 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7475 if (!command) {
7476 return WERR_NOMEM;
7479 DEBUG(10,("Running [%s]\n", command));
7480 ret = smbrun(command, &fd);
7481 DEBUG(10,("Returned [%d]\n", ret));
7482 TALLOC_FREE(command);
7483 if (ret != 0) {
7484 if (fd != -1) {
7485 close(fd);
7487 return WERR_ACCESS_DENIED;
7490 numlines = 0;
7491 qlines = fd_lines_load(fd, &numlines, 0);
7492 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7493 close(fd);
7496 *count = numlines;
7497 *lines = qlines;
7499 return WERR_OK;
7502 /****************************************************************************
7503 enumports level 1.
7504 ****************************************************************************/
7506 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7508 PORT_INFO_1 *ports=NULL;
7509 int i=0;
7510 WERROR result = WERR_OK;
7511 char **qlines = NULL;
7512 int numlines = 0;
7514 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7515 if (!W_ERROR_IS_OK(result)) {
7516 file_lines_free(qlines);
7517 return result;
7520 if(numlines) {
7521 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7522 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7523 dos_errstr(WERR_NOMEM)));
7524 file_lines_free(qlines);
7525 return WERR_NOMEM;
7528 for (i=0; i<numlines; i++) {
7529 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7530 fill_port_1(&ports[i], qlines[i]);
7533 file_lines_free(qlines);
7535 *returned = numlines;
7537 /* check the required size. */
7538 for (i=0; i<*returned; i++) {
7539 DEBUGADD(6,("adding port [%d]'s size\n", i));
7540 *needed += spoolss_size_port_info_1(&ports[i]);
7543 if (*needed > offered) {
7544 result = WERR_INSUFFICIENT_BUFFER;
7545 goto out;
7548 if (!rpcbuf_alloc_size(buffer, *needed)) {
7549 result = WERR_NOMEM;
7550 goto out;
7553 /* fill the buffer with the ports structures */
7554 for (i=0; i<*returned; i++) {
7555 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7556 smb_io_port_1("", buffer, &ports[i], 0);
7559 out:
7560 SAFE_FREE(ports);
7562 if ( !W_ERROR_IS_OK(result) )
7563 *returned = 0;
7565 return result;
7568 /****************************************************************************
7569 enumports level 2.
7570 ****************************************************************************/
7572 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7574 PORT_INFO_2 *ports=NULL;
7575 int i=0;
7576 WERROR result = WERR_OK;
7577 char **qlines = NULL;
7578 int numlines = 0;
7580 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7581 if ( !W_ERROR_IS_OK(result)) {
7582 file_lines_free(qlines);
7583 return result;
7586 if(numlines) {
7587 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7588 file_lines_free(qlines);
7589 return WERR_NOMEM;
7592 for (i=0; i<numlines; i++) {
7593 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7594 fill_port_2(&(ports[i]), qlines[i]);
7598 file_lines_free(qlines);
7600 *returned = numlines;
7602 /* check the required size. */
7603 for (i=0; i<*returned; i++) {
7604 DEBUGADD(6,("adding port [%d]'s size\n", i));
7605 *needed += spoolss_size_port_info_2(&ports[i]);
7608 if (*needed > offered) {
7609 result = WERR_INSUFFICIENT_BUFFER;
7610 goto out;
7613 if (!rpcbuf_alloc_size(buffer, *needed)) {
7614 result = WERR_NOMEM;
7615 goto out;
7618 /* fill the buffer with the ports structures */
7619 for (i=0; i<*returned; i++) {
7620 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7621 smb_io_port_2("", buffer, &ports[i], 0);
7624 out:
7625 SAFE_FREE(ports);
7627 if ( !W_ERROR_IS_OK(result) )
7628 *returned = 0;
7630 return result;
7633 /****************************************************************************
7634 enumports.
7635 ****************************************************************************/
7637 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7639 uint32 level = q_u->level;
7640 RPC_BUFFER *buffer = NULL;
7641 uint32 offered = q_u->offered;
7642 uint32 *needed = &r_u->needed;
7643 uint32 *returned = &r_u->returned;
7645 /* that's an [in out] buffer */
7647 if (!q_u->buffer && (offered!=0)) {
7648 return WERR_INVALID_PARAM;
7651 rpcbuf_move(q_u->buffer, &r_u->buffer);
7652 buffer = r_u->buffer;
7654 DEBUG(4,("_spoolss_enumports\n"));
7656 *returned=0;
7657 *needed=0;
7659 switch (level) {
7660 case 1:
7661 return enumports_level_1(buffer, offered, needed, returned);
7662 case 2:
7663 return enumports_level_2(buffer, offered, needed, returned);
7664 default:
7665 return WERR_UNKNOWN_LEVEL;
7669 /****************************************************************************
7670 ****************************************************************************/
7672 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7673 const SPOOL_PRINTER_INFO_LEVEL *info,
7674 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7675 uint32 user_switch, const SPOOL_USER_CTR *user,
7676 POLICY_HND *handle)
7678 NT_PRINTER_INFO_LEVEL *printer = NULL;
7679 fstring name;
7680 int snum;
7681 WERROR err = WERR_OK;
7683 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7684 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7685 return WERR_NOMEM;
7688 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7689 if (!convert_printer_info(info, printer, 2)) {
7690 free_a_printer(&printer, 2);
7691 return WERR_NOMEM;
7694 /* check to see if the printer already exists */
7696 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7697 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7698 printer->info_2->sharename));
7699 free_a_printer(&printer, 2);
7700 return WERR_PRINTER_ALREADY_EXISTS;
7703 /* FIXME!!! smbd should check to see if the driver is installed before
7704 trying to add a printer like this --jerry */
7706 if (*lp_addprinter_cmd() ) {
7707 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
7708 free_a_printer(&printer,2);
7709 return WERR_ACCESS_DENIED;
7711 } else {
7712 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7713 "smb.conf parameter \"addprinter command\" is defined. This"
7714 "parameter must exist for this call to succeed\n",
7715 printer->info_2->sharename ));
7718 /* use our primary netbios name since get_a_printer() will convert
7719 it to what the client expects on a case by case basis */
7721 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7722 printer->info_2->sharename);
7725 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7726 free_a_printer(&printer,2);
7727 return WERR_ACCESS_DENIED;
7730 /* you must be a printer admin to add a new printer */
7731 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7732 free_a_printer(&printer,2);
7733 return WERR_ACCESS_DENIED;
7737 * Do sanity check on the requested changes for Samba.
7740 if (!check_printer_ok(printer->info_2, snum)) {
7741 free_a_printer(&printer,2);
7742 return WERR_INVALID_PARAM;
7746 * When a printer is created, the drivername bound to the printer is used
7747 * to lookup previously saved driver initialization info, which is then
7748 * bound to the new printer, simulating what happens in the Windows arch.
7751 if (!devmode)
7753 set_driver_init(printer, 2);
7755 else
7757 /* A valid devmode was included, convert and link it
7759 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7761 if (!convert_devicemode(printer->info_2->printername, devmode,
7762 &printer->info_2->devmode))
7763 return WERR_NOMEM;
7766 /* write the ASCII on disk */
7767 err = mod_a_printer(printer, 2);
7768 if (!W_ERROR_IS_OK(err)) {
7769 free_a_printer(&printer,2);
7770 return err;
7773 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7774 /* Handle open failed - remove addition. */
7775 del_a_printer(printer->info_2->sharename);
7776 free_a_printer(&printer,2);
7777 return WERR_ACCESS_DENIED;
7780 update_c_setprinter(False);
7781 free_a_printer(&printer,2);
7783 return WERR_OK;
7786 /****************************************************************************
7787 ****************************************************************************/
7789 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7791 UNISTR2 *uni_srv_name = q_u->server_name;
7792 uint32 level = q_u->level;
7793 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7794 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7795 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7796 uint32 user_switch = q_u->user_switch;
7797 SPOOL_USER_CTR *user = &q_u->user_ctr;
7798 POLICY_HND *handle = &r_u->handle;
7800 switch (level) {
7801 case 1:
7802 /* we don't handle yet */
7803 /* but I know what to do ... */
7804 return WERR_UNKNOWN_LEVEL;
7805 case 2:
7806 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7807 devmode, sdb,
7808 user_switch, user, handle);
7809 default:
7810 return WERR_UNKNOWN_LEVEL;
7814 /****************************************************************************
7815 ****************************************************************************/
7817 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7819 uint32 level = q_u->level;
7820 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7821 WERROR err = WERR_OK;
7822 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7823 fstring driver_name;
7824 uint32 version;
7826 ZERO_STRUCT(driver);
7828 if (!convert_printer_driver_info(info, &driver, level)) {
7829 err = WERR_NOMEM;
7830 goto done;
7833 DEBUG(5,("Cleaning driver's information\n"));
7834 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7835 if (!W_ERROR_IS_OK(err))
7836 goto done;
7838 DEBUG(5,("Moving driver to final destination\n"));
7839 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7840 goto done;
7843 if (add_a_printer_driver(driver, level)!=0) {
7844 err = WERR_ACCESS_DENIED;
7845 goto done;
7849 * I think this is where he DrvUpgradePrinter() hook would be
7850 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7851 * server. Right now, we just need to send ourselves a message
7852 * to update each printer bound to this driver. --jerry
7855 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7856 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7857 driver_name));
7861 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7862 * decide if the driver init data should be deleted. The rules are:
7863 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7864 * 2) delete init data only if there is no 2k/Xp driver
7865 * 3) always delete init data
7866 * The generalized rule is always use init data from the highest order driver.
7867 * It is necessary to follow the driver install by an initialization step to
7868 * finish off this process.
7870 if (level == 3)
7871 version = driver.info_3->cversion;
7872 else if (level == 6)
7873 version = driver.info_6->version;
7874 else
7875 version = -1;
7876 switch (version) {
7878 * 9x printer driver - never delete init data
7880 case 0:
7881 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7882 driver_name));
7883 break;
7886 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7887 * there is no 2k/Xp driver init data for this driver name.
7889 case 2:
7891 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7893 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7895 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7897 if (!del_driver_init(driver_name))
7898 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7899 } else {
7901 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7903 free_a_printer_driver(driver1,3);
7904 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7905 driver_name));
7908 break;
7911 * 2k or Xp printer driver - always delete init data
7913 case 3:
7914 if (!del_driver_init(driver_name))
7915 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7916 break;
7918 default:
7919 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7920 break;
7924 done:
7925 free_a_printer_driver(driver, level);
7926 return err;
7929 /********************************************************************
7930 * spoolss_addprinterdriverex
7931 ********************************************************************/
7933 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7935 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7936 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7939 * we only support the semantics of AddPrinterDriver()
7940 * i.e. only copy files that are newer than existing ones
7943 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7944 return WERR_ACCESS_DENIED;
7946 ZERO_STRUCT(q_u_local);
7947 ZERO_STRUCT(r_u_local);
7949 /* just pass the information off to _spoolss_addprinterdriver() */
7950 q_u_local.server_name_ptr = q_u->server_name_ptr;
7951 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7952 q_u_local.level = q_u->level;
7953 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7955 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7958 /****************************************************************************
7959 ****************************************************************************/
7961 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7963 init_unistr(&info->name, name);
7966 /****************************************************************************
7967 ****************************************************************************/
7969 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7971 char *path = NULL;
7972 char *long_archi = NULL;
7973 char *servername = NULL;
7974 char *pservername = NULL;
7975 const char *short_archi;
7976 DRIVER_DIRECTORY_1 *info=NULL;
7977 WERROR result = WERR_OK;
7978 TALLOC_CTX *ctx = talloc_tos();
7980 servername = unistr2_to_ascii_talloc(ctx, name);
7981 if (!servername) {
7982 return WERR_NOMEM;
7984 long_archi = unistr2_to_ascii_talloc(ctx, uni_environment);
7985 if (!long_archi) {
7986 return WERR_NOMEM;
7989 /* check for beginning double '\'s and that the server
7990 long enough */
7992 pservername = servername;
7993 if ( *pservername == '\\' && strlen(servername)>2 ) {
7994 pservername += 2;
7997 if ( !is_myname_or_ipaddr( pservername ) )
7998 return WERR_INVALID_PARAM;
8000 if (!(short_archi = get_short_archi(long_archi)))
8001 return WERR_INVALID_ENVIRONMENT;
8003 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8004 return WERR_NOMEM;
8006 path = talloc_asprintf(ctx,
8007 "\\\\%s\\print$\\%s", pservername, short_archi);
8008 if (!path) {
8009 result = WERR_NOMEM;
8010 goto out;
8013 DEBUG(4,("printer driver directory: [%s]\n", path));
8015 fill_driverdir_1(info, path);
8017 *needed += spoolss_size_driverdir_info_1(info);
8019 if (*needed > offered) {
8020 result = WERR_INSUFFICIENT_BUFFER;
8021 goto out;
8024 if (!rpcbuf_alloc_size(buffer, *needed)) {
8025 result = WERR_NOMEM;
8026 goto out;
8029 smb_io_driverdir_1("", buffer, info, 0);
8031 out:
8032 SAFE_FREE(info);
8034 return result;
8037 /****************************************************************************
8038 ****************************************************************************/
8040 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8042 UNISTR2 *name = &q_u->name;
8043 UNISTR2 *uni_environment = &q_u->environment;
8044 uint32 level = q_u->level;
8045 RPC_BUFFER *buffer = NULL;
8046 uint32 offered = q_u->offered;
8047 uint32 *needed = &r_u->needed;
8049 /* that's an [in out] buffer */
8051 if (!q_u->buffer && (offered!=0)) {
8052 return WERR_INVALID_PARAM;
8055 rpcbuf_move(q_u->buffer, &r_u->buffer);
8056 buffer = r_u->buffer;
8058 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8060 *needed=0;
8062 switch(level) {
8063 case 1:
8064 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8065 default:
8066 return WERR_UNKNOWN_LEVEL;
8070 /****************************************************************************
8071 ****************************************************************************/
8073 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8075 POLICY_HND *handle = &q_u->handle;
8076 uint32 idx = q_u->index;
8077 uint32 in_value_len = q_u->valuesize;
8078 uint32 in_data_len = q_u->datasize;
8079 uint32 *out_max_value_len = &r_u->valuesize;
8080 uint16 **out_value = &r_u->value;
8081 uint32 *out_value_len = &r_u->realvaluesize;
8082 uint32 *out_type = &r_u->type;
8083 uint32 *out_max_data_len = &r_u->datasize;
8084 uint8 **data_out = &r_u->data;
8085 uint32 *out_data_len = &r_u->realdatasize;
8087 NT_PRINTER_INFO_LEVEL *printer = NULL;
8089 uint32 biggest_valuesize;
8090 uint32 biggest_datasize;
8091 uint32 data_len;
8092 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8093 int snum;
8094 WERROR result;
8095 REGISTRY_VALUE *val = NULL;
8096 NT_PRINTER_DATA *p_data;
8097 int i, key_index, num_values;
8098 int name_length;
8100 *out_type = 0;
8102 *out_max_data_len = 0;
8103 *data_out = NULL;
8104 *out_data_len = 0;
8106 DEBUG(5,("spoolss_enumprinterdata\n"));
8108 if (!Printer) {
8109 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8110 return WERR_BADFID;
8113 if (!get_printer_snum(p,handle, &snum, NULL))
8114 return WERR_BADFID;
8116 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8117 if (!W_ERROR_IS_OK(result))
8118 return result;
8120 p_data = printer->info_2->data;
8121 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8123 result = WERR_OK;
8126 * The NT machine wants to know the biggest size of value and data
8128 * cf: MSDN EnumPrinterData remark section
8131 if ( !in_value_len && !in_data_len && (key_index != -1) )
8133 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8135 biggest_valuesize = 0;
8136 biggest_datasize = 0;
8138 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8140 for ( i=0; i<num_values; i++ )
8142 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8144 name_length = strlen(val->valuename);
8145 if ( strlen(val->valuename) > biggest_valuesize )
8146 biggest_valuesize = name_length;
8148 if ( val->size > biggest_datasize )
8149 biggest_datasize = val->size;
8151 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8152 biggest_datasize));
8155 /* the value is an UNICODE string but real_value_size is the length
8156 in bytes including the trailing 0 */
8158 *out_value_len = 2 * (1+biggest_valuesize);
8159 *out_data_len = biggest_datasize;
8161 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8163 goto done;
8167 * the value len is wrong in NT sp3
8168 * that's the number of bytes not the number of unicode chars
8171 if ( key_index != -1 )
8172 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8174 if ( !val )
8177 /* out_value should default to "" or else NT4 has
8178 problems unmarshalling the response */
8180 *out_max_value_len=(in_value_len/sizeof(uint16));
8182 if (in_value_len) {
8183 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8185 result = WERR_NOMEM;
8186 goto done;
8188 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8189 } else {
8190 *out_value=NULL;
8191 *out_value_len = 0;
8194 /* the data is counted in bytes */
8196 *out_max_data_len = in_data_len;
8197 *out_data_len = in_data_len;
8199 /* only allocate when given a non-zero data_len */
8201 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8203 result = WERR_NOMEM;
8204 goto done;
8207 result = WERR_NO_MORE_ITEMS;
8209 else
8212 * the value is:
8213 * - counted in bytes in the request
8214 * - counted in UNICODE chars in the max reply
8215 * - counted in bytes in the real size
8217 * take a pause *before* coding not *during* coding
8220 /* name */
8221 *out_max_value_len=(in_value_len/sizeof(uint16));
8222 if (in_value_len) {
8223 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8225 result = WERR_NOMEM;
8226 goto done;
8229 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8230 } else {
8231 *out_value = NULL;
8232 *out_value_len = 0;
8235 /* type */
8237 *out_type = regval_type( val );
8239 /* data - counted in bytes */
8241 *out_max_data_len = in_data_len;
8242 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8244 result = WERR_NOMEM;
8245 goto done;
8247 data_len = regval_size(val);
8248 if ( *data_out && data_len )
8249 memcpy( *data_out, regval_data_p(val), data_len );
8250 *out_data_len = data_len;
8253 done:
8254 free_a_printer(&printer, 2);
8255 return result;
8258 /****************************************************************************
8259 ****************************************************************************/
8261 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8263 POLICY_HND *handle = &q_u->handle;
8264 UNISTR2 *value = &q_u->value;
8265 uint32 type = q_u->type;
8266 uint8 *data = q_u->data;
8267 uint32 real_len = q_u->real_len;
8269 NT_PRINTER_INFO_LEVEL *printer = NULL;
8270 int snum=0;
8271 WERROR status = WERR_OK;
8272 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8273 fstring valuename;
8275 DEBUG(5,("spoolss_setprinterdata\n"));
8277 if (!Printer) {
8278 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8279 return WERR_BADFID;
8282 if ( Printer->printer_type == SPLHND_SERVER ) {
8283 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8284 return WERR_INVALID_PARAM;
8287 if (!get_printer_snum(p,handle, &snum, NULL))
8288 return WERR_BADFID;
8291 * Access check : NT returns "access denied" if you make a
8292 * SetPrinterData call without the necessary privildge.
8293 * we were originally returning OK if nothing changed
8294 * which made Win2k issue **a lot** of SetPrinterData
8295 * when connecting to a printer --jerry
8298 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8300 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8301 status = WERR_ACCESS_DENIED;
8302 goto done;
8305 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8306 if (!W_ERROR_IS_OK(status))
8307 return status;
8309 unistr2_to_ascii(valuename, value, sizeof(valuename));
8312 * When client side code sets a magic printer data key, detect it and save
8313 * the current printer data and the magic key's data (its the DEVMODE) for
8314 * future printer/driver initializations.
8316 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8318 /* Set devmode and printer initialization info */
8319 status = save_driver_init( printer, 2, data, real_len );
8321 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8323 else
8325 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8326 type, data, real_len );
8327 if ( W_ERROR_IS_OK(status) )
8328 status = mod_a_printer(printer, 2);
8331 done:
8332 free_a_printer(&printer, 2);
8334 return status;
8337 /****************************************************************************
8338 ****************************************************************************/
8340 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8342 POLICY_HND *handle = &q_u->handle;
8343 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8344 int snum;
8346 DEBUG(5,("_spoolss_resetprinter\n"));
8349 * All we do is to check to see if the handle and queue is valid.
8350 * This call really doesn't mean anything to us because we only
8351 * support RAW printing. --jerry
8354 if (!Printer) {
8355 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8356 return WERR_BADFID;
8359 if (!get_printer_snum(p,handle, &snum, NULL))
8360 return WERR_BADFID;
8363 /* blindly return success */
8364 return WERR_OK;
8368 /****************************************************************************
8369 ****************************************************************************/
8371 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8373 POLICY_HND *handle = &q_u->handle;
8374 UNISTR2 *value = &q_u->valuename;
8376 NT_PRINTER_INFO_LEVEL *printer = NULL;
8377 int snum=0;
8378 WERROR status = WERR_OK;
8379 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8380 char *valuename = NULL;
8381 TALLOC_CTX *ctx = p->mem_ctx;
8383 DEBUG(5,("spoolss_deleteprinterdata\n"));
8385 if (!Printer) {
8386 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8387 return WERR_BADFID;
8390 if (!get_printer_snum(p, handle, &snum, NULL))
8391 return WERR_BADFID;
8393 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8394 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8395 return WERR_ACCESS_DENIED;
8398 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8399 if (!W_ERROR_IS_OK(status))
8400 return status;
8402 valuename = unistr2_to_ascii_talloc(ctx, value);
8403 if (!valuename) {
8404 free_a_printer(&printer, 2);
8405 return WERR_NOMEM;
8408 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8410 if ( W_ERROR_IS_OK(status) )
8411 mod_a_printer( printer, 2 );
8413 free_a_printer(&printer, 2);
8414 TALLOC_FREE(valuename);
8416 return status;
8419 /****************************************************************************
8420 ****************************************************************************/
8422 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8424 POLICY_HND *handle = &q_u->handle;
8425 FORM *form = &q_u->form;
8426 nt_forms_struct tmpForm;
8427 int snum;
8428 WERROR status = WERR_OK;
8429 NT_PRINTER_INFO_LEVEL *printer = NULL;
8431 int count=0;
8432 nt_forms_struct *list=NULL;
8433 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8435 DEBUG(5,("spoolss_addform\n"));
8437 if (!Printer) {
8438 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8439 return WERR_BADFID;
8443 /* forms can be added on printer of on the print server handle */
8445 if ( Printer->printer_type == SPLHND_PRINTER )
8447 if (!get_printer_snum(p,handle, &snum, NULL))
8448 return WERR_BADFID;
8450 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8451 if (!W_ERROR_IS_OK(status))
8452 goto done;
8455 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8456 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8457 status = WERR_ACCESS_DENIED;
8458 goto done;
8461 /* can't add if builtin */
8463 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8464 status = WERR_ALREADY_EXISTS;
8465 goto done;
8468 count = get_ntforms(&list);
8470 if(!add_a_form(&list, form, &count)) {
8471 status = WERR_NOMEM;
8472 goto done;
8475 write_ntforms(&list, count);
8478 * ChangeID must always be set if this is a printer
8481 if ( Printer->printer_type == SPLHND_PRINTER )
8482 status = mod_a_printer(printer, 2);
8484 done:
8485 if ( printer )
8486 free_a_printer(&printer, 2);
8487 SAFE_FREE(list);
8489 return status;
8492 /****************************************************************************
8493 ****************************************************************************/
8495 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8497 POLICY_HND *handle = &q_u->handle;
8498 UNISTR2 *form_name = &q_u->name;
8499 nt_forms_struct tmpForm;
8500 int count=0;
8501 nt_forms_struct *list=NULL;
8502 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8503 int snum;
8504 WERROR status = WERR_OK;
8505 NT_PRINTER_INFO_LEVEL *printer = NULL;
8507 DEBUG(5,("spoolss_deleteform\n"));
8509 if (!Printer) {
8510 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8511 return WERR_BADFID;
8514 /* forms can be deleted on printer of on the print server handle */
8516 if ( Printer->printer_type == SPLHND_PRINTER )
8518 if (!get_printer_snum(p,handle, &snum, NULL))
8519 return WERR_BADFID;
8521 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8522 if (!W_ERROR_IS_OK(status))
8523 goto done;
8526 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8527 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8528 status = WERR_ACCESS_DENIED;
8529 goto done;
8532 /* can't delete if builtin */
8534 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8535 status = WERR_INVALID_PARAM;
8536 goto done;
8539 count = get_ntforms(&list);
8541 if ( !delete_a_form(&list, form_name, &count, &status ))
8542 goto done;
8545 * ChangeID must always be set if this is a printer
8548 if ( Printer->printer_type == SPLHND_PRINTER )
8549 status = mod_a_printer(printer, 2);
8551 done:
8552 if ( printer )
8553 free_a_printer(&printer, 2);
8554 SAFE_FREE(list);
8556 return status;
8559 /****************************************************************************
8560 ****************************************************************************/
8562 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8564 POLICY_HND *handle = &q_u->handle;
8565 FORM *form = &q_u->form;
8566 nt_forms_struct tmpForm;
8567 int snum;
8568 WERROR status = WERR_OK;
8569 NT_PRINTER_INFO_LEVEL *printer = NULL;
8571 int count=0;
8572 nt_forms_struct *list=NULL;
8573 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8575 DEBUG(5,("spoolss_setform\n"));
8577 if (!Printer) {
8578 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8579 return WERR_BADFID;
8582 /* forms can be modified on printer of on the print server handle */
8584 if ( Printer->printer_type == SPLHND_PRINTER )
8586 if (!get_printer_snum(p,handle, &snum, NULL))
8587 return WERR_BADFID;
8589 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8590 if (!W_ERROR_IS_OK(status))
8591 goto done;
8594 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8595 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8596 status = WERR_ACCESS_DENIED;
8597 goto done;
8600 /* can't set if builtin */
8601 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8602 status = WERR_INVALID_PARAM;
8603 goto done;
8606 count = get_ntforms(&list);
8607 update_a_form(&list, form, count);
8608 write_ntforms(&list, count);
8611 * ChangeID must always be set if this is a printer
8614 if ( Printer->printer_type == SPLHND_PRINTER )
8615 status = mod_a_printer(printer, 2);
8618 done:
8619 if ( printer )
8620 free_a_printer(&printer, 2);
8621 SAFE_FREE(list);
8623 return status;
8626 /****************************************************************************
8627 enumprintprocessors level 1.
8628 ****************************************************************************/
8630 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8632 PRINTPROCESSOR_1 *info_1=NULL;
8633 WERROR result = WERR_OK;
8635 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8636 return WERR_NOMEM;
8638 (*returned) = 0x1;
8640 init_unistr(&info_1->name, "winprint");
8642 *needed += spoolss_size_printprocessor_info_1(info_1);
8644 if (*needed > offered) {
8645 result = WERR_INSUFFICIENT_BUFFER;
8646 goto out;
8649 if (!rpcbuf_alloc_size(buffer, *needed)) {
8650 result = WERR_NOMEM;
8651 goto out;
8654 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8656 out:
8657 SAFE_FREE(info_1);
8659 if ( !W_ERROR_IS_OK(result) )
8660 *returned = 0;
8662 return result;
8665 /****************************************************************************
8666 ****************************************************************************/
8668 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8670 uint32 level = q_u->level;
8671 RPC_BUFFER *buffer = NULL;
8672 uint32 offered = q_u->offered;
8673 uint32 *needed = &r_u->needed;
8674 uint32 *returned = &r_u->returned;
8676 /* that's an [in out] buffer */
8678 if (!q_u->buffer && (offered!=0)) {
8679 return WERR_INVALID_PARAM;
8682 rpcbuf_move(q_u->buffer, &r_u->buffer);
8683 buffer = r_u->buffer;
8685 DEBUG(5,("spoolss_enumprintprocessors\n"));
8688 * Enumerate the print processors ...
8690 * Just reply with "winprint", to keep NT happy
8691 * and I can use my nice printer checker.
8694 *returned=0;
8695 *needed=0;
8697 switch (level) {
8698 case 1:
8699 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8700 default:
8701 return WERR_UNKNOWN_LEVEL;
8705 /****************************************************************************
8706 enumprintprocdatatypes level 1.
8707 ****************************************************************************/
8709 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8711 PRINTPROCDATATYPE_1 *info_1=NULL;
8712 WERROR result = WERR_OK;
8714 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8715 return WERR_NOMEM;
8717 (*returned) = 0x1;
8719 init_unistr(&info_1->name, "RAW");
8721 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8723 if (*needed > offered) {
8724 result = WERR_INSUFFICIENT_BUFFER;
8725 goto out;
8728 if (!rpcbuf_alloc_size(buffer, *needed)) {
8729 result = WERR_NOMEM;
8730 goto out;
8733 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8735 out:
8736 SAFE_FREE(info_1);
8738 if ( !W_ERROR_IS_OK(result) )
8739 *returned = 0;
8741 return result;
8744 /****************************************************************************
8745 ****************************************************************************/
8747 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8749 uint32 level = q_u->level;
8750 RPC_BUFFER *buffer = NULL;
8751 uint32 offered = q_u->offered;
8752 uint32 *needed = &r_u->needed;
8753 uint32 *returned = &r_u->returned;
8755 /* that's an [in out] buffer */
8757 if (!q_u->buffer && (offered!=0)) {
8758 return WERR_INVALID_PARAM;
8761 rpcbuf_move(q_u->buffer, &r_u->buffer);
8762 buffer = r_u->buffer;
8764 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8766 *returned=0;
8767 *needed=0;
8769 switch (level) {
8770 case 1:
8771 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8772 default:
8773 return WERR_UNKNOWN_LEVEL;
8777 /****************************************************************************
8778 enumprintmonitors level 1.
8779 ****************************************************************************/
8781 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8783 PRINTMONITOR_1 *info_1;
8784 WERROR result = WERR_OK;
8785 int i;
8787 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8788 return WERR_NOMEM;
8790 *returned = 2;
8792 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8793 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8795 for ( i=0; i<*returned; i++ ) {
8796 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8799 if (*needed > offered) {
8800 result = WERR_INSUFFICIENT_BUFFER;
8801 goto out;
8804 if (!rpcbuf_alloc_size(buffer, *needed)) {
8805 result = WERR_NOMEM;
8806 goto out;
8809 for ( i=0; i<*returned; i++ ) {
8810 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8813 out:
8814 SAFE_FREE(info_1);
8816 if ( !W_ERROR_IS_OK(result) )
8817 *returned = 0;
8819 return result;
8822 /****************************************************************************
8823 enumprintmonitors level 2.
8824 ****************************************************************************/
8826 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8828 PRINTMONITOR_2 *info_2;
8829 WERROR result = WERR_OK;
8830 int i;
8832 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8833 return WERR_NOMEM;
8835 *returned = 2;
8837 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8838 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8839 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8841 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8842 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8843 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8845 for ( i=0; i<*returned; i++ ) {
8846 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8849 if (*needed > offered) {
8850 result = WERR_INSUFFICIENT_BUFFER;
8851 goto out;
8854 if (!rpcbuf_alloc_size(buffer, *needed)) {
8855 result = WERR_NOMEM;
8856 goto out;
8859 for ( i=0; i<*returned; i++ ) {
8860 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8863 out:
8864 SAFE_FREE(info_2);
8866 if ( !W_ERROR_IS_OK(result) )
8867 *returned = 0;
8869 return result;
8872 /****************************************************************************
8873 ****************************************************************************/
8875 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8877 uint32 level = q_u->level;
8878 RPC_BUFFER *buffer = NULL;
8879 uint32 offered = q_u->offered;
8880 uint32 *needed = &r_u->needed;
8881 uint32 *returned = &r_u->returned;
8883 /* that's an [in out] buffer */
8885 if (!q_u->buffer && (offered!=0)) {
8886 return WERR_INVALID_PARAM;
8889 rpcbuf_move(q_u->buffer, &r_u->buffer);
8890 buffer = r_u->buffer;
8892 DEBUG(5,("spoolss_enumprintmonitors\n"));
8895 * Enumerate the print monitors ...
8897 * Just reply with "Local Port", to keep NT happy
8898 * and I can use my nice printer checker.
8901 *returned=0;
8902 *needed=0;
8904 switch (level) {
8905 case 1:
8906 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8907 case 2:
8908 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8909 default:
8910 return WERR_UNKNOWN_LEVEL;
8914 /****************************************************************************
8915 ****************************************************************************/
8917 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8918 NT_PRINTER_INFO_LEVEL *ntprinter,
8919 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8920 uint32 *needed)
8922 int i=0;
8923 bool found=False;
8924 JOB_INFO_1 *info_1=NULL;
8925 WERROR result = WERR_OK;
8927 info_1=SMB_MALLOC_P(JOB_INFO_1);
8929 if (info_1 == NULL) {
8930 return WERR_NOMEM;
8933 for (i=0; i<count && found==False; i++) {
8934 if ((*queue)[i].job==(int)jobid)
8935 found=True;
8938 if (found==False) {
8939 SAFE_FREE(info_1);
8940 /* NT treats not found as bad param... yet another bad choice */
8941 return WERR_INVALID_PARAM;
8944 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8946 *needed += spoolss_size_job_info_1(info_1);
8948 if (*needed > offered) {
8949 result = WERR_INSUFFICIENT_BUFFER;
8950 goto out;
8953 if (!rpcbuf_alloc_size(buffer, *needed)) {
8954 result = WERR_NOMEM;
8955 goto out;
8958 smb_io_job_info_1("", buffer, info_1, 0);
8960 out:
8961 SAFE_FREE(info_1);
8963 return result;
8966 /****************************************************************************
8967 ****************************************************************************/
8969 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8970 NT_PRINTER_INFO_LEVEL *ntprinter,
8971 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8972 uint32 *needed)
8974 int i = 0;
8975 bool found = False;
8976 JOB_INFO_2 *info_2;
8977 WERROR result;
8978 DEVICEMODE *devmode = NULL;
8979 NT_DEVICEMODE *nt_devmode = NULL;
8981 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8982 return WERR_NOMEM;
8984 ZERO_STRUCTP(info_2);
8986 for ( i=0; i<count && found==False; i++ )
8988 if ((*queue)[i].job == (int)jobid)
8989 found = True;
8992 if ( !found ) {
8993 /* NT treats not found as bad param... yet another bad
8994 choice */
8995 result = WERR_INVALID_PARAM;
8996 goto done;
9000 * if the print job does not have a DEVMODE associated with it,
9001 * just use the one for the printer. A NULL devicemode is not
9002 * a failure condition
9005 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9006 devmode = construct_dev_mode(lp_const_servicename(snum));
9007 else {
9008 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9009 ZERO_STRUCTP( devmode );
9010 convert_nt_devicemode( devmode, nt_devmode );
9014 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9016 *needed += spoolss_size_job_info_2(info_2);
9018 if (*needed > offered) {
9019 result = WERR_INSUFFICIENT_BUFFER;
9020 goto done;
9023 if (!rpcbuf_alloc_size(buffer, *needed)) {
9024 result = WERR_NOMEM;
9025 goto done;
9028 smb_io_job_info_2("", buffer, info_2, 0);
9030 result = WERR_OK;
9032 done:
9033 /* Cleanup allocated memory */
9035 free_job_info_2(info_2); /* Also frees devmode */
9036 SAFE_FREE(info_2);
9038 return result;
9041 /****************************************************************************
9042 ****************************************************************************/
9044 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9046 POLICY_HND *handle = &q_u->handle;
9047 uint32 jobid = q_u->jobid;
9048 uint32 level = q_u->level;
9049 RPC_BUFFER *buffer = NULL;
9050 uint32 offered = q_u->offered;
9051 uint32 *needed = &r_u->needed;
9052 WERROR wstatus = WERR_OK;
9053 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9054 int snum;
9055 int count;
9056 print_queue_struct *queue = NULL;
9057 print_status_struct prt_status;
9059 /* that's an [in out] buffer */
9061 if (!q_u->buffer && (offered!=0)) {
9062 return WERR_INVALID_PARAM;
9065 rpcbuf_move(q_u->buffer, &r_u->buffer);
9066 buffer = r_u->buffer;
9068 DEBUG(5,("spoolss_getjob\n"));
9070 *needed = 0;
9072 if (!get_printer_snum(p, handle, &snum, NULL))
9073 return WERR_BADFID;
9075 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9076 if ( !W_ERROR_IS_OK(wstatus) )
9077 return wstatus;
9079 count = print_queue_status(snum, &queue, &prt_status);
9081 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9082 count, prt_status.status, prt_status.message));
9084 switch ( level ) {
9085 case 1:
9086 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9087 buffer, offered, needed);
9088 break;
9089 case 2:
9090 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9091 buffer, offered, needed);
9092 break;
9093 default:
9094 wstatus = WERR_UNKNOWN_LEVEL;
9095 break;
9098 SAFE_FREE(queue);
9099 free_a_printer( &ntprinter, 2 );
9101 return wstatus;
9104 /********************************************************************
9105 spoolss_getprinterdataex
9107 From MSDN documentation of GetPrinterDataEx: pass request
9108 to GetPrinterData if key is "PrinterDriverData".
9109 ********************************************************************/
9111 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9113 POLICY_HND *handle = &q_u->handle;
9114 uint32 in_size = q_u->size;
9115 uint32 *type = &r_u->type;
9116 uint32 *out_size = &r_u->size;
9117 uint8 **data = &r_u->data;
9118 uint32 *needed = &r_u->needed;
9119 fstring keyname, valuename;
9121 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9123 NT_PRINTER_INFO_LEVEL *printer = NULL;
9124 int snum = 0;
9125 WERROR status = WERR_OK;
9127 DEBUG(4,("_spoolss_getprinterdataex\n"));
9129 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname));
9130 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename));
9132 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9133 keyname, valuename));
9135 /* in case of problem, return some default values */
9137 *needed = 0;
9138 *type = 0;
9139 *out_size = in_size;
9141 if (!Printer) {
9142 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9143 status = WERR_BADFID;
9144 goto done;
9147 /* Is the handle to a printer or to the server? */
9149 if (Printer->printer_type == SPLHND_SERVER) {
9150 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9151 status = WERR_INVALID_PARAM;
9152 goto done;
9155 if ( !get_printer_snum(p,handle, &snum, NULL) )
9156 return WERR_BADFID;
9158 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9159 if ( !W_ERROR_IS_OK(status) )
9160 goto done;
9162 /* check to see if the keyname is valid */
9163 if ( !strlen(keyname) ) {
9164 status = WERR_INVALID_PARAM;
9165 goto done;
9168 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9169 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9170 free_a_printer( &printer, 2 );
9171 status = WERR_BADFILE;
9172 goto done;
9175 /* When given a new keyname, we should just create it */
9177 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9179 if (*needed > *out_size)
9180 status = WERR_MORE_DATA;
9182 done:
9183 if ( !W_ERROR_IS_OK(status) )
9185 DEBUG(5, ("error: allocating %d\n", *out_size));
9187 /* reply this param doesn't exist */
9189 if ( *out_size )
9191 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9192 status = WERR_NOMEM;
9193 goto done;
9195 } else {
9196 *data = NULL;
9200 if ( printer )
9201 free_a_printer( &printer, 2 );
9203 return status;
9206 /********************************************************************
9207 * spoolss_setprinterdataex
9208 ********************************************************************/
9210 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9212 POLICY_HND *handle = &q_u->handle;
9213 uint32 type = q_u->type;
9214 uint8 *data = q_u->data;
9215 uint32 real_len = q_u->real_len;
9217 NT_PRINTER_INFO_LEVEL *printer = NULL;
9218 int snum = 0;
9219 WERROR status = WERR_OK;
9220 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9221 fstring valuename;
9222 fstring keyname;
9223 char *oid_string;
9225 DEBUG(4,("_spoolss_setprinterdataex\n"));
9227 /* From MSDN documentation of SetPrinterDataEx: pass request to
9228 SetPrinterData if key is "PrinterDriverData" */
9230 if (!Printer) {
9231 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9232 return WERR_BADFID;
9235 if ( Printer->printer_type == SPLHND_SERVER ) {
9236 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9237 return WERR_INVALID_PARAM;
9240 if ( !get_printer_snum(p,handle, &snum, NULL) )
9241 return WERR_BADFID;
9244 * Access check : NT returns "access denied" if you make a
9245 * SetPrinterData call without the necessary privildge.
9246 * we were originally returning OK if nothing changed
9247 * which made Win2k issue **a lot** of SetPrinterData
9248 * when connecting to a printer --jerry
9251 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9253 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9254 return WERR_ACCESS_DENIED;
9257 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9258 if (!W_ERROR_IS_OK(status))
9259 return status;
9261 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename));
9262 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname));
9264 /* check for OID in valuename */
9266 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9268 *oid_string = '\0';
9269 oid_string++;
9272 /* save the registry data */
9274 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9276 if ( W_ERROR_IS_OK(status) )
9278 /* save the OID if one was specified */
9279 if ( oid_string ) {
9280 fstrcat( keyname, "\\" );
9281 fstrcat( keyname, SPOOL_OID_KEY );
9284 * I'm not checking the status here on purpose. Don't know
9285 * if this is right, but I'm returning the status from the
9286 * previous set_printer_dataex() call. I have no idea if
9287 * this is right. --jerry
9290 set_printer_dataex( printer, keyname, valuename,
9291 REG_SZ, (uint8 *)oid_string,
9292 strlen(oid_string)+1 );
9295 status = mod_a_printer(printer, 2);
9298 free_a_printer(&printer, 2);
9300 return status;
9304 /********************************************************************
9305 * spoolss_deleteprinterdataex
9306 ********************************************************************/
9308 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9310 POLICY_HND *handle = &q_u->handle;
9311 UNISTR2 *value = &q_u->valuename;
9312 UNISTR2 *key = &q_u->keyname;
9314 NT_PRINTER_INFO_LEVEL *printer = NULL;
9315 int snum=0;
9316 WERROR status = WERR_OK;
9317 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9318 char *valuename = NULL;
9319 char *keyname = NULL;
9320 TALLOC_CTX *ctx = p->mem_ctx;
9322 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9324 if (!Printer) {
9325 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9326 return WERR_BADFID;
9329 if (!get_printer_snum(p, handle, &snum, NULL))
9330 return WERR_BADFID;
9332 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9333 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9334 return WERR_ACCESS_DENIED;
9337 valuename = unistr2_to_ascii_talloc(ctx, value);
9338 keyname = unistr2_to_ascii_talloc(ctx, key);
9339 if (!valuename || !keyname) {
9340 return WERR_NOMEM;
9343 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9344 if (!W_ERROR_IS_OK(status))
9345 return status;
9347 status = delete_printer_dataex( printer, keyname, valuename );
9349 if ( W_ERROR_IS_OK(status) )
9350 mod_a_printer( printer, 2 );
9352 free_a_printer(&printer, 2);
9354 return status;
9357 /********************************************************************
9358 * spoolss_enumprinterkey
9359 ********************************************************************/
9362 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9364 fstring key;
9365 fstring *keynames = NULL;
9366 uint16 *enumkeys = NULL;
9367 int num_keys;
9368 int printerkey_len;
9369 POLICY_HND *handle = &q_u->handle;
9370 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9371 NT_PRINTER_DATA *data;
9372 NT_PRINTER_INFO_LEVEL *printer = NULL;
9373 int snum = 0;
9374 WERROR status = WERR_BADFILE;
9377 DEBUG(4,("_spoolss_enumprinterkey\n"));
9379 if (!Printer) {
9380 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9381 return WERR_BADFID;
9384 if ( !get_printer_snum(p,handle, &snum, NULL) )
9385 return WERR_BADFID;
9387 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9388 if (!W_ERROR_IS_OK(status))
9389 return status;
9391 /* get the list of subkey names */
9393 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9394 data = printer->info_2->data;
9396 num_keys = get_printer_subkeys( data, key, &keynames );
9398 if ( num_keys == -1 ) {
9399 status = WERR_BADFILE;
9400 goto done;
9403 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9405 r_u->needed = printerkey_len*2;
9407 if ( q_u->size < r_u->needed ) {
9408 status = WERR_MORE_DATA;
9409 goto done;
9412 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9413 status = WERR_NOMEM;
9414 goto done;
9417 status = WERR_OK;
9419 if ( q_u->size < r_u->needed )
9420 status = WERR_MORE_DATA;
9422 done:
9423 free_a_printer( &printer, 2 );
9424 SAFE_FREE( keynames );
9426 return status;
9429 /********************************************************************
9430 * spoolss_deleteprinterkey
9431 ********************************************************************/
9433 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9435 POLICY_HND *handle = &q_u->handle;
9436 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9437 fstring key;
9438 NT_PRINTER_INFO_LEVEL *printer = NULL;
9439 int snum=0;
9440 WERROR status;
9442 DEBUG(5,("spoolss_deleteprinterkey\n"));
9444 if (!Printer) {
9445 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9446 return WERR_BADFID;
9449 /* if keyname == NULL, return error */
9451 if ( !q_u->keyname.buffer )
9452 return WERR_INVALID_PARAM;
9454 if (!get_printer_snum(p, handle, &snum, NULL))
9455 return WERR_BADFID;
9457 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9458 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9459 return WERR_ACCESS_DENIED;
9462 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9463 if (!W_ERROR_IS_OK(status))
9464 return status;
9466 /* delete the key and all subneys */
9468 unistr2_to_ascii(key, &q_u->keyname, sizeof(key));
9470 status = delete_all_printer_data( printer->info_2, key );
9472 if ( W_ERROR_IS_OK(status) )
9473 status = mod_a_printer(printer, 2);
9475 free_a_printer( &printer, 2 );
9477 return status;
9481 /********************************************************************
9482 * spoolss_enumprinterdataex
9483 ********************************************************************/
9485 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9487 POLICY_HND *handle = &q_u->handle;
9488 uint32 in_size = q_u->size;
9489 uint32 num_entries,
9490 needed;
9491 NT_PRINTER_INFO_LEVEL *printer = NULL;
9492 PRINTER_ENUM_VALUES *enum_values = NULL;
9493 NT_PRINTER_DATA *p_data;
9494 fstring key;
9495 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9496 int snum;
9497 WERROR result;
9498 int key_index;
9499 int i;
9500 REGISTRY_VALUE *val;
9501 char *value_name;
9502 uint32 data_len;
9505 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9507 if (!Printer) {
9508 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9509 return WERR_BADFID;
9513 * first check for a keyname of NULL or "". Win2k seems to send
9514 * this a lot and we should send back WERR_INVALID_PARAM
9515 * no need to spend time looking up the printer in this case.
9516 * --jerry
9519 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9520 if ( !strlen(key) ) {
9521 result = WERR_INVALID_PARAM;
9522 goto done;
9525 /* get the printer off of disk */
9527 if (!get_printer_snum(p,handle, &snum, NULL))
9528 return WERR_BADFID;
9530 ZERO_STRUCT(printer);
9531 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9532 if (!W_ERROR_IS_OK(result))
9533 return result;
9535 /* now look for a match on the key name */
9537 p_data = printer->info_2->data;
9539 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9540 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9542 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9543 result = WERR_INVALID_PARAM;
9544 goto done;
9547 result = WERR_OK;
9548 needed = 0;
9550 /* allocate the memory for the array of pointers -- if necessary */
9552 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9553 if ( num_entries )
9555 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9557 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9558 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9559 result = WERR_NOMEM;
9560 goto done;
9563 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9567 * loop through all params and build the array to pass
9568 * back to the client
9571 for ( i=0; i<num_entries; i++ )
9573 /* lookup the registry value */
9575 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9576 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9578 /* copy the data */
9580 value_name = regval_name( val );
9581 init_unistr( &enum_values[i].valuename, value_name );
9582 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9583 enum_values[i].type = regval_type( val );
9585 data_len = regval_size( val );
9586 if ( data_len ) {
9587 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9589 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9590 data_len ));
9591 result = WERR_NOMEM;
9592 goto done;
9595 enum_values[i].data_len = data_len;
9597 /* keep track of the size of the array in bytes */
9599 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9602 /* housekeeping information in the reply */
9604 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9605 * the hand marshalled container size is a multiple
9606 * of 4 bytes for RPC alignment.
9609 if (needed % 4) {
9610 needed += 4-(needed % 4);
9613 r_u->needed = needed;
9614 r_u->returned = num_entries;
9616 if (needed > in_size) {
9617 result = WERR_MORE_DATA;
9618 goto done;
9621 /* copy data into the reply */
9623 r_u->ctr.size = r_u->needed;
9625 r_u->ctr.size_of_array = r_u->returned;
9626 r_u->ctr.values = enum_values;
9630 done:
9631 if ( printer )
9632 free_a_printer(&printer, 2);
9634 return result;
9637 /****************************************************************************
9638 ****************************************************************************/
9640 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
9642 init_unistr(&info->name, name);
9645 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9646 UNISTR2 *environment,
9647 RPC_BUFFER *buffer,
9648 uint32 offered,
9649 uint32 *needed)
9651 char *long_archi = NULL;
9652 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9653 WERROR result = WERR_OK;
9654 TALLOC_CTX *ctx = talloc_tos();
9656 long_archi = unistr2_to_ascii_talloc(ctx, environment);
9657 if (!long_archi) {
9658 return WERR_NOMEM;
9661 if (!get_short_archi(long_archi))
9662 return WERR_INVALID_ENVIRONMENT;
9664 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9665 return WERR_NOMEM;
9667 fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9669 *needed += spoolss_size_printprocessordirectory_info_1(info);
9671 if (*needed > offered) {
9672 result = WERR_INSUFFICIENT_BUFFER;
9673 goto out;
9676 if (!rpcbuf_alloc_size(buffer, *needed)) {
9677 result = WERR_INSUFFICIENT_BUFFER;
9678 goto out;
9681 smb_io_printprocessordirectory_1("", buffer, info, 0);
9683 out:
9684 SAFE_FREE(info);
9686 return result;
9689 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9691 uint32 level = q_u->level;
9692 RPC_BUFFER *buffer = NULL;
9693 uint32 offered = q_u->offered;
9694 uint32 *needed = &r_u->needed;
9695 WERROR result;
9697 /* that's an [in out] buffer */
9699 if (!q_u->buffer && (offered!=0)) {
9700 return WERR_INVALID_PARAM;
9703 rpcbuf_move(q_u->buffer, &r_u->buffer);
9704 buffer = r_u->buffer;
9706 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9708 *needed=0;
9710 switch(level) {
9711 case 1:
9712 result = getprintprocessordirectory_level_1
9713 (&q_u->name, &q_u->environment, buffer, offered, needed);
9714 break;
9715 default:
9716 result = WERR_UNKNOWN_LEVEL;
9719 return result;
9722 /*******************************************************************
9723 Streams the monitor UI DLL name in UNICODE
9724 *******************************************************************/
9726 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9727 RPC_BUFFER *out, uint32 *needed )
9729 const char *dllname = "tcpmonui.dll";
9731 *needed = (strlen(dllname)+1) * 2;
9733 if ( rpcbuf_get_size(out) < *needed ) {
9734 return WERR_INSUFFICIENT_BUFFER;
9737 if ( !make_monitorui_buf( out, dllname ) ) {
9738 return WERR_NOMEM;
9741 return WERR_OK;
9744 /*******************************************************************
9745 Create a new TCP/IP port
9746 *******************************************************************/
9748 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9749 RPC_BUFFER *out, uint32 *needed )
9751 NT_PORT_DATA_1 port1;
9752 TALLOC_CTX *ctx = talloc_tos();
9753 char *device_uri = NULL;
9755 ZERO_STRUCT( port1 );
9757 /* convert to our internal port data structure */
9759 if ( !convert_port_data_1( &port1, in ) ) {
9760 return WERR_NOMEM;
9763 /* create the device URI and call the add_port_hook() */
9765 switch ( port1.protocol ) {
9766 case PORT_PROTOCOL_DIRECT:
9767 device_uri = talloc_asprintf(ctx,
9768 "socket://%s:%d/", port1.hostaddr, port1.port );
9769 break;
9771 case PORT_PROTOCOL_LPR:
9772 device_uri = talloc_asprintf(ctx,
9773 "lpr://%s/%s", port1.hostaddr, port1.queue );
9774 break;
9776 default:
9777 return WERR_UNKNOWN_PORT;
9780 if (!device_uri) {
9781 return WERR_NOMEM;
9784 return add_port_hook(ctx, token, port1.name, device_uri );
9787 /*******************************************************************
9788 *******************************************************************/
9790 struct xcv_api_table xcvtcp_cmds[] = {
9791 { "MonitorUI", xcvtcp_monitorui },
9792 { "AddPort", xcvtcp_addport},
9793 { NULL, NULL }
9796 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9797 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9798 uint32 *needed )
9800 int i;
9802 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9804 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9805 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9806 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9809 return WERR_BADFUNC;
9812 /*******************************************************************
9813 *******************************************************************/
9814 #if 0 /* don't support management using the "Local Port" monitor */
9816 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9817 RPC_BUFFER *out, uint32 *needed )
9819 const char *dllname = "localui.dll";
9821 *needed = (strlen(dllname)+1) * 2;
9823 if ( rpcbuf_get_size(out) < *needed ) {
9824 return WERR_INSUFFICIENT_BUFFER;
9827 if ( !make_monitorui_buf( out, dllname )) {
9828 return WERR_NOMEM;
9831 return WERR_OK;
9834 /*******************************************************************
9835 *******************************************************************/
9837 struct xcv_api_table xcvlocal_cmds[] = {
9838 { "MonitorUI", xcvlocal_monitorui },
9839 { NULL, NULL }
9841 #else
9842 struct xcv_api_table xcvlocal_cmds[] = {
9843 { NULL, NULL }
9845 #endif
9849 /*******************************************************************
9850 *******************************************************************/
9852 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9853 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9854 uint32 *needed )
9856 int i;
9858 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9860 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9861 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9862 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9864 return WERR_BADFUNC;
9867 /*******************************************************************
9868 *******************************************************************/
9870 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9872 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9873 fstring command;
9875 if (!Printer) {
9876 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9877 return WERR_BADFID;
9880 /* Has to be a handle to the TCP/IP port monitor */
9882 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9883 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9884 return WERR_BADFID;
9887 /* requires administrative access to the server */
9889 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9890 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9891 return WERR_ACCESS_DENIED;
9894 /* Get the command name. There's numerous commands supported by the
9895 TCPMON interface. */
9897 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9898 q_u->dataname.uni_str_len*2, 0);
9900 /* Allocate the outgoing buffer */
9902 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9904 switch ( Printer->printer_type ) {
9905 case SPLHND_PORTMON_TCP:
9906 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9907 &q_u->indata, &r_u->outdata, &r_u->needed );
9908 case SPLHND_PORTMON_LOCAL:
9909 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9910 &q_u->indata, &r_u->outdata, &r_u->needed );
9913 return WERR_INVALID_PRINT_MONITOR;