mount.cifs: check access of credential files before opening
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
blobb4b9521c7ad4497bb51b72289a27fa0e6f7ae950
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
29 #include "includes.h"
31 extern userdom_struct current_user_info;
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
38 #endif
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
43 struct table_node {
44 const char *long_archi;
45 const char *short_archi;
46 int version;
49 static Printer_entry *printers_list;
51 typedef struct _counter_printer_0 {
52 struct _counter_printer_0 *next;
53 struct _counter_printer_0 *prev;
55 int snum;
56 uint32 counter;
57 } counter_printer_0;
59 static counter_printer_0 *counter_list;
61 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
62 static uint32 smb_connections=0;
65 /* in printing/nt_printing.c */
67 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
69 /* API table for Xcv Monitor functions */
71 struct xcv_api_table {
72 const char *name;
73 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
76 /********************************************************************
77 * Canonicalize servername.
78 ********************************************************************/
80 static const char *canon_servername(const char *servername)
82 const char *pservername = servername;
83 while (*pservername == '\\') {
84 pservername++;
86 return pservername;
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v)
92 switch (v) {
93 case LPQ_QUEUED:
94 return 0;
95 case LPQ_PAUSED:
96 return JOB_STATUS_PAUSED;
97 case LPQ_SPOOLING:
98 return JOB_STATUS_SPOOLING;
99 case LPQ_PRINTING:
100 return JOB_STATUS_PRINTING;
101 case LPQ_ERROR:
102 return JOB_STATUS_ERROR;
103 case LPQ_DELETING:
104 return JOB_STATUS_DELETING;
105 case LPQ_OFFLINE:
106 return JOB_STATUS_OFFLINE;
107 case LPQ_PAPEROUT:
108 return JOB_STATUS_PAPEROUT;
109 case LPQ_PRINTED:
110 return JOB_STATUS_PRINTED;
111 case LPQ_DELETED:
112 return JOB_STATUS_DELETED;
113 case LPQ_BLOCKED:
114 return JOB_STATUS_BLOCKED;
115 case LPQ_USER_INTERVENTION:
116 return JOB_STATUS_USER_INTERVENTION;
118 return 0;
121 static int nt_printq_status(int v)
123 switch (v) {
124 case LPQ_PAUSED:
125 return PRINTER_STATUS_PAUSED;
126 case LPQ_QUEUED:
127 case LPQ_SPOOLING:
128 case LPQ_PRINTING:
129 return 0;
131 return 0;
134 /****************************************************************************
135 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
136 ****************************************************************************/
138 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
140 if (*pp == NULL)
141 return;
143 SAFE_FREE((*pp)->ctr.type);
144 SAFE_FREE(*pp);
147 /***************************************************************************
148 Disconnect from the client
149 ****************************************************************************/
151 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
153 WERROR result;
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
166 return;
169 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
171 if (!W_ERROR_IS_OK(result))
172 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
173 dos_errstr(result)));
175 /* if it's the last connection, deconnect the IPC$ share */
176 if (smb_connections==1) {
178 cli_shutdown( notify_cli_pipe->cli );
179 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
181 message_deregister(MSG_PRINTER_NOTIFY2);
183 /* Tell the connections db we're no longer interested in
184 * printer notify messages. */
186 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
189 smb_connections--;
192 /****************************************************************************
193 Functions to free a printer entry datastruct.
194 ****************************************************************************/
196 static void free_printer_entry(void *ptr)
198 Printer_entry *Printer = (Printer_entry *)ptr;
200 if (Printer->notify.client_connected==True) {
201 int snum = -1;
203 if ( Printer->printer_type == SPLHND_SERVER) {
204 snum = -1;
205 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
206 } else if (Printer->printer_type == SPLHND_PRINTER) {
207 snum = print_queue_snum(Printer->sharename);
208 if (snum != -1)
209 srv_spoolss_replycloseprinter(snum,
210 &Printer->notify.client_hnd);
214 Printer->notify.flags=0;
215 Printer->notify.options=0;
216 Printer->notify.localmachine[0]='\0';
217 Printer->notify.printerlocal=0;
218 free_spool_notify_option(&Printer->notify.option);
219 Printer->notify.option=NULL;
220 Printer->notify.client_connected=False;
222 free_nt_devicemode( &Printer->nt_devmode );
223 free_a_printer( &Printer->printer_info, 2 );
225 talloc_destroy( Printer->ctx );
227 /* Remove from the internal list. */
228 DLIST_REMOVE(printers_list, Printer);
230 SAFE_FREE(Printer);
233 /****************************************************************************
234 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
235 ****************************************************************************/
237 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
239 SPOOL_NOTIFY_OPTION *new_sp = NULL;
241 if (!sp)
242 return NULL;
244 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
245 if (!new_sp)
246 return NULL;
248 *new_sp = *sp;
250 if (sp->ctr.count) {
251 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
253 if (!new_sp->ctr.type) {
254 SAFE_FREE(new_sp);
255 return NULL;
259 return new_sp;
262 /****************************************************************************
263 find printer index by handle
264 ****************************************************************************/
266 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
268 Printer_entry *find_printer = NULL;
270 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
271 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
272 return NULL;
275 return find_printer;
278 /****************************************************************************
279 Close printer index by handle.
280 ****************************************************************************/
282 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
284 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
286 if (!Printer) {
287 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
288 return False;
291 close_policy_hnd(p, hnd);
293 return True;
296 /****************************************************************************
297 Delete a printer given a handle.
298 ****************************************************************************/
299 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
301 char *cmd = lp_deleteprinter_cmd();
302 pstring command;
303 int ret;
304 SE_PRIV se_printop = SE_PRINT_OPERATOR;
305 BOOL is_print_op = False;
307 /* can't fail if we don't try */
309 if ( !*cmd )
310 return WERR_OK;
312 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
314 if ( token )
315 is_print_op = user_has_privileges( token, &se_printop );
317 DEBUG(10,("Running [%s]\n", command));
319 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
321 if ( is_print_op )
322 become_root();
324 if ( (ret = smbrun(command, NULL)) == 0 ) {
325 /* Tell everyone we updated smb.conf. */
326 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
329 if ( is_print_op )
330 unbecome_root();
332 /********** END SePrintOperatorPrivlege BLOCK **********/
334 DEBUGADD(10,("returned [%d]\n", ret));
336 if (ret != 0)
337 return WERR_BADFID; /* What to return here? */
339 /* go ahead and re-read the services immediately */
340 reload_services( False );
342 if ( lp_servicenumber( sharename ) < 0 )
343 return WERR_ACCESS_DENIED;
345 return WERR_OK;
348 /****************************************************************************
349 Delete a printer given a handle.
350 ****************************************************************************/
352 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
354 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
356 if (!Printer) {
357 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
358 return WERR_BADFID;
362 * It turns out that Windows allows delete printer on a handle
363 * opened by an admin user, then used on a pipe handle created
364 * by an anonymous user..... but they're working on security.... riiight !
365 * JRA.
368 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
369 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
370 return WERR_ACCESS_DENIED;
373 /* this does not need a become root since the access check has been
374 done on the handle already */
376 if (del_a_printer( Printer->sharename ) != 0) {
377 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
378 return WERR_BADFID;
381 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
384 /****************************************************************************
385 Return the snum of a printer corresponding to an handle.
386 ****************************************************************************/
388 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
390 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
392 if (!Printer) {
393 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
394 return False;
397 switch (Printer->printer_type) {
398 case SPLHND_PRINTER:
399 DEBUG(4,("short name:%s\n", Printer->sharename));
400 *number = print_queue_snum(Printer->sharename);
401 return (*number != -1);
402 case SPLHND_SERVER:
403 return False;
404 default:
405 return False;
409 /****************************************************************************
410 Set printer handle type.
411 Check if it's \\server or \\server\printer
412 ****************************************************************************/
414 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
416 DEBUG(3,("Setting printer type=%s\n", handlename));
418 if ( strlen(handlename) < 3 ) {
419 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
420 return False;
423 /* it's a print server */
424 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
425 DEBUGADD(4,("Printer is a print server\n"));
426 Printer->printer_type = SPLHND_SERVER;
428 /* it's a printer (set_printer_hnd_name() will handle port monitors */
429 else {
430 DEBUGADD(4,("Printer is a printer\n"));
431 Printer->printer_type = SPLHND_PRINTER;
434 return True;
437 /****************************************************************************
438 Set printer handle name.. Accept names like \\server, \\server\printer,
439 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
440 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
441 XcvDataPort() interface.
442 ****************************************************************************/
444 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
446 int snum;
447 int n_services=lp_numservices();
448 char *aprinter, *printername;
449 const char *servername;
450 fstring sname;
451 BOOL found=False;
452 NT_PRINTER_INFO_LEVEL *printer = NULL;
453 WERROR result;
455 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
457 aprinter = handlename;
458 if ( *handlename == '\\' ) {
459 servername = canon_servername(handlename);
460 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
461 *aprinter = '\0';
462 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;
525 /* This call doesn't fill in the location or comment from
526 * a CUPS server for efficiency with large numbers of printers.
527 * JRA.
529 result = get_a_printer_search( NULL, &printer, 2, sname );
530 if ( !W_ERROR_IS_OK(result) ) {
531 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
532 sname, dos_errstr(result)));
533 continue;
536 /* printername is always returned as \\server\printername */
537 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
538 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
539 printer->info_2->printername));
540 free_a_printer( &printer, 2);
541 continue;
544 printername++;
546 if ( strequal(printername, aprinter) ) {
547 free_a_printer( &printer, 2);
548 found = True;
549 break;
552 DEBUGADD(10, ("printername: %s\n", printername));
554 free_a_printer( &printer, 2);
557 free_a_printer( &printer, 2);
559 if ( !found ) {
560 DEBUGADD(4,("Printer not found\n"));
561 return False;
564 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
566 fstrcpy(Printer->sharename, sname);
568 return True;
571 /****************************************************************************
572 Find first available printer slot. creates a printer handle for you.
573 ****************************************************************************/
575 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
577 Printer_entry *new_printer;
579 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
581 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
582 return False;
584 ZERO_STRUCTP(new_printer);
586 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
587 SAFE_FREE(new_printer);
588 return False;
591 /* Add to the internal list. */
592 DLIST_ADD(printers_list, new_printer);
594 new_printer->notify.option=NULL;
596 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
597 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
598 close_printer_handle(p, hnd);
599 return False;
602 if (!set_printer_hnd_printertype(new_printer, name)) {
603 close_printer_handle(p, hnd);
604 return False;
607 if (!set_printer_hnd_name(new_printer, name)) {
608 close_printer_handle(p, hnd);
609 return False;
612 new_printer->access_granted = access_granted;
614 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
616 return True;
619 /***************************************************************************
620 check to see if the client motify handle is monitoring the notification
621 given by (notify_type, notify_field).
622 **************************************************************************/
624 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
625 uint16 notify_field)
627 return True;
630 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
631 uint16 notify_field)
633 SPOOL_NOTIFY_OPTION *option = p->notify.option;
634 uint32 i, j;
637 * Flags should always be zero when the change notify
638 * is registered by the client's spooler. A user Win32 app
639 * might use the flags though instead of the NOTIFY_OPTION_INFO
640 * --jerry
643 if (!option) {
644 return False;
647 if (p->notify.flags)
648 return is_monitoring_event_flags(
649 p->notify.flags, notify_type, notify_field);
651 for (i = 0; i < option->count; i++) {
653 /* Check match for notify_type */
655 if (option->ctr.type[i].type != notify_type)
656 continue;
658 /* Check match for field */
660 for (j = 0; j < option->ctr.type[i].count; j++) {
661 if (option->ctr.type[i].fields[j] == notify_field) {
662 return True;
667 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
668 p->servername, p->sharename, notify_type, notify_field));
670 return False;
673 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
675 static void notify_one_value(struct spoolss_notify_msg *msg,
676 SPOOL_NOTIFY_INFO_DATA *data,
677 TALLOC_CTX *mem_ctx)
679 data->notify_data.value[0] = msg->notify.value[0];
680 data->notify_data.value[1] = 0;
683 static void notify_string(struct spoolss_notify_msg *msg,
684 SPOOL_NOTIFY_INFO_DATA *data,
685 TALLOC_CTX *mem_ctx)
687 UNISTR2 unistr;
689 /* The length of the message includes the trailing \0 */
691 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
693 data->notify_data.data.length = msg->len * 2;
694 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
696 if (!data->notify_data.data.string) {
697 data->notify_data.data.length = 0;
698 return;
701 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
704 static void notify_system_time(struct spoolss_notify_msg *msg,
705 SPOOL_NOTIFY_INFO_DATA *data,
706 TALLOC_CTX *mem_ctx)
708 SYSTEMTIME systime;
709 prs_struct ps;
711 if (msg->len != sizeof(time_t)) {
712 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
713 msg->len));
714 return;
717 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
718 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
719 return;
722 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
723 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
724 prs_mem_free(&ps);
725 return;
728 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
729 prs_mem_free(&ps);
730 return;
733 data->notify_data.data.length = prs_offset(&ps);
734 if (prs_offset(&ps)) {
735 data->notify_data.data.string = (uint16 *)
736 TALLOC(mem_ctx, prs_offset(&ps));
737 if (!data->notify_data.data.string) {
738 prs_mem_free(&ps);
739 return;
741 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
742 } else {
743 data->notify_data.data.string = NULL;
746 prs_mem_free(&ps);
749 struct notify2_message_table {
750 const char *name;
751 void (*fn)(struct spoolss_notify_msg *msg,
752 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
755 static struct notify2_message_table printer_notify_table[] = {
756 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
757 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
758 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
759 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
760 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
761 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
762 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
763 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
764 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
765 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
766 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
767 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
768 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
769 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
770 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
771 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
772 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
773 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
774 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
777 static struct notify2_message_table job_notify_table[] = {
778 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
779 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
780 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
781 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
782 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
783 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
784 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
785 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
786 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
787 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
788 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
789 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
790 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
791 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
792 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
793 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
794 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
795 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
796 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
797 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
798 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
799 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
800 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
801 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
805 /***********************************************************************
806 Allocate talloc context for container object
807 **********************************************************************/
809 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
811 if ( !ctr )
812 return;
814 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
816 return;
819 /***********************************************************************
820 release all allocated memory and zero out structure
821 **********************************************************************/
823 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
825 if ( !ctr )
826 return;
828 if ( ctr->ctx )
829 talloc_destroy(ctr->ctx);
831 ZERO_STRUCTP(ctr);
833 return;
836 /***********************************************************************
837 **********************************************************************/
839 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
841 if ( !ctr )
842 return NULL;
844 return ctr->ctx;
847 /***********************************************************************
848 **********************************************************************/
850 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
852 if ( !ctr || !ctr->msg_groups )
853 return NULL;
855 if ( idx >= ctr->num_groups )
856 return NULL;
858 return &ctr->msg_groups[idx];
862 /***********************************************************************
863 How many groups of change messages do we have ?
864 **********************************************************************/
866 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
868 if ( !ctr )
869 return 0;
871 return ctr->num_groups;
874 /***********************************************************************
875 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
876 **********************************************************************/
878 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
880 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
881 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
882 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
883 int i, new_slot;
885 if ( !ctr || !msg )
886 return 0;
888 /* loop over all groups looking for a matching printer name */
890 for ( i=0; i<ctr->num_groups; i++ ) {
891 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
892 break;
895 /* add a new group? */
897 if ( i == ctr->num_groups ) {
898 ctr->num_groups++;
900 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
901 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
902 return 0;
904 ctr->msg_groups = groups;
906 /* clear the new entry and set the printer name */
908 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
909 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
912 /* add the change messages; 'i' is the correct index now regardless */
914 msg_grp = &ctr->msg_groups[i];
916 msg_grp->num_msgs++;
918 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
919 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
920 return 0;
922 msg_grp->msgs = msg_list;
924 new_slot = msg_grp->num_msgs-1;
925 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
927 /* need to allocate own copy of data */
929 if ( msg->len != 0 )
930 msg_grp->msgs[new_slot].notify.data = (char *)
931 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
933 return ctr->num_groups;
936 /***********************************************************************
937 Send a change notication message on all handles which have a call
938 back registered
939 **********************************************************************/
941 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
943 Printer_entry *p;
944 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
945 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
946 SPOOLSS_NOTIFY_MSG *messages;
947 int sending_msg_count;
949 if ( !msg_group ) {
950 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
951 return;
954 messages = msg_group->msgs;
956 if ( !messages ) {
957 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
958 return;
961 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
963 /* loop over all printers */
965 for (p = printers_list; p; p = p->next) {
966 SPOOL_NOTIFY_INFO_DATA *data;
967 uint32 data_len = 0;
968 uint32 id;
969 int i;
971 /* Is there notification on this handle? */
973 if ( !p->notify.client_connected )
974 continue;
976 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
978 /* For this printer? Print servers always receive
979 notifications. */
981 if ( ( p->printer_type == SPLHND_PRINTER ) &&
982 ( !strequal(msg_group->printername, p->sharename) ) )
983 continue;
985 DEBUG(10,("Our printer\n"));
987 /* allocate the max entries possible */
989 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
990 if (!data) {
991 return;
994 ZERO_STRUCTP(data);
996 /* build the array of change notifications */
998 sending_msg_count = 0;
1000 for ( i=0; i<msg_group->num_msgs; i++ ) {
1001 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1003 /* Are we monitoring this event? */
1005 if (!is_monitoring_event(p, msg->type, msg->field))
1006 continue;
1008 sending_msg_count++;
1011 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1012 msg->type, msg->field, p->sharename));
1015 * if the is a printer notification handle and not a job notification
1016 * type, then set the id to 0. Other wise just use what was specified
1017 * in the message.
1019 * When registering change notification on a print server handle
1020 * we always need to send back the id (snum) matching the printer
1021 * for which the change took place. For change notify registered
1022 * on a printer handle, this does not matter and the id should be 0.
1024 * --jerry
1027 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1028 id = 0;
1029 else
1030 id = msg->id;
1033 /* Convert unix jobid to smb jobid */
1035 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1036 id = sysjob_to_jobid(msg->id);
1038 if (id == -1) {
1039 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1040 goto done;
1044 construct_info_data( &data[data_len], msg->type, msg->field, id );
1046 switch(msg->type) {
1047 case PRINTER_NOTIFY_TYPE:
1048 if ( printer_notify_table[msg->field].fn )
1049 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1050 break;
1052 case JOB_NOTIFY_TYPE:
1053 if ( job_notify_table[msg->field].fn )
1054 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1055 break;
1057 default:
1058 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1059 goto done;
1062 data_len++;
1065 if ( sending_msg_count ) {
1066 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1067 data_len, data, p->notify.change, 0 );
1071 done:
1072 DEBUG(8,("send_notify2_changes: Exit...\n"));
1073 return;
1076 /***********************************************************************
1077 **********************************************************************/
1079 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1082 uint32 tv_sec, tv_usec;
1083 size_t offset = 0;
1085 /* Unpack message */
1087 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1088 msg->printer);
1090 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1091 &tv_sec, &tv_usec,
1092 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1094 if (msg->len == 0)
1095 tdb_unpack((char *)buf + offset, len - offset, "dd",
1096 &msg->notify.value[0], &msg->notify.value[1]);
1097 else
1098 tdb_unpack((char *)buf + offset, len - offset, "B",
1099 &msg->len, &msg->notify.data);
1101 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1102 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1104 tv->tv_sec = tv_sec;
1105 tv->tv_usec = tv_usec;
1107 if (msg->len == 0)
1108 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1109 msg->notify.value[1]));
1110 else
1111 dump_data(3, msg->notify.data, msg->len);
1113 return True;
1116 /********************************************************************
1117 Receive a notify2 message list
1118 ********************************************************************/
1120 static void receive_notify2_message_list(int msg_type, struct process_id src,
1121 void *msg, size_t len,
1122 void *private_data)
1124 size_t msg_count, i;
1125 char *buf = (char *)msg;
1126 char *msg_ptr;
1127 size_t msg_len;
1128 SPOOLSS_NOTIFY_MSG notify;
1129 SPOOLSS_NOTIFY_MSG_CTR messages;
1130 int num_groups;
1132 if (len < 4) {
1133 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1134 return;
1137 msg_count = IVAL(buf, 0);
1138 msg_ptr = buf + 4;
1140 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1142 if (msg_count == 0) {
1143 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1144 return;
1147 /* initialize the container */
1149 ZERO_STRUCT( messages );
1150 notify_msg_ctr_init( &messages );
1153 * build message groups for each printer identified
1154 * in a change_notify msg. Remember that a PCN message
1155 * includes the handle returned for the srv_spoolss_replyopenprinter()
1156 * call. Therefore messages are grouped according to printer handle.
1159 for ( i=0; i<msg_count; i++ ) {
1160 struct timeval msg_tv;
1162 if (msg_ptr + 4 - buf > len) {
1163 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1164 return;
1167 msg_len = IVAL(msg_ptr,0);
1168 msg_ptr += 4;
1170 if (msg_ptr + msg_len - buf > len) {
1171 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1172 return;
1175 /* unpack messages */
1177 ZERO_STRUCT( notify );
1178 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1179 msg_ptr += msg_len;
1181 /* add to correct list in container */
1183 notify_msg_ctr_addmsg( &messages, &notify );
1185 /* free memory that might have been allocated by notify2_unpack_msg() */
1187 if ( notify.len != 0 )
1188 SAFE_FREE( notify.notify.data );
1191 /* process each group of messages */
1193 num_groups = notify_msg_ctr_numgroups( &messages );
1194 for ( i=0; i<num_groups; i++ )
1195 send_notify2_changes( &messages, i );
1198 /* cleanup */
1200 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1202 notify_msg_ctr_destroy( &messages );
1204 return;
1207 /********************************************************************
1208 Send a message to ourself about new driver being installed
1209 so we can upgrade the information for each printer bound to this
1210 driver
1211 ********************************************************************/
1213 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1215 int len = strlen(drivername);
1217 if (!len)
1218 return False;
1220 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1221 drivername));
1223 message_send_pid(pid_to_procid(sys_getpid()),
1224 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1226 return True;
1229 /**********************************************************************
1230 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1231 over all printers, upgrading ones as necessary
1232 **********************************************************************/
1234 void do_drv_upgrade_printer(int msg_type, struct process_id src,
1235 void *buf, size_t len, void *private_data)
1237 fstring drivername;
1238 int snum;
1239 int n_services = lp_numservices();
1241 len = MIN(len,sizeof(drivername)-1);
1242 strncpy(drivername, (const char *)buf, len);
1244 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1246 /* Iterate the printer list */
1248 for (snum=0; snum<n_services; snum++)
1250 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1252 WERROR result;
1253 NT_PRINTER_INFO_LEVEL *printer = NULL;
1255 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1256 if (!W_ERROR_IS_OK(result))
1257 continue;
1259 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1261 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1263 /* all we care about currently is the change_id */
1265 result = mod_a_printer(printer, 2);
1266 if (!W_ERROR_IS_OK(result)) {
1267 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1268 dos_errstr(result)));
1272 free_a_printer(&printer, 2);
1276 /* all done */
1279 /********************************************************************
1280 Update the cache for all printq's with a registered client
1281 connection
1282 ********************************************************************/
1284 void update_monitored_printq_cache( void )
1286 Printer_entry *printer = printers_list;
1287 int snum;
1289 /* loop through all printers and update the cache where
1290 client_connected == True */
1291 while ( printer )
1293 if ( (printer->printer_type == SPLHND_PRINTER)
1294 && printer->notify.client_connected )
1296 snum = print_queue_snum(printer->sharename);
1297 print_queue_status( snum, NULL, NULL );
1300 printer = printer->next;
1303 return;
1305 /********************************************************************
1306 Send a message to ourself about new driver being installed
1307 so we can upgrade the information for each printer bound to this
1308 driver
1309 ********************************************************************/
1311 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1313 int len = strlen(drivername);
1315 if (!len)
1316 return False;
1318 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1319 drivername));
1321 message_send_pid(pid_to_procid(sys_getpid()),
1322 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1324 return True;
1327 /**********************************************************************
1328 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1329 over all printers, resetting printer data as neessary
1330 **********************************************************************/
1332 void reset_all_printerdata(int msg_type, struct process_id src,
1333 void *buf, size_t len, void *private_data)
1335 fstring drivername;
1336 int snum;
1337 int n_services = lp_numservices();
1339 len = MIN( len, sizeof(drivername)-1 );
1340 strncpy( drivername, (const char *)buf, len );
1342 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1344 /* Iterate the printer list */
1346 for ( snum=0; snum<n_services; snum++ )
1348 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1350 WERROR result;
1351 NT_PRINTER_INFO_LEVEL *printer = NULL;
1353 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1354 if ( !W_ERROR_IS_OK(result) )
1355 continue;
1358 * if the printer is bound to the driver,
1359 * then reset to the new driver initdata
1362 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1364 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1366 if ( !set_driver_init(printer, 2) ) {
1367 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1368 printer->info_2->printername, printer->info_2->drivername));
1371 result = mod_a_printer( printer, 2 );
1372 if ( !W_ERROR_IS_OK(result) ) {
1373 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1374 get_dos_error_msg(result)));
1378 free_a_printer( &printer, 2 );
1382 /* all done */
1384 return;
1387 /********************************************************************
1388 Copy routines used by convert_to_openprinterex()
1389 *******************************************************************/
1391 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1393 DEVICEMODE *d;
1394 int len;
1396 if (!devmode)
1397 return NULL;
1399 DEBUG (8,("dup_devmode\n"));
1401 /* bulk copy first */
1403 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1404 if (!d)
1405 return NULL;
1407 /* dup the pointer members separately */
1409 len = unistrlen(devmode->devicename.buffer);
1410 if (len != -1) {
1411 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1412 if (!d->devicename.buffer) {
1413 return NULL;
1415 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1416 return NULL;
1420 len = unistrlen(devmode->formname.buffer);
1421 if (len != -1) {
1422 d->formname.buffer = TALLOC_ARRAY(ctx, uint16, len);
1423 if (!d->formname.buffer) {
1424 return NULL;
1426 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1427 return NULL;
1430 if (devmode->driverextra) {
1431 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1432 devmode->driverextra);
1433 if (!d->dev_private) {
1434 return NULL;
1436 } else {
1437 d->dev_private = NULL;
1439 return d;
1442 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1444 if (!new_ctr || !ctr)
1445 return;
1447 DEBUG(8,("copy_devmode_ctr\n"));
1449 new_ctr->size = ctr->size;
1450 new_ctr->devmode_ptr = ctr->devmode_ptr;
1452 if(ctr->devmode_ptr)
1453 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1456 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1458 if (!new_def || !def)
1459 return;
1461 DEBUG(8,("copy_printer_defaults\n"));
1463 new_def->datatype_ptr = def->datatype_ptr;
1465 if (def->datatype_ptr)
1466 copy_unistr2(&new_def->datatype, &def->datatype);
1468 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1470 new_def->access_required = def->access_required;
1473 /********************************************************************
1474 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1475 * SPOOL_Q_OPEN_PRINTER_EX structure
1476 ********************************************************************/
1478 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1480 if (!q_u_ex || !q_u)
1481 return WERR_OK;
1483 DEBUG(8,("convert_to_openprinterex\n"));
1485 if ( q_u->printername ) {
1486 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1487 if (q_u_ex->printername == NULL)
1488 return WERR_NOMEM;
1489 copy_unistr2(q_u_ex->printername, q_u->printername);
1492 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1494 return WERR_OK;
1497 /********************************************************************
1498 * spoolss_open_printer
1500 * called from the spoolss dispatcher
1501 ********************************************************************/
1503 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1505 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1506 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1508 if (!q_u || !r_u)
1509 return WERR_NOMEM;
1511 ZERO_STRUCT(q_u_ex);
1512 ZERO_STRUCT(r_u_ex);
1514 /* convert the OpenPrinter() call to OpenPrinterEx() */
1516 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1517 if (!W_ERROR_IS_OK(r_u_ex.status))
1518 return r_u_ex.status;
1520 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1522 /* convert back to OpenPrinter() */
1524 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1526 return r_u->status;
1529 /********************************************************************
1530 ********************************************************************/
1532 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1534 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1535 POLICY_HND *handle = &r_u->handle;
1537 fstring name;
1538 int snum;
1539 struct current_user user;
1540 Printer_entry *Printer=NULL;
1542 if ( !q_u->printername )
1543 return WERR_INVALID_PRINTER_NAME;
1545 /* some sanity check because you can open a printer or a print server */
1546 /* aka: \\server\printer or \\server */
1548 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1550 DEBUGADD(3,("checking name: %s\n",name));
1552 if (!open_printer_hnd(p, handle, name, 0))
1553 return WERR_INVALID_PRINTER_NAME;
1555 Printer=find_printer_index_by_hnd(p, handle);
1556 if ( !Printer ) {
1557 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1558 "handle we created for printer %s\n", name ));
1559 close_printer_handle(p,handle);
1560 return WERR_INVALID_PRINTER_NAME;
1563 get_current_user(&user, p);
1566 * First case: the user is opening the print server:
1568 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1569 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1571 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1572 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1573 * or if the user is listed in the smb.conf printer admin parameter.
1575 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1576 * client view printer folder, but does not show the MSAPW.
1578 * Note: this test needs code to check access rights here too. Jeremy
1579 * could you look at this?
1581 * Second case: the user is opening a printer:
1582 * NT doesn't let us connect to a printer if the connecting user
1583 * doesn't have print permission.
1585 * Third case: user is opening a Port Monitor
1586 * access checks same as opening a handle to the print server.
1589 switch (Printer->printer_type )
1591 case SPLHND_SERVER:
1592 case SPLHND_PORTMON_TCP:
1593 case SPLHND_PORTMON_LOCAL:
1594 /* Printserver handles use global struct... */
1596 snum = -1;
1598 /* Map standard access rights to object specific access rights */
1600 se_map_standard(&printer_default->access_required,
1601 &printserver_std_mapping);
1603 /* Deny any object specific bits that don't apply to print
1604 servers (i.e printer and job specific bits) */
1606 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1608 if (printer_default->access_required &
1609 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1610 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1611 close_printer_handle(p, handle);
1612 return WERR_ACCESS_DENIED;
1615 /* Allow admin access */
1617 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1619 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1621 if (!lp_ms_add_printer_wizard()) {
1622 close_printer_handle(p, handle);
1623 return WERR_ACCESS_DENIED;
1626 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1627 and not a printer admin, then fail */
1629 if ((user.ut.uid != 0) &&
1630 !user_has_privileges(user.nt_user_token,
1631 &se_printop ) &&
1632 !token_contains_name_in_list(
1633 uidtoname(user.ut.uid), NULL,
1634 user.nt_user_token,
1635 lp_printer_admin(snum))) {
1636 close_printer_handle(p, handle);
1637 return WERR_ACCESS_DENIED;
1640 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1642 else
1644 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1647 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1648 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1650 /* We fall through to return WERR_OK */
1651 break;
1653 case SPLHND_PRINTER:
1654 /* NT doesn't let us connect to a printer if the connecting user
1655 doesn't have print permission. */
1657 if (!get_printer_snum(p, handle, &snum)) {
1658 close_printer_handle(p, handle);
1659 return WERR_BADFID;
1662 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1664 /* map an empty access mask to the minimum access mask */
1665 if (printer_default->access_required == 0x0)
1666 printer_default->access_required = PRINTER_ACCESS_USE;
1669 * If we are not serving the printer driver for this printer,
1670 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1671 * will keep NT clients happy --jerry
1674 if (lp_use_client_driver(snum)
1675 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1677 printer_default->access_required = PRINTER_ACCESS_USE;
1680 /* check smb.conf parameters and the the sec_desc */
1682 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1683 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1684 return WERR_ACCESS_DENIED;
1687 if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
1688 snum) ||
1689 !print_access_check(&user, snum,
1690 printer_default->access_required)) {
1691 DEBUG(3, ("access DENIED for printer open\n"));
1692 close_printer_handle(p, handle);
1693 return WERR_ACCESS_DENIED;
1696 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1697 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1698 close_printer_handle(p, handle);
1699 return WERR_ACCESS_DENIED;
1702 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1703 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1704 else
1705 printer_default->access_required = PRINTER_ACCESS_USE;
1707 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1708 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1710 break;
1712 default:
1713 /* sanity check to prevent programmer error */
1714 return WERR_BADFID;
1717 Printer->access_granted = printer_default->access_required;
1720 * If the client sent a devmode in the OpenPrinter() call, then
1721 * save it here in case we get a job submission on this handle
1724 if ( (Printer->printer_type != SPLHND_SERVER)
1725 && q_u->printer_default.devmode_cont.devmode_ptr )
1727 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1728 &Printer->nt_devmode );
1731 #if 0 /* JERRY -- I'm doubtful this is really effective */
1732 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1733 optimization in Windows 2000 clients --jerry */
1735 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1736 && (RA_WIN2K == get_remote_arch()) )
1738 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1739 sys_usleep( 500000 );
1741 #endif
1743 return WERR_OK;
1746 /****************************************************************************
1747 ****************************************************************************/
1749 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1750 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1752 BOOL ret;
1754 switch (level) {
1755 case 2:
1756 /* allocate memory if needed. Messy because
1757 convert_printer_info is used to update an existing
1758 printer or build a new one */
1760 if ( !printer->info_2 ) {
1761 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1762 if ( !printer->info_2 ) {
1763 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1764 return False;
1768 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1769 printer->info_2->setuptime = time(NULL);
1771 return ret;
1774 return False;
1777 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1778 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1780 BOOL result = True;
1782 switch (level) {
1783 case 3:
1784 printer->info_3=NULL;
1785 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1786 result = False;
1787 break;
1788 case 6:
1789 printer->info_6=NULL;
1790 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1791 result = False;
1792 break;
1793 default:
1794 break;
1797 return result;
1800 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1801 NT_DEVICEMODE **pp_nt_devmode)
1803 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1806 * Ensure nt_devmode is a valid pointer
1807 * as we will be overwriting it.
1810 if (nt_devmode == NULL) {
1811 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1812 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1813 return False;
1816 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1817 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1819 nt_devmode->specversion=devmode->specversion;
1820 nt_devmode->driverversion=devmode->driverversion;
1821 nt_devmode->size=devmode->size;
1822 nt_devmode->fields=devmode->fields;
1823 nt_devmode->orientation=devmode->orientation;
1824 nt_devmode->papersize=devmode->papersize;
1825 nt_devmode->paperlength=devmode->paperlength;
1826 nt_devmode->paperwidth=devmode->paperwidth;
1827 nt_devmode->scale=devmode->scale;
1828 nt_devmode->copies=devmode->copies;
1829 nt_devmode->defaultsource=devmode->defaultsource;
1830 nt_devmode->printquality=devmode->printquality;
1831 nt_devmode->color=devmode->color;
1832 nt_devmode->duplex=devmode->duplex;
1833 nt_devmode->yresolution=devmode->yresolution;
1834 nt_devmode->ttoption=devmode->ttoption;
1835 nt_devmode->collate=devmode->collate;
1837 nt_devmode->logpixels=devmode->logpixels;
1838 nt_devmode->bitsperpel=devmode->bitsperpel;
1839 nt_devmode->pelswidth=devmode->pelswidth;
1840 nt_devmode->pelsheight=devmode->pelsheight;
1841 nt_devmode->displayflags=devmode->displayflags;
1842 nt_devmode->displayfrequency=devmode->displayfrequency;
1843 nt_devmode->icmmethod=devmode->icmmethod;
1844 nt_devmode->icmintent=devmode->icmintent;
1845 nt_devmode->mediatype=devmode->mediatype;
1846 nt_devmode->dithertype=devmode->dithertype;
1847 nt_devmode->reserved1=devmode->reserved1;
1848 nt_devmode->reserved2=devmode->reserved2;
1849 nt_devmode->panningwidth=devmode->panningwidth;
1850 nt_devmode->panningheight=devmode->panningheight;
1853 * Only change private and driverextra if the incoming devmode
1854 * has a new one. JRA.
1857 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1858 SAFE_FREE(nt_devmode->nt_dev_private);
1859 nt_devmode->driverextra=devmode->driverextra;
1860 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1861 return False;
1862 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1865 *pp_nt_devmode = nt_devmode;
1867 return True;
1870 /********************************************************************
1871 * _spoolss_enddocprinter_internal.
1872 ********************************************************************/
1874 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1876 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1877 int snum;
1879 if (!Printer) {
1880 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1881 return WERR_BADFID;
1884 if (!get_printer_snum(p, handle, &snum))
1885 return WERR_BADFID;
1887 Printer->document_started=False;
1888 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1889 /* error codes unhandled so far ... */
1891 return WERR_OK;
1894 /********************************************************************
1895 * api_spoolss_closeprinter
1896 ********************************************************************/
1898 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1900 POLICY_HND *handle = &q_u->handle;
1902 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1904 if (Printer && Printer->document_started)
1905 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1907 if (!close_printer_handle(p, handle))
1908 return WERR_BADFID;
1910 /* clear the returned printer handle. Observed behavior
1911 from Win2k server. Don't think this really matters.
1912 Previous code just copied the value of the closed
1913 handle. --jerry */
1915 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1917 return WERR_OK;
1920 /********************************************************************
1921 * api_spoolss_deleteprinter
1923 ********************************************************************/
1925 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1927 POLICY_HND *handle = &q_u->handle;
1928 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1929 WERROR result;
1931 if (Printer && Printer->document_started)
1932 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1934 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1936 result = delete_printer_handle(p, handle);
1938 update_c_setprinter(False);
1940 return result;
1943 /*******************************************************************
1944 * static function to lookup the version id corresponding to an
1945 * long architecture string
1946 ******************************************************************/
1948 static int get_version_id (char * arch)
1950 int i;
1951 struct table_node archi_table[]= {
1953 {"Windows 4.0", "WIN40", 0 },
1954 {"Windows NT x86", "W32X86", 2 },
1955 {"Windows NT R4000", "W32MIPS", 2 },
1956 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1957 {"Windows NT PowerPC", "W32PPC", 2 },
1958 {"Windows IA64", "IA64", 3 },
1959 {"Windows x64", "x64", 3 },
1960 {NULL, "", -1 }
1963 for (i=0; archi_table[i].long_archi != NULL; i++)
1965 if (strcmp(arch, archi_table[i].long_archi) == 0)
1966 return (archi_table[i].version);
1969 return -1;
1972 /********************************************************************
1973 * _spoolss_deleteprinterdriver
1974 ********************************************************************/
1976 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1978 fstring driver;
1979 fstring arch;
1980 NT_PRINTER_DRIVER_INFO_LEVEL info;
1981 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1982 int version;
1983 struct current_user user;
1984 WERROR status;
1985 WERROR status_win2k = WERR_ACCESS_DENIED;
1986 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1988 get_current_user(&user, p);
1990 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1991 and not a printer admin, then fail */
1993 if ( (user.ut.uid != 0)
1994 && !user_has_privileges(user.nt_user_token, &se_printop )
1995 && !token_contains_name_in_list( uidtoname(user.ut.uid),
1996 NULL, user.nt_user_token, lp_printer_admin(-1)) )
1998 return WERR_ACCESS_DENIED;
2001 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2002 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2004 /* check that we have a valid driver name first */
2006 if ((version=get_version_id(arch)) == -1)
2007 return WERR_INVALID_ENVIRONMENT;
2009 ZERO_STRUCT(info);
2010 ZERO_STRUCT(info_win2k);
2012 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2014 /* try for Win2k driver if "Windows NT x86" */
2016 if ( version == 2 ) {
2017 version = 3;
2018 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2019 status = WERR_UNKNOWN_PRINTER_DRIVER;
2020 goto done;
2023 /* otherwise it was a failure */
2024 else {
2025 status = WERR_UNKNOWN_PRINTER_DRIVER;
2026 goto done;
2031 if (printer_driver_in_use(info.info_3)) {
2032 status = WERR_PRINTER_DRIVER_IN_USE;
2033 goto done;
2036 if ( version == 2 )
2038 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2040 /* if we get to here, we now have 2 driver info structures to remove */
2041 /* remove the Win2k driver first*/
2043 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2044 free_a_printer_driver( info_win2k, 3 );
2046 /* this should not have failed---if it did, report to client */
2047 if ( !W_ERROR_IS_OK(status_win2k) )
2049 status = status_win2k;
2050 goto done;
2055 status = delete_printer_driver(info.info_3, &user, version, False);
2057 /* if at least one of the deletes succeeded return OK */
2059 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2060 status = WERR_OK;
2062 done:
2063 free_a_printer_driver( info, 3 );
2065 return status;
2068 /********************************************************************
2069 * spoolss_deleteprinterdriverex
2070 ********************************************************************/
2072 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2074 fstring driver;
2075 fstring arch;
2076 NT_PRINTER_DRIVER_INFO_LEVEL info;
2077 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2078 int version;
2079 uint32 flags = q_u->delete_flags;
2080 BOOL delete_files;
2081 struct current_user user;
2082 WERROR status;
2083 WERROR status_win2k = WERR_ACCESS_DENIED;
2084 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2086 get_current_user(&user, p);
2088 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2089 and not a printer admin, then fail */
2091 if ( (user.ut.uid != 0)
2092 && !user_has_privileges(user.nt_user_token, &se_printop )
2093 && !token_contains_name_in_list( uidtoname(user.ut.uid),
2094 NULL, user.nt_user_token, lp_printer_admin(-1)) )
2096 return WERR_ACCESS_DENIED;
2099 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2100 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2102 /* check that we have a valid driver name first */
2103 if ((version=get_version_id(arch)) == -1) {
2104 /* this is what NT returns */
2105 return WERR_INVALID_ENVIRONMENT;
2108 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2109 version = q_u->version;
2111 ZERO_STRUCT(info);
2112 ZERO_STRUCT(info_win2k);
2114 status = get_a_printer_driver(&info, 3, driver, arch, version);
2116 if ( !W_ERROR_IS_OK(status) )
2119 * if the client asked for a specific version,
2120 * or this is something other than Windows NT x86,
2121 * then we've failed
2124 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2125 goto done;
2127 /* try for Win2k driver if "Windows NT x86" */
2129 version = 3;
2130 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2131 status = WERR_UNKNOWN_PRINTER_DRIVER;
2132 goto done;
2136 if ( printer_driver_in_use(info.info_3) ) {
2137 status = WERR_PRINTER_DRIVER_IN_USE;
2138 goto done;
2142 * we have a couple of cases to consider.
2143 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2144 * then the delete should fail if **any** files overlap with
2145 * other drivers
2146 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2147 * non-overlapping files
2148 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2149 * is set, the do not delete any files
2150 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2153 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2155 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2157 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2158 /* no idea of the correct error here */
2159 status = WERR_ACCESS_DENIED;
2160 goto done;
2164 /* also check for W32X86/3 if necessary; maybe we already have? */
2166 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2167 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2170 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2171 /* no idea of the correct error here */
2172 free_a_printer_driver( info_win2k, 3 );
2173 status = WERR_ACCESS_DENIED;
2174 goto done;
2177 /* if we get to here, we now have 2 driver info structures to remove */
2178 /* remove the Win2k driver first*/
2180 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2181 free_a_printer_driver( info_win2k, 3 );
2183 /* this should not have failed---if it did, report to client */
2185 if ( !W_ERROR_IS_OK(status_win2k) )
2186 goto done;
2190 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2192 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2193 status = WERR_OK;
2194 done:
2195 free_a_printer_driver( info, 3 );
2197 return status;
2201 /****************************************************************************
2202 Internal routine for retreiving printerdata
2203 ***************************************************************************/
2205 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2206 const char *key, const char *value, uint32 *type, uint8 **data,
2207 uint32 *needed, uint32 in_size )
2209 REGISTRY_VALUE *val;
2210 uint32 size;
2211 int data_len;
2213 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2214 return WERR_BADFILE;
2216 *type = regval_type( val );
2218 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2220 size = regval_size( val );
2222 /* copy the min(in_size, len) */
2224 if ( in_size ) {
2225 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2227 /* special case for 0 length values */
2228 if ( data_len ) {
2229 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2230 return WERR_NOMEM;
2232 else {
2233 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2234 return WERR_NOMEM;
2237 else
2238 *data = NULL;
2240 *needed = size;
2242 DEBUG(5,("get_printer_dataex: copy done\n"));
2244 return WERR_OK;
2247 /****************************************************************************
2248 Internal routine for removing printerdata
2249 ***************************************************************************/
2251 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2253 return delete_printer_data( printer->info_2, key, value );
2256 /****************************************************************************
2257 Internal routine for storing printerdata
2258 ***************************************************************************/
2260 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2261 uint32 type, uint8 *data, int real_len )
2263 /* the registry objects enforce uniqueness based on value name */
2265 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2268 /********************************************************************
2269 GetPrinterData on a printer server Handle.
2270 ********************************************************************/
2272 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2274 int i;
2276 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2278 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2279 *type = REG_DWORD;
2280 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2281 return WERR_NOMEM;
2282 SIVAL(*data, 0, 0x00);
2283 *needed = 0x4;
2284 return WERR_OK;
2287 if (!StrCaseCmp(value, "BeepEnabled")) {
2288 *type = REG_DWORD;
2289 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2290 return WERR_NOMEM;
2291 SIVAL(*data, 0, 0x00);
2292 *needed = 0x4;
2293 return WERR_OK;
2296 if (!StrCaseCmp(value, "EventLog")) {
2297 *type = REG_DWORD;
2298 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2299 return WERR_NOMEM;
2300 /* formally was 0x1b */
2301 SIVAL(*data, 0, 0x0);
2302 *needed = 0x4;
2303 return WERR_OK;
2306 if (!StrCaseCmp(value, "NetPopup")) {
2307 *type = REG_DWORD;
2308 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2309 return WERR_NOMEM;
2310 SIVAL(*data, 0, 0x00);
2311 *needed = 0x4;
2312 return WERR_OK;
2315 if (!StrCaseCmp(value, "MajorVersion")) {
2316 *type = REG_DWORD;
2317 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2318 return WERR_NOMEM;
2320 /* Windows NT 4.0 seems to not allow uploading of drivers
2321 to a server that reports 0x3 as the MajorVersion.
2322 need to investigate more how Win2k gets around this .
2323 -- jerry */
2325 if ( RA_WINNT == get_remote_arch() )
2326 SIVAL(*data, 0, 2);
2327 else
2328 SIVAL(*data, 0, 3);
2330 *needed = 0x4;
2331 return WERR_OK;
2334 if (!StrCaseCmp(value, "MinorVersion")) {
2335 *type = REG_DWORD;
2336 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2337 return WERR_NOMEM;
2338 SIVAL(*data, 0, 0);
2339 *needed = 0x4;
2340 return WERR_OK;
2343 /* REG_BINARY
2344 * uint32 size = 0x114
2345 * uint32 major = 5
2346 * uint32 minor = [0|1]
2347 * uint32 build = [2195|2600]
2348 * extra unicode string = e.g. "Service Pack 3"
2350 if (!StrCaseCmp(value, "OSVersion")) {
2351 *type = REG_BINARY;
2352 *needed = 0x114;
2354 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2355 return WERR_NOMEM;
2357 SIVAL(*data, 0, *needed); /* size */
2358 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2359 SIVAL(*data, 8, 0);
2360 SIVAL(*data, 12, 2195); /* build */
2362 /* leave extra string empty */
2364 return WERR_OK;
2368 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2369 const char *string="C:\\PRINTERS";
2370 *type = REG_SZ;
2371 *needed = 2*(strlen(string)+1);
2372 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2373 return WERR_NOMEM;
2374 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2376 /* it's done by hand ready to go on the wire */
2377 for (i=0; i<strlen(string); i++) {
2378 (*data)[2*i]=string[i];
2379 (*data)[2*i+1]='\0';
2381 return WERR_OK;
2384 if (!StrCaseCmp(value, "Architecture")) {
2385 const char *string="Windows NT x86";
2386 *type = REG_SZ;
2387 *needed = 2*(strlen(string)+1);
2388 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2389 return WERR_NOMEM;
2390 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2391 for (i=0; i<strlen(string); i++) {
2392 (*data)[2*i]=string[i];
2393 (*data)[2*i+1]='\0';
2395 return WERR_OK;
2398 if (!StrCaseCmp(value, "DsPresent")) {
2399 *type = REG_DWORD;
2400 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2401 return WERR_NOMEM;
2403 /* only show the publish check box if we are a
2404 memeber of a AD domain */
2406 if ( lp_security() == SEC_ADS )
2407 SIVAL(*data, 0, 0x01);
2408 else
2409 SIVAL(*data, 0, 0x00);
2411 *needed = 0x4;
2412 return WERR_OK;
2415 if (!StrCaseCmp(value, "DNSMachineName")) {
2416 pstring hostname;
2418 if (!get_mydnsfullname(hostname))
2419 return WERR_BADFILE;
2420 *type = REG_SZ;
2421 *needed = 2*(strlen(hostname)+1);
2422 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2423 return WERR_NOMEM;
2424 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2425 for (i=0; i<strlen(hostname); i++) {
2426 (*data)[2*i]=hostname[i];
2427 (*data)[2*i+1]='\0';
2429 return WERR_OK;
2433 return WERR_BADFILE;
2436 /********************************************************************
2437 * spoolss_getprinterdata
2438 ********************************************************************/
2440 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2442 POLICY_HND *handle = &q_u->handle;
2443 UNISTR2 *valuename = &q_u->valuename;
2444 uint32 in_size = q_u->size;
2445 uint32 *type = &r_u->type;
2446 uint32 *out_size = &r_u->size;
2447 uint8 **data = &r_u->data;
2448 uint32 *needed = &r_u->needed;
2449 WERROR status;
2450 fstring value;
2451 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2452 NT_PRINTER_INFO_LEVEL *printer = NULL;
2453 int snum = 0;
2456 * Reminder: when it's a string, the length is in BYTES
2457 * even if UNICODE is negociated.
2459 * JFM, 4/19/1999
2462 *out_size = in_size;
2464 /* in case of problem, return some default values */
2466 *needed = 0;
2467 *type = 0;
2469 DEBUG(4,("_spoolss_getprinterdata\n"));
2471 if ( !Printer ) {
2472 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2473 status = WERR_BADFID;
2474 goto done;
2477 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2479 if ( Printer->printer_type == SPLHND_SERVER )
2480 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2481 else
2483 if ( !get_printer_snum(p,handle, &snum) ) {
2484 status = WERR_BADFID;
2485 goto done;
2488 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2489 if ( !W_ERROR_IS_OK(status) )
2490 goto done;
2492 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2494 if ( strequal(value, "ChangeId") ) {
2495 *type = REG_DWORD;
2496 *needed = sizeof(uint32);
2497 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2498 status = WERR_NOMEM;
2499 goto done;
2501 SIVAL( *data, 0, printer->info_2->changeid );
2502 status = WERR_OK;
2504 else
2505 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2508 if (*needed > *out_size)
2509 status = WERR_MORE_DATA;
2511 done:
2512 if ( !W_ERROR_IS_OK(status) )
2514 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2516 /* reply this param doesn't exist */
2518 if ( *out_size ) {
2519 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2520 if ( printer )
2521 free_a_printer( &printer, 2 );
2522 return WERR_NOMEM;
2524 } else {
2525 *data = NULL;
2529 /* cleanup & exit */
2531 if ( printer )
2532 free_a_printer( &printer, 2 );
2534 return status;
2537 /*********************************************************
2538 Connect to the client machine.
2539 **********************************************************/
2541 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2542 struct in_addr *client_ip, const char *remote_machine)
2544 NTSTATUS ret;
2545 struct cli_state *the_cli;
2546 struct in_addr rm_addr;
2548 if ( is_zero_ip(*client_ip) ) {
2549 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2550 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2551 return False;
2554 if ( ismyip( rm_addr )) {
2555 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2556 return False;
2558 } else {
2559 rm_addr.s_addr = client_ip->s_addr;
2560 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2561 inet_ntoa(*client_ip) ));
2564 /* setup the connection */
2566 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2567 &rm_addr, 0, "IPC$", "IPC",
2568 "", /* username */
2569 "", /* domain */
2570 "", /* password */
2571 0, lp_client_signing(), NULL );
2573 if ( !NT_STATUS_IS_OK( ret ) ) {
2574 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2575 remote_machine ));
2576 return False;
2579 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2580 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2581 cli_shutdown(the_cli);
2582 return False;
2586 * Ok - we have an anonymous connection to the IPC$ share.
2587 * Now start the NT Domain stuff :-).
2590 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2591 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2592 remote_machine, nt_errstr(ret)));
2593 cli_shutdown(the_cli);
2594 return False;
2597 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2599 (*pp_pipe)->cli = the_cli;
2601 return True;
2604 /***************************************************************************
2605 Connect to the client.
2606 ****************************************************************************/
2608 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2609 uint32 localprinter, uint32 type,
2610 POLICY_HND *handle, struct in_addr *client_ip)
2612 WERROR result;
2615 * If it's the first connection, contact the client
2616 * and connect to the IPC$ share anonymously
2618 if (smb_connections==0) {
2619 fstring unix_printer;
2621 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2623 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ip, unix_printer ))
2624 return False;
2626 message_register(MSG_PRINTER_NOTIFY2,
2627 receive_notify2_message_list, NULL);
2628 /* Tell the connections db we're now interested in printer
2629 * notify messages. */
2630 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2634 * Tell the specific printing tdb we want messages for this printer
2635 * by registering our PID.
2638 if (!print_notify_register_pid(snum))
2639 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2641 smb_connections++;
2643 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2644 type, handle);
2646 if (!W_ERROR_IS_OK(result))
2647 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2648 dos_errstr(result)));
2650 return (W_ERROR_IS_OK(result));
2653 /********************************************************************
2654 * _spoolss_rffpcnex
2655 * ReplyFindFirstPrinterChangeNotifyEx
2657 * before replying OK: status=0 a rpc call is made to the workstation
2658 * asking ReplyOpenPrinter
2660 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2661 * called from api_spoolss_rffpcnex
2662 ********************************************************************/
2664 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2666 POLICY_HND *handle = &q_u->handle;
2667 uint32 flags = q_u->flags;
2668 uint32 options = q_u->options;
2669 UNISTR2 *localmachine = &q_u->localmachine;
2670 uint32 printerlocal = q_u->printerlocal;
2671 int snum = -1;
2672 SPOOL_NOTIFY_OPTION *option = q_u->option;
2673 struct in_addr client_ip;
2675 /* store the notify value in the printer struct */
2677 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2679 if (!Printer) {
2680 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2681 return WERR_BADFID;
2684 Printer->notify.flags=flags;
2685 Printer->notify.options=options;
2686 Printer->notify.printerlocal=printerlocal;
2688 if (Printer->notify.option)
2689 free_spool_notify_option(&Printer->notify.option);
2691 Printer->notify.option=dup_spool_notify_option(option);
2693 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2694 sizeof(Printer->notify.localmachine)-1);
2696 /* Connect to the client machine and send a ReplyOpenPrinter */
2698 if ( Printer->printer_type == SPLHND_SERVER)
2699 snum = -1;
2700 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2701 !get_printer_snum(p, handle, &snum) )
2702 return WERR_BADFID;
2704 client_ip.s_addr = inet_addr(p->conn->client_address);
2706 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2707 Printer->notify.printerlocal, 1,
2708 &Printer->notify.client_hnd, &client_ip))
2709 return WERR_SERVER_UNAVAILABLE;
2711 Printer->notify.client_connected=True;
2713 return WERR_OK;
2716 /*******************************************************************
2717 * fill a notify_info_data with the servername
2718 ********************************************************************/
2720 void spoolss_notify_server_name(int snum,
2721 SPOOL_NOTIFY_INFO_DATA *data,
2722 print_queue_struct *queue,
2723 NT_PRINTER_INFO_LEVEL *printer,
2724 TALLOC_CTX *mem_ctx)
2726 pstring temp;
2727 uint32 len;
2729 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2731 data->notify_data.data.length = len;
2732 if (len) {
2733 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2734 if (!data->notify_data.data.string) {
2735 data->notify_data.data.length = 0;
2736 return;
2739 memcpy(data->notify_data.data.string, temp, len);
2740 } else {
2741 data->notify_data.data.string = NULL;
2745 /*******************************************************************
2746 * fill a notify_info_data with the printername (not including the servername).
2747 ********************************************************************/
2749 void spoolss_notify_printer_name(int snum,
2750 SPOOL_NOTIFY_INFO_DATA *data,
2751 print_queue_struct *queue,
2752 NT_PRINTER_INFO_LEVEL *printer,
2753 TALLOC_CTX *mem_ctx)
2755 pstring temp;
2756 uint32 len;
2758 /* the notify name should not contain the \\server\ part */
2759 char *p = strrchr(printer->info_2->printername, '\\');
2761 if (!p) {
2762 p = printer->info_2->printername;
2763 } else {
2764 p++;
2767 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2769 data->notify_data.data.length = len;
2770 if (len) {
2771 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2772 if (!data->notify_data.data.string) {
2773 data->notify_data.data.length = 0;
2774 return;
2776 memcpy(data->notify_data.data.string, temp, len);
2777 } else {
2778 data->notify_data.data.string = NULL;
2782 /*******************************************************************
2783 * fill a notify_info_data with the servicename
2784 ********************************************************************/
2786 void spoolss_notify_share_name(int snum,
2787 SPOOL_NOTIFY_INFO_DATA *data,
2788 print_queue_struct *queue,
2789 NT_PRINTER_INFO_LEVEL *printer,
2790 TALLOC_CTX *mem_ctx)
2792 pstring temp;
2793 uint32 len;
2795 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2797 data->notify_data.data.length = len;
2798 if (len) {
2799 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2800 if (!data->notify_data.data.string) {
2801 data->notify_data.data.length = 0;
2802 return;
2804 memcpy(data->notify_data.data.string, temp, len);
2805 } else {
2806 data->notify_data.data.string = NULL;
2811 /*******************************************************************
2812 * fill a notify_info_data with the port name
2813 ********************************************************************/
2815 void spoolss_notify_port_name(int snum,
2816 SPOOL_NOTIFY_INFO_DATA *data,
2817 print_queue_struct *queue,
2818 NT_PRINTER_INFO_LEVEL *printer,
2819 TALLOC_CTX *mem_ctx)
2821 pstring temp;
2822 uint32 len;
2824 /* even if it's strange, that's consistant in all the code */
2826 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2828 data->notify_data.data.length = len;
2829 if (len) {
2830 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2832 if (!data->notify_data.data.string) {
2833 data->notify_data.data.length = 0;
2834 return;
2837 memcpy(data->notify_data.data.string, temp, len);
2838 } else {
2839 data->notify_data.data.string = NULL;
2843 /*******************************************************************
2844 * fill a notify_info_data with the printername
2845 * but it doesn't exist, have to see what to do
2846 ********************************************************************/
2848 void spoolss_notify_driver_name(int snum,
2849 SPOOL_NOTIFY_INFO_DATA *data,
2850 print_queue_struct *queue,
2851 NT_PRINTER_INFO_LEVEL *printer,
2852 TALLOC_CTX *mem_ctx)
2854 pstring temp;
2855 uint32 len;
2857 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2859 data->notify_data.data.length = len;
2860 if (len) {
2861 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2863 if (!data->notify_data.data.string) {
2864 data->notify_data.data.length = 0;
2865 return;
2868 memcpy(data->notify_data.data.string, temp, len);
2869 } else {
2870 data->notify_data.data.string = NULL;
2874 /*******************************************************************
2875 * fill a notify_info_data with the comment
2876 ********************************************************************/
2878 void spoolss_notify_comment(int snum,
2879 SPOOL_NOTIFY_INFO_DATA *data,
2880 print_queue_struct *queue,
2881 NT_PRINTER_INFO_LEVEL *printer,
2882 TALLOC_CTX *mem_ctx)
2884 pstring temp;
2885 uint32 len;
2887 if (*printer->info_2->comment == '\0')
2888 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2889 else
2890 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2892 data->notify_data.data.length = len;
2893 if (len) {
2894 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2896 if (!data->notify_data.data.string) {
2897 data->notify_data.data.length = 0;
2898 return;
2901 memcpy(data->notify_data.data.string, temp, len);
2902 } else {
2903 data->notify_data.data.string = NULL;
2907 /*******************************************************************
2908 * fill a notify_info_data with the comment
2909 * location = "Room 1, floor 2, building 3"
2910 ********************************************************************/
2912 void spoolss_notify_location(int snum,
2913 SPOOL_NOTIFY_INFO_DATA *data,
2914 print_queue_struct *queue,
2915 NT_PRINTER_INFO_LEVEL *printer,
2916 TALLOC_CTX *mem_ctx)
2918 pstring temp;
2919 uint32 len;
2921 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2923 data->notify_data.data.length = len;
2924 if (len) {
2925 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2927 if (!data->notify_data.data.string) {
2928 data->notify_data.data.length = 0;
2929 return;
2932 memcpy(data->notify_data.data.string, temp, len);
2933 } else {
2934 data->notify_data.data.string = NULL;
2938 /*******************************************************************
2939 * fill a notify_info_data with the device mode
2940 * jfm:xxxx don't to it for know but that's a real problem !!!
2941 ********************************************************************/
2943 static void spoolss_notify_devmode(int snum,
2944 SPOOL_NOTIFY_INFO_DATA *data,
2945 print_queue_struct *queue,
2946 NT_PRINTER_INFO_LEVEL *printer,
2947 TALLOC_CTX *mem_ctx)
2949 /* for a dummy implementation we have to zero the fields */
2950 data->notify_data.data.length = 0;
2951 data->notify_data.data.string = NULL;
2954 /*******************************************************************
2955 * fill a notify_info_data with the separator file name
2956 ********************************************************************/
2958 void spoolss_notify_sepfile(int snum,
2959 SPOOL_NOTIFY_INFO_DATA *data,
2960 print_queue_struct *queue,
2961 NT_PRINTER_INFO_LEVEL *printer,
2962 TALLOC_CTX *mem_ctx)
2964 pstring temp;
2965 uint32 len;
2967 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2969 data->notify_data.data.length = len;
2970 if (len) {
2971 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2973 if (!data->notify_data.data.string) {
2974 data->notify_data.data.length = 0;
2975 return;
2978 memcpy(data->notify_data.data.string, temp, len);
2979 } else {
2980 data->notify_data.data.string = NULL;
2984 /*******************************************************************
2985 * fill a notify_info_data with the print processor
2986 * jfm:xxxx return always winprint to indicate we don't do anything to it
2987 ********************************************************************/
2989 void spoolss_notify_print_processor(int snum,
2990 SPOOL_NOTIFY_INFO_DATA *data,
2991 print_queue_struct *queue,
2992 NT_PRINTER_INFO_LEVEL *printer,
2993 TALLOC_CTX *mem_ctx)
2995 pstring temp;
2996 uint32 len;
2998 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3000 data->notify_data.data.length = len;
3001 if (len) {
3002 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3004 if (!data->notify_data.data.string) {
3005 data->notify_data.data.length = 0;
3006 return;
3009 memcpy(data->notify_data.data.string, temp, len);
3010 } else {
3011 data->notify_data.data.string = NULL;
3015 /*******************************************************************
3016 * fill a notify_info_data with the print processor options
3017 * jfm:xxxx send an empty string
3018 ********************************************************************/
3020 void spoolss_notify_parameters(int snum,
3021 SPOOL_NOTIFY_INFO_DATA *data,
3022 print_queue_struct *queue,
3023 NT_PRINTER_INFO_LEVEL *printer,
3024 TALLOC_CTX *mem_ctx)
3026 pstring temp;
3027 uint32 len;
3029 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3031 data->notify_data.data.length = len;
3032 if (len) {
3033 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3035 if (!data->notify_data.data.string) {
3036 data->notify_data.data.length = 0;
3037 return;
3040 memcpy(data->notify_data.data.string, temp, len);
3041 } else {
3042 data->notify_data.data.string = NULL;
3046 /*******************************************************************
3047 * fill a notify_info_data with the data type
3048 * jfm:xxxx always send RAW as data type
3049 ********************************************************************/
3051 void spoolss_notify_datatype(int snum,
3052 SPOOL_NOTIFY_INFO_DATA *data,
3053 print_queue_struct *queue,
3054 NT_PRINTER_INFO_LEVEL *printer,
3055 TALLOC_CTX *mem_ctx)
3057 pstring temp;
3058 uint32 len;
3060 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3062 data->notify_data.data.length = len;
3063 if (len) {
3064 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3066 if (!data->notify_data.data.string) {
3067 data->notify_data.data.length = 0;
3068 return;
3071 memcpy(data->notify_data.data.string, temp, len);
3072 } else {
3073 data->notify_data.data.string = NULL;
3077 /*******************************************************************
3078 * fill a notify_info_data with the security descriptor
3079 * jfm:xxxx send an null pointer to say no security desc
3080 * have to implement security before !
3081 ********************************************************************/
3083 static void spoolss_notify_security_desc(int snum,
3084 SPOOL_NOTIFY_INFO_DATA *data,
3085 print_queue_struct *queue,
3086 NT_PRINTER_INFO_LEVEL *printer,
3087 TALLOC_CTX *mem_ctx)
3089 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3090 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3093 /*******************************************************************
3094 * fill a notify_info_data with the attributes
3095 * jfm:xxxx a samba printer is always shared
3096 ********************************************************************/
3098 void spoolss_notify_attributes(int snum,
3099 SPOOL_NOTIFY_INFO_DATA *data,
3100 print_queue_struct *queue,
3101 NT_PRINTER_INFO_LEVEL *printer,
3102 TALLOC_CTX *mem_ctx)
3104 data->notify_data.value[0] = printer->info_2->attributes;
3105 data->notify_data.value[1] = 0;
3108 /*******************************************************************
3109 * fill a notify_info_data with the priority
3110 ********************************************************************/
3112 static void spoolss_notify_priority(int snum,
3113 SPOOL_NOTIFY_INFO_DATA *data,
3114 print_queue_struct *queue,
3115 NT_PRINTER_INFO_LEVEL *printer,
3116 TALLOC_CTX *mem_ctx)
3118 data->notify_data.value[0] = printer->info_2->priority;
3119 data->notify_data.value[1] = 0;
3122 /*******************************************************************
3123 * fill a notify_info_data with the default priority
3124 ********************************************************************/
3126 static void spoolss_notify_default_priority(int snum,
3127 SPOOL_NOTIFY_INFO_DATA *data,
3128 print_queue_struct *queue,
3129 NT_PRINTER_INFO_LEVEL *printer,
3130 TALLOC_CTX *mem_ctx)
3132 data->notify_data.value[0] = printer->info_2->default_priority;
3133 data->notify_data.value[1] = 0;
3136 /*******************************************************************
3137 * fill a notify_info_data with the start time
3138 ********************************************************************/
3140 static void spoolss_notify_start_time(int snum,
3141 SPOOL_NOTIFY_INFO_DATA *data,
3142 print_queue_struct *queue,
3143 NT_PRINTER_INFO_LEVEL *printer,
3144 TALLOC_CTX *mem_ctx)
3146 data->notify_data.value[0] = printer->info_2->starttime;
3147 data->notify_data.value[1] = 0;
3150 /*******************************************************************
3151 * fill a notify_info_data with the until time
3152 ********************************************************************/
3154 static void spoolss_notify_until_time(int snum,
3155 SPOOL_NOTIFY_INFO_DATA *data,
3156 print_queue_struct *queue,
3157 NT_PRINTER_INFO_LEVEL *printer,
3158 TALLOC_CTX *mem_ctx)
3160 data->notify_data.value[0] = printer->info_2->untiltime;
3161 data->notify_data.value[1] = 0;
3164 /*******************************************************************
3165 * fill a notify_info_data with the status
3166 ********************************************************************/
3168 static void spoolss_notify_status(int snum,
3169 SPOOL_NOTIFY_INFO_DATA *data,
3170 print_queue_struct *queue,
3171 NT_PRINTER_INFO_LEVEL *printer,
3172 TALLOC_CTX *mem_ctx)
3174 print_status_struct status;
3176 print_queue_length(snum, &status);
3177 data->notify_data.value[0]=(uint32) status.status;
3178 data->notify_data.value[1] = 0;
3181 /*******************************************************************
3182 * fill a notify_info_data with the number of jobs queued
3183 ********************************************************************/
3185 void spoolss_notify_cjobs(int snum,
3186 SPOOL_NOTIFY_INFO_DATA *data,
3187 print_queue_struct *queue,
3188 NT_PRINTER_INFO_LEVEL *printer,
3189 TALLOC_CTX *mem_ctx)
3191 data->notify_data.value[0] = print_queue_length(snum, NULL);
3192 data->notify_data.value[1] = 0;
3195 /*******************************************************************
3196 * fill a notify_info_data with the average ppm
3197 ********************************************************************/
3199 static void spoolss_notify_average_ppm(int snum,
3200 SPOOL_NOTIFY_INFO_DATA *data,
3201 print_queue_struct *queue,
3202 NT_PRINTER_INFO_LEVEL *printer,
3203 TALLOC_CTX *mem_ctx)
3205 /* always respond 8 pages per minutes */
3206 /* a little hard ! */
3207 data->notify_data.value[0] = printer->info_2->averageppm;
3208 data->notify_data.value[1] = 0;
3211 /*******************************************************************
3212 * fill a notify_info_data with username
3213 ********************************************************************/
3215 static void spoolss_notify_username(int snum,
3216 SPOOL_NOTIFY_INFO_DATA *data,
3217 print_queue_struct *queue,
3218 NT_PRINTER_INFO_LEVEL *printer,
3219 TALLOC_CTX *mem_ctx)
3221 pstring temp;
3222 uint32 len;
3224 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3226 data->notify_data.data.length = len;
3227 if (len) {
3228 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3230 if (!data->notify_data.data.string) {
3231 data->notify_data.data.length = 0;
3232 return;
3235 memcpy(data->notify_data.data.string, temp, len);
3236 } else {
3237 data->notify_data.data.string = NULL;
3241 /*******************************************************************
3242 * fill a notify_info_data with job status
3243 ********************************************************************/
3245 static void spoolss_notify_job_status(int snum,
3246 SPOOL_NOTIFY_INFO_DATA *data,
3247 print_queue_struct *queue,
3248 NT_PRINTER_INFO_LEVEL *printer,
3249 TALLOC_CTX *mem_ctx)
3251 data->notify_data.value[0]=nt_printj_status(queue->status);
3252 data->notify_data.value[1] = 0;
3255 /*******************************************************************
3256 * fill a notify_info_data with job name
3257 ********************************************************************/
3259 static void spoolss_notify_job_name(int snum,
3260 SPOOL_NOTIFY_INFO_DATA *data,
3261 print_queue_struct *queue,
3262 NT_PRINTER_INFO_LEVEL *printer,
3263 TALLOC_CTX *mem_ctx)
3265 pstring temp;
3266 uint32 len;
3268 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3270 data->notify_data.data.length = len;
3271 if (len) {
3272 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3274 if (!data->notify_data.data.string) {
3275 data->notify_data.data.length = 0;
3276 return;
3279 memcpy(data->notify_data.data.string, temp, len);
3280 } else {
3281 data->notify_data.data.string = NULL;
3285 /*******************************************************************
3286 * fill a notify_info_data with job status
3287 ********************************************************************/
3289 static void spoolss_notify_job_status_string(int snum,
3290 SPOOL_NOTIFY_INFO_DATA *data,
3291 print_queue_struct *queue,
3292 NT_PRINTER_INFO_LEVEL *printer,
3293 TALLOC_CTX *mem_ctx)
3296 * Now we're returning job status codes we just return a "" here. JRA.
3299 const char *p = "";
3300 pstring temp;
3301 uint32 len;
3303 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3304 p = "unknown";
3306 switch (queue->status) {
3307 case LPQ_QUEUED:
3308 p = "Queued";
3309 break;
3310 case LPQ_PAUSED:
3311 p = ""; /* NT provides the paused string */
3312 break;
3313 case LPQ_SPOOLING:
3314 p = "Spooling";
3315 break;
3316 case LPQ_PRINTING:
3317 p = "Printing";
3318 break;
3320 #endif /* NO LONGER NEEDED. */
3322 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3324 data->notify_data.data.length = len;
3325 if (len) {
3326 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3328 if (!data->notify_data.data.string) {
3329 data->notify_data.data.length = 0;
3330 return;
3333 memcpy(data->notify_data.data.string, temp, len);
3334 } else {
3335 data->notify_data.data.string = NULL;
3339 /*******************************************************************
3340 * fill a notify_info_data with job time
3341 ********************************************************************/
3343 static void spoolss_notify_job_time(int snum,
3344 SPOOL_NOTIFY_INFO_DATA *data,
3345 print_queue_struct *queue,
3346 NT_PRINTER_INFO_LEVEL *printer,
3347 TALLOC_CTX *mem_ctx)
3349 data->notify_data.value[0]=0x0;
3350 data->notify_data.value[1]=0;
3353 /*******************************************************************
3354 * fill a notify_info_data with job size
3355 ********************************************************************/
3357 static void spoolss_notify_job_size(int snum,
3358 SPOOL_NOTIFY_INFO_DATA *data,
3359 print_queue_struct *queue,
3360 NT_PRINTER_INFO_LEVEL *printer,
3361 TALLOC_CTX *mem_ctx)
3363 data->notify_data.value[0]=queue->size;
3364 data->notify_data.value[1]=0;
3367 /*******************************************************************
3368 * fill a notify_info_data with page info
3369 ********************************************************************/
3370 static void spoolss_notify_total_pages(int snum,
3371 SPOOL_NOTIFY_INFO_DATA *data,
3372 print_queue_struct *queue,
3373 NT_PRINTER_INFO_LEVEL *printer,
3374 TALLOC_CTX *mem_ctx)
3376 data->notify_data.value[0]=queue->page_count;
3377 data->notify_data.value[1]=0;
3380 /*******************************************************************
3381 * fill a notify_info_data with pages printed info.
3382 ********************************************************************/
3383 static void spoolss_notify_pages_printed(int snum,
3384 SPOOL_NOTIFY_INFO_DATA *data,
3385 print_queue_struct *queue,
3386 NT_PRINTER_INFO_LEVEL *printer,
3387 TALLOC_CTX *mem_ctx)
3389 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3390 data->notify_data.value[1]=0;
3393 /*******************************************************************
3394 Fill a notify_info_data with job position.
3395 ********************************************************************/
3397 static void spoolss_notify_job_position(int snum,
3398 SPOOL_NOTIFY_INFO_DATA *data,
3399 print_queue_struct *queue,
3400 NT_PRINTER_INFO_LEVEL *printer,
3401 TALLOC_CTX *mem_ctx)
3403 data->notify_data.value[0]=queue->job;
3404 data->notify_data.value[1]=0;
3407 /*******************************************************************
3408 Fill a notify_info_data with submitted time.
3409 ********************************************************************/
3411 static void spoolss_notify_submitted_time(int snum,
3412 SPOOL_NOTIFY_INFO_DATA *data,
3413 print_queue_struct *queue,
3414 NT_PRINTER_INFO_LEVEL *printer,
3415 TALLOC_CTX *mem_ctx)
3417 struct tm *t;
3418 uint32 len;
3419 SYSTEMTIME st;
3420 char *p;
3422 t=gmtime(&queue->time);
3424 len = sizeof(SYSTEMTIME);
3426 data->notify_data.data.length = len;
3427 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3429 if (!data->notify_data.data.string) {
3430 data->notify_data.data.length = 0;
3431 return;
3434 make_systemtime(&st, t);
3437 * Systemtime must be linearized as a set of UINT16's.
3438 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3441 p = (char *)data->notify_data.data.string;
3442 SSVAL(p, 0, st.year);
3443 SSVAL(p, 2, st.month);
3444 SSVAL(p, 4, st.dayofweek);
3445 SSVAL(p, 6, st.day);
3446 SSVAL(p, 8, st.hour);
3447 SSVAL(p, 10, st.minute);
3448 SSVAL(p, 12, st.second);
3449 SSVAL(p, 14, st.milliseconds);
3452 struct s_notify_info_data_table
3454 uint16 type;
3455 uint16 field;
3456 const char *name;
3457 uint32 size;
3458 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3459 print_queue_struct *queue,
3460 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3463 /* A table describing the various print notification constants and
3464 whether the notification data is a pointer to a variable sized
3465 buffer, a one value uint32 or a two value uint32. */
3467 static const struct s_notify_info_data_table notify_info_data_table[] =
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3485 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3486 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3487 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3488 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3489 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3490 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3491 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3492 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3493 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3494 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3508 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3509 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3510 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3511 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3512 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3513 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3514 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3515 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3516 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3517 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3518 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3521 /*******************************************************************
3522 Return the size of info_data structure.
3523 ********************************************************************/
3525 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3527 int i=0;
3529 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3530 if ( (notify_info_data_table[i].type == type)
3531 && (notify_info_data_table[i].field == field) ) {
3532 switch(notify_info_data_table[i].size) {
3533 case NOTIFY_ONE_VALUE:
3534 case NOTIFY_TWO_VALUE:
3535 return 1;
3536 case NOTIFY_STRING:
3537 return 2;
3539 /* The only pointer notify data I have seen on
3540 the wire is the submitted time and this has
3541 the notify size set to 4. -tpot */
3543 case NOTIFY_POINTER:
3544 return 4;
3546 case NOTIFY_SECDESC:
3547 return 5;
3552 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3554 return 0;
3557 /*******************************************************************
3558 Return the type of notify_info_data.
3559 ********************************************************************/
3561 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3563 uint32 i=0;
3565 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3566 if (notify_info_data_table[i].type == type &&
3567 notify_info_data_table[i].field == field)
3568 return notify_info_data_table[i].size;
3571 return 0;
3574 /****************************************************************************
3575 ****************************************************************************/
3577 static BOOL search_notify(uint16 type, uint16 field, int *value)
3579 int i;
3581 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3582 if (notify_info_data_table[i].type == type &&
3583 notify_info_data_table[i].field == field &&
3584 notify_info_data_table[i].fn != NULL) {
3585 *value = i;
3586 return True;
3590 return False;
3593 /****************************************************************************
3594 ****************************************************************************/
3596 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3598 info_data->type = type;
3599 info_data->field = field;
3600 info_data->reserved = 0;
3602 info_data->size = size_of_notify_info_data(type, field);
3603 info_data->enc_type = type_of_notify_info_data(type, field);
3605 info_data->id = id;
3608 /*******************************************************************
3610 * fill a notify_info struct with info asked
3612 ********************************************************************/
3614 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3615 snum, SPOOL_NOTIFY_OPTION_TYPE
3616 *option_type, uint32 id,
3617 TALLOC_CTX *mem_ctx)
3619 int field_num,j;
3620 uint16 type;
3621 uint16 field;
3623 SPOOL_NOTIFY_INFO_DATA *current_data;
3624 NT_PRINTER_INFO_LEVEL *printer = NULL;
3625 print_queue_struct *queue=NULL;
3627 type=option_type->type;
3629 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3630 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3631 option_type->count, lp_servicename(snum)));
3633 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3634 return False;
3636 for(field_num=0; field_num<option_type->count; field_num++) {
3637 field = option_type->fields[field_num];
3639 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3641 if (!search_notify(type, field, &j) )
3642 continue;
3644 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3645 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3646 free_a_printer(&printer, 2);
3647 return False;
3650 current_data = &info->data[info->count];
3652 construct_info_data(current_data, type, field, id);
3654 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3655 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3657 notify_info_data_table[j].fn(snum, current_data, queue,
3658 printer, mem_ctx);
3660 info->count++;
3663 free_a_printer(&printer, 2);
3664 return True;
3667 /*******************************************************************
3669 * fill a notify_info struct with info asked
3671 ********************************************************************/
3673 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3674 SPOOL_NOTIFY_INFO *info,
3675 NT_PRINTER_INFO_LEVEL *printer,
3676 int snum, SPOOL_NOTIFY_OPTION_TYPE
3677 *option_type, uint32 id,
3678 TALLOC_CTX *mem_ctx)
3680 int field_num,j;
3681 uint16 type;
3682 uint16 field;
3684 SPOOL_NOTIFY_INFO_DATA *current_data;
3686 DEBUG(4,("construct_notify_jobs_info\n"));
3688 type = option_type->type;
3690 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3691 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3692 option_type->count));
3694 for(field_num=0; field_num<option_type->count; field_num++) {
3695 field = option_type->fields[field_num];
3697 if (!search_notify(type, field, &j) )
3698 continue;
3700 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3701 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3702 return False;
3705 current_data=&(info->data[info->count]);
3707 construct_info_data(current_data, type, field, id);
3708 notify_info_data_table[j].fn(snum, current_data, queue,
3709 printer, mem_ctx);
3710 info->count++;
3713 return True;
3717 * JFM: The enumeration is not that simple, it's even non obvious.
3719 * let's take an example: I want to monitor the PRINTER SERVER for
3720 * the printer's name and the number of jobs currently queued.
3721 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3722 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3724 * I have 3 printers on the back of my server.
3726 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3727 * structures.
3728 * Number Data Id
3729 * 1 printer 1 name 1
3730 * 2 printer 1 cjob 1
3731 * 3 printer 2 name 2
3732 * 4 printer 2 cjob 2
3733 * 5 printer 3 name 3
3734 * 6 printer 3 name 3
3736 * that's the print server case, the printer case is even worse.
3739 /*******************************************************************
3741 * enumerate all printers on the printserver
3742 * fill a notify_info struct with info asked
3744 ********************************************************************/
3746 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3747 SPOOL_NOTIFY_INFO *info,
3748 TALLOC_CTX *mem_ctx)
3750 int snum;
3751 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3752 int n_services=lp_numservices();
3753 int i;
3754 SPOOL_NOTIFY_OPTION *option;
3755 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3757 DEBUG(4,("printserver_notify_info\n"));
3759 if (!Printer)
3760 return WERR_BADFID;
3762 option=Printer->notify.option;
3763 info->version=2;
3764 info->data=NULL;
3765 info->count=0;
3767 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3768 sending a ffpcn() request first */
3770 if ( !option )
3771 return WERR_BADFID;
3773 for (i=0; i<option->count; i++) {
3774 option_type=&(option->ctr.type[i]);
3776 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3777 continue;
3779 for (snum=0; snum<n_services; snum++)
3781 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3782 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3786 #if 0
3788 * Debugging information, don't delete.
3791 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3792 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3793 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3795 for (i=0; i<info->count; i++) {
3796 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3797 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3798 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3800 #endif
3802 return WERR_OK;
3805 /*******************************************************************
3807 * fill a notify_info struct with info asked
3809 ********************************************************************/
3811 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3812 TALLOC_CTX *mem_ctx)
3814 int snum;
3815 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3816 int i;
3817 uint32 id;
3818 SPOOL_NOTIFY_OPTION *option;
3819 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3820 int count,j;
3821 print_queue_struct *queue=NULL;
3822 print_status_struct status;
3824 DEBUG(4,("printer_notify_info\n"));
3826 if (!Printer)
3827 return WERR_BADFID;
3829 option=Printer->notify.option;
3830 id = 0x0;
3831 info->version=2;
3832 info->data=NULL;
3833 info->count=0;
3835 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3836 sending a ffpcn() request first */
3838 if ( !option )
3839 return WERR_BADFID;
3841 get_printer_snum(p, hnd, &snum);
3843 for (i=0; i<option->count; i++) {
3844 option_type=&option->ctr.type[i];
3846 switch ( option_type->type ) {
3847 case PRINTER_NOTIFY_TYPE:
3848 if(construct_notify_printer_info(Printer, info, snum,
3849 option_type, id,
3850 mem_ctx))
3851 id--;
3852 break;
3854 case JOB_NOTIFY_TYPE: {
3855 NT_PRINTER_INFO_LEVEL *printer = NULL;
3857 count = print_queue_status(snum, &queue, &status);
3859 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3860 goto done;
3862 for (j=0; j<count; j++) {
3863 construct_notify_jobs_info(&queue[j], info,
3864 printer, snum,
3865 option_type,
3866 queue[j].job,
3867 mem_ctx);
3870 free_a_printer(&printer, 2);
3872 done:
3873 SAFE_FREE(queue);
3874 break;
3880 * Debugging information, don't delete.
3883 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3884 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3885 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3887 for (i=0; i<info->count; i++) {
3888 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3889 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3890 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3893 return WERR_OK;
3896 /********************************************************************
3897 * spoolss_rfnpcnex
3898 ********************************************************************/
3900 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3902 POLICY_HND *handle = &q_u->handle;
3903 SPOOL_NOTIFY_INFO *info = &r_u->info;
3905 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3906 WERROR result = WERR_BADFID;
3908 /* we always have a NOTIFY_INFO struct */
3909 r_u->info_ptr=0x1;
3911 if (!Printer) {
3912 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3913 OUR_HANDLE(handle)));
3914 goto done;
3917 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3920 * We are now using the change value, and
3921 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3922 * I don't have a global notification system, I'm sending back all the
3923 * informations even when _NOTHING_ has changed.
3926 /* We need to keep track of the change value to send back in
3927 RRPCN replies otherwise our updates are ignored. */
3929 Printer->notify.fnpcn = True;
3931 if (Printer->notify.client_connected) {
3932 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3933 Printer->notify.change = q_u->change;
3936 /* just ignore the SPOOL_NOTIFY_OPTION */
3938 switch (Printer->printer_type) {
3939 case SPLHND_SERVER:
3940 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3941 break;
3943 case SPLHND_PRINTER:
3944 result = printer_notify_info(p, handle, info, p->mem_ctx);
3945 break;
3948 Printer->notify.fnpcn = False;
3950 done:
3951 return result;
3954 /********************************************************************
3955 * construct_printer_info_0
3956 * fill a printer_info_0 struct
3957 ********************************************************************/
3959 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3961 pstring chaine;
3962 int count;
3963 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3964 counter_printer_0 *session_counter;
3965 uint32 global_counter;
3966 struct tm *t;
3967 time_t setuptime;
3968 print_status_struct status;
3970 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3971 return False;
3973 count = print_queue_length(snum, &status);
3975 /* check if we already have a counter for this printer */
3976 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3977 if (session_counter->snum == snum)
3978 break;
3981 /* it's the first time, add it to the list */
3982 if (session_counter==NULL) {
3983 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3984 free_a_printer(&ntprinter, 2);
3985 return False;
3987 ZERO_STRUCTP(session_counter);
3988 session_counter->snum=snum;
3989 session_counter->counter=0;
3990 DLIST_ADD(counter_list, session_counter);
3993 /* increment it */
3994 session_counter->counter++;
3996 /* JFM:
3997 * the global_counter should be stored in a TDB as it's common to all the clients
3998 * and should be zeroed on samba startup
4000 global_counter=session_counter->counter;
4002 pstrcpy(chaine,ntprinter->info_2->printername);
4004 init_unistr(&printer->printername, chaine);
4006 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
4007 init_unistr(&printer->servername, chaine);
4009 printer->cjobs = count;
4010 printer->total_jobs = 0;
4011 printer->total_bytes = 0;
4013 setuptime = (time_t)ntprinter->info_2->setuptime;
4014 t=gmtime(&setuptime);
4016 printer->year = t->tm_year+1900;
4017 printer->month = t->tm_mon+1;
4018 printer->dayofweek = t->tm_wday;
4019 printer->day = t->tm_mday;
4020 printer->hour = t->tm_hour;
4021 printer->minute = t->tm_min;
4022 printer->second = t->tm_sec;
4023 printer->milliseconds = 0;
4025 printer->global_counter = global_counter;
4026 printer->total_pages = 0;
4028 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4029 printer->major_version = 0x0005; /* NT 5 */
4030 printer->build_version = 0x0893; /* build 2195 */
4032 printer->unknown7 = 0x1;
4033 printer->unknown8 = 0x0;
4034 printer->unknown9 = 0x0;
4035 printer->session_counter = session_counter->counter;
4036 printer->unknown11 = 0x0;
4037 printer->printer_errors = 0x0; /* number of print failure */
4038 printer->unknown13 = 0x0;
4039 printer->unknown14 = 0x1;
4040 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4041 printer->unknown16 = 0x0;
4042 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4043 printer->unknown18 = 0x0;
4044 printer->status = nt_printq_status(status.status);
4045 printer->unknown20 = 0x0;
4046 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4047 printer->unknown22 = 0x0;
4048 printer->unknown23 = 0x6; /* 6 ???*/
4049 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4050 printer->unknown25 = 0;
4051 printer->unknown26 = 0;
4052 printer->unknown27 = 0;
4053 printer->unknown28 = 0;
4054 printer->unknown29 = 0;
4056 free_a_printer(&ntprinter,2);
4057 return (True);
4060 /********************************************************************
4061 * construct_printer_info_1
4062 * fill a printer_info_1 struct
4063 ********************************************************************/
4064 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4066 pstring chaine;
4067 pstring chaine2;
4068 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4070 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4071 return False;
4073 printer->flags=flags;
4075 if (*ntprinter->info_2->comment == '\0') {
4076 init_unistr(&printer->comment, lp_comment(snum));
4077 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4078 ntprinter->info_2->drivername, lp_comment(snum));
4080 else {
4081 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4082 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4083 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4086 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4088 init_unistr(&printer->description, chaine);
4089 init_unistr(&printer->name, chaine2);
4091 free_a_printer(&ntprinter,2);
4093 return True;
4096 /****************************************************************************
4097 Free a DEVMODE struct.
4098 ****************************************************************************/
4100 static void free_dev_mode(DEVICEMODE *dev)
4102 if (dev == NULL)
4103 return;
4105 SAFE_FREE(dev->dev_private);
4106 SAFE_FREE(dev);
4110 /****************************************************************************
4111 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4112 should be valid upon entry
4113 ****************************************************************************/
4115 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4117 if ( !devmode || !ntdevmode )
4118 return False;
4120 init_unistr(&devmode->devicename, ntdevmode->devicename);
4122 init_unistr(&devmode->formname, ntdevmode->formname);
4124 devmode->specversion = ntdevmode->specversion;
4125 devmode->driverversion = ntdevmode->driverversion;
4126 devmode->size = ntdevmode->size;
4127 devmode->driverextra = ntdevmode->driverextra;
4128 devmode->fields = ntdevmode->fields;
4130 devmode->orientation = ntdevmode->orientation;
4131 devmode->papersize = ntdevmode->papersize;
4132 devmode->paperlength = ntdevmode->paperlength;
4133 devmode->paperwidth = ntdevmode->paperwidth;
4134 devmode->scale = ntdevmode->scale;
4135 devmode->copies = ntdevmode->copies;
4136 devmode->defaultsource = ntdevmode->defaultsource;
4137 devmode->printquality = ntdevmode->printquality;
4138 devmode->color = ntdevmode->color;
4139 devmode->duplex = ntdevmode->duplex;
4140 devmode->yresolution = ntdevmode->yresolution;
4141 devmode->ttoption = ntdevmode->ttoption;
4142 devmode->collate = ntdevmode->collate;
4143 devmode->icmmethod = ntdevmode->icmmethod;
4144 devmode->icmintent = ntdevmode->icmintent;
4145 devmode->mediatype = ntdevmode->mediatype;
4146 devmode->dithertype = ntdevmode->dithertype;
4148 if (ntdevmode->nt_dev_private != NULL) {
4149 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4150 return False;
4153 return True;
4156 /****************************************************************************
4157 Create a DEVMODE struct. Returns malloced memory.
4158 ****************************************************************************/
4160 DEVICEMODE *construct_dev_mode(const char *servicename)
4162 NT_PRINTER_INFO_LEVEL *printer = NULL;
4163 DEVICEMODE *devmode = NULL;
4165 DEBUG(7,("construct_dev_mode\n"));
4167 DEBUGADD(8,("getting printer characteristics\n"));
4169 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4170 return NULL;
4172 if ( !printer->info_2->devmode ) {
4173 DEBUG(5, ("BONG! There was no device mode!\n"));
4174 goto done;
4177 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4178 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4179 goto done;
4182 ZERO_STRUCTP(devmode);
4184 DEBUGADD(8,("loading DEVICEMODE\n"));
4186 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4187 free_dev_mode( devmode );
4188 devmode = NULL;
4191 done:
4192 free_a_printer(&printer,2);
4194 return devmode;
4197 /********************************************************************
4198 * construct_printer_info_2
4199 * fill a printer_info_2 struct
4200 ********************************************************************/
4202 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4204 int count;
4205 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4207 print_status_struct status;
4209 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4210 return False;
4212 count = print_queue_length(snum, &status);
4214 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4215 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4216 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4217 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4218 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4220 if (*ntprinter->info_2->comment == '\0')
4221 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4222 else
4223 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4225 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4226 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4227 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4228 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4229 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4231 printer->attributes = ntprinter->info_2->attributes;
4233 printer->priority = ntprinter->info_2->priority; /* priority */
4234 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4235 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4236 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4237 printer->status = nt_printq_status(status.status); /* status */
4238 printer->cjobs = count; /* jobs */
4239 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4241 if ( !(printer->devmode = construct_dev_mode(
4242 lp_const_servicename(snum))) )
4243 DEBUG(8, ("Returning NULL Devicemode!\n"));
4245 printer->secdesc = NULL;
4247 if ( ntprinter->info_2->secdesc_buf
4248 && ntprinter->info_2->secdesc_buf->len != 0 )
4250 /* don't use talloc_steal() here unless you do a deep steal of all
4251 the SEC_DESC members */
4253 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4254 ntprinter->info_2->secdesc_buf->sec );
4257 free_a_printer(&ntprinter, 2);
4259 return True;
4262 /********************************************************************
4263 * construct_printer_info_3
4264 * fill a printer_info_3 struct
4265 ********************************************************************/
4267 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4269 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4270 PRINTER_INFO_3 *printer = NULL;
4272 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4273 return False;
4275 *pp_printer = NULL;
4276 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4277 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4278 free_a_printer(&ntprinter, 2);
4279 return False;
4282 ZERO_STRUCTP(printer);
4284 /* These are the components of the SD we are returning. */
4286 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4287 /* don't use talloc_steal() here unless you do a deep steal of all
4288 the SEC_DESC members */
4290 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4291 ntprinter->info_2->secdesc_buf->sec );
4294 free_a_printer(&ntprinter, 2);
4296 *pp_printer = printer;
4297 return True;
4300 /********************************************************************
4301 * construct_printer_info_4
4302 * fill a printer_info_4 struct
4303 ********************************************************************/
4305 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4307 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4309 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4310 return False;
4312 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4313 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4314 printer->attributes = ntprinter->info_2->attributes;
4316 free_a_printer(&ntprinter, 2);
4317 return True;
4320 /********************************************************************
4321 * construct_printer_info_5
4322 * fill a printer_info_5 struct
4323 ********************************************************************/
4325 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4327 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4329 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4330 return False;
4332 init_unistr(&printer->printername, ntprinter->info_2->printername);
4333 init_unistr(&printer->portname, ntprinter->info_2->portname);
4334 printer->attributes = ntprinter->info_2->attributes;
4336 /* these two are not used by NT+ according to MSDN */
4338 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4339 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4341 free_a_printer(&ntprinter, 2);
4343 return True;
4346 /********************************************************************
4347 * construct_printer_info_7
4348 * fill a printer_info_7 struct
4349 ********************************************************************/
4351 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4353 char *guid_str = NULL;
4354 struct GUID guid;
4356 if (is_printer_published(print_hnd, snum, &guid)) {
4357 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4358 strupper_m(guid_str);
4359 init_unistr(&printer->guid, guid_str);
4360 printer->action = SPOOL_DS_PUBLISH;
4361 } else {
4362 init_unistr(&printer->guid, "");
4363 printer->action = SPOOL_DS_UNPUBLISH;
4366 return True;
4369 /********************************************************************
4370 Spoolss_enumprinters.
4371 ********************************************************************/
4373 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4375 int snum;
4376 int i;
4377 int n_services=lp_numservices();
4378 PRINTER_INFO_1 *printers=NULL;
4379 PRINTER_INFO_1 current_prt;
4380 WERROR result = WERR_OK;
4382 DEBUG(4,("enum_all_printers_info_1\n"));
4384 for (snum=0; snum<n_services; snum++) {
4385 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4386 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4388 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4389 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4390 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4391 *returned=0;
4392 return WERR_NOMEM;
4394 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4396 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4397 (*returned)++;
4402 /* check the required size. */
4403 for (i=0; i<*returned; i++)
4404 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4406 if (*needed > offered) {
4407 result = WERR_INSUFFICIENT_BUFFER;
4408 goto out;
4411 if (!rpcbuf_alloc_size(buffer, *needed)) {
4412 result = WERR_NOMEM;
4413 goto out;
4416 /* fill the buffer with the structures */
4417 for (i=0; i<*returned; i++)
4418 smb_io_printer_info_1("", buffer, &printers[i], 0);
4420 out:
4421 /* clear memory */
4423 SAFE_FREE(printers);
4425 if ( !W_ERROR_IS_OK(result) )
4426 *returned = 0;
4428 return result;
4431 /********************************************************************
4432 enum_all_printers_info_1_local.
4433 *********************************************************************/
4435 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4437 DEBUG(4,("enum_all_printers_info_1_local\n"));
4439 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4442 /********************************************************************
4443 enum_all_printers_info_1_name.
4444 *********************************************************************/
4446 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4448 char *s = name;
4450 DEBUG(4,("enum_all_printers_info_1_name\n"));
4452 if ((name[0] == '\\') && (name[1] == '\\'))
4453 s = name + 2;
4455 if (is_myname_or_ipaddr(s)) {
4456 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4458 else
4459 return WERR_INVALID_NAME;
4462 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4463 /********************************************************************
4464 enum_all_printers_info_1_remote.
4465 *********************************************************************/
4467 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4469 PRINTER_INFO_1 *printer;
4470 fstring printername;
4471 fstring desc;
4472 fstring comment;
4473 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4474 WERROR result = WERR_OK;
4476 /* JFM: currently it's more a place holder than anything else.
4477 * In the spooler world there is a notion of server registration.
4478 * the print servers are registered on the PDC (in the same domain)
4480 * We should have a TDB here. The registration is done thru an
4481 * undocumented RPC call.
4484 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4485 return WERR_NOMEM;
4487 *returned=1;
4489 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4490 slprintf(desc, sizeof(desc)-1,"%s", name);
4491 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4493 init_unistr(&printer->description, desc);
4494 init_unistr(&printer->name, printername);
4495 init_unistr(&printer->comment, comment);
4496 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4498 /* check the required size. */
4499 *needed += spoolss_size_printer_info_1(printer);
4501 if (*needed > offered) {
4502 result = WERR_INSUFFICIENT_BUFFER;
4503 goto out;
4506 if (!rpcbuf_alloc_size(buffer, *needed)) {
4507 result = WERR_NOMEM;
4508 goto out;
4511 /* fill the buffer with the structures */
4512 smb_io_printer_info_1("", buffer, printer, 0);
4514 out:
4515 /* clear memory */
4516 SAFE_FREE(printer);
4518 if ( !W_ERROR_IS_OK(result) )
4519 *returned = 0;
4521 return result;
4524 #endif
4526 /********************************************************************
4527 enum_all_printers_info_1_network.
4528 *********************************************************************/
4530 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4532 char *s = name;
4534 DEBUG(4,("enum_all_printers_info_1_network\n"));
4536 /* If we respond to a enum_printers level 1 on our name with flags
4537 set to PRINTER_ENUM_REMOTE with a list of printers then these
4538 printers incorrectly appear in the APW browse list.
4539 Specifically the printers for the server appear at the workgroup
4540 level where all the other servers in the domain are
4541 listed. Windows responds to this call with a
4542 WERR_CAN_NOT_COMPLETE so we should do the same. */
4544 if (name[0] == '\\' && name[1] == '\\')
4545 s = name + 2;
4547 if (is_myname_or_ipaddr(s))
4548 return WERR_CAN_NOT_COMPLETE;
4550 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4553 /********************************************************************
4554 * api_spoolss_enumprinters
4556 * called from api_spoolss_enumprinters (see this to understand)
4557 ********************************************************************/
4559 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4561 int snum;
4562 int i;
4563 int n_services=lp_numservices();
4564 PRINTER_INFO_2 *printers=NULL;
4565 PRINTER_INFO_2 current_prt;
4566 WERROR result = WERR_OK;
4568 *returned = 0;
4570 for (snum=0; snum<n_services; snum++) {
4571 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4572 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4574 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4575 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4576 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4577 *returned = 0;
4578 return WERR_NOMEM;
4581 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4583 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4585 (*returned)++;
4590 /* check the required size. */
4591 for (i=0; i<*returned; i++)
4592 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4594 if (*needed > offered) {
4595 result = WERR_INSUFFICIENT_BUFFER;
4596 goto out;
4599 if (!rpcbuf_alloc_size(buffer, *needed)) {
4600 result = WERR_NOMEM;
4601 goto out;
4604 /* fill the buffer with the structures */
4605 for (i=0; i<*returned; i++)
4606 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4608 out:
4609 /* clear memory */
4611 for (i=0; i<*returned; i++)
4612 free_devmode(printers[i].devmode);
4614 SAFE_FREE(printers);
4616 if ( !W_ERROR_IS_OK(result) )
4617 *returned = 0;
4619 return result;
4622 /********************************************************************
4623 * handle enumeration of printers at level 1
4624 ********************************************************************/
4626 static WERROR enumprinters_level1( uint32 flags, fstring name,
4627 RPC_BUFFER *buffer, uint32 offered,
4628 uint32 *needed, uint32 *returned)
4630 /* Not all the flags are equals */
4632 if (flags & PRINTER_ENUM_LOCAL)
4633 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4635 if (flags & PRINTER_ENUM_NAME)
4636 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4638 #if 0 /* JERRY - disabled for now */
4639 if (flags & PRINTER_ENUM_REMOTE)
4640 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4641 #endif
4643 if (flags & PRINTER_ENUM_NETWORK)
4644 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4646 return WERR_OK; /* NT4sp5 does that */
4649 /********************************************************************
4650 * handle enumeration of printers at level 2
4651 ********************************************************************/
4653 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4654 RPC_BUFFER *buffer, uint32 offered,
4655 uint32 *needed, uint32 *returned)
4657 if (flags & PRINTER_ENUM_LOCAL) {
4658 return enum_all_printers_info_2(buffer, offered, needed, returned);
4661 if (flags & PRINTER_ENUM_NAME) {
4662 if (is_myname_or_ipaddr(canon_servername(servername)))
4663 return enum_all_printers_info_2(buffer, offered, needed, returned);
4664 else
4665 return WERR_INVALID_NAME;
4668 if (flags & PRINTER_ENUM_REMOTE)
4669 return WERR_UNKNOWN_LEVEL;
4671 return WERR_OK;
4674 /********************************************************************
4675 * handle enumeration of printers at level 5
4676 ********************************************************************/
4678 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4679 RPC_BUFFER *buffer, uint32 offered,
4680 uint32 *needed, uint32 *returned)
4682 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4683 return WERR_OK;
4686 /********************************************************************
4687 * api_spoolss_enumprinters
4689 * called from api_spoolss_enumprinters (see this to understand)
4690 ********************************************************************/
4692 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4694 uint32 flags = q_u->flags;
4695 UNISTR2 *servername = &q_u->servername;
4696 uint32 level = q_u->level;
4697 RPC_BUFFER *buffer = NULL;
4698 uint32 offered = q_u->offered;
4699 uint32 *needed = &r_u->needed;
4700 uint32 *returned = &r_u->returned;
4702 fstring name;
4704 /* that's an [in out] buffer */
4706 if (!q_u->buffer && (offered!=0)) {
4707 return WERR_INVALID_PARAM;
4710 rpcbuf_move(q_u->buffer, &r_u->buffer);
4711 buffer = r_u->buffer;
4713 DEBUG(4,("_spoolss_enumprinters\n"));
4715 *needed=0;
4716 *returned=0;
4719 * Level 1:
4720 * flags==PRINTER_ENUM_NAME
4721 * if name=="" then enumerates all printers
4722 * if name!="" then enumerate the printer
4723 * flags==PRINTER_ENUM_REMOTE
4724 * name is NULL, enumerate printers
4725 * Level 2: name!="" enumerates printers, name can't be NULL
4726 * Level 3: doesn't exist
4727 * Level 4: does a local registry lookup
4728 * Level 5: same as Level 2
4731 unistr2_to_ascii(name, servername, sizeof(name)-1);
4732 strupper_m(name);
4734 switch (level) {
4735 case 1:
4736 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4737 case 2:
4738 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4739 case 5:
4740 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4741 case 3:
4742 case 4:
4743 break;
4745 return WERR_UNKNOWN_LEVEL;
4748 /****************************************************************************
4749 ****************************************************************************/
4751 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4753 PRINTER_INFO_0 *printer=NULL;
4754 WERROR result = WERR_OK;
4756 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4757 return WERR_NOMEM;
4759 construct_printer_info_0(print_hnd, printer, snum);
4761 /* check the required size. */
4762 *needed += spoolss_size_printer_info_0(printer);
4764 if (*needed > offered) {
4765 result = WERR_INSUFFICIENT_BUFFER;
4766 goto out;
4769 if (!rpcbuf_alloc_size(buffer, *needed)) {
4770 result = WERR_NOMEM;
4771 goto out;
4774 /* fill the buffer with the structures */
4775 smb_io_printer_info_0("", buffer, printer, 0);
4777 out:
4778 /* clear memory */
4780 SAFE_FREE(printer);
4782 return result;
4785 /****************************************************************************
4786 ****************************************************************************/
4788 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4790 PRINTER_INFO_1 *printer=NULL;
4791 WERROR result = WERR_OK;
4793 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4794 return WERR_NOMEM;
4796 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4798 /* check the required size. */
4799 *needed += spoolss_size_printer_info_1(printer);
4801 if (*needed > offered) {
4802 result = WERR_INSUFFICIENT_BUFFER;
4803 goto out;
4806 if (!rpcbuf_alloc_size(buffer, *needed)) {
4807 result = WERR_NOMEM;
4808 goto out;
4811 /* fill the buffer with the structures */
4812 smb_io_printer_info_1("", buffer, printer, 0);
4814 out:
4815 /* clear memory */
4816 SAFE_FREE(printer);
4818 return result;
4821 /****************************************************************************
4822 ****************************************************************************/
4824 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4826 PRINTER_INFO_2 *printer=NULL;
4827 WERROR result = WERR_OK;
4829 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4830 return WERR_NOMEM;
4832 construct_printer_info_2(print_hnd, printer, snum);
4834 /* check the required size. */
4835 *needed += spoolss_size_printer_info_2(printer);
4837 if (*needed > offered) {
4838 result = WERR_INSUFFICIENT_BUFFER;
4839 goto out;
4842 if (!rpcbuf_alloc_size(buffer, *needed)) {
4843 result = WERR_NOMEM;
4844 goto out;
4847 /* fill the buffer with the structures */
4848 if (!smb_io_printer_info_2("", buffer, printer, 0))
4849 result = WERR_NOMEM;
4851 out:
4852 /* clear memory */
4853 free_printer_info_2(printer);
4855 return result;
4858 /****************************************************************************
4859 ****************************************************************************/
4861 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4863 PRINTER_INFO_3 *printer=NULL;
4864 WERROR result = WERR_OK;
4866 if (!construct_printer_info_3(print_hnd, &printer, snum))
4867 return WERR_NOMEM;
4869 /* check the required size. */
4870 *needed += spoolss_size_printer_info_3(printer);
4872 if (*needed > offered) {
4873 result = WERR_INSUFFICIENT_BUFFER;
4874 goto out;
4877 if (!rpcbuf_alloc_size(buffer, *needed)) {
4878 result = WERR_NOMEM;
4879 goto out;
4882 /* fill the buffer with the structures */
4883 smb_io_printer_info_3("", buffer, printer, 0);
4885 out:
4886 /* clear memory */
4887 free_printer_info_3(printer);
4889 return result;
4892 /****************************************************************************
4893 ****************************************************************************/
4895 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4897 PRINTER_INFO_4 *printer=NULL;
4898 WERROR result = WERR_OK;
4900 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4901 return WERR_NOMEM;
4903 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4904 SAFE_FREE(printer);
4905 return WERR_NOMEM;
4908 /* check the required size. */
4909 *needed += spoolss_size_printer_info_4(printer);
4911 if (*needed > offered) {
4912 result = WERR_INSUFFICIENT_BUFFER;
4913 goto out;
4916 if (!rpcbuf_alloc_size(buffer, *needed)) {
4917 result = WERR_NOMEM;
4918 goto out;
4921 /* fill the buffer with the structures */
4922 smb_io_printer_info_4("", buffer, printer, 0);
4924 out:
4925 /* clear memory */
4926 free_printer_info_4(printer);
4928 return result;
4931 /****************************************************************************
4932 ****************************************************************************/
4934 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4936 PRINTER_INFO_5 *printer=NULL;
4937 WERROR result = WERR_OK;
4939 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4940 return WERR_NOMEM;
4942 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4943 free_printer_info_5(printer);
4944 return WERR_NOMEM;
4947 /* check the required size. */
4948 *needed += spoolss_size_printer_info_5(printer);
4950 if (*needed > offered) {
4951 result = WERR_INSUFFICIENT_BUFFER;
4952 goto out;
4955 if (!rpcbuf_alloc_size(buffer, *needed)) {
4956 result = WERR_NOMEM;
4957 goto out;
4960 /* fill the buffer with the structures */
4961 smb_io_printer_info_5("", buffer, printer, 0);
4963 out:
4964 /* clear memory */
4965 free_printer_info_5(printer);
4967 return result;
4970 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4972 PRINTER_INFO_7 *printer=NULL;
4973 WERROR result = WERR_OK;
4975 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4976 return WERR_NOMEM;
4978 if (!construct_printer_info_7(print_hnd, printer, snum))
4979 return WERR_NOMEM;
4981 /* check the required size. */
4982 *needed += spoolss_size_printer_info_7(printer);
4984 if (*needed > offered) {
4985 result = WERR_INSUFFICIENT_BUFFER;
4986 goto out;
4989 if (!rpcbuf_alloc_size(buffer, *needed)) {
4990 result = WERR_NOMEM;
4991 goto out;
4995 /* fill the buffer with the structures */
4996 smb_io_printer_info_7("", buffer, printer, 0);
4998 out:
4999 /* clear memory */
5000 free_printer_info_7(printer);
5002 return result;
5005 /****************************************************************************
5006 ****************************************************************************/
5008 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5010 POLICY_HND *handle = &q_u->handle;
5011 uint32 level = q_u->level;
5012 RPC_BUFFER *buffer = NULL;
5013 uint32 offered = q_u->offered;
5014 uint32 *needed = &r_u->needed;
5015 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5017 int snum;
5019 /* that's an [in out] buffer */
5021 if (!q_u->buffer && (offered!=0)) {
5022 return WERR_INVALID_PARAM;
5025 rpcbuf_move(q_u->buffer, &r_u->buffer);
5026 buffer = r_u->buffer;
5028 *needed=0;
5030 if (!get_printer_snum(p, handle, &snum))
5031 return WERR_BADFID;
5033 switch (level) {
5034 case 0:
5035 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5036 case 1:
5037 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5038 case 2:
5039 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5040 case 3:
5041 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5042 case 4:
5043 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5044 case 5:
5045 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5046 case 7:
5047 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5049 return WERR_UNKNOWN_LEVEL;
5052 /********************************************************************
5053 * fill a DRIVER_INFO_1 struct
5054 ********************************************************************/
5056 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5058 init_unistr( &info->name, driver.info_3->name);
5061 /********************************************************************
5062 * construct_printer_driver_info_1
5063 ********************************************************************/
5065 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5067 NT_PRINTER_INFO_LEVEL *printer = NULL;
5068 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5070 ZERO_STRUCT(driver);
5072 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5073 return WERR_INVALID_PRINTER_NAME;
5075 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5076 free_a_printer(&printer, 2);
5077 return WERR_UNKNOWN_PRINTER_DRIVER;
5080 fill_printer_driver_info_1(info, driver, servername, architecture);
5082 free_a_printer(&printer,2);
5084 return WERR_OK;
5087 /********************************************************************
5088 * construct_printer_driver_info_2
5089 * fill a printer_info_2 struct
5090 ********************************************************************/
5092 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5094 pstring temp;
5095 const char *cservername = canon_servername(servername);
5097 info->version=driver.info_3->cversion;
5099 init_unistr( &info->name, driver.info_3->name );
5100 init_unistr( &info->architecture, driver.info_3->environment );
5103 if (strlen(driver.info_3->driverpath)) {
5104 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", cservername, driver.info_3->driverpath);
5105 init_unistr( &info->driverpath, temp );
5106 } else
5107 init_unistr( &info->driverpath, "" );
5109 if (strlen(driver.info_3->datafile)) {
5110 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", cservername, driver.info_3->datafile);
5111 init_unistr( &info->datafile, temp );
5112 } else
5113 init_unistr( &info->datafile, "" );
5115 if (strlen(driver.info_3->configfile)) {
5116 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", cservername, driver.info_3->configfile);
5117 init_unistr( &info->configfile, temp );
5118 } else
5119 init_unistr( &info->configfile, "" );
5122 /********************************************************************
5123 * construct_printer_driver_info_2
5124 * fill a printer_info_2 struct
5125 ********************************************************************/
5127 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5129 NT_PRINTER_INFO_LEVEL *printer = NULL;
5130 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5132 ZERO_STRUCT(printer);
5133 ZERO_STRUCT(driver);
5135 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5136 return WERR_INVALID_PRINTER_NAME;
5138 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5139 free_a_printer(&printer, 2);
5140 return WERR_UNKNOWN_PRINTER_DRIVER;
5143 fill_printer_driver_info_2(info, driver, servername);
5145 free_a_printer(&printer,2);
5147 return WERR_OK;
5150 /********************************************************************
5151 * copy a strings array and convert to UNICODE
5153 * convert an array of ascii string to a UNICODE string
5154 ********************************************************************/
5156 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5158 int i=0;
5159 int j=0;
5160 const char *v;
5161 pstring line;
5163 DEBUG(6,("init_unistr_array\n"));
5164 *uni_array=NULL;
5166 while (True)
5168 if ( !char_array )
5169 v = "";
5170 else
5172 v = char_array[i];
5173 if (!v)
5174 v = ""; /* hack to handle null lists */
5177 /* hack to allow this to be used in places other than when generating
5178 the list of dependent files */
5180 if ( servername )
5181 slprintf( line, sizeof(line)-1, "\\\\%s%s", canon_servername(servername), v );
5182 else
5183 pstrcpy( line, v );
5185 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5187 /* add one extra unit16 for the second terminating NULL */
5189 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5190 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5191 return 0;
5194 if ( !strlen(v) )
5195 break;
5197 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5198 i++;
5201 if (*uni_array) {
5202 /* special case for ""; we need to add both NULL's here */
5203 if (!j)
5204 (*uni_array)[j++]=0x0000;
5205 (*uni_array)[j]=0x0000;
5208 DEBUGADD(6,("last one:done\n"));
5210 /* return size of array in uint16's */
5212 return j+1;
5215 /********************************************************************
5216 * construct_printer_info_3
5217 * fill a printer_info_3 struct
5218 ********************************************************************/
5220 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5222 pstring temp;
5223 const char *cservername = canon_servername(servername);
5225 ZERO_STRUCTP(info);
5227 info->version=driver.info_3->cversion;
5229 init_unistr( &info->name, driver.info_3->name );
5230 init_unistr( &info->architecture, driver.info_3->environment );
5232 if (strlen(driver.info_3->driverpath)) {
5233 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", cservername, driver.info_3->driverpath);
5234 init_unistr( &info->driverpath, temp );
5235 } else
5236 init_unistr( &info->driverpath, "" );
5238 if (strlen(driver.info_3->datafile)) {
5239 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", cservername, driver.info_3->datafile);
5240 init_unistr( &info->datafile, temp );
5241 } else
5242 init_unistr( &info->datafile, "" );
5244 if (strlen(driver.info_3->configfile)) {
5245 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", cservername, driver.info_3->configfile);
5246 init_unistr( &info->configfile, temp );
5247 } else
5248 init_unistr( &info->configfile, "" );
5250 if (strlen(driver.info_3->helpfile)) {
5251 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", cservername, driver.info_3->helpfile);
5252 init_unistr( &info->helpfile, temp );
5253 } else
5254 init_unistr( &info->helpfile, "" );
5256 init_unistr( &info->monitorname, driver.info_3->monitorname );
5257 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5259 info->dependentfiles=NULL;
5260 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5263 /********************************************************************
5264 * construct_printer_info_3
5265 * fill a printer_info_3 struct
5266 ********************************************************************/
5268 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5270 NT_PRINTER_INFO_LEVEL *printer = NULL;
5271 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5272 WERROR status;
5273 ZERO_STRUCT(driver);
5275 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5276 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5277 if (!W_ERROR_IS_OK(status))
5278 return WERR_INVALID_PRINTER_NAME;
5280 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5281 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5283 #if 0 /* JERRY */
5286 * I put this code in during testing. Helpful when commenting out the
5287 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5288 * as win2k always queries the driver using an infor level of 6.
5289 * I've left it in (but ifdef'd out) because I'll probably
5290 * use it in experimentation again in the future. --jerry 22/01/2002
5293 if (!W_ERROR_IS_OK(status)) {
5295 * Is this a W2k client ?
5297 if (version == 3) {
5298 /* Yes - try again with a WinNT driver. */
5299 version = 2;
5300 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5301 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5303 #endif
5305 if (!W_ERROR_IS_OK(status)) {
5306 free_a_printer(&printer,2);
5307 return WERR_UNKNOWN_PRINTER_DRIVER;
5310 #if 0 /* JERRY */
5312 #endif
5315 fill_printer_driver_info_3(info, driver, servername);
5317 free_a_printer(&printer,2);
5319 return WERR_OK;
5322 /********************************************************************
5323 * construct_printer_info_6
5324 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5325 ********************************************************************/
5327 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5329 pstring temp;
5330 fstring nullstr;
5331 const char *cservername = canon_servername(servername);
5333 ZERO_STRUCTP(info);
5334 memset(&nullstr, '\0', sizeof(fstring));
5336 info->version=driver.info_3->cversion;
5338 init_unistr( &info->name, driver.info_3->name );
5339 init_unistr( &info->architecture, driver.info_3->environment );
5341 if (strlen(driver.info_3->driverpath)) {
5342 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", cservername, driver.info_3->driverpath);
5343 init_unistr( &info->driverpath, temp );
5344 } else
5345 init_unistr( &info->driverpath, "" );
5347 if (strlen(driver.info_3->datafile)) {
5348 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", cservername, driver.info_3->datafile);
5349 init_unistr( &info->datafile, temp );
5350 } else
5351 init_unistr( &info->datafile, "" );
5353 if (strlen(driver.info_3->configfile)) {
5354 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", cservername, driver.info_3->configfile);
5355 init_unistr( &info->configfile, temp );
5356 } else
5357 init_unistr( &info->configfile, "" );
5359 if (strlen(driver.info_3->helpfile)) {
5360 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", cservername, driver.info_3->helpfile);
5361 init_unistr( &info->helpfile, temp );
5362 } else
5363 init_unistr( &info->helpfile, "" );
5365 init_unistr( &info->monitorname, driver.info_3->monitorname );
5366 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5368 info->dependentfiles = NULL;
5369 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5371 info->previousdrivernames=NULL;
5372 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5374 info->driver_date=0;
5376 info->padding=0;
5377 info->driver_version_low=0;
5378 info->driver_version_high=0;
5380 init_unistr( &info->mfgname, "");
5381 init_unistr( &info->oem_url, "");
5382 init_unistr( &info->hardware_id, "");
5383 init_unistr( &info->provider, "");
5386 /********************************************************************
5387 * construct_printer_info_6
5388 * fill a printer_info_6 struct
5389 ********************************************************************/
5391 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5392 const char *servername, fstring architecture, uint32 version)
5394 NT_PRINTER_INFO_LEVEL *printer = NULL;
5395 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5396 WERROR status;
5398 ZERO_STRUCT(driver);
5400 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5402 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5404 if (!W_ERROR_IS_OK(status))
5405 return WERR_INVALID_PRINTER_NAME;
5407 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5409 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5411 if (!W_ERROR_IS_OK(status))
5414 * Is this a W2k client ?
5417 if (version < 3) {
5418 free_a_printer(&printer,2);
5419 return WERR_UNKNOWN_PRINTER_DRIVER;
5422 /* Yes - try again with a WinNT driver. */
5423 version = 2;
5424 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5425 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5426 if (!W_ERROR_IS_OK(status)) {
5427 free_a_printer(&printer,2);
5428 return WERR_UNKNOWN_PRINTER_DRIVER;
5432 fill_printer_driver_info_6(info, driver, servername);
5434 free_a_printer(&printer,2);
5435 free_a_printer_driver(driver, 3);
5437 return WERR_OK;
5440 /****************************************************************************
5441 ****************************************************************************/
5443 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5445 SAFE_FREE(info->dependentfiles);
5448 /****************************************************************************
5449 ****************************************************************************/
5451 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5453 SAFE_FREE(info->dependentfiles);
5456 /****************************************************************************
5457 ****************************************************************************/
5459 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5461 DRIVER_INFO_1 *info=NULL;
5462 WERROR result;
5464 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5465 return WERR_NOMEM;
5467 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5468 if (!W_ERROR_IS_OK(result))
5469 goto out;
5471 /* check the required size. */
5472 *needed += spoolss_size_printer_driver_info_1(info);
5474 if (*needed > offered) {
5475 result = WERR_INSUFFICIENT_BUFFER;
5476 goto out;
5479 if (!rpcbuf_alloc_size(buffer, *needed)) {
5480 result = WERR_NOMEM;
5481 goto out;
5484 /* fill the buffer with the structures */
5485 smb_io_printer_driver_info_1("", buffer, info, 0);
5487 out:
5488 /* clear memory */
5489 SAFE_FREE(info);
5491 return result;
5494 /****************************************************************************
5495 ****************************************************************************/
5497 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5499 DRIVER_INFO_2 *info=NULL;
5500 WERROR result;
5502 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5503 return WERR_NOMEM;
5505 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5506 if (!W_ERROR_IS_OK(result))
5507 goto out;
5509 /* check the required size. */
5510 *needed += spoolss_size_printer_driver_info_2(info);
5512 if (*needed > offered) {
5513 result = WERR_INSUFFICIENT_BUFFER;
5514 goto out;
5517 if (!rpcbuf_alloc_size(buffer, *needed)) {
5518 result = WERR_NOMEM;
5519 goto out;
5522 /* fill the buffer with the structures */
5523 smb_io_printer_driver_info_2("", buffer, info, 0);
5525 out:
5526 /* clear memory */
5527 SAFE_FREE(info);
5529 return result;
5532 /****************************************************************************
5533 ****************************************************************************/
5535 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5537 DRIVER_INFO_3 info;
5538 WERROR result;
5540 ZERO_STRUCT(info);
5542 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5543 if (!W_ERROR_IS_OK(result))
5544 goto out;
5546 /* check the required size. */
5547 *needed += spoolss_size_printer_driver_info_3(&info);
5549 if (*needed > offered) {
5550 result = WERR_INSUFFICIENT_BUFFER;
5551 goto out;
5554 if (!rpcbuf_alloc_size(buffer, *needed)) {
5555 result = WERR_NOMEM;
5556 goto out;
5559 /* fill the buffer with the structures */
5560 smb_io_printer_driver_info_3("", buffer, &info, 0);
5562 out:
5563 free_printer_driver_info_3(&info);
5565 return result;
5568 /****************************************************************************
5569 ****************************************************************************/
5571 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5573 DRIVER_INFO_6 info;
5574 WERROR result;
5576 ZERO_STRUCT(info);
5578 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5579 if (!W_ERROR_IS_OK(result))
5580 goto out;
5582 /* check the required size. */
5583 *needed += spoolss_size_printer_driver_info_6(&info);
5585 if (*needed > offered) {
5586 result = WERR_INSUFFICIENT_BUFFER;
5587 goto out;
5590 if (!rpcbuf_alloc_size(buffer, *needed)) {
5591 result = WERR_NOMEM;
5592 goto out;
5595 /* fill the buffer with the structures */
5596 smb_io_printer_driver_info_6("", buffer, &info, 0);
5598 out:
5599 free_printer_driver_info_6(&info);
5601 return result;
5604 /****************************************************************************
5605 ****************************************************************************/
5607 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5609 POLICY_HND *handle = &q_u->handle;
5610 UNISTR2 *uni_arch = &q_u->architecture;
5611 uint32 level = q_u->level;
5612 uint32 clientmajorversion = q_u->clientmajorversion;
5613 RPC_BUFFER *buffer = NULL;
5614 uint32 offered = q_u->offered;
5615 uint32 *needed = &r_u->needed;
5616 uint32 *servermajorversion = &r_u->servermajorversion;
5617 uint32 *serverminorversion = &r_u->serverminorversion;
5618 Printer_entry *printer;
5620 fstring servername;
5621 fstring architecture;
5622 int snum;
5624 /* that's an [in out] buffer */
5626 if (!q_u->buffer && (offered!=0)) {
5627 return WERR_INVALID_PARAM;
5630 rpcbuf_move(q_u->buffer, &r_u->buffer);
5631 buffer = r_u->buffer;
5633 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5635 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5636 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5637 return WERR_INVALID_PRINTER_NAME;
5640 *needed = 0;
5641 *servermajorversion = 0;
5642 *serverminorversion = 0;
5644 fstrcpy(servername, get_server_name( printer ));
5645 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5647 if (!get_printer_snum(p, handle, &snum))
5648 return WERR_BADFID;
5650 switch (level) {
5651 case 1:
5652 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5653 case 2:
5654 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5655 case 3:
5656 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5657 case 6:
5658 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5659 #if 0 /* JERRY */
5660 case 101:
5661 /* apparently this call is the equivalent of
5662 EnumPrinterDataEx() for the DsDriver key */
5663 break;
5664 #endif
5667 return WERR_UNKNOWN_LEVEL;
5670 /****************************************************************************
5671 ****************************************************************************/
5673 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5675 POLICY_HND *handle = &q_u->handle;
5677 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5679 if (!Printer) {
5680 DEBUG(3,("Error in startpageprinter printer handle\n"));
5681 return WERR_BADFID;
5684 Printer->page_started=True;
5685 return WERR_OK;
5688 /****************************************************************************
5689 ****************************************************************************/
5691 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5693 POLICY_HND *handle = &q_u->handle;
5694 int snum;
5696 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5698 if (!Printer) {
5699 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5700 return WERR_BADFID;
5703 if (!get_printer_snum(p, handle, &snum))
5704 return WERR_BADFID;
5706 Printer->page_started=False;
5707 print_job_endpage(snum, Printer->jobid);
5709 return WERR_OK;
5712 /********************************************************************
5713 * api_spoolss_getprinter
5714 * called from the spoolss dispatcher
5716 ********************************************************************/
5718 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5720 POLICY_HND *handle = &q_u->handle;
5721 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5722 uint32 *jobid = &r_u->jobid;
5724 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5725 int snum;
5726 pstring jobname;
5727 fstring datatype;
5728 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5729 struct current_user user;
5731 if (!Printer) {
5732 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5733 return WERR_BADFID;
5736 get_current_user(&user, p);
5739 * a nice thing with NT is it doesn't listen to what you tell it.
5740 * when asked to send _only_ RAW datas, it tries to send datas
5741 * in EMF format.
5743 * So I add checks like in NT Server ...
5746 if (info_1->p_datatype != 0) {
5747 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5748 if (strcmp(datatype, "RAW") != 0) {
5749 (*jobid)=0;
5750 return WERR_INVALID_DATATYPE;
5754 /* get the share number of the printer */
5755 if (!get_printer_snum(p, handle, &snum)) {
5756 return WERR_BADFID;
5759 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5761 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5763 /* An error occured in print_job_start() so return an appropriate
5764 NT error code. */
5766 if (Printer->jobid == -1) {
5767 return map_werror_from_unix(errno);
5770 Printer->document_started=True;
5771 (*jobid) = Printer->jobid;
5773 return WERR_OK;
5776 /********************************************************************
5777 * api_spoolss_getprinter
5778 * called from the spoolss dispatcher
5780 ********************************************************************/
5782 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5784 POLICY_HND *handle = &q_u->handle;
5786 return _spoolss_enddocprinter_internal(p, handle);
5789 /****************************************************************************
5790 ****************************************************************************/
5792 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5794 POLICY_HND *handle = &q_u->handle;
5795 uint32 buffer_size = q_u->buffer_size;
5796 uint8 *buffer = q_u->buffer;
5797 uint32 *buffer_written = &q_u->buffer_size2;
5798 int snum;
5799 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5801 if (!Printer) {
5802 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5803 r_u->buffer_written = q_u->buffer_size2;
5804 return WERR_BADFID;
5807 if (!get_printer_snum(p, handle, &snum))
5808 return WERR_BADFID;
5810 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5811 (SMB_OFF_T)-1, (size_t)buffer_size);
5812 if (*buffer_written == (uint32)-1) {
5813 r_u->buffer_written = 0;
5814 if (errno == ENOSPC)
5815 return WERR_NO_SPOOL_SPACE;
5816 else
5817 return WERR_ACCESS_DENIED;
5820 r_u->buffer_written = q_u->buffer_size2;
5822 return WERR_OK;
5825 /********************************************************************
5826 * api_spoolss_getprinter
5827 * called from the spoolss dispatcher
5829 ********************************************************************/
5831 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5832 pipes_struct *p)
5834 struct current_user user;
5835 int snum;
5836 WERROR errcode = WERR_BADFUNC;
5837 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5839 get_current_user(&user, p);
5841 if (!Printer) {
5842 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5843 return WERR_BADFID;
5846 if (!get_printer_snum(p, handle, &snum))
5847 return WERR_BADFID;
5849 switch (command) {
5850 case PRINTER_CONTROL_PAUSE:
5851 if (print_queue_pause(&user, snum, &errcode)) {
5852 errcode = WERR_OK;
5854 break;
5855 case PRINTER_CONTROL_RESUME:
5856 case PRINTER_CONTROL_UNPAUSE:
5857 if (print_queue_resume(&user, snum, &errcode)) {
5858 errcode = WERR_OK;
5860 break;
5861 case PRINTER_CONTROL_PURGE:
5862 if (print_queue_purge(&user, snum, &errcode)) {
5863 errcode = WERR_OK;
5865 break;
5866 default:
5867 return WERR_UNKNOWN_LEVEL;
5870 return errcode;
5873 /********************************************************************
5874 * api_spoolss_abortprinter
5875 * From MSDN: "Deletes printer's spool file if printer is configured
5876 * for spooling"
5877 ********************************************************************/
5879 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5881 POLICY_HND *handle = &q_u->handle;
5882 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5883 int snum;
5884 struct current_user user;
5885 WERROR errcode = WERR_OK;
5887 if (!Printer) {
5888 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5889 return WERR_BADFID;
5892 if (!get_printer_snum(p, handle, &snum))
5893 return WERR_BADFID;
5895 get_current_user( &user, p );
5897 print_job_delete( &user, snum, Printer->jobid, &errcode );
5899 return errcode;
5902 /********************************************************************
5903 * called by spoolss_api_setprinter
5904 * when updating a printer description
5905 ********************************************************************/
5907 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5908 const SPOOL_PRINTER_INFO_LEVEL *info,
5909 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5911 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5912 WERROR result;
5913 int snum;
5915 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5917 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5918 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5919 OUR_HANDLE(handle)));
5921 result = WERR_BADFID;
5922 goto done;
5925 if (!secdesc_ctr) {
5926 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5927 result = WERR_INVALID_PARAM;
5928 goto done;
5931 /* Check the user has permissions to change the security
5932 descriptor. By experimentation with two NT machines, the user
5933 requires Full Access to the printer to change security
5934 information. */
5936 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5937 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5938 result = WERR_ACCESS_DENIED;
5939 goto done;
5942 /* NT seems to like setting the security descriptor even though
5943 nothing may have actually changed. */
5945 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5947 if (DEBUGLEVEL >= 10) {
5948 SEC_ACL *the_acl;
5949 int i;
5951 the_acl = old_secdesc_ctr->sec->dacl;
5952 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5953 PRINTERNAME(snum), the_acl->num_aces));
5955 for (i = 0; i < the_acl->num_aces; i++) {
5956 fstring sid_str;
5958 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5960 DEBUG(10, ("%s 0x%08x\n", sid_str,
5961 the_acl->aces[i].access_mask));
5964 the_acl = secdesc_ctr->sec->dacl;
5966 if (the_acl) {
5967 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5968 PRINTERNAME(snum), the_acl->num_aces));
5970 for (i = 0; i < the_acl->num_aces; i++) {
5971 fstring sid_str;
5973 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5975 DEBUG(10, ("%s 0x%08x\n", sid_str,
5976 the_acl->aces[i].access_mask));
5978 } else {
5979 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5983 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5984 if (!new_secdesc_ctr) {
5985 result = WERR_NOMEM;
5986 goto done;
5989 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5990 result = WERR_OK;
5991 goto done;
5994 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5996 done:
5998 return result;
6001 /********************************************************************
6002 Canonicalize printer info from a client
6004 ATTN: It does not matter what we set the servername to hear
6005 since we do the necessary work in get_a_printer() to set it to
6006 the correct value based on what the client sent in the
6007 _spoolss_open_printer_ex().
6008 ********************************************************************/
6010 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6012 fstring printername;
6013 const char *p;
6015 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6016 "portname=%s drivername=%s comment=%s location=%s\n",
6017 info->servername, info->printername, info->sharename,
6018 info->portname, info->drivername, info->comment, info->location));
6020 /* we force some elements to "correct" values */
6021 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6022 fstrcpy(info->sharename, lp_servicename(snum));
6024 /* check to see if we allow printername != sharename */
6026 if ( lp_force_printername(snum) ) {
6027 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6028 global_myname(), info->sharename );
6029 } else {
6031 /* make sure printername is in \\server\printername format */
6033 fstrcpy( printername, info->printername );
6034 p = printername;
6035 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6036 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6037 p++;
6040 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6041 global_myname(), p );
6044 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6045 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6049 return True;
6052 /****************************************************************************
6053 ****************************************************************************/
6055 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
6057 char *cmd = lp_addport_cmd();
6058 pstring command;
6059 int ret;
6060 int fd;
6061 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6062 BOOL is_print_op = False;
6064 if ( !*cmd ) {
6065 return WERR_ACCESS_DENIED;
6068 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
6070 if ( token )
6071 is_print_op = user_has_privileges( token, &se_printop );
6073 DEBUG(10,("Running [%s]\n", command));
6075 /********* BEGIN SePrintOperatorPrivilege **********/
6077 if ( is_print_op )
6078 become_root();
6080 ret = smbrun(command, &fd);
6082 if ( is_print_op )
6083 unbecome_root();
6085 /********* END SePrintOperatorPrivilege **********/
6087 DEBUGADD(10,("returned [%d]\n", ret));
6089 if ( ret != 0 ) {
6090 if (fd != -1)
6091 close(fd);
6092 return WERR_ACCESS_DENIED;
6095 return WERR_OK;
6098 /****************************************************************************
6099 ****************************************************************************/
6101 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6103 char *cmd = lp_addprinter_cmd();
6104 char **qlines;
6105 pstring command;
6106 int numlines;
6107 int ret;
6108 int fd;
6109 fstring remote_machine = "%m";
6110 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6111 BOOL is_print_op = False;
6113 standard_sub_basic(current_user_info.smb_name,
6114 current_user_info.domain,
6115 remote_machine,sizeof(remote_machine));
6117 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6118 cmd, printer->info_2->printername, printer->info_2->sharename,
6119 printer->info_2->portname, printer->info_2->drivername,
6120 printer->info_2->location, printer->info_2->comment, remote_machine);
6122 if ( token )
6123 is_print_op = user_has_privileges( token, &se_printop );
6125 DEBUG(10,("Running [%s]\n", command));
6127 /********* BEGIN SePrintOperatorPrivilege **********/
6129 if ( is_print_op )
6130 become_root();
6132 if ( (ret = smbrun(command, &fd)) == 0 ) {
6133 /* Tell everyone we updated smb.conf. */
6134 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6137 if ( is_print_op )
6138 unbecome_root();
6140 /********* END SePrintOperatorPrivilege **********/
6142 DEBUGADD(10,("returned [%d]\n", ret));
6144 if ( ret != 0 ) {
6145 if (fd != -1)
6146 close(fd);
6147 return False;
6150 /* reload our services immediately */
6151 reload_services( False );
6153 numlines = 0;
6154 /* Get lines and convert them back to dos-codepage */
6155 qlines = fd_lines_load(fd, &numlines, 0);
6156 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6157 close(fd);
6159 /* Set the portname to what the script says the portname should be. */
6160 /* but don't require anything to be return from the script exit a good error code */
6162 if (numlines) {
6163 /* Set the portname to what the script says the portname should be. */
6164 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6165 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6168 file_lines_free(qlines);
6169 return True;
6173 /********************************************************************
6174 * Called by spoolss_api_setprinter
6175 * when updating a printer description.
6176 ********************************************************************/
6178 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6179 const SPOOL_PRINTER_INFO_LEVEL *info,
6180 DEVICEMODE *devmode)
6182 int snum;
6183 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6184 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6185 WERROR result;
6186 UNISTR2 buffer;
6187 fstring asc_buffer;
6189 DEBUG(8,("update_printer\n"));
6191 result = WERR_OK;
6193 if (!Printer) {
6194 result = WERR_BADFID;
6195 goto done;
6198 if (!get_printer_snum(p, handle, &snum)) {
6199 result = WERR_BADFID;
6200 goto done;
6203 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6204 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6205 result = WERR_BADFID;
6206 goto done;
6209 DEBUGADD(8,("Converting info_2 struct\n"));
6212 * convert_printer_info converts the incoming
6213 * info from the client and overwrites the info
6214 * just read from the tdb in the pointer 'printer'.
6217 if (!convert_printer_info(info, printer, level)) {
6218 result = WERR_NOMEM;
6219 goto done;
6222 if (devmode) {
6223 /* we have a valid devmode
6224 convert it and link it*/
6226 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6227 if (!convert_devicemode(printer->info_2->printername, devmode,
6228 &printer->info_2->devmode)) {
6229 result = WERR_NOMEM;
6230 goto done;
6234 /* Do sanity check on the requested changes for Samba */
6236 if (!check_printer_ok(printer->info_2, snum)) {
6237 result = WERR_INVALID_PARAM;
6238 goto done;
6241 /* FIXME!!! If the driver has changed we really should verify that
6242 it is installed before doing much else --jerry */
6244 /* Check calling user has permission to update printer description */
6246 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6247 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6248 result = WERR_ACCESS_DENIED;
6249 goto done;
6252 /* Call addprinter hook */
6253 /* Check changes to see if this is really needed */
6255 if ( *lp_addprinter_cmd()
6256 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6257 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6258 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6259 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6261 /* add_printer_hook() will call reload_services() */
6263 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6264 result = WERR_ACCESS_DENIED;
6265 goto done;
6270 * When a *new* driver is bound to a printer, the drivername is used to
6271 * lookup previously saved driver initialization info, which is then
6272 * bound to the printer, simulating what happens in the Windows arch.
6274 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6276 if (!set_driver_init(printer, 2))
6278 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6279 printer->info_2->drivername));
6282 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6283 printer->info_2->drivername));
6285 notify_printer_driver(snum, printer->info_2->drivername);
6289 * flag which changes actually occured. This is a small subset of
6290 * all the possible changes. We also have to update things in the
6291 * DsSpooler key.
6294 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6295 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6296 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6297 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6299 notify_printer_comment(snum, printer->info_2->comment);
6302 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6303 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6304 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6305 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6307 notify_printer_sharename(snum, printer->info_2->sharename);
6310 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6311 char *pname;
6313 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6314 pname++;
6315 else
6316 pname = printer->info_2->printername;
6319 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6320 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6321 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6323 notify_printer_printername( snum, pname );
6326 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6327 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6328 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6329 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6331 notify_printer_port(snum, printer->info_2->portname);
6334 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6335 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6336 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6337 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6339 notify_printer_location(snum, printer->info_2->location);
6342 /* here we need to update some more DsSpooler keys */
6343 /* uNCName, serverName, shortServerName */
6345 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6346 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6347 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6348 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6349 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6351 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6352 global_myname(), printer->info_2->sharename );
6353 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6354 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6355 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6357 /* Update printer info */
6358 result = mod_a_printer(printer, 2);
6360 done:
6361 free_a_printer(&printer, 2);
6362 free_a_printer(&old_printer, 2);
6365 return result;
6368 /****************************************************************************
6369 ****************************************************************************/
6370 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6371 const SPOOL_PRINTER_INFO_LEVEL *info)
6373 #ifdef HAVE_ADS
6374 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6375 int snum;
6376 Printer_entry *Printer;
6378 if ( lp_security() != SEC_ADS ) {
6379 return WERR_UNKNOWN_LEVEL;
6382 Printer = find_printer_index_by_hnd(p, handle);
6384 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6386 if (!Printer)
6387 return WERR_BADFID;
6389 if (!get_printer_snum(p, handle, &snum))
6390 return WERR_BADFID;
6392 nt_printer_publish(Printer, snum, info7->action);
6394 return WERR_OK;
6395 #else
6396 return WERR_UNKNOWN_LEVEL;
6397 #endif
6399 /****************************************************************************
6400 ****************************************************************************/
6402 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6404 POLICY_HND *handle = &q_u->handle;
6405 uint32 level = q_u->level;
6406 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6407 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6408 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6409 uint32 command = q_u->command;
6410 WERROR result;
6412 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6414 if (!Printer) {
6415 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6416 return WERR_BADFID;
6419 /* check the level */
6420 switch (level) {
6421 case 0:
6422 return control_printer(handle, command, p);
6423 case 2:
6424 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6425 if (!W_ERROR_IS_OK(result))
6426 return result;
6427 if (secdesc_ctr)
6428 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6429 return result;
6430 case 3:
6431 return update_printer_sec(handle, level, info, p,
6432 secdesc_ctr);
6433 case 7:
6434 return publish_or_unpublish_printer(p, handle, info);
6435 default:
6436 return WERR_UNKNOWN_LEVEL;
6440 /****************************************************************************
6441 ****************************************************************************/
6443 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6445 POLICY_HND *handle = &q_u->handle;
6446 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6448 if (!Printer) {
6449 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6450 return WERR_BADFID;
6453 if (Printer->notify.client_connected==True) {
6454 int snum = -1;
6456 if ( Printer->printer_type == SPLHND_SERVER)
6457 snum = -1;
6458 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6459 !get_printer_snum(p, handle, &snum) )
6460 return WERR_BADFID;
6462 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6465 Printer->notify.flags=0;
6466 Printer->notify.options=0;
6467 Printer->notify.localmachine[0]='\0';
6468 Printer->notify.printerlocal=0;
6469 if (Printer->notify.option)
6470 free_spool_notify_option(&Printer->notify.option);
6471 Printer->notify.client_connected=False;
6473 return WERR_OK;
6476 /****************************************************************************
6477 ****************************************************************************/
6479 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6481 /* that's an [in out] buffer */
6483 if (!q_u->buffer && (q_u->offered!=0)) {
6484 return WERR_INVALID_PARAM;
6487 rpcbuf_move(q_u->buffer, &r_u->buffer);
6489 r_u->needed = 0;
6490 return WERR_INVALID_PARAM; /* this is what a NT server
6491 returns for AddJob. AddJob
6492 must fail on non-local
6493 printers */
6496 /****************************************************************************
6497 ****************************************************************************/
6499 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6500 int position, int snum,
6501 const NT_PRINTER_INFO_LEVEL *ntprinter)
6503 struct tm *t;
6505 t=gmtime(&queue->time);
6507 job_info->jobid=queue->job;
6508 init_unistr(&job_info->printername, lp_servicename(snum));
6509 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6510 init_unistr(&job_info->username, queue->fs_user);
6511 init_unistr(&job_info->document, queue->fs_file);
6512 init_unistr(&job_info->datatype, "RAW");
6513 init_unistr(&job_info->text_status, "");
6514 job_info->status=nt_printj_status(queue->status);
6515 job_info->priority=queue->priority;
6516 job_info->position=position;
6517 job_info->totalpages=queue->page_count;
6518 job_info->pagesprinted=0;
6520 make_systemtime(&job_info->submitted, t);
6523 /****************************************************************************
6524 ****************************************************************************/
6526 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6527 int position, int snum,
6528 const NT_PRINTER_INFO_LEVEL *ntprinter,
6529 DEVICEMODE *devmode)
6531 struct tm *t;
6533 t=gmtime(&queue->time);
6535 job_info->jobid=queue->job;
6537 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6539 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6540 init_unistr(&job_info->username, queue->fs_user);
6541 init_unistr(&job_info->document, queue->fs_file);
6542 init_unistr(&job_info->notifyname, queue->fs_user);
6543 init_unistr(&job_info->datatype, "RAW");
6544 init_unistr(&job_info->printprocessor, "winprint");
6545 init_unistr(&job_info->parameters, "");
6546 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6547 init_unistr(&job_info->text_status, "");
6549 /* and here the security descriptor */
6551 job_info->status=nt_printj_status(queue->status);
6552 job_info->priority=queue->priority;
6553 job_info->position=position;
6554 job_info->starttime=0;
6555 job_info->untiltime=0;
6556 job_info->totalpages=queue->page_count;
6557 job_info->size=queue->size;
6558 make_systemtime(&(job_info->submitted), t);
6559 job_info->timeelapsed=0;
6560 job_info->pagesprinted=0;
6562 job_info->devmode = devmode;
6564 return (True);
6567 /****************************************************************************
6568 Enumjobs at level 1.
6569 ****************************************************************************/
6571 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6572 const NT_PRINTER_INFO_LEVEL *ntprinter,
6573 RPC_BUFFER *buffer, uint32 offered,
6574 uint32 *needed, uint32 *returned)
6576 JOB_INFO_1 *info;
6577 int i;
6578 WERROR result = WERR_OK;
6580 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6581 if (info==NULL) {
6582 *returned=0;
6583 return WERR_NOMEM;
6586 for (i=0; i<*returned; i++)
6587 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6589 /* check the required size. */
6590 for (i=0; i<*returned; i++)
6591 (*needed) += spoolss_size_job_info_1(&info[i]);
6593 if (*needed > offered) {
6594 result = WERR_INSUFFICIENT_BUFFER;
6595 goto out;
6598 if (!rpcbuf_alloc_size(buffer, *needed)) {
6599 result = WERR_NOMEM;
6600 goto out;
6603 /* fill the buffer with the structures */
6604 for (i=0; i<*returned; i++)
6605 smb_io_job_info_1("", buffer, &info[i], 0);
6607 out:
6608 /* clear memory */
6609 SAFE_FREE(info);
6611 if ( !W_ERROR_IS_OK(result) )
6612 *returned = 0;
6614 return result;
6617 /****************************************************************************
6618 Enumjobs at level 2.
6619 ****************************************************************************/
6621 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6622 const NT_PRINTER_INFO_LEVEL *ntprinter,
6623 RPC_BUFFER *buffer, uint32 offered,
6624 uint32 *needed, uint32 *returned)
6626 JOB_INFO_2 *info = NULL;
6627 int i;
6628 WERROR result = WERR_OK;
6629 DEVICEMODE *devmode = NULL;
6631 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6632 *returned=0;
6633 return WERR_NOMEM;
6636 /* this should not be a failure condition if the devmode is NULL */
6638 devmode = construct_dev_mode(lp_const_servicename(snum));
6640 for (i=0; i<*returned; i++)
6641 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6643 /* check the required size. */
6644 for (i=0; i<*returned; i++)
6645 (*needed) += spoolss_size_job_info_2(&info[i]);
6647 if (*needed > offered) {
6648 result = WERR_INSUFFICIENT_BUFFER;
6649 goto out;
6652 if (!rpcbuf_alloc_size(buffer, *needed)) {
6653 result = WERR_NOMEM;
6654 goto out;
6657 /* fill the buffer with the structures */
6658 for (i=0; i<*returned; i++)
6659 smb_io_job_info_2("", buffer, &info[i], 0);
6661 out:
6662 free_devmode(devmode);
6663 SAFE_FREE(info);
6665 if ( !W_ERROR_IS_OK(result) )
6666 *returned = 0;
6668 return result;
6672 /****************************************************************************
6673 Enumjobs.
6674 ****************************************************************************/
6676 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6678 POLICY_HND *handle = &q_u->handle;
6679 uint32 level = q_u->level;
6680 RPC_BUFFER *buffer = NULL;
6681 uint32 offered = q_u->offered;
6682 uint32 *needed = &r_u->needed;
6683 uint32 *returned = &r_u->returned;
6684 WERROR wret;
6685 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6686 int snum;
6687 print_status_struct prt_status;
6688 print_queue_struct *queue=NULL;
6690 /* that's an [in out] buffer */
6692 if (!q_u->buffer && (offered!=0)) {
6693 return WERR_INVALID_PARAM;
6696 rpcbuf_move(q_u->buffer, &r_u->buffer);
6697 buffer = r_u->buffer;
6699 DEBUG(4,("_spoolss_enumjobs\n"));
6701 *needed=0;
6702 *returned=0;
6704 /* lookup the printer snum and tdb entry */
6706 if (!get_printer_snum(p, handle, &snum))
6707 return WERR_BADFID;
6709 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6710 if ( !W_ERROR_IS_OK(wret) )
6711 return wret;
6713 *returned = print_queue_status(snum, &queue, &prt_status);
6714 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6716 if (*returned == 0) {
6717 SAFE_FREE(queue);
6718 free_a_printer(&ntprinter, 2);
6719 return WERR_OK;
6722 switch (level) {
6723 case 1:
6724 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6725 break;
6726 case 2:
6727 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6728 break;
6729 default:
6730 *returned=0;
6731 wret = WERR_UNKNOWN_LEVEL;
6732 break;
6735 SAFE_FREE(queue);
6736 free_a_printer( &ntprinter, 2 );
6737 return wret;
6740 /****************************************************************************
6741 ****************************************************************************/
6743 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6745 return WERR_OK;
6748 /****************************************************************************
6749 ****************************************************************************/
6751 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6753 POLICY_HND *handle = &q_u->handle;
6754 uint32 jobid = q_u->jobid;
6755 uint32 command = q_u->command;
6757 struct current_user user;
6758 int snum;
6759 WERROR errcode = WERR_BADFUNC;
6761 if (!get_printer_snum(p, handle, &snum)) {
6762 return WERR_BADFID;
6765 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6766 return WERR_INVALID_PRINTER_NAME;
6769 get_current_user(&user, p);
6771 switch (command) {
6772 case JOB_CONTROL_CANCEL:
6773 case JOB_CONTROL_DELETE:
6774 if (print_job_delete(&user, snum, jobid, &errcode)) {
6775 errcode = WERR_OK;
6777 break;
6778 case JOB_CONTROL_PAUSE:
6779 if (print_job_pause(&user, snum, jobid, &errcode)) {
6780 errcode = WERR_OK;
6782 break;
6783 case JOB_CONTROL_RESTART:
6784 case JOB_CONTROL_RESUME:
6785 if (print_job_resume(&user, snum, jobid, &errcode)) {
6786 errcode = WERR_OK;
6788 break;
6789 default:
6790 return WERR_UNKNOWN_LEVEL;
6793 return errcode;
6796 /****************************************************************************
6797 Enumerates all printer drivers at level 1.
6798 ****************************************************************************/
6800 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6802 int i;
6803 int ndrivers;
6804 uint32 version;
6805 fstring *list = NULL;
6806 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6807 DRIVER_INFO_1 *driver_info_1=NULL;
6808 WERROR result = WERR_OK;
6810 *returned=0;
6812 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6813 list=NULL;
6814 ndrivers=get_ntdrivers(&list, architecture, version);
6815 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6817 if(ndrivers == -1) {
6818 SAFE_FREE(driver_info_1);
6819 return WERR_NOMEM;
6822 if(ndrivers != 0) {
6823 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6824 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6825 SAFE_FREE(list);
6826 return WERR_NOMEM;
6830 for (i=0; i<ndrivers; i++) {
6831 WERROR status;
6832 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6833 ZERO_STRUCT(driver);
6834 status = get_a_printer_driver(&driver, 3, list[i],
6835 architecture, version);
6836 if (!W_ERROR_IS_OK(status)) {
6837 SAFE_FREE(list);
6838 SAFE_FREE(driver_info_1);
6839 return status;
6841 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6842 free_a_printer_driver(driver, 3);
6845 *returned+=ndrivers;
6846 SAFE_FREE(list);
6849 /* check the required size. */
6850 for (i=0; i<*returned; i++) {
6851 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6852 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6855 if (*needed > offered) {
6856 result = WERR_INSUFFICIENT_BUFFER;
6857 goto out;
6860 if (!rpcbuf_alloc_size(buffer, *needed)) {
6861 result = WERR_NOMEM;
6862 goto out;
6865 /* fill the buffer with the driver structures */
6866 for (i=0; i<*returned; i++) {
6867 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6868 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6871 out:
6872 SAFE_FREE(driver_info_1);
6874 if ( !W_ERROR_IS_OK(result) )
6875 *returned = 0;
6877 return result;
6880 /****************************************************************************
6881 Enumerates all printer drivers at level 2.
6882 ****************************************************************************/
6884 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6886 int i;
6887 int ndrivers;
6888 uint32 version;
6889 fstring *list = NULL;
6890 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6891 DRIVER_INFO_2 *driver_info_2=NULL;
6892 WERROR result = WERR_OK;
6894 *returned=0;
6896 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6897 list=NULL;
6898 ndrivers=get_ntdrivers(&list, architecture, version);
6899 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6901 if(ndrivers == -1) {
6902 SAFE_FREE(driver_info_2);
6903 return WERR_NOMEM;
6906 if(ndrivers != 0) {
6907 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6908 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6909 SAFE_FREE(list);
6910 return WERR_NOMEM;
6914 for (i=0; i<ndrivers; i++) {
6915 WERROR status;
6917 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6918 ZERO_STRUCT(driver);
6919 status = get_a_printer_driver(&driver, 3, list[i],
6920 architecture, version);
6921 if (!W_ERROR_IS_OK(status)) {
6922 SAFE_FREE(list);
6923 SAFE_FREE(driver_info_2);
6924 return status;
6926 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6927 free_a_printer_driver(driver, 3);
6930 *returned+=ndrivers;
6931 SAFE_FREE(list);
6934 /* check the required size. */
6935 for (i=0; i<*returned; i++) {
6936 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6937 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6940 if (*needed > offered) {
6941 result = WERR_INSUFFICIENT_BUFFER;
6942 goto out;
6945 if (!rpcbuf_alloc_size(buffer, *needed)) {
6946 result = WERR_NOMEM;
6947 goto out;
6950 /* fill the buffer with the form structures */
6951 for (i=0; i<*returned; i++) {
6952 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6953 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6956 out:
6957 SAFE_FREE(driver_info_2);
6959 if ( !W_ERROR_IS_OK(result) )
6960 *returned = 0;
6962 return result;
6965 /****************************************************************************
6966 Enumerates all printer drivers at level 3.
6967 ****************************************************************************/
6969 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6971 int i;
6972 int ndrivers;
6973 uint32 version;
6974 fstring *list = NULL;
6975 DRIVER_INFO_3 *driver_info_3=NULL;
6976 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6977 WERROR result = WERR_OK;
6979 *returned=0;
6981 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6982 list=NULL;
6983 ndrivers=get_ntdrivers(&list, architecture, version);
6984 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6986 if(ndrivers == -1) {
6987 SAFE_FREE(driver_info_3);
6988 return WERR_NOMEM;
6991 if(ndrivers != 0) {
6992 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6993 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6994 SAFE_FREE(list);
6995 return WERR_NOMEM;
6999 for (i=0; i<ndrivers; i++) {
7000 WERROR status;
7002 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7003 ZERO_STRUCT(driver);
7004 status = get_a_printer_driver(&driver, 3, list[i],
7005 architecture, version);
7006 if (!W_ERROR_IS_OK(status)) {
7007 SAFE_FREE(list);
7008 SAFE_FREE(driver_info_3);
7009 return status;
7011 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7012 free_a_printer_driver(driver, 3);
7015 *returned+=ndrivers;
7016 SAFE_FREE(list);
7019 /* check the required size. */
7020 for (i=0; i<*returned; i++) {
7021 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7022 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7025 if (*needed > offered) {
7026 result = WERR_INSUFFICIENT_BUFFER;
7027 goto out;
7030 if (!rpcbuf_alloc_size(buffer, *needed)) {
7031 result = WERR_NOMEM;
7032 goto out;
7035 /* fill the buffer with the driver structures */
7036 for (i=0; i<*returned; i++) {
7037 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7038 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7041 out:
7042 for (i=0; i<*returned; i++) {
7043 SAFE_FREE(driver_info_3[i].dependentfiles);
7046 SAFE_FREE(driver_info_3);
7048 if ( !W_ERROR_IS_OK(result) )
7049 *returned = 0;
7051 return result;
7054 /****************************************************************************
7055 Enumerates all printer drivers.
7056 ****************************************************************************/
7058 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7060 uint32 level = q_u->level;
7061 RPC_BUFFER *buffer = NULL;
7062 uint32 offered = q_u->offered;
7063 uint32 *needed = &r_u->needed;
7064 uint32 *returned = &r_u->returned;
7065 const char *cservername;
7066 fstring servername;
7067 fstring architecture;
7069 /* that's an [in out] buffer */
7071 if (!q_u->buffer && (offered!=0)) {
7072 return WERR_INVALID_PARAM;
7075 rpcbuf_move(q_u->buffer, &r_u->buffer);
7076 buffer = r_u->buffer;
7078 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7080 *needed = 0;
7081 *returned = 0;
7083 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7084 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7086 cservername = canon_servername(servername);
7088 if (!is_myname_or_ipaddr(cservername))
7089 return WERR_UNKNOWN_PRINTER_DRIVER;
7091 switch (level) {
7092 case 1:
7093 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7094 case 2:
7095 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7096 case 3:
7097 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7098 default:
7099 return WERR_UNKNOWN_LEVEL;
7103 /****************************************************************************
7104 ****************************************************************************/
7106 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7108 form->flag=list->flag;
7109 init_unistr(&form->name, list->name);
7110 form->width=list->width;
7111 form->length=list->length;
7112 form->left=list->left;
7113 form->top=list->top;
7114 form->right=list->right;
7115 form->bottom=list->bottom;
7118 /****************************************************************************
7119 ****************************************************************************/
7121 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7123 uint32 level = q_u->level;
7124 RPC_BUFFER *buffer = NULL;
7125 uint32 offered = q_u->offered;
7126 uint32 *needed = &r_u->needed;
7127 uint32 *numofforms = &r_u->numofforms;
7128 uint32 numbuiltinforms;
7130 nt_forms_struct *list=NULL;
7131 nt_forms_struct *builtinlist=NULL;
7132 FORM_1 *forms_1;
7133 int buffer_size=0;
7134 int i;
7136 /* that's an [in out] buffer */
7138 if (!q_u->buffer && (offered!=0) ) {
7139 return WERR_INVALID_PARAM;
7142 rpcbuf_move(q_u->buffer, &r_u->buffer);
7143 buffer = r_u->buffer;
7145 DEBUG(4,("_spoolss_enumforms\n"));
7146 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7147 DEBUGADD(5,("Info level [%d]\n", level));
7149 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7150 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7151 *numofforms = get_ntforms(&list);
7152 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7153 *numofforms += numbuiltinforms;
7155 if (*numofforms == 0) {
7156 SAFE_FREE(builtinlist);
7157 SAFE_FREE(list);
7158 return WERR_NO_MORE_ITEMS;
7161 switch (level) {
7162 case 1:
7163 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7164 SAFE_FREE(builtinlist);
7165 SAFE_FREE(list);
7166 *numofforms=0;
7167 return WERR_NOMEM;
7170 /* construct the list of form structures */
7171 for (i=0; i<numbuiltinforms; i++) {
7172 DEBUGADD(6,("Filling form number [%d]\n",i));
7173 fill_form_1(&forms_1[i], &builtinlist[i]);
7176 SAFE_FREE(builtinlist);
7178 for (; i<*numofforms; i++) {
7179 DEBUGADD(6,("Filling form number [%d]\n",i));
7180 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7183 SAFE_FREE(list);
7185 /* check the required size. */
7186 for (i=0; i<numbuiltinforms; i++) {
7187 DEBUGADD(6,("adding form [%d]'s size\n",i));
7188 buffer_size += spoolss_size_form_1(&forms_1[i]);
7190 for (; i<*numofforms; i++) {
7191 DEBUGADD(6,("adding form [%d]'s size\n",i));
7192 buffer_size += spoolss_size_form_1(&forms_1[i]);
7195 *needed=buffer_size;
7197 if (*needed > offered) {
7198 SAFE_FREE(forms_1);
7199 *numofforms=0;
7200 return WERR_INSUFFICIENT_BUFFER;
7203 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7204 SAFE_FREE(forms_1);
7205 *numofforms=0;
7206 return WERR_NOMEM;
7209 /* fill the buffer with the form structures */
7210 for (i=0; i<numbuiltinforms; i++) {
7211 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7212 smb_io_form_1("", buffer, &forms_1[i], 0);
7214 for (; i<*numofforms; i++) {
7215 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7216 smb_io_form_1("", buffer, &forms_1[i], 0);
7219 SAFE_FREE(forms_1);
7221 return WERR_OK;
7223 default:
7224 SAFE_FREE(list);
7225 SAFE_FREE(builtinlist);
7226 return WERR_UNKNOWN_LEVEL;
7230 /****************************************************************************
7231 ****************************************************************************/
7233 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7235 uint32 level = q_u->level;
7236 UNISTR2 *uni_formname = &q_u->formname;
7237 RPC_BUFFER *buffer = NULL;
7238 uint32 offered = q_u->offered;
7239 uint32 *needed = &r_u->needed;
7241 nt_forms_struct *list=NULL;
7242 nt_forms_struct builtin_form;
7243 BOOL foundBuiltin;
7244 FORM_1 form_1;
7245 fstring form_name;
7246 int buffer_size=0;
7247 int numofforms=0, i=0;
7249 /* that's an [in out] buffer */
7251 if (!q_u->buffer && (offered!=0)) {
7252 return WERR_INVALID_PARAM;
7255 rpcbuf_move(q_u->buffer, &r_u->buffer);
7256 buffer = r_u->buffer;
7258 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7260 DEBUG(4,("_spoolss_getform\n"));
7261 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7262 DEBUGADD(5,("Info level [%d]\n", level));
7264 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7265 if (!foundBuiltin) {
7266 numofforms = get_ntforms(&list);
7267 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7269 if (numofforms == 0)
7270 return WERR_BADFID;
7273 switch (level) {
7274 case 1:
7275 if (foundBuiltin) {
7276 fill_form_1(&form_1, &builtin_form);
7277 } else {
7279 /* Check if the requested name is in the list of form structures */
7280 for (i=0; i<numofforms; i++) {
7282 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7284 if (strequal(form_name, list[i].name)) {
7285 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7286 fill_form_1(&form_1, &list[i]);
7287 break;
7291 SAFE_FREE(list);
7292 if (i == numofforms) {
7293 return WERR_BADFID;
7296 /* check the required size. */
7298 *needed=spoolss_size_form_1(&form_1);
7300 if (*needed > offered)
7301 return WERR_INSUFFICIENT_BUFFER;
7303 if (!rpcbuf_alloc_size(buffer, buffer_size))
7304 return WERR_NOMEM;
7306 /* fill the buffer with the form structures */
7307 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7308 smb_io_form_1("", buffer, &form_1, 0);
7310 return WERR_OK;
7312 default:
7313 SAFE_FREE(list);
7314 return WERR_UNKNOWN_LEVEL;
7318 /****************************************************************************
7319 ****************************************************************************/
7321 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7323 init_unistr(&port->port_name, name);
7326 /****************************************************************************
7327 TODO: This probably needs distinguish between TCP/IP and Local ports
7328 somehow.
7329 ****************************************************************************/
7331 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7333 init_unistr(&port->port_name, name);
7334 init_unistr(&port->monitor_name, "Local Monitor");
7335 init_unistr(&port->description, SPL_LOCAL_PORT );
7336 port->port_type=PORT_TYPE_WRITE;
7337 port->reserved=0x0;
7341 /****************************************************************************
7342 wrapper around the enumer ports command
7343 ****************************************************************************/
7345 WERROR enumports_hook( int *count, char ***lines )
7347 char *cmd = lp_enumports_cmd();
7348 char **qlines;
7349 pstring command;
7350 int numlines;
7351 int ret;
7352 int fd;
7354 *count = 0;
7355 *lines = NULL;
7357 /* if no hook then just fill in the default port */
7359 if ( !*cmd ) {
7360 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7361 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7362 qlines[1] = NULL;
7363 numlines = 1;
7365 else {
7366 /* we have a valid enumport command */
7368 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7370 DEBUG(10,("Running [%s]\n", command));
7371 ret = smbrun(command, &fd);
7372 DEBUG(10,("Returned [%d]\n", ret));
7373 if (ret != 0) {
7374 if (fd != -1) {
7375 close(fd);
7377 return WERR_ACCESS_DENIED;
7380 numlines = 0;
7381 qlines = fd_lines_load(fd, &numlines, 0);
7382 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7383 close(fd);
7386 *count = numlines;
7387 *lines = qlines;
7389 return WERR_OK;
7392 /****************************************************************************
7393 enumports level 1.
7394 ****************************************************************************/
7396 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7398 PORT_INFO_1 *ports=NULL;
7399 int i=0;
7400 WERROR result = WERR_OK;
7401 char **qlines = NULL;
7402 int numlines = 0;
7404 result = enumports_hook( &numlines, &qlines );
7405 if (!W_ERROR_IS_OK(result)) {
7406 file_lines_free(qlines);
7407 return result;
7410 if(numlines) {
7411 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7412 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7413 dos_errstr(WERR_NOMEM)));
7414 file_lines_free(qlines);
7415 return WERR_NOMEM;
7418 for (i=0; i<numlines; i++) {
7419 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7420 fill_port_1(&ports[i], qlines[i]);
7423 file_lines_free(qlines);
7425 *returned = numlines;
7427 /* check the required size. */
7428 for (i=0; i<*returned; i++) {
7429 DEBUGADD(6,("adding port [%d]'s size\n", i));
7430 *needed += spoolss_size_port_info_1(&ports[i]);
7433 if (*needed > offered) {
7434 result = WERR_INSUFFICIENT_BUFFER;
7435 goto out;
7438 if (!rpcbuf_alloc_size(buffer, *needed)) {
7439 result = WERR_NOMEM;
7440 goto out;
7443 /* fill the buffer with the ports structures */
7444 for (i=0; i<*returned; i++) {
7445 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7446 smb_io_port_1("", buffer, &ports[i], 0);
7449 out:
7450 SAFE_FREE(ports);
7452 if ( !W_ERROR_IS_OK(result) )
7453 *returned = 0;
7455 return result;
7458 /****************************************************************************
7459 enumports level 2.
7460 ****************************************************************************/
7462 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7464 PORT_INFO_2 *ports=NULL;
7465 int i=0;
7466 WERROR result = WERR_OK;
7467 char **qlines = NULL;
7468 int numlines = 0;
7470 result = enumports_hook( &numlines, &qlines );
7471 if ( !W_ERROR_IS_OK(result)) {
7472 file_lines_free(qlines);
7473 return result;
7476 if(numlines) {
7477 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7478 file_lines_free(qlines);
7479 return WERR_NOMEM;
7482 for (i=0; i<numlines; i++) {
7483 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7484 fill_port_2(&(ports[i]), qlines[i]);
7488 file_lines_free(qlines);
7490 *returned = numlines;
7492 /* check the required size. */
7493 for (i=0; i<*returned; i++) {
7494 DEBUGADD(6,("adding port [%d]'s size\n", i));
7495 *needed += spoolss_size_port_info_2(&ports[i]);
7498 if (*needed > offered) {
7499 result = WERR_INSUFFICIENT_BUFFER;
7500 goto out;
7503 if (!rpcbuf_alloc_size(buffer, *needed)) {
7504 result = WERR_NOMEM;
7505 goto out;
7508 /* fill the buffer with the ports structures */
7509 for (i=0; i<*returned; i++) {
7510 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7511 smb_io_port_2("", buffer, &ports[i], 0);
7514 out:
7515 SAFE_FREE(ports);
7517 if ( !W_ERROR_IS_OK(result) )
7518 *returned = 0;
7520 return result;
7523 /****************************************************************************
7524 enumports.
7525 ****************************************************************************/
7527 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7529 uint32 level = q_u->level;
7530 RPC_BUFFER *buffer = NULL;
7531 uint32 offered = q_u->offered;
7532 uint32 *needed = &r_u->needed;
7533 uint32 *returned = &r_u->returned;
7535 /* that's an [in out] buffer */
7537 if (!q_u->buffer && (offered!=0)) {
7538 return WERR_INVALID_PARAM;
7541 rpcbuf_move(q_u->buffer, &r_u->buffer);
7542 buffer = r_u->buffer;
7544 DEBUG(4,("_spoolss_enumports\n"));
7546 *returned=0;
7547 *needed=0;
7549 switch (level) {
7550 case 1:
7551 return enumports_level_1(buffer, offered, needed, returned);
7552 case 2:
7553 return enumports_level_2(buffer, offered, needed, returned);
7554 default:
7555 return WERR_UNKNOWN_LEVEL;
7559 /****************************************************************************
7560 ****************************************************************************/
7562 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7563 const SPOOL_PRINTER_INFO_LEVEL *info,
7564 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7565 uint32 user_switch, const SPOOL_USER_CTR *user,
7566 POLICY_HND *handle)
7568 NT_PRINTER_INFO_LEVEL *printer = NULL;
7569 fstring name;
7570 int snum;
7571 WERROR err = WERR_OK;
7573 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7574 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7575 return WERR_NOMEM;
7578 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7579 if (!convert_printer_info(info, printer, 2)) {
7580 free_a_printer(&printer, 2);
7581 return WERR_NOMEM;
7584 /* check to see if the printer already exists */
7586 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7587 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7588 printer->info_2->sharename));
7589 free_a_printer(&printer, 2);
7590 return WERR_PRINTER_ALREADY_EXISTS;
7593 /* FIXME!!! smbd should check to see if the driver is installed before
7594 trying to add a printer like this --jerry */
7596 if (*lp_addprinter_cmd() ) {
7597 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7598 free_a_printer(&printer,2);
7599 return WERR_ACCESS_DENIED;
7601 } else {
7602 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7603 "smb.conf parameter \"addprinter command\" is defined. This"
7604 "parameter must exist for this call to succeed\n",
7605 printer->info_2->sharename ));
7608 /* use our primary netbios name since get_a_printer() will convert
7609 it to what the client expects on a case by case basis */
7611 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7612 printer->info_2->sharename);
7615 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7616 free_a_printer(&printer,2);
7617 return WERR_ACCESS_DENIED;
7620 /* you must be a printer admin to add a new printer */
7621 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7622 free_a_printer(&printer,2);
7623 return WERR_ACCESS_DENIED;
7627 * Do sanity check on the requested changes for Samba.
7630 if (!check_printer_ok(printer->info_2, snum)) {
7631 free_a_printer(&printer,2);
7632 return WERR_INVALID_PARAM;
7636 * When a printer is created, the drivername bound to the printer is used
7637 * to lookup previously saved driver initialization info, which is then
7638 * bound to the new printer, simulating what happens in the Windows arch.
7641 if (!devmode)
7643 set_driver_init(printer, 2);
7645 else
7647 /* A valid devmode was included, convert and link it
7649 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7651 if (!convert_devicemode(printer->info_2->printername, devmode,
7652 &printer->info_2->devmode))
7653 return WERR_NOMEM;
7656 /* write the ASCII on disk */
7657 err = mod_a_printer(printer, 2);
7658 if (!W_ERROR_IS_OK(err)) {
7659 free_a_printer(&printer,2);
7660 return err;
7663 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7664 /* Handle open failed - remove addition. */
7665 del_a_printer(printer->info_2->sharename);
7666 free_a_printer(&printer,2);
7667 return WERR_ACCESS_DENIED;
7670 update_c_setprinter(False);
7671 free_a_printer(&printer,2);
7673 return WERR_OK;
7676 /****************************************************************************
7677 ****************************************************************************/
7679 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7681 UNISTR2 *uni_srv_name = q_u->server_name;
7682 uint32 level = q_u->level;
7683 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7684 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7685 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7686 uint32 user_switch = q_u->user_switch;
7687 SPOOL_USER_CTR *user = &q_u->user_ctr;
7688 POLICY_HND *handle = &r_u->handle;
7690 switch (level) {
7691 case 1:
7692 /* we don't handle yet */
7693 /* but I know what to do ... */
7694 return WERR_UNKNOWN_LEVEL;
7695 case 2:
7696 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7697 devmode, sdb,
7698 user_switch, user, handle);
7699 default:
7700 return WERR_UNKNOWN_LEVEL;
7704 /****************************************************************************
7705 ****************************************************************************/
7707 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7709 uint32 level = q_u->level;
7710 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7711 WERROR err = WERR_OK;
7712 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7713 struct current_user user;
7714 fstring driver_name;
7715 uint32 version;
7717 ZERO_STRUCT(driver);
7719 get_current_user(&user, p);
7721 if (!convert_printer_driver_info(info, &driver, level)) {
7722 err = WERR_NOMEM;
7723 goto done;
7726 DEBUG(5,("Cleaning driver's information\n"));
7727 err = clean_up_driver_struct(driver, level, &user);
7728 if (!W_ERROR_IS_OK(err))
7729 goto done;
7731 DEBUG(5,("Moving driver to final destination\n"));
7732 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7733 goto done;
7736 if (add_a_printer_driver(driver, level)!=0) {
7737 err = WERR_ACCESS_DENIED;
7738 goto done;
7742 * I think this is where he DrvUpgradePrinter() hook would be
7743 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7744 * server. Right now, we just need to send ourselves a message
7745 * to update each printer bound to this driver. --jerry
7748 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7749 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7750 driver_name));
7754 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7755 * decide if the driver init data should be deleted. The rules are:
7756 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7757 * 2) delete init data only if there is no 2k/Xp driver
7758 * 3) always delete init data
7759 * The generalized rule is always use init data from the highest order driver.
7760 * It is necessary to follow the driver install by an initialization step to
7761 * finish off this process.
7763 if (level == 3)
7764 version = driver.info_3->cversion;
7765 else if (level == 6)
7766 version = driver.info_6->version;
7767 else
7768 version = -1;
7769 switch (version) {
7771 * 9x printer driver - never delete init data
7773 case 0:
7774 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7775 driver_name));
7776 break;
7779 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7780 * there is no 2k/Xp driver init data for this driver name.
7782 case 2:
7784 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7786 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7788 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7790 if (!del_driver_init(driver_name))
7791 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7792 } else {
7794 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7796 free_a_printer_driver(driver1,3);
7797 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7798 driver_name));
7801 break;
7804 * 2k or Xp printer driver - always delete init data
7806 case 3:
7807 if (!del_driver_init(driver_name))
7808 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7809 break;
7811 default:
7812 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7813 break;
7817 done:
7818 free_a_printer_driver(driver, level);
7819 return err;
7822 /********************************************************************
7823 * spoolss_addprinterdriverex
7824 ********************************************************************/
7826 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7828 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7829 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7832 * we only support the semantics of AddPrinterDriver()
7833 * i.e. only copy files that are newer than existing ones
7836 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7837 return WERR_ACCESS_DENIED;
7839 ZERO_STRUCT(q_u_local);
7840 ZERO_STRUCT(r_u_local);
7842 /* just pass the information off to _spoolss_addprinterdriver() */
7843 q_u_local.server_name_ptr = q_u->server_name_ptr;
7844 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7845 q_u_local.level = q_u->level;
7846 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7848 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7851 /****************************************************************************
7852 ****************************************************************************/
7854 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7856 init_unistr(&info->name, name);
7859 /****************************************************************************
7860 ****************************************************************************/
7862 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7864 pstring path;
7865 pstring long_archi;
7866 fstring servername;
7867 const char *pservername;
7868 const char *short_archi;
7869 DRIVER_DIRECTORY_1 *info=NULL;
7870 WERROR result = WERR_OK;
7872 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7873 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7875 pservername = canon_servername(servername);
7877 if ( !is_myname_or_ipaddr( pservername ) )
7878 return WERR_INVALID_PARAM;
7880 if (!(short_archi = get_short_archi(long_archi)))
7881 return WERR_INVALID_ENVIRONMENT;
7883 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7884 return WERR_NOMEM;
7886 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7888 DEBUG(4,("printer driver directory: [%s]\n", path));
7890 fill_driverdir_1(info, path);
7892 *needed += spoolss_size_driverdir_info_1(info);
7894 if (*needed > offered) {
7895 result = WERR_INSUFFICIENT_BUFFER;
7896 goto out;
7899 if (!rpcbuf_alloc_size(buffer, *needed)) {
7900 result = WERR_NOMEM;
7901 goto out;
7904 smb_io_driverdir_1("", buffer, info, 0);
7906 out:
7907 SAFE_FREE(info);
7909 return result;
7912 /****************************************************************************
7913 ****************************************************************************/
7915 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7917 UNISTR2 *name = &q_u->name;
7918 UNISTR2 *uni_environment = &q_u->environment;
7919 uint32 level = q_u->level;
7920 RPC_BUFFER *buffer = NULL;
7921 uint32 offered = q_u->offered;
7922 uint32 *needed = &r_u->needed;
7924 /* that's an [in out] buffer */
7926 if (!q_u->buffer && (offered!=0)) {
7927 return WERR_INVALID_PARAM;
7930 rpcbuf_move(q_u->buffer, &r_u->buffer);
7931 buffer = r_u->buffer;
7933 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7935 *needed=0;
7937 switch(level) {
7938 case 1:
7939 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7940 default:
7941 return WERR_UNKNOWN_LEVEL;
7945 /****************************************************************************
7946 ****************************************************************************/
7948 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7950 POLICY_HND *handle = &q_u->handle;
7951 uint32 idx = q_u->index;
7952 uint32 in_value_len = q_u->valuesize;
7953 uint32 in_data_len = q_u->datasize;
7954 uint32 *out_max_value_len = &r_u->valuesize;
7955 uint16 **out_value = &r_u->value;
7956 uint32 *out_value_len = &r_u->realvaluesize;
7957 uint32 *out_type = &r_u->type;
7958 uint32 *out_max_data_len = &r_u->datasize;
7959 uint8 **data_out = &r_u->data;
7960 uint32 *out_data_len = &r_u->realdatasize;
7962 NT_PRINTER_INFO_LEVEL *printer = NULL;
7964 uint32 biggest_valuesize;
7965 uint32 biggest_datasize;
7966 uint32 data_len;
7967 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7968 int snum;
7969 WERROR result;
7970 REGISTRY_VALUE *val = NULL;
7971 NT_PRINTER_DATA *p_data;
7972 int i, key_index, num_values;
7973 int name_length;
7975 *out_type = 0;
7977 *out_max_data_len = 0;
7978 *data_out = NULL;
7979 *out_data_len = 0;
7981 DEBUG(5,("spoolss_enumprinterdata\n"));
7983 if (!Printer) {
7984 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7985 return WERR_BADFID;
7988 if (!get_printer_snum(p,handle, &snum))
7989 return WERR_BADFID;
7991 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7992 if (!W_ERROR_IS_OK(result))
7993 return result;
7995 p_data = printer->info_2->data;
7996 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7998 result = WERR_OK;
8001 * The NT machine wants to know the biggest size of value and data
8003 * cf: MSDN EnumPrinterData remark section
8006 if ( !in_value_len && !in_data_len && (key_index != -1) )
8008 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8010 biggest_valuesize = 0;
8011 biggest_datasize = 0;
8013 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8015 for ( i=0; i<num_values; i++ )
8017 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8019 name_length = strlen(val->valuename);
8020 if ( strlen(val->valuename) > biggest_valuesize )
8021 biggest_valuesize = name_length;
8023 if ( val->size > biggest_datasize )
8024 biggest_datasize = val->size;
8026 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8027 biggest_datasize));
8030 /* the value is an UNICODE string but real_value_size is the length
8031 in bytes including the trailing 0 */
8033 *out_value_len = 2 * (1+biggest_valuesize);
8034 *out_data_len = biggest_datasize;
8036 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8038 goto done;
8042 * the value len is wrong in NT sp3
8043 * that's the number of bytes not the number of unicode chars
8046 if ( key_index != -1 )
8047 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8049 if ( !val )
8052 /* out_value should default to "" or else NT4 has
8053 problems unmarshalling the response */
8055 *out_max_value_len=(in_value_len/sizeof(uint16));
8057 if (in_value_len) {
8058 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8060 result = WERR_NOMEM;
8061 goto done;
8063 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8064 } else {
8065 *out_value=NULL;
8066 *out_value_len = 0;
8069 /* the data is counted in bytes */
8071 *out_max_data_len = in_data_len;
8072 *out_data_len = in_data_len;
8074 /* only allocate when given a non-zero data_len */
8076 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8078 result = WERR_NOMEM;
8079 goto done;
8082 result = WERR_NO_MORE_ITEMS;
8084 else
8087 * the value is:
8088 * - counted in bytes in the request
8089 * - counted in UNICODE chars in the max reply
8090 * - counted in bytes in the real size
8092 * take a pause *before* coding not *during* coding
8095 /* name */
8096 *out_max_value_len=(in_value_len/sizeof(uint16));
8097 if (in_value_len) {
8098 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8100 result = WERR_NOMEM;
8101 goto done;
8104 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8105 } else {
8106 *out_value = NULL;
8107 *out_value_len = 0;
8110 /* type */
8112 *out_type = regval_type( val );
8114 /* data - counted in bytes */
8116 *out_max_data_len = in_data_len;
8117 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8119 result = WERR_NOMEM;
8120 goto done;
8122 data_len = regval_size(val);
8123 if ( *data_out && data_len )
8124 memcpy( *data_out, regval_data_p(val), data_len );
8125 *out_data_len = data_len;
8128 done:
8129 free_a_printer(&printer, 2);
8130 return result;
8133 /****************************************************************************
8134 ****************************************************************************/
8136 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8138 POLICY_HND *handle = &q_u->handle;
8139 UNISTR2 *value = &q_u->value;
8140 uint32 type = q_u->type;
8141 uint8 *data = q_u->data;
8142 uint32 real_len = q_u->real_len;
8144 NT_PRINTER_INFO_LEVEL *printer = NULL;
8145 int snum=0;
8146 WERROR status = WERR_OK;
8147 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8148 fstring valuename;
8150 DEBUG(5,("spoolss_setprinterdata\n"));
8152 if (!Printer) {
8153 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8154 return WERR_BADFID;
8157 if ( Printer->printer_type == SPLHND_SERVER ) {
8158 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8159 return WERR_INVALID_PARAM;
8162 if (!get_printer_snum(p,handle, &snum))
8163 return WERR_BADFID;
8166 * Access check : NT returns "access denied" if you make a
8167 * SetPrinterData call without the necessary privildge.
8168 * we were originally returning OK if nothing changed
8169 * which made Win2k issue **a lot** of SetPrinterData
8170 * when connecting to a printer --jerry
8173 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8175 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8176 status = WERR_ACCESS_DENIED;
8177 goto done;
8180 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8181 if (!W_ERROR_IS_OK(status))
8182 return status;
8184 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8187 * When client side code sets a magic printer data key, detect it and save
8188 * the current printer data and the magic key's data (its the DEVMODE) for
8189 * future printer/driver initializations.
8191 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8193 /* Set devmode and printer initialization info */
8194 status = save_driver_init( printer, 2, data, real_len );
8196 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8198 else
8200 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8201 type, data, real_len );
8202 if ( W_ERROR_IS_OK(status) )
8203 status = mod_a_printer(printer, 2);
8206 done:
8207 free_a_printer(&printer, 2);
8209 return status;
8212 /****************************************************************************
8213 ****************************************************************************/
8215 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8217 POLICY_HND *handle = &q_u->handle;
8218 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8219 int snum;
8221 DEBUG(5,("_spoolss_resetprinter\n"));
8224 * All we do is to check to see if the handle and queue is valid.
8225 * This call really doesn't mean anything to us because we only
8226 * support RAW printing. --jerry
8229 if (!Printer) {
8230 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8231 return WERR_BADFID;
8234 if (!get_printer_snum(p,handle, &snum))
8235 return WERR_BADFID;
8238 /* blindly return success */
8239 return WERR_OK;
8243 /****************************************************************************
8244 ****************************************************************************/
8246 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8248 POLICY_HND *handle = &q_u->handle;
8249 UNISTR2 *value = &q_u->valuename;
8251 NT_PRINTER_INFO_LEVEL *printer = NULL;
8252 int snum=0;
8253 WERROR status = WERR_OK;
8254 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8255 pstring valuename;
8257 DEBUG(5,("spoolss_deleteprinterdata\n"));
8259 if (!Printer) {
8260 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8261 return WERR_BADFID;
8264 if (!get_printer_snum(p, handle, &snum))
8265 return WERR_BADFID;
8267 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8268 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8269 return WERR_ACCESS_DENIED;
8272 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8273 if (!W_ERROR_IS_OK(status))
8274 return status;
8276 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8278 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8280 if ( W_ERROR_IS_OK(status) )
8281 mod_a_printer( printer, 2 );
8283 free_a_printer(&printer, 2);
8285 return status;
8288 /****************************************************************************
8289 ****************************************************************************/
8291 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8293 POLICY_HND *handle = &q_u->handle;
8294 FORM *form = &q_u->form;
8295 nt_forms_struct tmpForm;
8296 int snum;
8297 WERROR status = WERR_OK;
8298 NT_PRINTER_INFO_LEVEL *printer = NULL;
8300 int count=0;
8301 nt_forms_struct *list=NULL;
8302 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8304 DEBUG(5,("spoolss_addform\n"));
8306 if (!Printer) {
8307 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8308 return WERR_BADFID;
8312 /* forms can be added on printer of on the print server handle */
8314 if ( Printer->printer_type == SPLHND_PRINTER )
8316 if (!get_printer_snum(p,handle, &snum))
8317 return WERR_BADFID;
8319 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8320 if (!W_ERROR_IS_OK(status))
8321 goto done;
8324 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8325 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8326 status = WERR_ACCESS_DENIED;
8327 goto done;
8330 /* can't add if builtin */
8332 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8333 status = WERR_ALREADY_EXISTS;
8334 goto done;
8337 count = get_ntforms(&list);
8339 if(!add_a_form(&list, form, &count)) {
8340 status = WERR_NOMEM;
8341 goto done;
8344 write_ntforms(&list, count);
8347 * ChangeID must always be set if this is a printer
8350 if ( Printer->printer_type == SPLHND_PRINTER )
8351 status = mod_a_printer(printer, 2);
8353 done:
8354 if ( printer )
8355 free_a_printer(&printer, 2);
8356 SAFE_FREE(list);
8358 return status;
8361 /****************************************************************************
8362 ****************************************************************************/
8364 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8366 POLICY_HND *handle = &q_u->handle;
8367 UNISTR2 *form_name = &q_u->name;
8368 nt_forms_struct tmpForm;
8369 int count=0;
8370 nt_forms_struct *list=NULL;
8371 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8372 int snum;
8373 WERROR status = WERR_OK;
8374 NT_PRINTER_INFO_LEVEL *printer = NULL;
8376 DEBUG(5,("spoolss_deleteform\n"));
8378 if (!Printer) {
8379 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8380 return WERR_BADFID;
8383 /* forms can be deleted on printer of on the print server handle */
8385 if ( Printer->printer_type == SPLHND_PRINTER )
8387 if (!get_printer_snum(p,handle, &snum))
8388 return WERR_BADFID;
8390 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8391 if (!W_ERROR_IS_OK(status))
8392 goto done;
8395 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8396 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8397 status = WERR_ACCESS_DENIED;
8398 goto done;
8401 /* can't delete if builtin */
8403 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8404 status = WERR_INVALID_PARAM;
8405 goto done;
8408 count = get_ntforms(&list);
8410 if ( !delete_a_form(&list, form_name, &count, &status ))
8411 goto done;
8414 * ChangeID must always be set if this is a printer
8417 if ( Printer->printer_type == SPLHND_PRINTER )
8418 status = mod_a_printer(printer, 2);
8420 done:
8421 if ( printer )
8422 free_a_printer(&printer, 2);
8423 SAFE_FREE(list);
8425 return status;
8428 /****************************************************************************
8429 ****************************************************************************/
8431 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8433 POLICY_HND *handle = &q_u->handle;
8434 FORM *form = &q_u->form;
8435 nt_forms_struct tmpForm;
8436 int snum;
8437 WERROR status = WERR_OK;
8438 NT_PRINTER_INFO_LEVEL *printer = NULL;
8440 int count=0;
8441 nt_forms_struct *list=NULL;
8442 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8444 DEBUG(5,("spoolss_setform\n"));
8446 if (!Printer) {
8447 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8448 return WERR_BADFID;
8451 /* forms can be modified on printer of on the print server handle */
8453 if ( Printer->printer_type == SPLHND_PRINTER )
8455 if (!get_printer_snum(p,handle, &snum))
8456 return WERR_BADFID;
8458 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8459 if (!W_ERROR_IS_OK(status))
8460 goto done;
8463 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8464 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8465 status = WERR_ACCESS_DENIED;
8466 goto done;
8469 /* can't set if builtin */
8470 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8471 status = WERR_INVALID_PARAM;
8472 goto done;
8475 count = get_ntforms(&list);
8476 update_a_form(&list, form, count);
8477 write_ntforms(&list, count);
8480 * ChangeID must always be set if this is a printer
8483 if ( Printer->printer_type == SPLHND_PRINTER )
8484 status = mod_a_printer(printer, 2);
8487 done:
8488 if ( printer )
8489 free_a_printer(&printer, 2);
8490 SAFE_FREE(list);
8492 return status;
8495 /****************************************************************************
8496 enumprintprocessors level 1.
8497 ****************************************************************************/
8499 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8501 PRINTPROCESSOR_1 *info_1=NULL;
8502 WERROR result = WERR_OK;
8504 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8505 return WERR_NOMEM;
8507 (*returned) = 0x1;
8509 init_unistr(&info_1->name, "winprint");
8511 *needed += spoolss_size_printprocessor_info_1(info_1);
8513 if (*needed > offered) {
8514 result = WERR_INSUFFICIENT_BUFFER;
8515 goto out;
8518 if (!rpcbuf_alloc_size(buffer, *needed)) {
8519 result = WERR_NOMEM;
8520 goto out;
8523 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8525 out:
8526 SAFE_FREE(info_1);
8528 if ( !W_ERROR_IS_OK(result) )
8529 *returned = 0;
8531 return result;
8534 /****************************************************************************
8535 ****************************************************************************/
8537 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8539 uint32 level = q_u->level;
8540 RPC_BUFFER *buffer = NULL;
8541 uint32 offered = q_u->offered;
8542 uint32 *needed = &r_u->needed;
8543 uint32 *returned = &r_u->returned;
8545 /* that's an [in out] buffer */
8547 if (!q_u->buffer && (offered!=0)) {
8548 return WERR_INVALID_PARAM;
8551 rpcbuf_move(q_u->buffer, &r_u->buffer);
8552 buffer = r_u->buffer;
8554 DEBUG(5,("spoolss_enumprintprocessors\n"));
8557 * Enumerate the print processors ...
8559 * Just reply with "winprint", to keep NT happy
8560 * and I can use my nice printer checker.
8563 *returned=0;
8564 *needed=0;
8566 switch (level) {
8567 case 1:
8568 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8569 default:
8570 return WERR_UNKNOWN_LEVEL;
8574 /****************************************************************************
8575 enumprintprocdatatypes level 1.
8576 ****************************************************************************/
8578 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8580 PRINTPROCDATATYPE_1 *info_1=NULL;
8581 WERROR result = WERR_OK;
8583 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8584 return WERR_NOMEM;
8586 (*returned) = 0x1;
8588 init_unistr(&info_1->name, "RAW");
8590 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8592 if (*needed > offered) {
8593 result = WERR_INSUFFICIENT_BUFFER;
8594 goto out;
8597 if (!rpcbuf_alloc_size(buffer, *needed)) {
8598 result = WERR_NOMEM;
8599 goto out;
8602 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8604 out:
8605 SAFE_FREE(info_1);
8607 if ( !W_ERROR_IS_OK(result) )
8608 *returned = 0;
8610 return result;
8613 /****************************************************************************
8614 ****************************************************************************/
8616 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8618 uint32 level = q_u->level;
8619 RPC_BUFFER *buffer = NULL;
8620 uint32 offered = q_u->offered;
8621 uint32 *needed = &r_u->needed;
8622 uint32 *returned = &r_u->returned;
8624 /* that's an [in out] buffer */
8626 if (!q_u->buffer && (offered!=0)) {
8627 return WERR_INVALID_PARAM;
8630 rpcbuf_move(q_u->buffer, &r_u->buffer);
8631 buffer = r_u->buffer;
8633 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8635 *returned=0;
8636 *needed=0;
8638 switch (level) {
8639 case 1:
8640 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8641 default:
8642 return WERR_UNKNOWN_LEVEL;
8646 /****************************************************************************
8647 enumprintmonitors level 1.
8648 ****************************************************************************/
8650 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8652 PRINTMONITOR_1 *info_1;
8653 WERROR result = WERR_OK;
8654 int i;
8656 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8657 return WERR_NOMEM;
8659 *returned = 2;
8661 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8662 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8664 for ( i=0; i<*returned; i++ ) {
8665 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8668 if (*needed > offered) {
8669 result = WERR_INSUFFICIENT_BUFFER;
8670 goto out;
8673 if (!rpcbuf_alloc_size(buffer, *needed)) {
8674 result = WERR_NOMEM;
8675 goto out;
8678 for ( i=0; i<*returned; i++ ) {
8679 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8682 out:
8683 SAFE_FREE(info_1);
8685 if ( !W_ERROR_IS_OK(result) )
8686 *returned = 0;
8688 return result;
8691 /****************************************************************************
8692 enumprintmonitors level 2.
8693 ****************************************************************************/
8695 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8697 PRINTMONITOR_2 *info_2;
8698 WERROR result = WERR_OK;
8699 int i;
8701 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8702 return WERR_NOMEM;
8704 *returned = 2;
8706 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8707 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8708 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8710 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8711 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8712 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8714 for ( i=0; i<*returned; i++ ) {
8715 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8718 if (*needed > offered) {
8719 result = WERR_INSUFFICIENT_BUFFER;
8720 goto out;
8723 if (!rpcbuf_alloc_size(buffer, *needed)) {
8724 result = WERR_NOMEM;
8725 goto out;
8728 for ( i=0; i<*returned; i++ ) {
8729 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8732 out:
8733 SAFE_FREE(info_2);
8735 if ( !W_ERROR_IS_OK(result) )
8736 *returned = 0;
8738 return result;
8741 /****************************************************************************
8742 ****************************************************************************/
8744 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8746 uint32 level = q_u->level;
8747 RPC_BUFFER *buffer = NULL;
8748 uint32 offered = q_u->offered;
8749 uint32 *needed = &r_u->needed;
8750 uint32 *returned = &r_u->returned;
8752 /* that's an [in out] buffer */
8754 if (!q_u->buffer && (offered!=0)) {
8755 return WERR_INVALID_PARAM;
8758 rpcbuf_move(q_u->buffer, &r_u->buffer);
8759 buffer = r_u->buffer;
8761 DEBUG(5,("spoolss_enumprintmonitors\n"));
8764 * Enumerate the print monitors ...
8766 * Just reply with "Local Port", to keep NT happy
8767 * and I can use my nice printer checker.
8770 *returned=0;
8771 *needed=0;
8773 switch (level) {
8774 case 1:
8775 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8776 case 2:
8777 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8778 default:
8779 return WERR_UNKNOWN_LEVEL;
8783 /****************************************************************************
8784 ****************************************************************************/
8786 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8787 NT_PRINTER_INFO_LEVEL *ntprinter,
8788 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8789 uint32 *needed)
8791 int i=0;
8792 BOOL found=False;
8793 JOB_INFO_1 *info_1=NULL;
8794 WERROR result = WERR_OK;
8796 info_1=SMB_MALLOC_P(JOB_INFO_1);
8798 if (info_1 == NULL) {
8799 return WERR_NOMEM;
8802 for (i=0; i<count && found==False; i++) {
8803 if ((*queue)[i].job==(int)jobid)
8804 found=True;
8807 if (found==False) {
8808 SAFE_FREE(info_1);
8809 /* NT treats not found as bad param... yet another bad choice */
8810 return WERR_INVALID_PARAM;
8813 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8815 *needed += spoolss_size_job_info_1(info_1);
8817 if (*needed > offered) {
8818 result = WERR_INSUFFICIENT_BUFFER;
8819 goto out;
8822 if (!rpcbuf_alloc_size(buffer, *needed)) {
8823 result = WERR_NOMEM;
8824 goto out;
8827 smb_io_job_info_1("", buffer, info_1, 0);
8829 out:
8830 SAFE_FREE(info_1);
8832 return result;
8835 /****************************************************************************
8836 ****************************************************************************/
8838 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8839 NT_PRINTER_INFO_LEVEL *ntprinter,
8840 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8841 uint32 *needed)
8843 int i = 0;
8844 BOOL found = False;
8845 JOB_INFO_2 *info_2;
8846 WERROR result;
8847 DEVICEMODE *devmode = NULL;
8848 NT_DEVICEMODE *nt_devmode = NULL;
8850 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8851 return WERR_NOMEM;
8853 ZERO_STRUCTP(info_2);
8855 for ( i=0; i<count && found==False; i++ )
8857 if ((*queue)[i].job == (int)jobid)
8858 found = True;
8861 if ( !found ) {
8862 /* NT treats not found as bad param... yet another bad
8863 choice */
8864 result = WERR_INVALID_PARAM;
8865 goto done;
8869 * if the print job does not have a DEVMODE associated with it,
8870 * just use the one for the printer. A NULL devicemode is not
8871 * a failure condition
8874 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8875 devmode = construct_dev_mode(lp_const_servicename(snum));
8876 else {
8877 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8878 ZERO_STRUCTP( devmode );
8879 convert_nt_devicemode( devmode, nt_devmode );
8883 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8885 *needed += spoolss_size_job_info_2(info_2);
8887 if (*needed > offered) {
8888 result = WERR_INSUFFICIENT_BUFFER;
8889 goto done;
8892 if (!rpcbuf_alloc_size(buffer, *needed)) {
8893 result = WERR_NOMEM;
8894 goto done;
8897 smb_io_job_info_2("", buffer, info_2, 0);
8899 result = WERR_OK;
8901 done:
8902 /* Cleanup allocated memory */
8904 free_job_info_2(info_2); /* Also frees devmode */
8905 SAFE_FREE(info_2);
8907 return result;
8910 /****************************************************************************
8911 ****************************************************************************/
8913 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8915 POLICY_HND *handle = &q_u->handle;
8916 uint32 jobid = q_u->jobid;
8917 uint32 level = q_u->level;
8918 RPC_BUFFER *buffer = NULL;
8919 uint32 offered = q_u->offered;
8920 uint32 *needed = &r_u->needed;
8921 WERROR wstatus = WERR_OK;
8922 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8923 int snum;
8924 int count;
8925 print_queue_struct *queue = NULL;
8926 print_status_struct prt_status;
8928 /* that's an [in out] buffer */
8930 if (!q_u->buffer && (offered!=0)) {
8931 return WERR_INVALID_PARAM;
8934 rpcbuf_move(q_u->buffer, &r_u->buffer);
8935 buffer = r_u->buffer;
8937 DEBUG(5,("spoolss_getjob\n"));
8939 *needed = 0;
8941 if (!get_printer_snum(p, handle, &snum))
8942 return WERR_BADFID;
8944 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8945 if ( !W_ERROR_IS_OK(wstatus) )
8946 return wstatus;
8948 count = print_queue_status(snum, &queue, &prt_status);
8950 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8951 count, prt_status.status, prt_status.message));
8953 switch ( level ) {
8954 case 1:
8955 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8956 buffer, offered, needed);
8957 break;
8958 case 2:
8959 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8960 buffer, offered, needed);
8961 break;
8962 default:
8963 wstatus = WERR_UNKNOWN_LEVEL;
8964 break;
8967 SAFE_FREE(queue);
8968 free_a_printer( &ntprinter, 2 );
8970 return wstatus;
8973 /********************************************************************
8974 spoolss_getprinterdataex
8976 From MSDN documentation of GetPrinterDataEx: pass request
8977 to GetPrinterData if key is "PrinterDriverData".
8978 ********************************************************************/
8980 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8982 POLICY_HND *handle = &q_u->handle;
8983 uint32 in_size = q_u->size;
8984 uint32 *type = &r_u->type;
8985 uint32 *out_size = &r_u->size;
8986 uint8 **data = &r_u->data;
8987 uint32 *needed = &r_u->needed;
8988 fstring keyname, valuename;
8990 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8992 NT_PRINTER_INFO_LEVEL *printer = NULL;
8993 int snum = 0;
8994 WERROR status = WERR_OK;
8996 DEBUG(4,("_spoolss_getprinterdataex\n"));
8998 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8999 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
9001 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9002 keyname, valuename));
9004 /* in case of problem, return some default values */
9006 *needed = 0;
9007 *type = 0;
9008 *out_size = in_size;
9010 if (!Printer) {
9011 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9012 status = WERR_BADFID;
9013 goto done;
9016 /* Is the handle to a printer or to the server? */
9018 if (Printer->printer_type == SPLHND_SERVER) {
9019 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9020 status = WERR_INVALID_PARAM;
9021 goto done;
9024 if ( !get_printer_snum(p,handle, &snum) )
9025 return WERR_BADFID;
9027 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9028 if ( !W_ERROR_IS_OK(status) )
9029 goto done;
9031 /* check to see if the keyname is valid */
9032 if ( !strlen(keyname) ) {
9033 status = WERR_INVALID_PARAM;
9034 goto done;
9037 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9038 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9039 free_a_printer( &printer, 2 );
9040 status = WERR_BADFILE;
9041 goto done;
9044 /* When given a new keyname, we should just create it */
9046 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9048 if (*needed > *out_size)
9049 status = WERR_MORE_DATA;
9051 done:
9052 if ( !W_ERROR_IS_OK(status) )
9054 DEBUG(5, ("error: allocating %d\n", *out_size));
9056 /* reply this param doesn't exist */
9058 if ( *out_size )
9060 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9061 status = WERR_NOMEM;
9062 goto done;
9064 } else {
9065 *data = NULL;
9069 if ( printer )
9070 free_a_printer( &printer, 2 );
9072 return status;
9075 /********************************************************************
9076 * spoolss_setprinterdataex
9077 ********************************************************************/
9079 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9081 POLICY_HND *handle = &q_u->handle;
9082 uint32 type = q_u->type;
9083 uint8 *data = q_u->data;
9084 uint32 real_len = q_u->real_len;
9086 NT_PRINTER_INFO_LEVEL *printer = NULL;
9087 int snum = 0;
9088 WERROR status = WERR_OK;
9089 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9090 fstring valuename;
9091 fstring keyname;
9092 char *oid_string;
9094 DEBUG(4,("_spoolss_setprinterdataex\n"));
9096 /* From MSDN documentation of SetPrinterDataEx: pass request to
9097 SetPrinterData if key is "PrinterDriverData" */
9099 if (!Printer) {
9100 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9101 return WERR_BADFID;
9104 if ( Printer->printer_type == SPLHND_SERVER ) {
9105 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9106 return WERR_INVALID_PARAM;
9109 if ( !get_printer_snum(p,handle, &snum) )
9110 return WERR_BADFID;
9113 * Access check : NT returns "access denied" if you make a
9114 * SetPrinterData call without the necessary privildge.
9115 * we were originally returning OK if nothing changed
9116 * which made Win2k issue **a lot** of SetPrinterData
9117 * when connecting to a printer --jerry
9120 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9122 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9123 return WERR_ACCESS_DENIED;
9126 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9127 if (!W_ERROR_IS_OK(status))
9128 return status;
9130 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9131 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9133 /* check for OID in valuename */
9135 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9137 *oid_string = '\0';
9138 oid_string++;
9141 /* save the registry data */
9143 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9145 if ( W_ERROR_IS_OK(status) )
9147 /* save the OID if one was specified */
9148 if ( oid_string ) {
9149 fstrcat( keyname, "\\" );
9150 fstrcat( keyname, SPOOL_OID_KEY );
9153 * I'm not checking the status here on purpose. Don't know
9154 * if this is right, but I'm returning the status from the
9155 * previous set_printer_dataex() call. I have no idea if
9156 * this is right. --jerry
9159 set_printer_dataex( printer, keyname, valuename,
9160 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9163 status = mod_a_printer(printer, 2);
9166 free_a_printer(&printer, 2);
9168 return status;
9172 /********************************************************************
9173 * spoolss_deleteprinterdataex
9174 ********************************************************************/
9176 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9178 POLICY_HND *handle = &q_u->handle;
9179 UNISTR2 *value = &q_u->valuename;
9180 UNISTR2 *key = &q_u->keyname;
9182 NT_PRINTER_INFO_LEVEL *printer = NULL;
9183 int snum=0;
9184 WERROR status = WERR_OK;
9185 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9186 pstring valuename, keyname;
9188 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9190 if (!Printer) {
9191 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9192 return WERR_BADFID;
9195 if (!get_printer_snum(p, handle, &snum))
9196 return WERR_BADFID;
9198 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9199 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9200 return WERR_ACCESS_DENIED;
9203 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9204 if (!W_ERROR_IS_OK(status))
9205 return status;
9207 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9208 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9210 status = delete_printer_dataex( printer, keyname, valuename );
9212 if ( W_ERROR_IS_OK(status) )
9213 mod_a_printer( printer, 2 );
9215 free_a_printer(&printer, 2);
9217 return status;
9220 /********************************************************************
9221 * spoolss_enumprinterkey
9222 ********************************************************************/
9225 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9227 fstring key;
9228 fstring *keynames = NULL;
9229 uint16 *enumkeys = NULL;
9230 int num_keys;
9231 int printerkey_len;
9232 POLICY_HND *handle = &q_u->handle;
9233 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9234 NT_PRINTER_DATA *data;
9235 NT_PRINTER_INFO_LEVEL *printer = NULL;
9236 int snum = 0;
9237 WERROR status = WERR_BADFILE;
9240 DEBUG(4,("_spoolss_enumprinterkey\n"));
9242 if (!Printer) {
9243 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9244 return WERR_BADFID;
9247 if ( !get_printer_snum(p,handle, &snum) )
9248 return WERR_BADFID;
9250 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9251 if (!W_ERROR_IS_OK(status))
9252 return status;
9254 /* get the list of subkey names */
9256 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9257 data = printer->info_2->data;
9259 num_keys = get_printer_subkeys( data, key, &keynames );
9261 if ( num_keys == -1 ) {
9262 status = WERR_BADFILE;
9263 goto done;
9266 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9268 r_u->needed = printerkey_len*2;
9270 if ( q_u->size < r_u->needed ) {
9271 status = WERR_MORE_DATA;
9272 goto done;
9275 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9276 status = WERR_NOMEM;
9277 goto done;
9280 status = WERR_OK;
9282 if ( q_u->size < r_u->needed )
9283 status = WERR_MORE_DATA;
9285 done:
9286 free_a_printer( &printer, 2 );
9287 SAFE_FREE( keynames );
9289 return status;
9292 /********************************************************************
9293 * spoolss_deleteprinterkey
9294 ********************************************************************/
9296 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9298 POLICY_HND *handle = &q_u->handle;
9299 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9300 fstring key;
9301 NT_PRINTER_INFO_LEVEL *printer = NULL;
9302 int snum=0;
9303 WERROR status;
9305 DEBUG(5,("spoolss_deleteprinterkey\n"));
9307 if (!Printer) {
9308 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9309 return WERR_BADFID;
9312 /* if keyname == NULL, return error */
9314 if ( !q_u->keyname.buffer )
9315 return WERR_INVALID_PARAM;
9317 if (!get_printer_snum(p, handle, &snum))
9318 return WERR_BADFID;
9320 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9321 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9322 return WERR_ACCESS_DENIED;
9325 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9326 if (!W_ERROR_IS_OK(status))
9327 return status;
9329 /* delete the key and all subneys */
9331 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9333 status = delete_all_printer_data( printer->info_2, key );
9335 if ( W_ERROR_IS_OK(status) )
9336 status = mod_a_printer(printer, 2);
9338 free_a_printer( &printer, 2 );
9340 return status;
9344 /********************************************************************
9345 * spoolss_enumprinterdataex
9346 ********************************************************************/
9348 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9350 POLICY_HND *handle = &q_u->handle;
9351 uint32 in_size = q_u->size;
9352 uint32 num_entries,
9353 needed;
9354 NT_PRINTER_INFO_LEVEL *printer = NULL;
9355 PRINTER_ENUM_VALUES *enum_values = NULL;
9356 NT_PRINTER_DATA *p_data;
9357 fstring key;
9358 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9359 int snum;
9360 WERROR result;
9361 int key_index;
9362 int i;
9363 REGISTRY_VALUE *val;
9364 char *value_name;
9365 uint32 data_len;
9368 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9370 if (!Printer) {
9371 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9372 return WERR_BADFID;
9376 * first check for a keyname of NULL or "". Win2k seems to send
9377 * this a lot and we should send back WERR_INVALID_PARAM
9378 * no need to spend time looking up the printer in this case.
9379 * --jerry
9382 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9383 if ( !strlen(key) ) {
9384 result = WERR_INVALID_PARAM;
9385 goto done;
9388 /* get the printer off of disk */
9390 if (!get_printer_snum(p,handle, &snum))
9391 return WERR_BADFID;
9393 ZERO_STRUCT(printer);
9394 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9395 if (!W_ERROR_IS_OK(result))
9396 return result;
9398 /* now look for a match on the key name */
9400 p_data = printer->info_2->data;
9402 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9403 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9405 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9406 result = WERR_INVALID_PARAM;
9407 goto done;
9410 result = WERR_OK;
9411 needed = 0;
9413 /* allocate the memory for the array of pointers -- if necessary */
9415 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9416 if ( num_entries )
9418 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9420 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9421 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9422 result = WERR_NOMEM;
9423 goto done;
9426 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9430 * loop through all params and build the array to pass
9431 * back to the client
9434 for ( i=0; i<num_entries; i++ )
9436 /* lookup the registry value */
9438 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9439 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9441 /* copy the data */
9443 value_name = regval_name( val );
9444 init_unistr( &enum_values[i].valuename, value_name );
9445 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9446 enum_values[i].type = regval_type( val );
9448 data_len = regval_size( val );
9449 if ( data_len ) {
9450 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9452 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9453 data_len ));
9454 result = WERR_NOMEM;
9455 goto done;
9458 enum_values[i].data_len = data_len;
9460 /* keep track of the size of the array in bytes */
9462 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9465 /* housekeeping information in the reply */
9467 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9468 * the hand marshalled container size is a multiple
9469 * of 4 bytes for RPC alignment.
9472 if (needed % 4) {
9473 needed += 4-(needed % 4);
9476 r_u->needed = needed;
9477 r_u->returned = num_entries;
9479 if (needed > in_size) {
9480 result = WERR_MORE_DATA;
9481 goto done;
9484 /* copy data into the reply */
9486 /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9487 response buffer size is != the offered buffer size
9489 r_u->ctr.size = r_u->needed;
9491 r_u->ctr.size = in_size;
9493 r_u->ctr.size_of_array = r_u->returned;
9494 r_u->ctr.values = enum_values;
9498 done:
9499 if ( printer )
9500 free_a_printer(&printer, 2);
9502 return result;
9505 /****************************************************************************
9506 ****************************************************************************/
9508 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9510 init_unistr(&info->name, name);
9513 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9514 UNISTR2 *environment,
9515 RPC_BUFFER *buffer,
9516 uint32 offered,
9517 uint32 *needed)
9519 pstring path;
9520 pstring long_archi;
9521 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9522 WERROR result = WERR_OK;
9524 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9526 if (!get_short_archi(long_archi))
9527 return WERR_INVALID_ENVIRONMENT;
9529 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9530 return WERR_NOMEM;
9532 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9534 fill_printprocessordirectory_1(info, path);
9536 *needed += spoolss_size_printprocessordirectory_info_1(info);
9538 if (*needed > offered) {
9539 result = WERR_INSUFFICIENT_BUFFER;
9540 goto out;
9543 if (!rpcbuf_alloc_size(buffer, *needed)) {
9544 result = WERR_INSUFFICIENT_BUFFER;
9545 goto out;
9548 smb_io_printprocessordirectory_1("", buffer, info, 0);
9550 out:
9551 SAFE_FREE(info);
9553 return result;
9556 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9558 uint32 level = q_u->level;
9559 RPC_BUFFER *buffer = NULL;
9560 uint32 offered = q_u->offered;
9561 uint32 *needed = &r_u->needed;
9562 WERROR result;
9564 /* that's an [in out] buffer */
9566 if (!q_u->buffer && (offered!=0)) {
9567 return WERR_INVALID_PARAM;
9570 rpcbuf_move(q_u->buffer, &r_u->buffer);
9571 buffer = r_u->buffer;
9573 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9575 *needed=0;
9577 switch(level) {
9578 case 1:
9579 result = getprintprocessordirectory_level_1
9580 (&q_u->name, &q_u->environment, buffer, offered, needed);
9581 break;
9582 default:
9583 result = WERR_UNKNOWN_LEVEL;
9586 return result;
9589 /*******************************************************************
9590 Streams the monitor UI DLL name in UNICODE
9591 *******************************************************************/
9593 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9594 RPC_BUFFER *out, uint32 *needed )
9596 const char *dllname = "tcpmonui.dll";
9598 *needed = (strlen(dllname)+1) * 2;
9600 if ( rpcbuf_get_size(out) < *needed ) {
9601 return WERR_INSUFFICIENT_BUFFER;
9604 if ( !make_monitorui_buf( out, dllname ) ) {
9605 return WERR_NOMEM;
9608 return WERR_OK;
9611 /*******************************************************************
9612 Create a new TCP/IP port
9613 *******************************************************************/
9615 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9616 RPC_BUFFER *out, uint32 *needed )
9618 NT_PORT_DATA_1 port1;
9619 pstring device_uri;
9621 ZERO_STRUCT( port1 );
9623 /* convert to our internal port data structure */
9625 if ( !convert_port_data_1( &port1, in ) ) {
9626 return WERR_NOMEM;
9629 /* create the device URI and call the add_port_hook() */
9631 switch ( port1.protocol ) {
9632 case PORT_PROTOCOL_DIRECT:
9633 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9634 break;
9636 case PORT_PROTOCOL_LPR:
9637 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9638 break;
9640 default:
9641 return WERR_UNKNOWN_PORT;
9644 return add_port_hook( token, port1.name, device_uri );
9647 /*******************************************************************
9648 *******************************************************************/
9650 struct xcv_api_table xcvtcp_cmds[] = {
9651 { "MonitorUI", xcvtcp_monitorui },
9652 { "AddPort", xcvtcp_addport},
9653 { NULL, NULL }
9656 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9657 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9658 uint32 *needed )
9660 int i;
9662 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9664 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9665 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9666 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9669 return WERR_BADFUNC;
9672 /*******************************************************************
9673 *******************************************************************/
9674 #if 0 /* don't support management using the "Local Port" monitor */
9676 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9677 RPC_BUFFER *out, uint32 *needed )
9679 const char *dllname = "localui.dll";
9681 *needed = (strlen(dllname)+1) * 2;
9683 if ( rpcbuf_get_size(out) < *needed ) {
9684 return WERR_INSUFFICIENT_BUFFER;
9687 if ( !make_monitorui_buf( out, dllname )) {
9688 return WERR_NOMEM;
9691 return WERR_OK;
9694 /*******************************************************************
9695 *******************************************************************/
9697 struct xcv_api_table xcvlocal_cmds[] = {
9698 { "MonitorUI", xcvlocal_monitorui },
9699 { NULL, NULL }
9701 #else
9702 struct xcv_api_table xcvlocal_cmds[] = {
9703 { NULL, NULL }
9705 #endif
9709 /*******************************************************************
9710 *******************************************************************/
9712 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9713 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9714 uint32 *needed )
9716 int i;
9718 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9720 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9721 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9722 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9724 return WERR_BADFUNC;
9727 /*******************************************************************
9728 *******************************************************************/
9730 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9732 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9733 fstring command;
9735 if (!Printer) {
9736 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9737 return WERR_BADFID;
9740 /* Has to be a handle to the TCP/IP port monitor */
9742 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9743 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9744 return WERR_BADFID;
9747 /* requires administrative access to the server */
9749 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9750 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9751 return WERR_ACCESS_DENIED;
9754 /* Get the command name. There's numerous commands supported by the
9755 TCPMON interface. */
9757 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9758 q_u->dataname.uni_str_len*2, 0);
9760 /* Allocate the outgoing buffer */
9762 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9764 switch ( Printer->printer_type ) {
9765 case SPLHND_PORTMON_TCP:
9766 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9767 &q_u->indata, &r_u->outdata, &r_u->needed );
9768 case SPLHND_PORTMON_LOCAL:
9769 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9770 &q_u->indata, &r_u->outdata, &r_u->needed );
9773 return WERR_INVALID_PRINT_MONITOR;