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. */
31 extern userdom_struct current_user_info;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 const char *long_archi;
45 const char *short_archi;
49 static Printer_entry *printers_list;
51 typedef struct _counter_printer_0 {
52 struct _counter_printer_0 *next;
53 struct _counter_printer_0 *prev;
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 {
73 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
77 /* translate between internal status numbers and NT status numbers */
78 static int nt_printj_status(int v)
84 return JOB_STATUS_PAUSED;
86 return JOB_STATUS_SPOOLING;
88 return JOB_STATUS_PRINTING;
90 return JOB_STATUS_ERROR;
92 return JOB_STATUS_DELETING;
94 return JOB_STATUS_OFFLINE;
96 return JOB_STATUS_PAPEROUT;
98 return JOB_STATUS_PRINTED;
100 return JOB_STATUS_DELETED;
102 return JOB_STATUS_BLOCKED;
103 case LPQ_USER_INTERVENTION:
104 return JOB_STATUS_USER_INTERVENTION;
109 static int nt_printq_status(int v)
113 return PRINTER_STATUS_PAUSED;
122 /****************************************************************************
123 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
124 ****************************************************************************/
126 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
131 SAFE_FREE((*pp)->ctr.type);
135 /***************************************************************************
136 Disconnect from the client
137 ****************************************************************************/
139 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
144 * Tell the specific printing tdb we no longer want messages for this printer
145 * by deregistering our PID.
148 if (!print_notify_deregister_pid(snum))
149 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
151 /* weird if the test succeds !!! */
152 if (smb_connections==0) {
153 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
157 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
159 if (!W_ERROR_IS_OK(result))
160 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
161 dos_errstr(result)));
163 /* if it's the last connection, deconnect the IPC$ share */
164 if (smb_connections==1) {
166 cli_shutdown( notify_cli_pipe->cli );
167 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
169 message_deregister(MSG_PRINTER_NOTIFY2);
171 /* Tell the connections db we're no longer interested in
172 * printer notify messages. */
174 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
180 /****************************************************************************
181 Functions to free a printer entry datastruct.
182 ****************************************************************************/
184 static void free_printer_entry(void *ptr)
186 Printer_entry *Printer = (Printer_entry *)ptr;
188 if (Printer->notify.client_connected==True) {
191 if ( Printer->printer_type == SPLHND_SERVER) {
193 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
194 } else if (Printer->printer_type == SPLHND_PRINTER) {
195 snum = print_queue_snum(Printer->sharename);
197 srv_spoolss_replycloseprinter(snum,
198 &Printer->notify.client_hnd);
202 Printer->notify.flags=0;
203 Printer->notify.options=0;
204 Printer->notify.localmachine[0]='\0';
205 Printer->notify.printerlocal=0;
206 free_spool_notify_option(&Printer->notify.option);
207 Printer->notify.option=NULL;
208 Printer->notify.client_connected=False;
210 free_nt_devicemode( &Printer->nt_devmode );
211 free_a_printer( &Printer->printer_info, 2 );
213 talloc_destroy( Printer->ctx );
215 /* Remove from the internal list. */
216 DLIST_REMOVE(printers_list, Printer);
221 /****************************************************************************
222 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
223 ****************************************************************************/
225 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
227 SPOOL_NOTIFY_OPTION *new_sp = NULL;
232 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
239 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
241 if (!new_sp->ctr.type) {
250 /****************************************************************************
251 find printer index by handle
252 ****************************************************************************/
254 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
256 Printer_entry *find_printer = NULL;
258 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
259 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
266 /****************************************************************************
267 Close printer index by handle.
268 ****************************************************************************/
270 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
272 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
275 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
279 close_policy_hnd(p, hnd);
284 /****************************************************************************
285 Delete a printer given a handle.
286 ****************************************************************************/
287 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
289 char *cmd = lp_deleteprinter_cmd();
292 SE_PRIV se_printop = SE_PRINT_OPERATOR;
293 BOOL is_print_op = False;
295 /* can't fail if we don't try */
300 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
303 is_print_op = user_has_privileges( token, &se_printop );
305 DEBUG(10,("Running [%s]\n", command));
307 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
312 if ( (ret = smbrun(command, NULL)) == 0 ) {
313 /* Tell everyone we updated smb.conf. */
314 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
320 /********** END SePrintOperatorPrivlege BLOCK **********/
322 DEBUGADD(10,("returned [%d]\n", ret));
325 return WERR_BADFID; /* What to return here? */
327 /* go ahead and re-read the services immediately */
328 reload_services( False );
330 if ( share_defined( sharename ) )
331 return WERR_ACCESS_DENIED;
336 /****************************************************************************
337 Delete a printer given a handle.
338 ****************************************************************************/
340 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
342 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
345 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
350 * It turns out that Windows allows delete printer on a handle
351 * opened by an admin user, then used on a pipe handle created
352 * by an anonymous user..... but they're working on security.... riiight !
356 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
357 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
358 return WERR_ACCESS_DENIED;
361 /* this does not need a become root since the access check has been
362 done on the handle already */
364 if (del_a_printer( Printer->sharename ) != 0) {
365 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
369 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
372 /****************************************************************************
373 Return the snum of a printer corresponding to an handle.
374 ****************************************************************************/
376 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
377 struct share_params **params)
379 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
382 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
386 switch (Printer->printer_type) {
388 DEBUG(4,("short name:%s\n", Printer->sharename));
389 *number = print_queue_snum(Printer->sharename);
390 if ((*number != -1) && (params != NULL)) {
391 *params = get_share_params(tmp_talloc_ctx(),
393 if (*params == NULL) {
397 return (*number != -1);
405 /****************************************************************************
406 Set printer handle type.
407 Check if it's \\server or \\server\printer
408 ****************************************************************************/
410 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
412 DEBUG(3,("Setting printer type=%s\n", handlename));
414 if ( strlen(handlename) < 3 ) {
415 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
419 /* it's a print server */
420 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
421 DEBUGADD(4,("Printer is a print server\n"));
422 Printer->printer_type = SPLHND_SERVER;
424 /* it's a printer (set_printer_hnd_name() will handle port monitors */
426 DEBUGADD(4,("Printer is a printer\n"));
427 Printer->printer_type = SPLHND_PRINTER;
433 /****************************************************************************
434 Set printer handle name.. Accept names like \\server, \\server\printer,
435 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
436 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
437 XcvDataPort() interface.
438 ****************************************************************************/
440 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
443 int n_services=lp_numservices();
444 char *aprinter, *printername;
445 const char *servername;
448 NT_PRINTER_INFO_LEVEL *printer = NULL;
451 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
453 aprinter = handlename;
454 if ( *handlename == '\\' ) {
455 servername = handlename + 2;
456 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
465 /* save the servername to fill in replies on this handle */
467 if ( !is_myname_or_ipaddr( servername ) )
470 fstrcpy( Printer->servername, servername );
472 if ( Printer->printer_type == SPLHND_SERVER )
475 if ( Printer->printer_type != SPLHND_PRINTER )
478 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
480 /* check for the Port Monitor Interface */
482 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
483 Printer->printer_type = SPLHND_PORTMON_TCP;
484 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
487 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
488 Printer->printer_type = SPLHND_PORTMON_LOCAL;
489 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
493 /* Search all sharenames first as this is easier than pulling
494 the printer_info_2 off of disk. Don't use find_service() since
495 that calls out to map_username() */
497 /* do another loop to look for printernames */
499 for (snum=0; !found && snum<n_services; snum++) {
501 /* no point going on if this is not a printer */
503 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
506 fstrcpy(sname, lp_servicename(snum));
507 if ( strequal( aprinter, sname ) ) {
512 /* no point looking up the printer object if
513 we aren't allowing printername != sharename */
515 if ( lp_force_printername(snum) )
518 fstrcpy(sname, lp_servicename(snum));
521 result = get_a_printer( NULL, &printer, 2, sname );
522 if ( !W_ERROR_IS_OK(result) ) {
523 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
524 sname, dos_errstr(result)));
528 /* printername is always returned as \\server\printername */
529 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
530 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
531 printer->info_2->printername));
532 free_a_printer( &printer, 2);
538 if ( strequal(printername, aprinter) ) {
539 free_a_printer( &printer, 2);
544 DEBUGADD(10, ("printername: %s\n", printername));
546 free_a_printer( &printer, 2);
549 free_a_printer( &printer, 2);
552 DEBUGADD(4,("Printer not found\n"));
556 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
558 fstrcpy(Printer->sharename, sname);
563 /****************************************************************************
564 Find first available printer slot. creates a printer handle for you.
565 ****************************************************************************/
567 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
569 Printer_entry *new_printer;
571 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
573 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
576 ZERO_STRUCTP(new_printer);
578 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
579 SAFE_FREE(new_printer);
583 /* Add to the internal list. */
584 DLIST_ADD(printers_list, new_printer);
586 new_printer->notify.option=NULL;
588 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
589 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
590 close_printer_handle(p, hnd);
594 if (!set_printer_hnd_printertype(new_printer, name)) {
595 close_printer_handle(p, hnd);
599 if (!set_printer_hnd_name(new_printer, name)) {
600 close_printer_handle(p, hnd);
604 new_printer->access_granted = access_granted;
606 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
611 /***************************************************************************
612 check to see if the client motify handle is monitoring the notification
613 given by (notify_type, notify_field).
614 **************************************************************************/
616 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
622 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
625 SPOOL_NOTIFY_OPTION *option = p->notify.option;
629 * Flags should always be zero when the change notify
630 * is registered by the client's spooler. A user Win32 app
631 * might use the flags though instead of the NOTIFY_OPTION_INFO
640 return is_monitoring_event_flags(
641 p->notify.flags, notify_type, notify_field);
643 for (i = 0; i < option->count; i++) {
645 /* Check match for notify_type */
647 if (option->ctr.type[i].type != notify_type)
650 /* Check match for field */
652 for (j = 0; j < option->ctr.type[i].count; j++) {
653 if (option->ctr.type[i].fields[j] == notify_field) {
659 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
660 p->servername, p->sharename, notify_type, notify_field));
665 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
667 static void notify_one_value(struct spoolss_notify_msg *msg,
668 SPOOL_NOTIFY_INFO_DATA *data,
671 data->notify_data.value[0] = msg->notify.value[0];
672 data->notify_data.value[1] = 0;
675 static void notify_string(struct spoolss_notify_msg *msg,
676 SPOOL_NOTIFY_INFO_DATA *data,
681 /* The length of the message includes the trailing \0 */
683 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
685 data->notify_data.data.length = msg->len * 2;
686 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
688 if (!data->notify_data.data.string) {
689 data->notify_data.data.length = 0;
693 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
696 static void notify_system_time(struct spoolss_notify_msg *msg,
697 SPOOL_NOTIFY_INFO_DATA *data,
703 if (msg->len != sizeof(time_t)) {
704 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
709 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
710 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
714 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
715 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
720 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
725 data->notify_data.data.length = prs_offset(&ps);
726 data->notify_data.data.string = (uint16 *)
727 TALLOC(mem_ctx, prs_offset(&ps));
728 if (!data->notify_data.data.string) {
733 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
738 struct notify2_message_table {
740 void (*fn)(struct spoolss_notify_msg *msg,
741 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
744 static struct notify2_message_table printer_notify_table[] = {
745 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
746 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
747 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
748 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
749 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
750 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
751 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
752 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
753 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
754 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
755 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
756 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
757 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
758 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
759 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
760 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
761 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
762 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
763 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
766 static struct notify2_message_table job_notify_table[] = {
767 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
768 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
769 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
770 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
771 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
772 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
773 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
774 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
775 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
776 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
777 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
778 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
779 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
780 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
781 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
782 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
783 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
784 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
785 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
786 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
787 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
788 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
789 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
790 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
794 /***********************************************************************
795 Allocate talloc context for container object
796 **********************************************************************/
798 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
803 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
808 /***********************************************************************
809 release all allocated memory and zero out structure
810 **********************************************************************/
812 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
818 talloc_destroy(ctr->ctx);
825 /***********************************************************************
826 **********************************************************************/
828 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
836 /***********************************************************************
837 **********************************************************************/
839 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
841 if ( !ctr || !ctr->msg_groups )
844 if ( idx >= ctr->num_groups )
847 return &ctr->msg_groups[idx];
851 /***********************************************************************
852 How many groups of change messages do we have ?
853 **********************************************************************/
855 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
860 return ctr->num_groups;
863 /***********************************************************************
864 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
865 **********************************************************************/
867 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
869 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
870 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
871 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
877 /* loop over all groups looking for a matching printer name */
879 for ( i=0; i<ctr->num_groups; i++ ) {
880 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
884 /* add a new group? */
886 if ( i == ctr->num_groups ) {
889 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
890 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
893 ctr->msg_groups = groups;
895 /* clear the new entry and set the printer name */
897 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
898 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
901 /* add the change messages; 'i' is the correct index now regardless */
903 msg_grp = &ctr->msg_groups[i];
907 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
908 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
911 msg_grp->msgs = msg_list;
913 new_slot = msg_grp->num_msgs-1;
914 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
916 /* need to allocate own copy of data */
919 msg_grp->msgs[new_slot].notify.data = (char *)
920 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
922 return ctr->num_groups;
925 /***********************************************************************
926 Send a change notication message on all handles which have a call
928 **********************************************************************/
930 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
933 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
934 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
935 SPOOLSS_NOTIFY_MSG *messages;
936 int sending_msg_count;
939 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
943 messages = msg_group->msgs;
946 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
950 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
952 /* loop over all printers */
954 for (p = printers_list; p; p = p->next) {
955 SPOOL_NOTIFY_INFO_DATA *data;
960 /* Is there notification on this handle? */
962 if ( !p->notify.client_connected )
965 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
967 /* For this printer? Print servers always receive
970 if ( ( p->printer_type == SPLHND_PRINTER ) &&
971 ( !strequal(msg_group->printername, p->sharename) ) )
974 DEBUG(10,("Our printer\n"));
976 /* allocate the max entries possible */
978 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
985 /* build the array of change notifications */
987 sending_msg_count = 0;
989 for ( i=0; i<msg_group->num_msgs; i++ ) {
990 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
992 /* Are we monitoring this event? */
994 if (!is_monitoring_event(p, msg->type, msg->field))
1000 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1001 msg->type, msg->field, p->sharename));
1004 * if the is a printer notification handle and not a job notification
1005 * type, then set the id to 0. Other wise just use what was specified
1008 * When registering change notification on a print server handle
1009 * we always need to send back the id (snum) matching the printer
1010 * for which the change took place. For change notify registered
1011 * on a printer handle, this does not matter and the id should be 0.
1016 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1022 /* Convert unix jobid to smb jobid */
1024 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1025 id = sysjob_to_jobid(msg->id);
1028 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1033 construct_info_data( &data[data_len], msg->type, msg->field, id );
1036 case PRINTER_NOTIFY_TYPE:
1037 if ( printer_notify_table[msg->field].fn )
1038 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1041 case JOB_NOTIFY_TYPE:
1042 if ( job_notify_table[msg->field].fn )
1043 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1047 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1054 if ( sending_msg_count ) {
1055 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1056 data_len, data, p->notify.change, 0 );
1061 DEBUG(8,("send_notify2_changes: Exit...\n"));
1065 /***********************************************************************
1066 **********************************************************************/
1068 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1071 uint32 tv_sec, tv_usec;
1074 /* Unpack message */
1076 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1079 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1081 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1084 tdb_unpack((char *)buf + offset, len - offset, "dd",
1085 &msg->notify.value[0], &msg->notify.value[1]);
1087 tdb_unpack((char *)buf + offset, len - offset, "B",
1088 &msg->len, &msg->notify.data);
1090 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1091 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1093 tv->tv_sec = tv_sec;
1094 tv->tv_usec = tv_usec;
1097 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1098 msg->notify.value[1]));
1100 dump_data(3, msg->notify.data, msg->len);
1105 /********************************************************************
1106 Receive a notify2 message list
1107 ********************************************************************/
1109 static void receive_notify2_message_list(int msg_type, struct process_id src,
1110 void *msg, size_t len)
1112 size_t msg_count, i;
1113 char *buf = (char *)msg;
1116 SPOOLSS_NOTIFY_MSG notify;
1117 SPOOLSS_NOTIFY_MSG_CTR messages;
1121 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1125 msg_count = IVAL(buf, 0);
1128 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1130 if (msg_count == 0) {
1131 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1135 /* initialize the container */
1137 ZERO_STRUCT( messages );
1138 notify_msg_ctr_init( &messages );
1141 * build message groups for each printer identified
1142 * in a change_notify msg. Remember that a PCN message
1143 * includes the handle returned for the srv_spoolss_replyopenprinter()
1144 * call. Therefore messages are grouped according to printer handle.
1147 for ( i=0; i<msg_count; i++ ) {
1148 struct timeval msg_tv;
1150 if (msg_ptr + 4 - buf > len) {
1151 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1155 msg_len = IVAL(msg_ptr,0);
1158 if (msg_ptr + msg_len - buf > len) {
1159 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1163 /* unpack messages */
1165 ZERO_STRUCT( notify );
1166 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1169 /* add to correct list in container */
1171 notify_msg_ctr_addmsg( &messages, ¬ify );
1173 /* free memory that might have been allocated by notify2_unpack_msg() */
1175 if ( notify.len != 0 )
1176 SAFE_FREE( notify.notify.data );
1179 /* process each group of messages */
1181 num_groups = notify_msg_ctr_numgroups( &messages );
1182 for ( i=0; i<num_groups; i++ )
1183 send_notify2_changes( &messages, i );
1188 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1190 notify_msg_ctr_destroy( &messages );
1195 /********************************************************************
1196 Send a message to ourself about new driver being installed
1197 so we can upgrade the information for each printer bound to this
1199 ********************************************************************/
1201 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1203 int len = strlen(drivername);
1208 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1211 message_send_pid(pid_to_procid(sys_getpid()),
1212 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1217 /**********************************************************************
1218 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1219 over all printers, upgrading ones as necessary
1220 **********************************************************************/
1222 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1226 int n_services = lp_numservices();
1228 len = MIN(len,sizeof(drivername)-1);
1229 strncpy(drivername, (const char *)buf, len);
1231 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1233 /* Iterate the printer list */
1235 for (snum=0; snum<n_services; snum++)
1237 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1240 NT_PRINTER_INFO_LEVEL *printer = NULL;
1242 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1243 if (!W_ERROR_IS_OK(result))
1246 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1248 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1250 /* all we care about currently is the change_id */
1252 result = mod_a_printer(printer, 2);
1253 if (!W_ERROR_IS_OK(result)) {
1254 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1255 dos_errstr(result)));
1259 free_a_printer(&printer, 2);
1266 /********************************************************************
1267 Update the cache for all printq's with a registered client
1269 ********************************************************************/
1271 void update_monitored_printq_cache( void )
1273 Printer_entry *printer = printers_list;
1276 /* loop through all printers and update the cache where
1277 client_connected == True */
1280 if ( (printer->printer_type == SPLHND_PRINTER)
1281 && printer->notify.client_connected )
1283 snum = print_queue_snum(printer->sharename);
1284 print_queue_status( snum, NULL, NULL );
1287 printer = printer->next;
1292 /********************************************************************
1293 Send a message to ourself about new driver being installed
1294 so we can upgrade the information for each printer bound to this
1296 ********************************************************************/
1298 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1300 int len = strlen(drivername);
1305 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1308 message_send_pid(pid_to_procid(sys_getpid()),
1309 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1314 /**********************************************************************
1315 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1316 over all printers, resetting printer data as neessary
1317 **********************************************************************/
1319 void reset_all_printerdata(int msg_type, struct process_id src,
1320 void *buf, size_t len)
1324 int n_services = lp_numservices();
1326 len = MIN( len, sizeof(drivername)-1 );
1327 strncpy( drivername, (const char *)buf, len );
1329 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1331 /* Iterate the printer list */
1333 for ( snum=0; snum<n_services; snum++ )
1335 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1338 NT_PRINTER_INFO_LEVEL *printer = NULL;
1340 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1341 if ( !W_ERROR_IS_OK(result) )
1345 * if the printer is bound to the driver,
1346 * then reset to the new driver initdata
1349 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1351 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1353 if ( !set_driver_init(printer, 2) ) {
1354 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1355 printer->info_2->printername, printer->info_2->drivername));
1358 result = mod_a_printer( printer, 2 );
1359 if ( !W_ERROR_IS_OK(result) ) {
1360 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1361 get_dos_error_msg(result)));
1365 free_a_printer( &printer, 2 );
1374 /********************************************************************
1375 Copy routines used by convert_to_openprinterex()
1376 *******************************************************************/
1378 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1386 DEBUG (8,("dup_devmode\n"));
1388 /* bulk copy first */
1390 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1394 /* dup the pointer members separately */
1396 len = unistrlen(devmode->devicename.buffer);
1398 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1399 if (!d->devicename.buffer) {
1402 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1407 len = unistrlen(devmode->formname.buffer);
1409 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1410 if (!d->devicename.buffer) {
1413 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1417 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1418 devmode->driverextra);
1419 if (!d->dev_private) {
1425 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1427 if (!new_ctr || !ctr)
1430 DEBUG(8,("copy_devmode_ctr\n"));
1432 new_ctr->size = ctr->size;
1433 new_ctr->devmode_ptr = ctr->devmode_ptr;
1435 if(ctr->devmode_ptr)
1436 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1439 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1441 if (!new_def || !def)
1444 DEBUG(8,("copy_printer_defaults\n"));
1446 new_def->datatype_ptr = def->datatype_ptr;
1448 if (def->datatype_ptr)
1449 copy_unistr2(&new_def->datatype, &def->datatype);
1451 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1453 new_def->access_required = def->access_required;
1456 /********************************************************************
1457 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1458 * SPOOL_Q_OPEN_PRINTER_EX structure
1459 ********************************************************************/
1461 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1463 if (!q_u_ex || !q_u)
1466 DEBUG(8,("convert_to_openprinterex\n"));
1468 if ( q_u->printername ) {
1469 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1470 if (q_u_ex->printername == NULL)
1472 copy_unistr2(q_u_ex->printername, q_u->printername);
1475 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1480 /********************************************************************
1481 * spoolss_open_printer
1483 * called from the spoolss dispatcher
1484 ********************************************************************/
1486 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1488 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1489 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1494 ZERO_STRUCT(q_u_ex);
1495 ZERO_STRUCT(r_u_ex);
1497 /* convert the OpenPrinter() call to OpenPrinterEx() */
1499 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1500 if (!W_ERROR_IS_OK(r_u_ex.status))
1501 return r_u_ex.status;
1503 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1505 /* convert back to OpenPrinter() */
1507 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1512 /********************************************************************
1513 ********************************************************************/
1515 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1517 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1518 POLICY_HND *handle = &r_u->handle;
1522 Printer_entry *Printer=NULL;
1524 if ( !q_u->printername )
1525 return WERR_INVALID_PRINTER_NAME;
1527 /* some sanity check because you can open a printer or a print server */
1528 /* aka: \\server\printer or \\server */
1530 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1532 DEBUGADD(3,("checking name: %s\n",name));
1534 if (!open_printer_hnd(p, handle, name, 0))
1535 return WERR_INVALID_PRINTER_NAME;
1537 Printer=find_printer_index_by_hnd(p, handle);
1539 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1540 "handle we created for printer %s\n", name ));
1541 close_printer_handle(p,handle);
1542 return WERR_INVALID_PRINTER_NAME;
1546 * First case: the user is opening the print server:
1548 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1549 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1551 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1552 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1553 * or if the user is listed in the smb.conf printer admin parameter.
1555 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1556 * client view printer folder, but does not show the MSAPW.
1558 * Note: this test needs code to check access rights here too. Jeremy
1559 * could you look at this?
1561 * Second case: the user is opening a printer:
1562 * NT doesn't let us connect to a printer if the connecting user
1563 * doesn't have print permission.
1565 * Third case: user is opening a Port Monitor
1566 * access checks same as opening a handle to the print server.
1569 switch (Printer->printer_type )
1572 case SPLHND_PORTMON_TCP:
1573 case SPLHND_PORTMON_LOCAL:
1574 /* Printserver handles use global struct... */
1578 /* Map standard access rights to object specific access rights */
1580 se_map_standard(&printer_default->access_required,
1581 &printserver_std_mapping);
1583 /* Deny any object specific bits that don't apply to print
1584 servers (i.e printer and job specific bits) */
1586 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1588 if (printer_default->access_required &
1589 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1590 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1591 close_printer_handle(p, handle);
1592 return WERR_ACCESS_DENIED;
1595 /* Allow admin access */
1597 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1599 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1601 if (!lp_ms_add_printer_wizard()) {
1602 close_printer_handle(p, handle);
1603 return WERR_ACCESS_DENIED;
1606 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1607 and not a printer admin, then fail */
1609 if ((p->pipe_user.ut.uid != 0) &&
1610 !user_has_privileges(p->pipe_user.nt_user_token,
1612 !token_contains_name_in_list(
1613 uidtoname(p->pipe_user.ut.uid), NULL,
1614 p->pipe_user.nt_user_token,
1615 lp_printer_admin(snum))) {
1616 close_printer_handle(p, handle);
1617 return WERR_ACCESS_DENIED;
1620 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1624 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1627 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1628 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1630 /* We fall through to return WERR_OK */
1633 case SPLHND_PRINTER:
1634 /* NT doesn't let us connect to a printer if the connecting user
1635 doesn't have print permission. */
1637 if (!get_printer_snum(p, handle, &snum, NULL)) {
1638 close_printer_handle(p, handle);
1642 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1644 /* map an empty access mask to the minimum access mask */
1645 if (printer_default->access_required == 0x0)
1646 printer_default->access_required = PRINTER_ACCESS_USE;
1649 * If we are not serving the printer driver for this printer,
1650 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1651 * will keep NT clients happy --jerry
1654 if (lp_use_client_driver(snum)
1655 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1657 printer_default->access_required = PRINTER_ACCESS_USE;
1660 /* check smb.conf parameters and the the sec_desc */
1662 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1663 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1664 return WERR_ACCESS_DENIED;
1667 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1668 p->pipe_user.nt_user_token, snum) ||
1669 !print_access_check(&p->pipe_user, snum,
1670 printer_default->access_required)) {
1671 DEBUG(3, ("access DENIED for printer open\n"));
1672 close_printer_handle(p, handle);
1673 return WERR_ACCESS_DENIED;
1676 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1677 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1678 close_printer_handle(p, handle);
1679 return WERR_ACCESS_DENIED;
1682 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1683 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1685 printer_default->access_required = PRINTER_ACCESS_USE;
1687 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1688 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1693 /* sanity check to prevent programmer error */
1697 Printer->access_granted = printer_default->access_required;
1700 * If the client sent a devmode in the OpenPrinter() call, then
1701 * save it here in case we get a job submission on this handle
1704 if ( (Printer->printer_type != SPLHND_SERVER)
1705 && q_u->printer_default.devmode_cont.devmode_ptr )
1707 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1708 &Printer->nt_devmode );
1711 #if 0 /* JERRY -- I'm doubtful this is really effective */
1712 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1713 optimization in Windows 2000 clients --jerry */
1715 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1716 && (RA_WIN2K == get_remote_arch()) )
1718 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1719 sys_usleep( 500000 );
1726 /****************************************************************************
1727 ****************************************************************************/
1729 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1730 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1736 /* allocate memory if needed. Messy because
1737 convert_printer_info is used to update an existing
1738 printer or build a new one */
1740 if ( !printer->info_2 ) {
1741 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1742 if ( !printer->info_2 ) {
1743 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1748 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1749 printer->info_2->setuptime = time(NULL);
1757 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1758 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1764 printer->info_3=NULL;
1765 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1769 printer->info_6=NULL;
1770 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1780 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1781 NT_DEVICEMODE **pp_nt_devmode)
1783 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1786 * Ensure nt_devmode is a valid pointer
1787 * as we will be overwriting it.
1790 if (nt_devmode == NULL) {
1791 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1792 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1796 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1797 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1799 nt_devmode->specversion=devmode->specversion;
1800 nt_devmode->driverversion=devmode->driverversion;
1801 nt_devmode->size=devmode->size;
1802 nt_devmode->fields=devmode->fields;
1803 nt_devmode->orientation=devmode->orientation;
1804 nt_devmode->papersize=devmode->papersize;
1805 nt_devmode->paperlength=devmode->paperlength;
1806 nt_devmode->paperwidth=devmode->paperwidth;
1807 nt_devmode->scale=devmode->scale;
1808 nt_devmode->copies=devmode->copies;
1809 nt_devmode->defaultsource=devmode->defaultsource;
1810 nt_devmode->printquality=devmode->printquality;
1811 nt_devmode->color=devmode->color;
1812 nt_devmode->duplex=devmode->duplex;
1813 nt_devmode->yresolution=devmode->yresolution;
1814 nt_devmode->ttoption=devmode->ttoption;
1815 nt_devmode->collate=devmode->collate;
1817 nt_devmode->logpixels=devmode->logpixels;
1818 nt_devmode->bitsperpel=devmode->bitsperpel;
1819 nt_devmode->pelswidth=devmode->pelswidth;
1820 nt_devmode->pelsheight=devmode->pelsheight;
1821 nt_devmode->displayflags=devmode->displayflags;
1822 nt_devmode->displayfrequency=devmode->displayfrequency;
1823 nt_devmode->icmmethod=devmode->icmmethod;
1824 nt_devmode->icmintent=devmode->icmintent;
1825 nt_devmode->mediatype=devmode->mediatype;
1826 nt_devmode->dithertype=devmode->dithertype;
1827 nt_devmode->reserved1=devmode->reserved1;
1828 nt_devmode->reserved2=devmode->reserved2;
1829 nt_devmode->panningwidth=devmode->panningwidth;
1830 nt_devmode->panningheight=devmode->panningheight;
1833 * Only change private and driverextra if the incoming devmode
1834 * has a new one. JRA.
1837 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1838 SAFE_FREE(nt_devmode->nt_dev_private);
1839 nt_devmode->driverextra=devmode->driverextra;
1840 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1842 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1845 *pp_nt_devmode = nt_devmode;
1850 /********************************************************************
1851 * _spoolss_enddocprinter_internal.
1852 ********************************************************************/
1854 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1856 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1860 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1864 if (!get_printer_snum(p, handle, &snum, NULL))
1867 Printer->document_started=False;
1868 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1869 /* error codes unhandled so far ... */
1874 /********************************************************************
1875 * api_spoolss_closeprinter
1876 ********************************************************************/
1878 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1880 POLICY_HND *handle = &q_u->handle;
1882 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1884 if (Printer && Printer->document_started)
1885 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1887 if (!close_printer_handle(p, handle))
1890 /* clear the returned printer handle. Observed behavior
1891 from Win2k server. Don't think this really matters.
1892 Previous code just copied the value of the closed
1895 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1900 /********************************************************************
1901 * api_spoolss_deleteprinter
1903 ********************************************************************/
1905 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1907 POLICY_HND *handle = &q_u->handle;
1908 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1911 if (Printer && Printer->document_started)
1912 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1914 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1916 result = delete_printer_handle(p, handle);
1918 update_c_setprinter(False);
1923 /*******************************************************************
1924 * static function to lookup the version id corresponding to an
1925 * long architecture string
1926 ******************************************************************/
1928 static int get_version_id (char * arch)
1931 struct table_node archi_table[]= {
1933 {"Windows 4.0", "WIN40", 0 },
1934 {"Windows NT x86", "W32X86", 2 },
1935 {"Windows NT R4000", "W32MIPS", 2 },
1936 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1937 {"Windows NT PowerPC", "W32PPC", 2 },
1938 {"Windows IA64", "IA64", 3 },
1939 {"Windows x64", "x64", 3 },
1943 for (i=0; archi_table[i].long_archi != NULL; i++)
1945 if (strcmp(arch, archi_table[i].long_archi) == 0)
1946 return (archi_table[i].version);
1952 /********************************************************************
1953 * _spoolss_deleteprinterdriver
1954 ********************************************************************/
1956 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1960 NT_PRINTER_DRIVER_INFO_LEVEL info;
1961 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1964 WERROR status_win2k = WERR_ACCESS_DENIED;
1965 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1967 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1968 and not a printer admin, then fail */
1970 if ( (p->pipe_user.ut.uid != 0)
1971 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
1972 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
1973 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
1975 return WERR_ACCESS_DENIED;
1978 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1979 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1981 /* check that we have a valid driver name first */
1983 if ((version=get_version_id(arch)) == -1)
1984 return WERR_INVALID_ENVIRONMENT;
1987 ZERO_STRUCT(info_win2k);
1989 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1991 /* try for Win2k driver if "Windows NT x86" */
1993 if ( version == 2 ) {
1995 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1996 status = WERR_UNKNOWN_PRINTER_DRIVER;
2000 /* otherwise it was a failure */
2002 status = WERR_UNKNOWN_PRINTER_DRIVER;
2008 if (printer_driver_in_use(info.info_3)) {
2009 status = WERR_PRINTER_DRIVER_IN_USE;
2015 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2017 /* if we get to here, we now have 2 driver info structures to remove */
2018 /* remove the Win2k driver first*/
2020 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2021 free_a_printer_driver( info_win2k, 3 );
2023 /* this should not have failed---if it did, report to client */
2024 if ( !W_ERROR_IS_OK(status_win2k) )
2026 status = status_win2k;
2032 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2034 /* if at least one of the deletes succeeded return OK */
2036 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2040 free_a_printer_driver( info, 3 );
2045 /********************************************************************
2046 * spoolss_deleteprinterdriverex
2047 ********************************************************************/
2049 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2053 NT_PRINTER_DRIVER_INFO_LEVEL info;
2054 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2056 uint32 flags = q_u->delete_flags;
2059 WERROR status_win2k = WERR_ACCESS_DENIED;
2060 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2062 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2063 and not a printer admin, then fail */
2065 if ( (p->pipe_user.ut.uid != 0)
2066 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2067 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2068 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2070 return WERR_ACCESS_DENIED;
2073 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2074 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2076 /* check that we have a valid driver name first */
2077 if ((version=get_version_id(arch)) == -1) {
2078 /* this is what NT returns */
2079 return WERR_INVALID_ENVIRONMENT;
2082 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2083 version = q_u->version;
2086 ZERO_STRUCT(info_win2k);
2088 status = get_a_printer_driver(&info, 3, driver, arch, version);
2090 if ( !W_ERROR_IS_OK(status) )
2093 * if the client asked for a specific version,
2094 * or this is something other than Windows NT x86,
2098 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2101 /* try for Win2k driver if "Windows NT x86" */
2104 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2105 status = WERR_UNKNOWN_PRINTER_DRIVER;
2110 if ( printer_driver_in_use(info.info_3) ) {
2111 status = WERR_PRINTER_DRIVER_IN_USE;
2116 * we have a couple of cases to consider.
2117 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2118 * then the delete should fail if **any** files overlap with
2120 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2121 * non-overlapping files
2122 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2123 * is set, the do not delete any files
2124 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2127 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2129 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2131 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2132 /* no idea of the correct error here */
2133 status = WERR_ACCESS_DENIED;
2138 /* also check for W32X86/3 if necessary; maybe we already have? */
2140 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2141 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2144 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2145 /* no idea of the correct error here */
2146 free_a_printer_driver( info_win2k, 3 );
2147 status = WERR_ACCESS_DENIED;
2151 /* if we get to here, we now have 2 driver info structures to remove */
2152 /* remove the Win2k driver first*/
2154 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2155 free_a_printer_driver( info_win2k, 3 );
2157 /* this should not have failed---if it did, report to client */
2159 if ( !W_ERROR_IS_OK(status_win2k) )
2164 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2166 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2169 free_a_printer_driver( info, 3 );
2175 /****************************************************************************
2176 Internal routine for retreiving printerdata
2177 ***************************************************************************/
2179 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2180 const char *key, const char *value, uint32 *type, uint8 **data,
2181 uint32 *needed, uint32 in_size )
2183 REGISTRY_VALUE *val;
2187 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2188 return WERR_BADFILE;
2190 *type = regval_type( val );
2192 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2194 size = regval_size( val );
2196 /* copy the min(in_size, len) */
2199 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2201 /* special case for 0 length values */
2203 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2207 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2216 DEBUG(5,("get_printer_dataex: copy done\n"));
2221 /****************************************************************************
2222 Internal routine for removing printerdata
2223 ***************************************************************************/
2225 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2227 return delete_printer_data( printer->info_2, key, value );
2230 /****************************************************************************
2231 Internal routine for storing printerdata
2232 ***************************************************************************/
2234 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2235 uint32 type, uint8 *data, int real_len )
2237 /* the registry objects enforce uniqueness based on value name */
2239 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2242 /********************************************************************
2243 GetPrinterData on a printer server Handle.
2244 ********************************************************************/
2246 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2250 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2252 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2254 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2260 if (!StrCaseCmp(value, "BeepEnabled")) {
2262 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2264 SIVAL(*data, 0, 0x00);
2269 if (!StrCaseCmp(value, "EventLog")) {
2271 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2273 /* formally was 0x1b */
2274 SIVAL(*data, 0, 0x0);
2279 if (!StrCaseCmp(value, "NetPopup")) {
2281 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2283 SIVAL(*data, 0, 0x00);
2288 if (!StrCaseCmp(value, "MajorVersion")) {
2290 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2293 /* Windows NT 4.0 seems to not allow uploading of drivers
2294 to a server that reports 0x3 as the MajorVersion.
2295 need to investigate more how Win2k gets around this .
2298 if ( RA_WINNT == get_remote_arch() )
2307 if (!StrCaseCmp(value, "MinorVersion")) {
2309 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2317 * uint32 size = 0x114
2319 * uint32 minor = [0|1]
2320 * uint32 build = [2195|2600]
2321 * extra unicode string = e.g. "Service Pack 3"
2323 if (!StrCaseCmp(value, "OSVersion")) {
2327 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2330 SIVAL(*data, 0, *needed); /* size */
2331 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2333 SIVAL(*data, 12, 2195); /* build */
2335 /* leave extra string empty */
2341 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2342 const char *string="C:\\PRINTERS";
2344 *needed = 2*(strlen(string)+1);
2345 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2347 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2349 /* it's done by hand ready to go on the wire */
2350 for (i=0; i<strlen(string); i++) {
2351 (*data)[2*i]=string[i];
2352 (*data)[2*i+1]='\0';
2357 if (!StrCaseCmp(value, "Architecture")) {
2358 const char *string="Windows NT x86";
2360 *needed = 2*(strlen(string)+1);
2361 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2363 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2364 for (i=0; i<strlen(string); i++) {
2365 (*data)[2*i]=string[i];
2366 (*data)[2*i+1]='\0';
2371 if (!StrCaseCmp(value, "DsPresent")) {
2373 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2376 /* only show the publish check box if we are a
2377 memeber of a AD domain */
2379 if ( lp_security() == SEC_ADS )
2380 SIVAL(*data, 0, 0x01);
2382 SIVAL(*data, 0, 0x00);
2388 if (!StrCaseCmp(value, "DNSMachineName")) {
2391 if (!get_mydnsfullname(hostname))
2392 return WERR_BADFILE;
2394 *needed = 2*(strlen(hostname)+1);
2395 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2397 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2398 for (i=0; i<strlen(hostname); i++) {
2399 (*data)[2*i]=hostname[i];
2400 (*data)[2*i+1]='\0';
2406 return WERR_BADFILE;
2409 /********************************************************************
2410 * spoolss_getprinterdata
2411 ********************************************************************/
2413 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2415 POLICY_HND *handle = &q_u->handle;
2416 UNISTR2 *valuename = &q_u->valuename;
2417 uint32 in_size = q_u->size;
2418 uint32 *type = &r_u->type;
2419 uint32 *out_size = &r_u->size;
2420 uint8 **data = &r_u->data;
2421 uint32 *needed = &r_u->needed;
2424 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2425 NT_PRINTER_INFO_LEVEL *printer = NULL;
2429 * Reminder: when it's a string, the length is in BYTES
2430 * even if UNICODE is negociated.
2435 *out_size = in_size;
2437 /* in case of problem, return some default values */
2442 DEBUG(4,("_spoolss_getprinterdata\n"));
2445 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2446 status = WERR_BADFID;
2450 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2452 if ( Printer->printer_type == SPLHND_SERVER )
2453 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2456 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2457 status = WERR_BADFID;
2461 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2462 if ( !W_ERROR_IS_OK(status) )
2465 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2467 if ( strequal(value, "ChangeId") ) {
2469 *needed = sizeof(uint32);
2470 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2471 status = WERR_NOMEM;
2474 SIVAL( *data, 0, printer->info_2->changeid );
2478 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2481 if (*needed > *out_size)
2482 status = WERR_MORE_DATA;
2485 if ( !W_ERROR_IS_OK(status) )
2487 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2489 /* reply this param doesn't exist */
2492 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2494 free_a_printer( &printer, 2 );
2503 /* cleanup & exit */
2506 free_a_printer( &printer, 2 );
2511 /*********************************************************
2512 Connect to the client machine.
2513 **********************************************************/
2515 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2516 struct in_addr *client_ip, const char *remote_machine)
2519 struct cli_state *the_cli;
2520 struct in_addr rm_addr;
2522 if ( is_zero_ip(*client_ip) ) {
2523 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2524 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2528 if ( ismyip( rm_addr )) {
2529 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2533 rm_addr.s_addr = client_ip->s_addr;
2534 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2535 inet_ntoa(*client_ip) ));
2538 /* setup the connection */
2540 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2541 &rm_addr, 0, "IPC$", "IPC",
2545 0, lp_client_signing(), NULL );
2547 if ( !NT_STATUS_IS_OK( ret ) ) {
2548 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2553 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2554 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2555 cli_shutdown(the_cli);
2560 * Ok - we have an anonymous connection to the IPC$ share.
2561 * Now start the NT Domain stuff :-).
2564 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2565 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2566 remote_machine, nt_errstr(ret)));
2567 cli_shutdown(the_cli);
2571 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2573 (*pp_pipe)->cli = the_cli;
2578 /***************************************************************************
2579 Connect to the client.
2580 ****************************************************************************/
2582 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2583 uint32 localprinter, uint32 type,
2584 POLICY_HND *handle, struct in_addr *client_ip)
2589 * If it's the first connection, contact the client
2590 * and connect to the IPC$ share anonymously
2592 if (smb_connections==0) {
2593 fstring unix_printer;
2595 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2597 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2600 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2601 /* Tell the connections db we're now interested in printer
2602 * notify messages. */
2603 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2607 * Tell the specific printing tdb we want messages for this printer
2608 * by registering our PID.
2611 if (!print_notify_register_pid(snum))
2612 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2616 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2619 if (!W_ERROR_IS_OK(result))
2620 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2621 dos_errstr(result)));
2623 return (W_ERROR_IS_OK(result));
2626 /********************************************************************
2628 * ReplyFindFirstPrinterChangeNotifyEx
2630 * before replying OK: status=0 a rpc call is made to the workstation
2631 * asking ReplyOpenPrinter
2633 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2634 * called from api_spoolss_rffpcnex
2635 ********************************************************************/
2637 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2639 POLICY_HND *handle = &q_u->handle;
2640 uint32 flags = q_u->flags;
2641 uint32 options = q_u->options;
2642 UNISTR2 *localmachine = &q_u->localmachine;
2643 uint32 printerlocal = q_u->printerlocal;
2645 SPOOL_NOTIFY_OPTION *option = q_u->option;
2646 struct in_addr client_ip;
2648 /* store the notify value in the printer struct */
2650 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2653 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2657 Printer->notify.flags=flags;
2658 Printer->notify.options=options;
2659 Printer->notify.printerlocal=printerlocal;
2661 if (Printer->notify.option)
2662 free_spool_notify_option(&Printer->notify.option);
2664 Printer->notify.option=dup_spool_notify_option(option);
2666 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2667 sizeof(Printer->notify.localmachine)-1);
2669 /* Connect to the client machine and send a ReplyOpenPrinter */
2671 if ( Printer->printer_type == SPLHND_SERVER)
2673 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2674 !get_printer_snum(p, handle, &snum, NULL) )
2677 client_ip.s_addr = inet_addr(p->conn->client_address);
2679 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2680 Printer->notify.printerlocal, 1,
2681 &Printer->notify.client_hnd, &client_ip))
2682 return WERR_SERVER_UNAVAILABLE;
2684 Printer->notify.client_connected=True;
2689 /*******************************************************************
2690 * fill a notify_info_data with the servername
2691 ********************************************************************/
2693 void spoolss_notify_server_name(int snum,
2694 SPOOL_NOTIFY_INFO_DATA *data,
2695 print_queue_struct *queue,
2696 NT_PRINTER_INFO_LEVEL *printer,
2697 TALLOC_CTX *mem_ctx)
2702 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2704 data->notify_data.data.length = len;
2705 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2707 if (!data->notify_data.data.string) {
2708 data->notify_data.data.length = 0;
2712 memcpy(data->notify_data.data.string, temp, len);
2715 /*******************************************************************
2716 * fill a notify_info_data with the printername (not including the servername).
2717 ********************************************************************/
2719 void spoolss_notify_printer_name(int snum,
2720 SPOOL_NOTIFY_INFO_DATA *data,
2721 print_queue_struct *queue,
2722 NT_PRINTER_INFO_LEVEL *printer,
2723 TALLOC_CTX *mem_ctx)
2728 /* the notify name should not contain the \\server\ part */
2729 char *p = strrchr(printer->info_2->printername, '\\');
2732 p = printer->info_2->printername;
2737 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2739 data->notify_data.data.length = len;
2740 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2742 if (!data->notify_data.data.string) {
2743 data->notify_data.data.length = 0;
2747 memcpy(data->notify_data.data.string, temp, len);
2750 /*******************************************************************
2751 * fill a notify_info_data with the servicename
2752 ********************************************************************/
2754 void spoolss_notify_share_name(int snum,
2755 SPOOL_NOTIFY_INFO_DATA *data,
2756 print_queue_struct *queue,
2757 NT_PRINTER_INFO_LEVEL *printer,
2758 TALLOC_CTX *mem_ctx)
2763 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2765 data->notify_data.data.length = len;
2766 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2768 if (!data->notify_data.data.string) {
2769 data->notify_data.data.length = 0;
2773 memcpy(data->notify_data.data.string, temp, len);
2776 /*******************************************************************
2777 * fill a notify_info_data with the port name
2778 ********************************************************************/
2780 void spoolss_notify_port_name(int snum,
2781 SPOOL_NOTIFY_INFO_DATA *data,
2782 print_queue_struct *queue,
2783 NT_PRINTER_INFO_LEVEL *printer,
2784 TALLOC_CTX *mem_ctx)
2789 /* even if it's strange, that's consistant in all the code */
2791 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2793 data->notify_data.data.length = len;
2794 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2796 if (!data->notify_data.data.string) {
2797 data->notify_data.data.length = 0;
2801 memcpy(data->notify_data.data.string, temp, len);
2804 /*******************************************************************
2805 * fill a notify_info_data with the printername
2806 * but it doesn't exist, have to see what to do
2807 ********************************************************************/
2809 void spoolss_notify_driver_name(int snum,
2810 SPOOL_NOTIFY_INFO_DATA *data,
2811 print_queue_struct *queue,
2812 NT_PRINTER_INFO_LEVEL *printer,
2813 TALLOC_CTX *mem_ctx)
2818 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2820 data->notify_data.data.length = len;
2821 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2823 if (!data->notify_data.data.string) {
2824 data->notify_data.data.length = 0;
2828 memcpy(data->notify_data.data.string, temp, len);
2831 /*******************************************************************
2832 * fill a notify_info_data with the comment
2833 ********************************************************************/
2835 void spoolss_notify_comment(int snum,
2836 SPOOL_NOTIFY_INFO_DATA *data,
2837 print_queue_struct *queue,
2838 NT_PRINTER_INFO_LEVEL *printer,
2839 TALLOC_CTX *mem_ctx)
2844 if (*printer->info_2->comment == '\0')
2845 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2847 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2849 data->notify_data.data.length = len;
2850 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2852 if (!data->notify_data.data.string) {
2853 data->notify_data.data.length = 0;
2857 memcpy(data->notify_data.data.string, temp, len);
2860 /*******************************************************************
2861 * fill a notify_info_data with the comment
2862 * location = "Room 1, floor 2, building 3"
2863 ********************************************************************/
2865 void spoolss_notify_location(int snum,
2866 SPOOL_NOTIFY_INFO_DATA *data,
2867 print_queue_struct *queue,
2868 NT_PRINTER_INFO_LEVEL *printer,
2869 TALLOC_CTX *mem_ctx)
2874 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2876 data->notify_data.data.length = len;
2877 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2879 if (!data->notify_data.data.string) {
2880 data->notify_data.data.length = 0;
2884 memcpy(data->notify_data.data.string, temp, len);
2887 /*******************************************************************
2888 * fill a notify_info_data with the device mode
2889 * jfm:xxxx don't to it for know but that's a real problem !!!
2890 ********************************************************************/
2892 static void spoolss_notify_devmode(int snum,
2893 SPOOL_NOTIFY_INFO_DATA *data,
2894 print_queue_struct *queue,
2895 NT_PRINTER_INFO_LEVEL *printer,
2896 TALLOC_CTX *mem_ctx)
2898 /* for a dummy implementation we have to zero the fields */
2899 data->notify_data.data.length = 0;
2900 data->notify_data.data.string = NULL;
2903 /*******************************************************************
2904 * fill a notify_info_data with the separator file name
2905 ********************************************************************/
2907 void spoolss_notify_sepfile(int snum,
2908 SPOOL_NOTIFY_INFO_DATA *data,
2909 print_queue_struct *queue,
2910 NT_PRINTER_INFO_LEVEL *printer,
2911 TALLOC_CTX *mem_ctx)
2916 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2918 data->notify_data.data.length = len;
2919 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2921 if (!data->notify_data.data.string) {
2922 data->notify_data.data.length = 0;
2926 memcpy(data->notify_data.data.string, temp, len);
2929 /*******************************************************************
2930 * fill a notify_info_data with the print processor
2931 * jfm:xxxx return always winprint to indicate we don't do anything to it
2932 ********************************************************************/
2934 void spoolss_notify_print_processor(int snum,
2935 SPOOL_NOTIFY_INFO_DATA *data,
2936 print_queue_struct *queue,
2937 NT_PRINTER_INFO_LEVEL *printer,
2938 TALLOC_CTX *mem_ctx)
2943 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2945 data->notify_data.data.length = len;
2946 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2948 if (!data->notify_data.data.string) {
2949 data->notify_data.data.length = 0;
2953 memcpy(data->notify_data.data.string, temp, len);
2956 /*******************************************************************
2957 * fill a notify_info_data with the print processor options
2958 * jfm:xxxx send an empty string
2959 ********************************************************************/
2961 void spoolss_notify_parameters(int snum,
2962 SPOOL_NOTIFY_INFO_DATA *data,
2963 print_queue_struct *queue,
2964 NT_PRINTER_INFO_LEVEL *printer,
2965 TALLOC_CTX *mem_ctx)
2970 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2972 data->notify_data.data.length = len;
2973 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2975 if (!data->notify_data.data.string) {
2976 data->notify_data.data.length = 0;
2980 memcpy(data->notify_data.data.string, temp, len);
2983 /*******************************************************************
2984 * fill a notify_info_data with the data type
2985 * jfm:xxxx always send RAW as data type
2986 ********************************************************************/
2988 void spoolss_notify_datatype(int snum,
2989 SPOOL_NOTIFY_INFO_DATA *data,
2990 print_queue_struct *queue,
2991 NT_PRINTER_INFO_LEVEL *printer,
2992 TALLOC_CTX *mem_ctx)
2997 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2999 data->notify_data.data.length = len;
3000 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3002 if (!data->notify_data.data.string) {
3003 data->notify_data.data.length = 0;
3007 memcpy(data->notify_data.data.string, temp, len);
3010 /*******************************************************************
3011 * fill a notify_info_data with the security descriptor
3012 * jfm:xxxx send an null pointer to say no security desc
3013 * have to implement security before !
3014 ********************************************************************/
3016 static void spoolss_notify_security_desc(int snum,
3017 SPOOL_NOTIFY_INFO_DATA *data,
3018 print_queue_struct *queue,
3019 NT_PRINTER_INFO_LEVEL *printer,
3020 TALLOC_CTX *mem_ctx)
3022 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3023 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3026 /*******************************************************************
3027 * fill a notify_info_data with the attributes
3028 * jfm:xxxx a samba printer is always shared
3029 ********************************************************************/
3031 void spoolss_notify_attributes(int snum,
3032 SPOOL_NOTIFY_INFO_DATA *data,
3033 print_queue_struct *queue,
3034 NT_PRINTER_INFO_LEVEL *printer,
3035 TALLOC_CTX *mem_ctx)
3037 data->notify_data.value[0] = printer->info_2->attributes;
3038 data->notify_data.value[1] = 0;
3041 /*******************************************************************
3042 * fill a notify_info_data with the priority
3043 ********************************************************************/
3045 static void spoolss_notify_priority(int snum,
3046 SPOOL_NOTIFY_INFO_DATA *data,
3047 print_queue_struct *queue,
3048 NT_PRINTER_INFO_LEVEL *printer,
3049 TALLOC_CTX *mem_ctx)
3051 data->notify_data.value[0] = printer->info_2->priority;
3052 data->notify_data.value[1] = 0;
3055 /*******************************************************************
3056 * fill a notify_info_data with the default priority
3057 ********************************************************************/
3059 static void spoolss_notify_default_priority(int snum,
3060 SPOOL_NOTIFY_INFO_DATA *data,
3061 print_queue_struct *queue,
3062 NT_PRINTER_INFO_LEVEL *printer,
3063 TALLOC_CTX *mem_ctx)
3065 data->notify_data.value[0] = printer->info_2->default_priority;
3066 data->notify_data.value[1] = 0;
3069 /*******************************************************************
3070 * fill a notify_info_data with the start time
3071 ********************************************************************/
3073 static void spoolss_notify_start_time(int snum,
3074 SPOOL_NOTIFY_INFO_DATA *data,
3075 print_queue_struct *queue,
3076 NT_PRINTER_INFO_LEVEL *printer,
3077 TALLOC_CTX *mem_ctx)
3079 data->notify_data.value[0] = printer->info_2->starttime;
3080 data->notify_data.value[1] = 0;
3083 /*******************************************************************
3084 * fill a notify_info_data with the until time
3085 ********************************************************************/
3087 static void spoolss_notify_until_time(int snum,
3088 SPOOL_NOTIFY_INFO_DATA *data,
3089 print_queue_struct *queue,
3090 NT_PRINTER_INFO_LEVEL *printer,
3091 TALLOC_CTX *mem_ctx)
3093 data->notify_data.value[0] = printer->info_2->untiltime;
3094 data->notify_data.value[1] = 0;
3097 /*******************************************************************
3098 * fill a notify_info_data with the status
3099 ********************************************************************/
3101 static void spoolss_notify_status(int snum,
3102 SPOOL_NOTIFY_INFO_DATA *data,
3103 print_queue_struct *queue,
3104 NT_PRINTER_INFO_LEVEL *printer,
3105 TALLOC_CTX *mem_ctx)
3107 print_status_struct status;
3109 print_queue_length(snum, &status);
3110 data->notify_data.value[0]=(uint32) status.status;
3111 data->notify_data.value[1] = 0;
3114 /*******************************************************************
3115 * fill a notify_info_data with the number of jobs queued
3116 ********************************************************************/
3118 void spoolss_notify_cjobs(int snum,
3119 SPOOL_NOTIFY_INFO_DATA *data,
3120 print_queue_struct *queue,
3121 NT_PRINTER_INFO_LEVEL *printer,
3122 TALLOC_CTX *mem_ctx)
3124 data->notify_data.value[0] = print_queue_length(snum, NULL);
3125 data->notify_data.value[1] = 0;
3128 /*******************************************************************
3129 * fill a notify_info_data with the average ppm
3130 ********************************************************************/
3132 static void spoolss_notify_average_ppm(int snum,
3133 SPOOL_NOTIFY_INFO_DATA *data,
3134 print_queue_struct *queue,
3135 NT_PRINTER_INFO_LEVEL *printer,
3136 TALLOC_CTX *mem_ctx)
3138 /* always respond 8 pages per minutes */
3139 /* a little hard ! */
3140 data->notify_data.value[0] = printer->info_2->averageppm;
3141 data->notify_data.value[1] = 0;
3144 /*******************************************************************
3145 * fill a notify_info_data with username
3146 ********************************************************************/
3148 static void spoolss_notify_username(int snum,
3149 SPOOL_NOTIFY_INFO_DATA *data,
3150 print_queue_struct *queue,
3151 NT_PRINTER_INFO_LEVEL *printer,
3152 TALLOC_CTX *mem_ctx)
3157 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3159 data->notify_data.data.length = len;
3160 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3162 if (!data->notify_data.data.string) {
3163 data->notify_data.data.length = 0;
3167 memcpy(data->notify_data.data.string, temp, len);
3170 /*******************************************************************
3171 * fill a notify_info_data with job status
3172 ********************************************************************/
3174 static void spoolss_notify_job_status(int snum,
3175 SPOOL_NOTIFY_INFO_DATA *data,
3176 print_queue_struct *queue,
3177 NT_PRINTER_INFO_LEVEL *printer,
3178 TALLOC_CTX *mem_ctx)
3180 data->notify_data.value[0]=nt_printj_status(queue->status);
3181 data->notify_data.value[1] = 0;
3184 /*******************************************************************
3185 * fill a notify_info_data with job name
3186 ********************************************************************/
3188 static void spoolss_notify_job_name(int snum,
3189 SPOOL_NOTIFY_INFO_DATA *data,
3190 print_queue_struct *queue,
3191 NT_PRINTER_INFO_LEVEL *printer,
3192 TALLOC_CTX *mem_ctx)
3197 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3199 data->notify_data.data.length = len;
3200 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3202 if (!data->notify_data.data.string) {
3203 data->notify_data.data.length = 0;
3207 memcpy(data->notify_data.data.string, temp, len);
3210 /*******************************************************************
3211 * fill a notify_info_data with job status
3212 ********************************************************************/
3214 static void spoolss_notify_job_status_string(int snum,
3215 SPOOL_NOTIFY_INFO_DATA *data,
3216 print_queue_struct *queue,
3217 NT_PRINTER_INFO_LEVEL *printer,
3218 TALLOC_CTX *mem_ctx)
3221 * Now we're returning job status codes we just return a "" here. JRA.
3228 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3231 switch (queue->status) {
3236 p = ""; /* NT provides the paused string */
3245 #endif /* NO LONGER NEEDED. */
3247 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3249 data->notify_data.data.length = len;
3250 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3252 if (!data->notify_data.data.string) {
3253 data->notify_data.data.length = 0;
3257 memcpy(data->notify_data.data.string, temp, len);
3260 /*******************************************************************
3261 * fill a notify_info_data with job time
3262 ********************************************************************/
3264 static void spoolss_notify_job_time(int snum,
3265 SPOOL_NOTIFY_INFO_DATA *data,
3266 print_queue_struct *queue,
3267 NT_PRINTER_INFO_LEVEL *printer,
3268 TALLOC_CTX *mem_ctx)
3270 data->notify_data.value[0]=0x0;
3271 data->notify_data.value[1]=0;
3274 /*******************************************************************
3275 * fill a notify_info_data with job size
3276 ********************************************************************/
3278 static void spoolss_notify_job_size(int snum,
3279 SPOOL_NOTIFY_INFO_DATA *data,
3280 print_queue_struct *queue,
3281 NT_PRINTER_INFO_LEVEL *printer,
3282 TALLOC_CTX *mem_ctx)
3284 data->notify_data.value[0]=queue->size;
3285 data->notify_data.value[1]=0;
3288 /*******************************************************************
3289 * fill a notify_info_data with page info
3290 ********************************************************************/
3291 static void spoolss_notify_total_pages(int snum,
3292 SPOOL_NOTIFY_INFO_DATA *data,
3293 print_queue_struct *queue,
3294 NT_PRINTER_INFO_LEVEL *printer,
3295 TALLOC_CTX *mem_ctx)
3297 data->notify_data.value[0]=queue->page_count;
3298 data->notify_data.value[1]=0;
3301 /*******************************************************************
3302 * fill a notify_info_data with pages printed info.
3303 ********************************************************************/
3304 static void spoolss_notify_pages_printed(int snum,
3305 SPOOL_NOTIFY_INFO_DATA *data,
3306 print_queue_struct *queue,
3307 NT_PRINTER_INFO_LEVEL *printer,
3308 TALLOC_CTX *mem_ctx)
3310 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3311 data->notify_data.value[1]=0;
3314 /*******************************************************************
3315 Fill a notify_info_data with job position.
3316 ********************************************************************/
3318 static void spoolss_notify_job_position(int snum,
3319 SPOOL_NOTIFY_INFO_DATA *data,
3320 print_queue_struct *queue,
3321 NT_PRINTER_INFO_LEVEL *printer,
3322 TALLOC_CTX *mem_ctx)
3324 data->notify_data.value[0]=queue->job;
3325 data->notify_data.value[1]=0;
3328 /*******************************************************************
3329 Fill a notify_info_data with submitted time.
3330 ********************************************************************/
3332 static void spoolss_notify_submitted_time(int snum,
3333 SPOOL_NOTIFY_INFO_DATA *data,
3334 print_queue_struct *queue,
3335 NT_PRINTER_INFO_LEVEL *printer,
3336 TALLOC_CTX *mem_ctx)
3343 t=gmtime(&queue->time);
3345 len = sizeof(SYSTEMTIME);
3347 data->notify_data.data.length = len;
3348 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3350 if (!data->notify_data.data.string) {
3351 data->notify_data.data.length = 0;
3355 make_systemtime(&st, t);
3358 * Systemtime must be linearized as a set of UINT16's.
3359 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3362 p = (char *)data->notify_data.data.string;
3363 SSVAL(p, 0, st.year);
3364 SSVAL(p, 2, st.month);
3365 SSVAL(p, 4, st.dayofweek);
3366 SSVAL(p, 6, st.day);
3367 SSVAL(p, 8, st.hour);
3368 SSVAL(p, 10, st.minute);
3369 SSVAL(p, 12, st.second);
3370 SSVAL(p, 14, st.milliseconds);
3373 struct s_notify_info_data_table
3379 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3380 print_queue_struct *queue,
3381 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3384 /* A table describing the various print notification constants and
3385 whether the notification data is a pointer to a variable sized
3386 buffer, a one value uint32 or a two value uint32. */
3388 static const struct s_notify_info_data_table notify_info_data_table[] =
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3439 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3442 /*******************************************************************
3443 Return the size of info_data structure.
3444 ********************************************************************/
3446 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3450 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3451 if ( (notify_info_data_table[i].type == type)
3452 && (notify_info_data_table[i].field == field) ) {
3453 switch(notify_info_data_table[i].size) {
3454 case NOTIFY_ONE_VALUE:
3455 case NOTIFY_TWO_VALUE:
3460 /* The only pointer notify data I have seen on
3461 the wire is the submitted time and this has
3462 the notify size set to 4. -tpot */
3464 case NOTIFY_POINTER:
3467 case NOTIFY_SECDESC:
3473 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3478 /*******************************************************************
3479 Return the type of notify_info_data.
3480 ********************************************************************/
3482 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3486 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3487 if (notify_info_data_table[i].type == type &&
3488 notify_info_data_table[i].field == field)
3489 return notify_info_data_table[i].size;
3495 /****************************************************************************
3496 ****************************************************************************/
3498 static BOOL search_notify(uint16 type, uint16 field, int *value)
3502 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3503 if (notify_info_data_table[i].type == type &&
3504 notify_info_data_table[i].field == field &&
3505 notify_info_data_table[i].fn != NULL) {
3514 /****************************************************************************
3515 ****************************************************************************/
3517 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3519 info_data->type = type;
3520 info_data->field = field;
3521 info_data->reserved = 0;
3523 info_data->size = size_of_notify_info_data(type, field);
3524 info_data->enc_type = type_of_notify_info_data(type, field);
3529 /*******************************************************************
3531 * fill a notify_info struct with info asked
3533 ********************************************************************/
3535 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3536 snum, SPOOL_NOTIFY_OPTION_TYPE
3537 *option_type, uint32 id,
3538 TALLOC_CTX *mem_ctx)
3544 SPOOL_NOTIFY_INFO_DATA *current_data;
3545 NT_PRINTER_INFO_LEVEL *printer = NULL;
3546 print_queue_struct *queue=NULL;
3548 type=option_type->type;
3550 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3551 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3552 option_type->count, lp_servicename(snum)));
3554 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3557 for(field_num=0; field_num<option_type->count; field_num++) {
3558 field = option_type->fields[field_num];
3560 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3562 if (!search_notify(type, field, &j) )
3565 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3566 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3567 free_a_printer(&printer, 2);
3571 current_data = &info->data[info->count];
3573 construct_info_data(current_data, type, field, id);
3575 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3576 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3578 notify_info_data_table[j].fn(snum, current_data, queue,
3584 free_a_printer(&printer, 2);
3588 /*******************************************************************
3590 * fill a notify_info struct with info asked
3592 ********************************************************************/
3594 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3595 SPOOL_NOTIFY_INFO *info,
3596 NT_PRINTER_INFO_LEVEL *printer,
3597 int snum, SPOOL_NOTIFY_OPTION_TYPE
3598 *option_type, uint32 id,
3599 TALLOC_CTX *mem_ctx)
3605 SPOOL_NOTIFY_INFO_DATA *current_data;
3607 DEBUG(4,("construct_notify_jobs_info\n"));
3609 type = option_type->type;
3611 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3612 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3613 option_type->count));
3615 for(field_num=0; field_num<option_type->count; field_num++) {
3616 field = option_type->fields[field_num];
3618 if (!search_notify(type, field, &j) )
3621 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3622 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3626 current_data=&(info->data[info->count]);
3628 construct_info_data(current_data, type, field, id);
3629 notify_info_data_table[j].fn(snum, current_data, queue,
3638 * JFM: The enumeration is not that simple, it's even non obvious.
3640 * let's take an example: I want to monitor the PRINTER SERVER for
3641 * the printer's name and the number of jobs currently queued.
3642 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3643 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3645 * I have 3 printers on the back of my server.
3647 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3650 * 1 printer 1 name 1
3651 * 2 printer 1 cjob 1
3652 * 3 printer 2 name 2
3653 * 4 printer 2 cjob 2
3654 * 5 printer 3 name 3
3655 * 6 printer 3 name 3
3657 * that's the print server case, the printer case is even worse.
3660 /*******************************************************************
3662 * enumerate all printers on the printserver
3663 * fill a notify_info struct with info asked
3665 ********************************************************************/
3667 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3668 SPOOL_NOTIFY_INFO *info,
3669 TALLOC_CTX *mem_ctx)
3672 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3673 int n_services=lp_numservices();
3675 SPOOL_NOTIFY_OPTION *option;
3676 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3678 DEBUG(4,("printserver_notify_info\n"));
3683 option=Printer->notify.option;
3688 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3689 sending a ffpcn() request first */
3694 for (i=0; i<option->count; i++) {
3695 option_type=&(option->ctr.type[i]);
3697 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3700 for (snum=0; snum<n_services; snum++)
3702 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3703 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3709 * Debugging information, don't delete.
3712 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3713 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3714 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3716 for (i=0; i<info->count; i++) {
3717 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3718 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3719 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3726 /*******************************************************************
3728 * fill a notify_info struct with info asked
3730 ********************************************************************/
3732 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3733 TALLOC_CTX *mem_ctx)
3736 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3739 SPOOL_NOTIFY_OPTION *option;
3740 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3742 print_queue_struct *queue=NULL;
3743 print_status_struct status;
3745 DEBUG(4,("printer_notify_info\n"));
3750 option=Printer->notify.option;
3756 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3757 sending a ffpcn() request first */
3762 get_printer_snum(p, hnd, &snum, NULL);
3764 for (i=0; i<option->count; i++) {
3765 option_type=&option->ctr.type[i];
3767 switch ( option_type->type ) {
3768 case PRINTER_NOTIFY_TYPE:
3769 if(construct_notify_printer_info(Printer, info, snum,
3775 case JOB_NOTIFY_TYPE: {
3776 NT_PRINTER_INFO_LEVEL *printer = NULL;
3778 count = print_queue_status(snum, &queue, &status);
3780 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3783 for (j=0; j<count; j++) {
3784 construct_notify_jobs_info(&queue[j], info,
3791 free_a_printer(&printer, 2);
3801 * Debugging information, don't delete.
3804 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3805 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3806 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3808 for (i=0; i<info->count; i++) {
3809 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3810 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3811 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3817 /********************************************************************
3819 ********************************************************************/
3821 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3823 POLICY_HND *handle = &q_u->handle;
3824 SPOOL_NOTIFY_INFO *info = &r_u->info;
3826 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3827 WERROR result = WERR_BADFID;
3829 /* we always have a NOTIFY_INFO struct */
3833 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3834 OUR_HANDLE(handle)));
3838 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3841 * We are now using the change value, and
3842 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3843 * I don't have a global notification system, I'm sending back all the
3844 * informations even when _NOTHING_ has changed.
3847 /* We need to keep track of the change value to send back in
3848 RRPCN replies otherwise our updates are ignored. */
3850 Printer->notify.fnpcn = True;
3852 if (Printer->notify.client_connected) {
3853 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3854 Printer->notify.change = q_u->change;
3857 /* just ignore the SPOOL_NOTIFY_OPTION */
3859 switch (Printer->printer_type) {
3861 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3864 case SPLHND_PRINTER:
3865 result = printer_notify_info(p, handle, info, p->mem_ctx);
3869 Printer->notify.fnpcn = False;
3875 /********************************************************************
3876 * construct_printer_info_0
3877 * fill a printer_info_0 struct
3878 ********************************************************************/
3880 static BOOL construct_printer_info_0(Printer_entry *print_hnd,
3881 PRINTER_INFO_0 *printer,
3882 const struct share_params *params)
3886 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3887 counter_printer_0 *session_counter;
3888 uint32 global_counter;
3891 print_status_struct status;
3893 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
3894 lp_const_servicename(params->service))))
3897 count = print_queue_length(params->service, &status);
3899 /* check if we already have a counter for this printer */
3900 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3901 if (session_counter->snum == params->service)
3905 /* it's the first time, add it to the list */
3906 if (session_counter==NULL) {
3907 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3908 free_a_printer(&ntprinter, 2);
3911 ZERO_STRUCTP(session_counter);
3912 session_counter->snum=params->service;
3913 session_counter->counter=0;
3914 DLIST_ADD(counter_list, session_counter);
3918 session_counter->counter++;
3921 * the global_counter should be stored in a TDB as it's common to all the clients
3922 * and should be zeroed on samba startup
3924 global_counter=session_counter->counter;
3926 pstrcpy(chaine,ntprinter->info_2->printername);
3928 init_unistr(&printer->printername, chaine);
3930 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3931 init_unistr(&printer->servername, chaine);
3933 printer->cjobs = count;
3934 printer->total_jobs = 0;
3935 printer->total_bytes = 0;
3937 setuptime = (time_t)ntprinter->info_2->setuptime;
3938 t=gmtime(&setuptime);
3940 printer->year = t->tm_year+1900;
3941 printer->month = t->tm_mon+1;
3942 printer->dayofweek = t->tm_wday;
3943 printer->day = t->tm_mday;
3944 printer->hour = t->tm_hour;
3945 printer->minute = t->tm_min;
3946 printer->second = t->tm_sec;
3947 printer->milliseconds = 0;
3949 printer->global_counter = global_counter;
3950 printer->total_pages = 0;
3952 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3953 printer->major_version = 0x0005; /* NT 5 */
3954 printer->build_version = 0x0893; /* build 2195 */
3956 printer->unknown7 = 0x1;
3957 printer->unknown8 = 0x0;
3958 printer->unknown9 = 0x0;
3959 printer->session_counter = session_counter->counter;
3960 printer->unknown11 = 0x0;
3961 printer->printer_errors = 0x0; /* number of print failure */
3962 printer->unknown13 = 0x0;
3963 printer->unknown14 = 0x1;
3964 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3965 printer->unknown16 = 0x0;
3966 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3967 printer->unknown18 = 0x0;
3968 printer->status = nt_printq_status(status.status);
3969 printer->unknown20 = 0x0;
3970 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3971 printer->unknown22 = 0x0;
3972 printer->unknown23 = 0x6; /* 6 ???*/
3973 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3974 printer->unknown25 = 0;
3975 printer->unknown26 = 0;
3976 printer->unknown27 = 0;
3977 printer->unknown28 = 0;
3978 printer->unknown29 = 0;
3980 free_a_printer(&ntprinter,2);
3984 /********************************************************************
3985 * construct_printer_info_1
3986 * fill a printer_info_1 struct
3987 ********************************************************************/
3988 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags,
3989 PRINTER_INFO_1 *printer,
3990 const struct share_params *params)
3994 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3996 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
3997 lp_const_servicename(params->service))))
4000 printer->flags=flags;
4002 if (*ntprinter->info_2->comment == '\0') {
4003 init_unistr(&printer->comment, lp_comment(params->service));
4004 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4005 ntprinter->info_2->drivername,
4006 lp_comment(params->service));
4009 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4010 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4011 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4014 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4016 init_unistr(&printer->description, chaine);
4017 init_unistr(&printer->name, chaine2);
4019 free_a_printer(&ntprinter,2);
4024 /****************************************************************************
4025 Free a DEVMODE struct.
4026 ****************************************************************************/
4028 static void free_dev_mode(DEVICEMODE *dev)
4033 SAFE_FREE(dev->dev_private);
4038 /****************************************************************************
4039 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4040 should be valid upon entry
4041 ****************************************************************************/
4043 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4045 if ( !devmode || !ntdevmode )
4048 init_unistr(&devmode->devicename, ntdevmode->devicename);
4050 init_unistr(&devmode->formname, ntdevmode->formname);
4052 devmode->specversion = ntdevmode->specversion;
4053 devmode->driverversion = ntdevmode->driverversion;
4054 devmode->size = ntdevmode->size;
4055 devmode->driverextra = ntdevmode->driverextra;
4056 devmode->fields = ntdevmode->fields;
4058 devmode->orientation = ntdevmode->orientation;
4059 devmode->papersize = ntdevmode->papersize;
4060 devmode->paperlength = ntdevmode->paperlength;
4061 devmode->paperwidth = ntdevmode->paperwidth;
4062 devmode->scale = ntdevmode->scale;
4063 devmode->copies = ntdevmode->copies;
4064 devmode->defaultsource = ntdevmode->defaultsource;
4065 devmode->printquality = ntdevmode->printquality;
4066 devmode->color = ntdevmode->color;
4067 devmode->duplex = ntdevmode->duplex;
4068 devmode->yresolution = ntdevmode->yresolution;
4069 devmode->ttoption = ntdevmode->ttoption;
4070 devmode->collate = ntdevmode->collate;
4071 devmode->icmmethod = ntdevmode->icmmethod;
4072 devmode->icmintent = ntdevmode->icmintent;
4073 devmode->mediatype = ntdevmode->mediatype;
4074 devmode->dithertype = ntdevmode->dithertype;
4076 if (ntdevmode->nt_dev_private != NULL) {
4077 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4084 /****************************************************************************
4085 Create a DEVMODE struct. Returns malloced memory.
4086 ****************************************************************************/
4088 DEVICEMODE *construct_dev_mode(const char *servicename)
4090 NT_PRINTER_INFO_LEVEL *printer = NULL;
4091 DEVICEMODE *devmode = NULL;
4093 DEBUG(7,("construct_dev_mode\n"));
4095 DEBUGADD(8,("getting printer characteristics\n"));
4097 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4100 if ( !printer->info_2->devmode ) {
4101 DEBUG(5, ("BONG! There was no device mode!\n"));
4105 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4106 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4110 ZERO_STRUCTP(devmode);
4112 DEBUGADD(8,("loading DEVICEMODE\n"));
4114 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4115 free_dev_mode( devmode );
4120 free_a_printer(&printer,2);
4125 /********************************************************************
4126 * construct_printer_info_2
4127 * fill a printer_info_2 struct
4128 ********************************************************************/
4130 static BOOL construct_printer_info_2(Printer_entry *print_hnd,
4131 PRINTER_INFO_2 *printer,
4132 const struct share_params *params)
4135 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4137 print_status_struct status;
4139 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4140 lp_const_servicename(params->service))))
4143 count = print_queue_length(params->service, &status);
4145 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4146 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4147 init_unistr(&printer->sharename, lp_servicename(params->service)); /* sharename */
4148 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4149 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4151 if (*ntprinter->info_2->comment == '\0')
4152 init_unistr(&printer->comment, lp_comment(params->service)); /* comment */
4154 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4156 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4157 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4158 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4159 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4160 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4162 printer->attributes = ntprinter->info_2->attributes;
4164 printer->priority = ntprinter->info_2->priority; /* priority */
4165 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4166 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4167 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4168 printer->status = nt_printq_status(status.status); /* status */
4169 printer->cjobs = count; /* jobs */
4170 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4172 if ( !(printer->devmode = construct_dev_mode(
4173 lp_const_servicename(params->service))) )
4174 DEBUG(8, ("Returning NULL Devicemode!\n"));
4176 printer->secdesc = NULL;
4178 if ( ntprinter->info_2->secdesc_buf
4179 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4181 /* don't use talloc_steal() here unless you do a deep steal of all
4182 the SEC_DESC members */
4184 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4185 ntprinter->info_2->secdesc_buf->sd );
4188 free_a_printer(&ntprinter, 2);
4193 /********************************************************************
4194 * construct_printer_info_3
4195 * fill a printer_info_3 struct
4196 ********************************************************************/
4198 static BOOL construct_printer_info_3(Printer_entry *print_hnd,
4199 PRINTER_INFO_3 **pp_printer,
4200 const struct share_params *params)
4202 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4203 PRINTER_INFO_3 *printer = NULL;
4205 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4206 lp_const_servicename(params->service))))
4210 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4211 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4212 free_a_printer(&ntprinter, 2);
4216 ZERO_STRUCTP(printer);
4218 /* These are the components of the SD we are returning. */
4220 printer->flags = 0x4;
4222 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4223 /* don't use talloc_steal() here unless you do a deep steal of all
4224 the SEC_DESC members */
4226 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4227 ntprinter->info_2->secdesc_buf->sd );
4230 free_a_printer(&ntprinter, 2);
4232 *pp_printer = printer;
4236 /********************************************************************
4237 * construct_printer_info_4
4238 * fill a printer_info_4 struct
4239 ********************************************************************/
4241 static BOOL construct_printer_info_4(Printer_entry *print_hnd,
4242 PRINTER_INFO_4 *printer,
4243 const struct share_params *params)
4245 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4247 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4248 lp_const_servicename(params->service))))
4251 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4252 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4253 printer->attributes = ntprinter->info_2->attributes;
4255 free_a_printer(&ntprinter, 2);
4259 /********************************************************************
4260 * construct_printer_info_5
4261 * fill a printer_info_5 struct
4262 ********************************************************************/
4264 static BOOL construct_printer_info_5(Printer_entry *print_hnd,
4265 PRINTER_INFO_5 *printer,
4266 const struct share_params *params)
4268 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4270 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4271 lp_const_servicename(params->service))))
4274 init_unistr(&printer->printername, ntprinter->info_2->printername);
4275 init_unistr(&printer->portname, ntprinter->info_2->portname);
4276 printer->attributes = ntprinter->info_2->attributes;
4278 /* these two are not used by NT+ according to MSDN */
4280 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4281 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4283 free_a_printer(&ntprinter, 2);
4288 /********************************************************************
4289 * construct_printer_info_6
4290 * fill a printer_info_6 struct
4291 ********************************************************************/
4293 static BOOL construct_printer_info_6(Printer_entry *print_hnd,
4294 PRINTER_INFO_6 *printer,
4295 const struct share_params *params)
4297 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4299 print_status_struct status;
4301 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4302 lp_const_servicename(params->service))))
4305 count = print_queue_length(params->service, &status);
4307 printer->status = nt_printq_status(status.status);
4309 free_a_printer(&ntprinter, 2);
4314 /********************************************************************
4315 * construct_printer_info_7
4316 * fill a printer_info_7 struct
4317 ********************************************************************/
4319 static BOOL construct_printer_info_7(Printer_entry *print_hnd,
4320 PRINTER_INFO_7 *printer,
4321 const struct share_params *params)
4323 char *guid_str = NULL;
4326 if (is_printer_published(print_hnd, params->service, &guid)) {
4327 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4328 strupper_m(guid_str);
4329 init_unistr(&printer->guid, guid_str);
4330 printer->action = SPOOL_DS_PUBLISH;
4332 init_unistr(&printer->guid, "");
4333 printer->action = SPOOL_DS_UNPUBLISH;
4339 /********************************************************************
4340 Spoolss_enumprinters.
4341 ********************************************************************/
4343 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4346 struct share_iterator *shares;
4347 struct share_params *printer;
4348 PRINTER_INFO_1 *printers=NULL;
4349 WERROR result = WERR_OK;
4351 DEBUG(4,("enum_all_printers_info_1\n"));
4353 if (!(shares = share_list_all(NULL))) {
4354 DEBUG(5, ("Could not list printers\n"));
4355 return WERR_ACCESS_DENIED;
4358 while ((printer = next_printer(shares)) != NULL) {
4359 PRINTER_INFO_1 current_prt;
4361 DEBUG(4,("Found a printer in smb.conf: %s\n",
4362 lp_servicename(printer->service)));
4364 if (!construct_printer_info_1(NULL, flags, ¤t_prt,
4369 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1,
4370 *returned +1)) == NULL) {
4371 DEBUG(2,("enum_all_printers_info_1: failed to enlarge "
4372 "printers buffer!\n"));
4374 TALLOC_FREE(shares);
4377 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n",
4380 memcpy(&printers[*returned], ¤t_prt,
4381 sizeof(PRINTER_INFO_1));
4383 TALLOC_FREE(printer);
4386 /* check the required size. */
4387 for (i=0; i<*returned; i++)
4388 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4390 if (*needed > offered) {
4391 result = WERR_INSUFFICIENT_BUFFER;
4395 if (!rpcbuf_alloc_size(buffer, *needed)) {
4396 result = WERR_NOMEM;
4400 /* fill the buffer with the structures */
4401 for (i=0; i<*returned; i++)
4402 smb_io_printer_info_1("", buffer, &printers[i], 0);
4407 SAFE_FREE(printers);
4408 TALLOC_FREE(shares);
4410 if ( !W_ERROR_IS_OK(result) )
4416 /********************************************************************
4417 enum_all_printers_info_1_local.
4418 *********************************************************************/
4420 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4422 DEBUG(4,("enum_all_printers_info_1_local\n"));
4424 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4427 /********************************************************************
4428 enum_all_printers_info_1_name.
4429 *********************************************************************/
4431 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4435 DEBUG(4,("enum_all_printers_info_1_name\n"));
4437 if ((name[0] == '\\') && (name[1] == '\\'))
4440 if (is_myname_or_ipaddr(s)) {
4441 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4444 return WERR_INVALID_NAME;
4447 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4448 /********************************************************************
4449 enum_all_printers_info_1_remote.
4450 *********************************************************************/
4452 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4454 PRINTER_INFO_1 *printer;
4455 fstring printername;
4458 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4459 WERROR result = WERR_OK;
4461 /* JFM: currently it's more a place holder than anything else.
4462 * In the spooler world there is a notion of server registration.
4463 * the print servers are registered on the PDC (in the same domain)
4465 * We should have a TDB here. The registration is done thru an
4466 * undocumented RPC call.
4469 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4474 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4475 slprintf(desc, sizeof(desc)-1,"%s", name);
4476 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4478 init_unistr(&printer->description, desc);
4479 init_unistr(&printer->name, printername);
4480 init_unistr(&printer->comment, comment);
4481 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4483 /* check the required size. */
4484 *needed += spoolss_size_printer_info_1(printer);
4486 if (*needed > offered) {
4487 result = WERR_INSUFFICIENT_BUFFER;
4491 if (!rpcbuf_alloc_size(buffer, *needed)) {
4492 result = WERR_NOMEM;
4496 /* fill the buffer with the structures */
4497 smb_io_printer_info_1("", buffer, printer, 0);
4503 if ( !W_ERROR_IS_OK(result) )
4511 /********************************************************************
4512 enum_all_printers_info_1_network.
4513 *********************************************************************/
4515 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4519 DEBUG(4,("enum_all_printers_info_1_network\n"));
4521 /* If we respond to a enum_printers level 1 on our name with flags
4522 set to PRINTER_ENUM_REMOTE with a list of printers then these
4523 printers incorrectly appear in the APW browse list.
4524 Specifically the printers for the server appear at the workgroup
4525 level where all the other servers in the domain are
4526 listed. Windows responds to this call with a
4527 WERR_CAN_NOT_COMPLETE so we should do the same. */
4529 if (name[0] == '\\' && name[1] == '\\')
4532 if (is_myname_or_ipaddr(s))
4533 return WERR_CAN_NOT_COMPLETE;
4535 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4538 /********************************************************************
4539 * api_spoolss_enumprinters
4541 * called from api_spoolss_enumprinters (see this to understand)
4542 ********************************************************************/
4544 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4547 struct share_iterator *shares;
4548 struct share_params *printer;
4549 PRINTER_INFO_2 *printers=NULL;
4550 WERROR result = WERR_OK;
4554 if (!(shares = share_list_all(NULL))) {
4555 DEBUG(5, ("Could not list printers\n"));
4556 return WERR_ACCESS_DENIED;
4559 while ((printer = next_printer(shares)) != NULL) {
4560 PRINTER_INFO_2 current_prt;
4562 DEBUG(4,("Found a printer in smb.conf: %s\n",
4563 lp_servicename(printer->service)));
4565 if (!construct_printer_info_2(NULL, ¤t_prt,
4569 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2,
4571 DEBUG(2,("enum_all_printers_info_2: failed to enlarge "
4572 "printers buffer!\n"));
4574 TALLOC_FREE(shares);
4578 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n",
4581 memcpy(&printers[*returned], ¤t_prt,
4582 sizeof(PRINTER_INFO_2));
4584 TALLOC_FREE(printer);
4587 /* check the required size. */
4588 for (i=0; i<*returned; i++)
4589 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4591 if (*needed > offered) {
4592 result = WERR_INSUFFICIENT_BUFFER;
4596 if (!rpcbuf_alloc_size(buffer, *needed)) {
4597 result = WERR_NOMEM;
4601 /* fill the buffer with the structures */
4602 for (i=0; i<*returned; i++)
4603 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4608 for (i=0; i<*returned; i++)
4609 free_devmode(printers[i].devmode);
4611 SAFE_FREE(printers);
4612 TALLOC_FREE(shares);
4614 if ( !W_ERROR_IS_OK(result) )
4620 /********************************************************************
4621 * handle enumeration of printers at level 1
4622 ********************************************************************/
4624 static WERROR enumprinters_level1( uint32 flags, fstring name,
4625 RPC_BUFFER *buffer, uint32 offered,
4626 uint32 *needed, uint32 *returned)
4628 /* Not all the flags are equals */
4630 if (flags & PRINTER_ENUM_LOCAL)
4631 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4633 if (flags & PRINTER_ENUM_NAME)
4634 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4636 #if 0 /* JERRY - disabled for now */
4637 if (flags & PRINTER_ENUM_REMOTE)
4638 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4641 if (flags & PRINTER_ENUM_NETWORK)
4642 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4644 return WERR_OK; /* NT4sp5 does that */
4647 /********************************************************************
4648 * handle enumeration of printers at level 2
4649 ********************************************************************/
4651 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4652 RPC_BUFFER *buffer, uint32 offered,
4653 uint32 *needed, uint32 *returned)
4655 char *s = servername;
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 ((servername[0] == '\\') && (servername[1] == '\\'))
4664 if (is_myname_or_ipaddr(s))
4665 return enum_all_printers_info_2(buffer, offered, needed, returned);
4667 return WERR_INVALID_NAME;
4670 if (flags & PRINTER_ENUM_REMOTE)
4671 return WERR_UNKNOWN_LEVEL;
4676 /********************************************************************
4677 * handle enumeration of printers at level 5
4678 ********************************************************************/
4680 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4681 RPC_BUFFER *buffer, uint32 offered,
4682 uint32 *needed, uint32 *returned)
4684 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4688 /********************************************************************
4689 * api_spoolss_enumprinters
4691 * called from api_spoolss_enumprinters (see this to understand)
4692 ********************************************************************/
4694 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4696 uint32 flags = q_u->flags;
4697 UNISTR2 *servername = &q_u->servername;
4698 uint32 level = q_u->level;
4699 RPC_BUFFER *buffer = NULL;
4700 uint32 offered = q_u->offered;
4701 uint32 *needed = &r_u->needed;
4702 uint32 *returned = &r_u->returned;
4706 /* that's an [in out] buffer */
4708 if (!q_u->buffer && (offered!=0)) {
4709 return WERR_INVALID_PARAM;
4712 rpcbuf_move(q_u->buffer, &r_u->buffer);
4713 buffer = r_u->buffer;
4715 DEBUG(4,("_spoolss_enumprinters\n"));
4722 * flags==PRINTER_ENUM_NAME
4723 * if name=="" then enumerates all printers
4724 * if name!="" then enumerate the printer
4725 * flags==PRINTER_ENUM_REMOTE
4726 * name is NULL, enumerate printers
4727 * Level 2: name!="" enumerates printers, name can't be NULL
4728 * Level 3: doesn't exist
4729 * Level 4: does a local registry lookup
4730 * Level 5: same as Level 2
4733 unistr2_to_ascii(name, servername, sizeof(name)-1);
4738 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4740 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4742 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4747 return WERR_UNKNOWN_LEVEL;
4750 /****************************************************************************
4751 ****************************************************************************/
4753 static WERROR getprinter_level_0(Printer_entry *print_hnd,
4754 const struct share_params *params,
4755 RPC_BUFFER *buffer, uint32 offered,
4758 PRINTER_INFO_0 *printer=NULL;
4759 WERROR result = WERR_OK;
4761 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4764 construct_printer_info_0(print_hnd, printer, params);
4766 /* check the required size. */
4767 *needed += spoolss_size_printer_info_0(printer);
4769 if (*needed > offered) {
4770 result = WERR_INSUFFICIENT_BUFFER;
4774 if (!rpcbuf_alloc_size(buffer, *needed)) {
4775 result = WERR_NOMEM;
4779 /* fill the buffer with the structures */
4780 smb_io_printer_info_0("", buffer, printer, 0);
4790 /****************************************************************************
4791 ****************************************************************************/
4793 static WERROR getprinter_level_1(Printer_entry *print_hnd,
4794 const struct share_params *params,
4795 RPC_BUFFER *buffer, uint32 offered,
4798 PRINTER_INFO_1 *printer=NULL;
4799 WERROR result = WERR_OK;
4801 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4804 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer,
4807 /* check the required size. */
4808 *needed += spoolss_size_printer_info_1(printer);
4810 if (*needed > offered) {
4811 result = WERR_INSUFFICIENT_BUFFER;
4815 if (!rpcbuf_alloc_size(buffer, *needed)) {
4816 result = WERR_NOMEM;
4820 /* fill the buffer with the structures */
4821 smb_io_printer_info_1("", buffer, printer, 0);
4830 /****************************************************************************
4831 ****************************************************************************/
4833 static WERROR getprinter_level_2(Printer_entry *print_hnd,
4834 const struct share_params *params,
4835 RPC_BUFFER *buffer, uint32 offered,
4838 PRINTER_INFO_2 *printer=NULL;
4839 WERROR result = WERR_OK;
4841 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4844 construct_printer_info_2(print_hnd, printer, params);
4846 /* check the required size. */
4847 *needed += spoolss_size_printer_info_2(printer);
4849 if (*needed > offered) {
4850 result = WERR_INSUFFICIENT_BUFFER;
4854 if (!rpcbuf_alloc_size(buffer, *needed)) {
4855 result = WERR_NOMEM;
4859 /* fill the buffer with the structures */
4860 if (!smb_io_printer_info_2("", buffer, printer, 0))
4861 result = WERR_NOMEM;
4865 free_printer_info_2(printer);
4870 /****************************************************************************
4871 ****************************************************************************/
4873 static WERROR getprinter_level_3(Printer_entry *print_hnd,
4874 const struct share_params *params,
4875 RPC_BUFFER *buffer, uint32 offered,
4878 PRINTER_INFO_3 *printer=NULL;
4879 WERROR result = WERR_OK;
4881 if (!construct_printer_info_3(print_hnd, &printer, params))
4884 /* check the required size. */
4885 *needed += spoolss_size_printer_info_3(printer);
4887 if (*needed > offered) {
4888 result = WERR_INSUFFICIENT_BUFFER;
4892 if (!rpcbuf_alloc_size(buffer, *needed)) {
4893 result = WERR_NOMEM;
4897 /* fill the buffer with the structures */
4898 smb_io_printer_info_3("", buffer, printer, 0);
4902 free_printer_info_3(printer);
4907 /****************************************************************************
4908 ****************************************************************************/
4910 static WERROR getprinter_level_4(Printer_entry *print_hnd,
4911 const struct share_params *params,
4912 RPC_BUFFER *buffer, uint32 offered,
4915 PRINTER_INFO_4 *printer=NULL;
4916 WERROR result = WERR_OK;
4918 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4921 if (!construct_printer_info_4(print_hnd, printer, params)) {
4926 /* check the required size. */
4927 *needed += spoolss_size_printer_info_4(printer);
4929 if (*needed > offered) {
4930 result = WERR_INSUFFICIENT_BUFFER;
4934 if (!rpcbuf_alloc_size(buffer, *needed)) {
4935 result = WERR_NOMEM;
4939 /* fill the buffer with the structures */
4940 smb_io_printer_info_4("", buffer, printer, 0);
4944 free_printer_info_4(printer);
4949 /****************************************************************************
4950 ****************************************************************************/
4952 static WERROR getprinter_level_5(Printer_entry *print_hnd,
4953 const struct share_params *params,
4954 RPC_BUFFER *buffer, uint32 offered,
4957 PRINTER_INFO_5 *printer=NULL;
4958 WERROR result = WERR_OK;
4960 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4963 if (!construct_printer_info_5(print_hnd, printer, params)) {
4964 free_printer_info_5(printer);
4968 /* check the required size. */
4969 *needed += spoolss_size_printer_info_5(printer);
4971 if (*needed > offered) {
4972 result = WERR_INSUFFICIENT_BUFFER;
4976 if (!rpcbuf_alloc_size(buffer, *needed)) {
4977 result = WERR_NOMEM;
4981 /* fill the buffer with the structures */
4982 smb_io_printer_info_5("", buffer, printer, 0);
4986 free_printer_info_5(printer);
4991 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4992 const struct share_params *params,
4993 RPC_BUFFER *buffer, uint32 offered,
4996 PRINTER_INFO_6 *printer;
4997 WERROR result = WERR_OK;
4999 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5003 if (!construct_printer_info_6(print_hnd, printer, params)) {
5004 free_printer_info_6(printer);
5008 /* check the required size. */
5009 *needed += spoolss_size_printer_info_6(printer);
5011 if (*needed > offered) {
5012 result = WERR_INSUFFICIENT_BUFFER;
5016 if (!rpcbuf_alloc_size(buffer, *needed)) {
5017 result = WERR_NOMEM;
5021 /* fill the buffer with the structures */
5022 smb_io_printer_info_6("", buffer, printer, 0);
5026 free_printer_info_6(printer);
5031 static WERROR getprinter_level_7(Printer_entry *print_hnd,
5032 const struct share_params *params,
5033 RPC_BUFFER *buffer, uint32 offered,
5036 PRINTER_INFO_7 *printer=NULL;
5037 WERROR result = WERR_OK;
5039 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5042 if (!construct_printer_info_7(print_hnd, printer, params))
5045 /* check the required size. */
5046 *needed += spoolss_size_printer_info_7(printer);
5048 if (*needed > offered) {
5049 result = WERR_INSUFFICIENT_BUFFER;
5053 if (!rpcbuf_alloc_size(buffer, *needed)) {
5054 result = WERR_NOMEM;
5059 /* fill the buffer with the structures */
5060 smb_io_printer_info_7("", buffer, printer, 0);
5064 free_printer_info_7(printer);
5069 /****************************************************************************
5070 ****************************************************************************/
5072 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5074 POLICY_HND *handle = &q_u->handle;
5075 uint32 level = q_u->level;
5076 RPC_BUFFER *buffer = NULL;
5077 uint32 offered = q_u->offered;
5078 uint32 *needed = &r_u->needed;
5079 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5080 struct share_params *params;
5084 /* that's an [in out] buffer */
5086 if (!q_u->buffer && (offered!=0)) {
5087 return WERR_INVALID_PARAM;
5090 rpcbuf_move(q_u->buffer, &r_u->buffer);
5091 buffer = r_u->buffer;
5095 if (!get_printer_snum(p, handle, &snum, ¶ms))
5100 return getprinter_level_0(Printer, params, buffer, offered,
5103 return getprinter_level_1(Printer, params, buffer, offered,
5106 return getprinter_level_2(Printer, params, buffer, offered,
5109 return getprinter_level_3(Printer, params, buffer, offered,
5112 return getprinter_level_4(Printer, params, buffer, offered,
5115 return getprinter_level_5(Printer, params, buffer, offered,
5118 return getprinter_level_6(Printer, params, buffer, offered,
5121 return getprinter_level_7(Printer, params, buffer, offered,
5124 return WERR_UNKNOWN_LEVEL;
5127 /********************************************************************
5128 * fill a DRIVER_INFO_1 struct
5129 ********************************************************************/
5131 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5133 init_unistr( &info->name, driver.info_3->name);
5136 /********************************************************************
5137 * construct_printer_driver_info_1
5138 ********************************************************************/
5140 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5142 NT_PRINTER_INFO_LEVEL *printer = NULL;
5143 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5145 ZERO_STRUCT(driver);
5147 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5148 return WERR_INVALID_PRINTER_NAME;
5150 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5151 free_a_printer(&printer, 2);
5152 return WERR_UNKNOWN_PRINTER_DRIVER;
5155 fill_printer_driver_info_1(info, driver, servername, architecture);
5157 free_a_printer(&printer,2);
5162 /********************************************************************
5163 * construct_printer_driver_info_2
5164 * fill a printer_info_2 struct
5165 ********************************************************************/
5167 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5171 info->version=driver.info_3->cversion;
5173 init_unistr( &info->name, driver.info_3->name );
5174 init_unistr( &info->architecture, driver.info_3->environment );
5177 if (strlen(driver.info_3->driverpath)) {
5178 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5179 init_unistr( &info->driverpath, temp );
5181 init_unistr( &info->driverpath, "" );
5183 if (strlen(driver.info_3->datafile)) {
5184 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5185 init_unistr( &info->datafile, temp );
5187 init_unistr( &info->datafile, "" );
5189 if (strlen(driver.info_3->configfile)) {
5190 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5191 init_unistr( &info->configfile, temp );
5193 init_unistr( &info->configfile, "" );
5196 /********************************************************************
5197 * construct_printer_driver_info_2
5198 * fill a printer_info_2 struct
5199 ********************************************************************/
5201 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5203 NT_PRINTER_INFO_LEVEL *printer = NULL;
5204 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5206 ZERO_STRUCT(printer);
5207 ZERO_STRUCT(driver);
5209 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5210 return WERR_INVALID_PRINTER_NAME;
5212 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5213 free_a_printer(&printer, 2);
5214 return WERR_UNKNOWN_PRINTER_DRIVER;
5217 fill_printer_driver_info_2(info, driver, servername);
5219 free_a_printer(&printer,2);
5224 /********************************************************************
5225 * copy a strings array and convert to UNICODE
5227 * convert an array of ascii string to a UNICODE string
5228 ********************************************************************/
5230 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5237 DEBUG(6,("init_unistr_array\n"));
5248 v = ""; /* hack to handle null lists */
5251 /* hack to allow this to be used in places other than when generating
5252 the list of dependent files */
5255 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5259 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5261 /* add one extra unit16 for the second terminating NULL */
5263 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5264 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5271 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5276 /* special case for ""; we need to add both NULL's here */
5278 (*uni_array)[j++]=0x0000;
5279 (*uni_array)[j]=0x0000;
5282 DEBUGADD(6,("last one:done\n"));
5284 /* return size of array in uint16's */
5289 /********************************************************************
5290 * construct_printer_info_3
5291 * fill a printer_info_3 struct
5292 ********************************************************************/
5294 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5300 info->version=driver.info_3->cversion;
5302 init_unistr( &info->name, driver.info_3->name );
5303 init_unistr( &info->architecture, driver.info_3->environment );
5305 if (strlen(driver.info_3->driverpath)) {
5306 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5307 init_unistr( &info->driverpath, temp );
5309 init_unistr( &info->driverpath, "" );
5311 if (strlen(driver.info_3->datafile)) {
5312 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5313 init_unistr( &info->datafile, temp );
5315 init_unistr( &info->datafile, "" );
5317 if (strlen(driver.info_3->configfile)) {
5318 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5319 init_unistr( &info->configfile, temp );
5321 init_unistr( &info->configfile, "" );
5323 if (strlen(driver.info_3->helpfile)) {
5324 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5325 init_unistr( &info->helpfile, temp );
5327 init_unistr( &info->helpfile, "" );
5329 init_unistr( &info->monitorname, driver.info_3->monitorname );
5330 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5332 info->dependentfiles=NULL;
5333 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5336 /********************************************************************
5337 * construct_printer_info_3
5338 * fill a printer_info_3 struct
5339 ********************************************************************/
5341 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5343 NT_PRINTER_INFO_LEVEL *printer = NULL;
5344 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5346 ZERO_STRUCT(driver);
5348 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5349 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5350 if (!W_ERROR_IS_OK(status))
5351 return WERR_INVALID_PRINTER_NAME;
5353 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5354 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5359 * I put this code in during testing. Helpful when commenting out the
5360 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5361 * as win2k always queries the driver using an infor level of 6.
5362 * I've left it in (but ifdef'd out) because I'll probably
5363 * use it in experimentation again in the future. --jerry 22/01/2002
5366 if (!W_ERROR_IS_OK(status)) {
5368 * Is this a W2k client ?
5371 /* Yes - try again with a WinNT driver. */
5373 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5374 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5378 if (!W_ERROR_IS_OK(status)) {
5379 free_a_printer(&printer,2);
5380 return WERR_UNKNOWN_PRINTER_DRIVER;
5388 fill_printer_driver_info_3(info, driver, servername);
5390 free_a_printer(&printer,2);
5395 /********************************************************************
5396 * construct_printer_info_6
5397 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5398 ********************************************************************/
5400 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5406 memset(&nullstr, '\0', sizeof(fstring));
5408 info->version=driver.info_3->cversion;
5410 init_unistr( &info->name, driver.info_3->name );
5411 init_unistr( &info->architecture, driver.info_3->environment );
5413 if (strlen(driver.info_3->driverpath)) {
5414 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5415 init_unistr( &info->driverpath, temp );
5417 init_unistr( &info->driverpath, "" );
5419 if (strlen(driver.info_3->datafile)) {
5420 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5421 init_unistr( &info->datafile, temp );
5423 init_unistr( &info->datafile, "" );
5425 if (strlen(driver.info_3->configfile)) {
5426 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5427 init_unistr( &info->configfile, temp );
5429 init_unistr( &info->configfile, "" );
5431 if (strlen(driver.info_3->helpfile)) {
5432 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5433 init_unistr( &info->helpfile, temp );
5435 init_unistr( &info->helpfile, "" );
5437 init_unistr( &info->monitorname, driver.info_3->monitorname );
5438 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5440 info->dependentfiles = NULL;
5441 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5443 info->previousdrivernames=NULL;
5444 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5446 info->driver_date=0;
5449 info->driver_version_low=0;
5450 info->driver_version_high=0;
5452 init_unistr( &info->mfgname, "");
5453 init_unistr( &info->oem_url, "");
5454 init_unistr( &info->hardware_id, "");
5455 init_unistr( &info->provider, "");
5458 /********************************************************************
5459 * construct_printer_info_6
5460 * fill a printer_info_6 struct
5461 ********************************************************************/
5463 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5464 fstring servername, fstring architecture, uint32 version)
5466 NT_PRINTER_INFO_LEVEL *printer = NULL;
5467 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5470 ZERO_STRUCT(driver);
5472 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5474 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5476 if (!W_ERROR_IS_OK(status))
5477 return WERR_INVALID_PRINTER_NAME;
5479 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5481 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5483 if (!W_ERROR_IS_OK(status))
5486 * Is this a W2k client ?
5490 free_a_printer(&printer,2);
5491 return WERR_UNKNOWN_PRINTER_DRIVER;
5494 /* Yes - try again with a WinNT driver. */
5496 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5497 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5498 if (!W_ERROR_IS_OK(status)) {
5499 free_a_printer(&printer,2);
5500 return WERR_UNKNOWN_PRINTER_DRIVER;
5504 fill_printer_driver_info_6(info, driver, servername);
5506 free_a_printer(&printer,2);
5507 free_a_printer_driver(driver, 3);
5512 /****************************************************************************
5513 ****************************************************************************/
5515 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5517 SAFE_FREE(info->dependentfiles);
5520 /****************************************************************************
5521 ****************************************************************************/
5523 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5525 SAFE_FREE(info->dependentfiles);
5528 /****************************************************************************
5529 ****************************************************************************/
5531 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5533 DRIVER_INFO_1 *info=NULL;
5536 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5539 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5540 if (!W_ERROR_IS_OK(result))
5543 /* check the required size. */
5544 *needed += spoolss_size_printer_driver_info_1(info);
5546 if (*needed > offered) {
5547 result = WERR_INSUFFICIENT_BUFFER;
5551 if (!rpcbuf_alloc_size(buffer, *needed)) {
5552 result = WERR_NOMEM;
5556 /* fill the buffer with the structures */
5557 smb_io_printer_driver_info_1("", buffer, info, 0);
5566 /****************************************************************************
5567 ****************************************************************************/
5569 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5571 DRIVER_INFO_2 *info=NULL;
5574 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5577 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5578 if (!W_ERROR_IS_OK(result))
5581 /* check the required size. */
5582 *needed += spoolss_size_printer_driver_info_2(info);
5584 if (*needed > offered) {
5585 result = WERR_INSUFFICIENT_BUFFER;
5589 if (!rpcbuf_alloc_size(buffer, *needed)) {
5590 result = WERR_NOMEM;
5594 /* fill the buffer with the structures */
5595 smb_io_printer_driver_info_2("", buffer, info, 0);
5604 /****************************************************************************
5605 ****************************************************************************/
5607 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5614 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5615 if (!W_ERROR_IS_OK(result))
5618 /* check the required size. */
5619 *needed += spoolss_size_printer_driver_info_3(&info);
5621 if (*needed > offered) {
5622 result = WERR_INSUFFICIENT_BUFFER;
5626 if (!rpcbuf_alloc_size(buffer, *needed)) {
5627 result = WERR_NOMEM;
5631 /* fill the buffer with the structures */
5632 smb_io_printer_driver_info_3("", buffer, &info, 0);
5635 free_printer_driver_info_3(&info);
5640 /****************************************************************************
5641 ****************************************************************************/
5643 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5650 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5651 if (!W_ERROR_IS_OK(result))
5654 /* check the required size. */
5655 *needed += spoolss_size_printer_driver_info_6(&info);
5657 if (*needed > offered) {
5658 result = WERR_INSUFFICIENT_BUFFER;
5662 if (!rpcbuf_alloc_size(buffer, *needed)) {
5663 result = WERR_NOMEM;
5667 /* fill the buffer with the structures */
5668 smb_io_printer_driver_info_6("", buffer, &info, 0);
5671 free_printer_driver_info_6(&info);
5676 /****************************************************************************
5677 ****************************************************************************/
5679 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5681 POLICY_HND *handle = &q_u->handle;
5682 UNISTR2 *uni_arch = &q_u->architecture;
5683 uint32 level = q_u->level;
5684 uint32 clientmajorversion = q_u->clientmajorversion;
5685 RPC_BUFFER *buffer = NULL;
5686 uint32 offered = q_u->offered;
5687 uint32 *needed = &r_u->needed;
5688 uint32 *servermajorversion = &r_u->servermajorversion;
5689 uint32 *serverminorversion = &r_u->serverminorversion;
5690 Printer_entry *printer;
5693 fstring architecture;
5696 /* that's an [in out] buffer */
5698 if (!q_u->buffer && (offered!=0)) {
5699 return WERR_INVALID_PARAM;
5702 rpcbuf_move(q_u->buffer, &r_u->buffer);
5703 buffer = r_u->buffer;
5705 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5707 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5708 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5709 return WERR_INVALID_PRINTER_NAME;
5713 *servermajorversion = 0;
5714 *serverminorversion = 0;
5716 fstrcpy(servername, get_server_name( printer ));
5717 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5719 if (!get_printer_snum(p, handle, &snum, NULL))
5724 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5726 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5728 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5730 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5733 /* apparently this call is the equivalent of
5734 EnumPrinterDataEx() for the DsDriver key */
5739 return WERR_UNKNOWN_LEVEL;
5742 /****************************************************************************
5743 ****************************************************************************/
5745 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5747 POLICY_HND *handle = &q_u->handle;
5749 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5752 DEBUG(3,("Error in startpageprinter printer handle\n"));
5756 Printer->page_started=True;
5760 /****************************************************************************
5761 ****************************************************************************/
5763 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5765 POLICY_HND *handle = &q_u->handle;
5768 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5771 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5775 if (!get_printer_snum(p, handle, &snum, NULL))
5778 Printer->page_started=False;
5779 print_job_endpage(snum, Printer->jobid);
5784 /********************************************************************
5785 * api_spoolss_getprinter
5786 * called from the spoolss dispatcher
5788 ********************************************************************/
5790 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5792 POLICY_HND *handle = &q_u->handle;
5793 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5794 uint32 *jobid = &r_u->jobid;
5796 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5800 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5803 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5808 * a nice thing with NT is it doesn't listen to what you tell it.
5809 * when asked to send _only_ RAW datas, it tries to send datas
5812 * So I add checks like in NT Server ...
5815 if (info_1->p_datatype != 0) {
5816 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5817 if (strcmp(datatype, "RAW") != 0) {
5819 return WERR_INVALID_DATATYPE;
5823 /* get the share number of the printer */
5824 if (!get_printer_snum(p, handle, &snum, NULL)) {
5828 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5830 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5832 /* An error occured in print_job_start() so return an appropriate
5835 if (Printer->jobid == -1) {
5836 return map_werror_from_unix(errno);
5839 Printer->document_started=True;
5840 (*jobid) = Printer->jobid;
5845 /********************************************************************
5846 * api_spoolss_getprinter
5847 * called from the spoolss dispatcher
5849 ********************************************************************/
5851 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5853 POLICY_HND *handle = &q_u->handle;
5855 return _spoolss_enddocprinter_internal(p, handle);
5858 /****************************************************************************
5859 ****************************************************************************/
5861 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5863 POLICY_HND *handle = &q_u->handle;
5864 uint32 buffer_size = q_u->buffer_size;
5865 uint8 *buffer = q_u->buffer;
5866 uint32 *buffer_written = &q_u->buffer_size2;
5868 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5871 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5872 r_u->buffer_written = q_u->buffer_size2;
5876 if (!get_printer_snum(p, handle, &snum, NULL))
5879 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5880 (SMB_OFF_T)-1, (size_t)buffer_size);
5881 if (*buffer_written == (uint32)-1) {
5882 r_u->buffer_written = 0;
5883 if (errno == ENOSPC)
5884 return WERR_NO_SPOOL_SPACE;
5886 return WERR_ACCESS_DENIED;
5889 r_u->buffer_written = q_u->buffer_size2;
5894 /********************************************************************
5895 * api_spoolss_getprinter
5896 * called from the spoolss dispatcher
5898 ********************************************************************/
5900 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5904 WERROR errcode = WERR_BADFUNC;
5905 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5908 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5912 if (!get_printer_snum(p, handle, &snum, NULL))
5916 case PRINTER_CONTROL_PAUSE:
5917 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5921 case PRINTER_CONTROL_RESUME:
5922 case PRINTER_CONTROL_UNPAUSE:
5923 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5927 case PRINTER_CONTROL_PURGE:
5928 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5933 return WERR_UNKNOWN_LEVEL;
5939 /********************************************************************
5940 * api_spoolss_abortprinter
5941 * From MSDN: "Deletes printer's spool file if printer is configured
5943 ********************************************************************/
5945 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5947 POLICY_HND *handle = &q_u->handle;
5948 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5950 WERROR errcode = WERR_OK;
5953 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5957 if (!get_printer_snum(p, handle, &snum, NULL))
5960 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5965 /********************************************************************
5966 * called by spoolss_api_setprinter
5967 * when updating a printer description
5968 ********************************************************************/
5970 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5971 const SPOOL_PRINTER_INFO_LEVEL *info,
5972 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5974 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5978 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5980 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5981 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5982 OUR_HANDLE(handle)));
5984 result = WERR_BADFID;
5988 /* Check the user has permissions to change the security
5989 descriptor. By experimentation with two NT machines, the user
5990 requires Full Access to the printer to change security
5993 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5994 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5995 result = WERR_ACCESS_DENIED;
5999 /* NT seems to like setting the security descriptor even though
6000 nothing may have actually changed. */
6002 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
6004 if (DEBUGLEVEL >= 10) {
6008 the_acl = old_secdesc_ctr->sd->dacl;
6009 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6010 PRINTERNAME(snum), the_acl->num_aces));
6012 for (i = 0; i < the_acl->num_aces; i++) {
6015 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6017 DEBUG(10, ("%s 0x%08x\n", sid_str,
6018 the_acl->aces[i].access_mask));
6021 the_acl = secdesc_ctr->sd->dacl;
6024 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6025 PRINTERNAME(snum), the_acl->num_aces));
6027 for (i = 0; i < the_acl->num_aces; i++) {
6030 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6032 DEBUG(10, ("%s 0x%08x\n", sid_str,
6033 the_acl->aces[i].access_mask));
6036 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6040 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6041 if (!new_secdesc_ctr) {
6042 result = WERR_NOMEM;
6046 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6051 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6058 /********************************************************************
6059 Canonicalize printer info from a client
6061 ATTN: It does not matter what we set the servername to hear
6062 since we do the necessary work in get_a_printer() to set it to
6063 the correct value based on what the client sent in the
6064 _spoolss_open_printer_ex().
6065 ********************************************************************/
6067 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6069 fstring printername;
6072 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6073 "portname=%s drivername=%s comment=%s location=%s\n",
6074 info->servername, info->printername, info->sharename,
6075 info->portname, info->drivername, info->comment, info->location));
6077 /* we force some elements to "correct" values */
6078 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6079 fstrcpy(info->sharename, lp_servicename(snum));
6081 /* check to see if we allow printername != sharename */
6083 if ( lp_force_printername(snum) ) {
6084 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6085 global_myname(), info->sharename );
6088 /* make sure printername is in \\server\printername format */
6090 fstrcpy( printername, info->printername );
6092 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6093 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6097 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6098 global_myname(), p );
6101 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6102 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6109 /****************************************************************************
6110 ****************************************************************************/
6112 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
6114 char *cmd = lp_addport_cmd();
6118 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6119 BOOL is_print_op = False;
6122 return WERR_ACCESS_DENIED;
6125 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
6128 is_print_op = user_has_privileges( token, &se_printop );
6130 DEBUG(10,("Running [%s]\n", command));
6132 /********* BEGIN SePrintOperatorPrivilege **********/
6137 ret = smbrun(command, &fd);
6142 /********* END SePrintOperatorPrivilege **********/
6144 DEBUGADD(10,("returned [%d]\n", ret));
6149 return WERR_ACCESS_DENIED;
6155 /****************************************************************************
6156 ****************************************************************************/
6158 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6160 char *cmd = lp_addprinter_cmd();
6166 fstring remote_machine = "%m";
6167 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6168 BOOL is_print_op = False;
6170 standard_sub_basic(current_user_info.smb_name,
6171 current_user_info.domain,
6172 remote_machine,sizeof(remote_machine));
6174 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6175 cmd, printer->info_2->printername, printer->info_2->sharename,
6176 printer->info_2->portname, printer->info_2->drivername,
6177 printer->info_2->location, printer->info_2->comment, remote_machine);
6180 is_print_op = user_has_privileges( token, &se_printop );
6182 DEBUG(10,("Running [%s]\n", command));
6184 /********* BEGIN SePrintOperatorPrivilege **********/
6189 if ( (ret = smbrun(command, &fd)) == 0 ) {
6190 /* Tell everyone we updated smb.conf. */
6191 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6197 /********* END SePrintOperatorPrivilege **********/
6199 DEBUGADD(10,("returned [%d]\n", ret));
6207 /* reload our services immediately */
6208 reload_services( False );
6211 /* Get lines and convert them back to dos-codepage */
6212 qlines = fd_lines_load(fd, &numlines, 0);
6213 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6216 /* Set the portname to what the script says the portname should be. */
6217 /* but don't require anything to be return from the script exit a good error code */
6220 /* Set the portname to what the script says the portname should be. */
6221 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6222 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6225 file_lines_free(qlines);
6230 /********************************************************************
6231 * Called by spoolss_api_setprinter
6232 * when updating a printer description.
6233 ********************************************************************/
6235 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6236 const SPOOL_PRINTER_INFO_LEVEL *info,
6237 DEVICEMODE *devmode)
6240 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6241 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6246 DEBUG(8,("update_printer\n"));
6251 result = WERR_BADFID;
6255 if (!get_printer_snum(p, handle, &snum, NULL)) {
6256 result = WERR_BADFID;
6260 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6261 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6262 result = WERR_BADFID;
6266 DEBUGADD(8,("Converting info_2 struct\n"));
6269 * convert_printer_info converts the incoming
6270 * info from the client and overwrites the info
6271 * just read from the tdb in the pointer 'printer'.
6274 if (!convert_printer_info(info, printer, level)) {
6275 result = WERR_NOMEM;
6280 /* we have a valid devmode
6281 convert it and link it*/
6283 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6284 if (!convert_devicemode(printer->info_2->printername, devmode,
6285 &printer->info_2->devmode)) {
6286 result = WERR_NOMEM;
6291 /* Do sanity check on the requested changes for Samba */
6293 if (!check_printer_ok(printer->info_2, snum)) {
6294 result = WERR_INVALID_PARAM;
6298 /* FIXME!!! If the driver has changed we really should verify that
6299 it is installed before doing much else --jerry */
6301 /* Check calling user has permission to update printer description */
6303 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6304 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6305 result = WERR_ACCESS_DENIED;
6309 /* Call addprinter hook */
6310 /* Check changes to see if this is really needed */
6312 if ( *lp_addprinter_cmd()
6313 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6314 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6315 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6316 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6318 /* add_printer_hook() will call reload_services() */
6320 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6321 result = WERR_ACCESS_DENIED;
6327 * When a *new* driver is bound to a printer, the drivername is used to
6328 * lookup previously saved driver initialization info, which is then
6329 * bound to the printer, simulating what happens in the Windows arch.
6331 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6333 if (!set_driver_init(printer, 2))
6335 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6336 printer->info_2->drivername));
6339 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6340 printer->info_2->drivername));
6342 notify_printer_driver(snum, printer->info_2->drivername);
6346 * flag which changes actually occured. This is a small subset of
6347 * all the possible changes. We also have to update things in the
6351 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6352 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6353 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6354 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6356 notify_printer_comment(snum, printer->info_2->comment);
6359 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6360 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6361 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6362 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6364 notify_printer_sharename(snum, printer->info_2->sharename);
6367 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6370 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6373 pname = printer->info_2->printername;
6376 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6377 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6378 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6380 notify_printer_printername( snum, pname );
6383 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6384 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6385 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6386 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6388 notify_printer_port(snum, printer->info_2->portname);
6391 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6392 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6393 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6394 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6396 notify_printer_location(snum, printer->info_2->location);
6399 /* here we need to update some more DsSpooler keys */
6400 /* uNCName, serverName, shortServerName */
6402 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6403 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6404 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6405 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6406 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6408 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6409 global_myname(), printer->info_2->sharename );
6410 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6411 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6412 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6414 /* Update printer info */
6415 result = mod_a_printer(printer, 2);
6418 free_a_printer(&printer, 2);
6419 free_a_printer(&old_printer, 2);
6425 /****************************************************************************
6426 ****************************************************************************/
6427 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6428 const SPOOL_PRINTER_INFO_LEVEL *info)
6431 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6433 Printer_entry *Printer;
6435 if ( lp_security() != SEC_ADS ) {
6436 return WERR_UNKNOWN_LEVEL;
6439 Printer = find_printer_index_by_hnd(p, handle);
6441 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6446 if (!get_printer_snum(p, handle, &snum, NULL))
6449 nt_printer_publish(Printer, snum, info7->action);
6453 return WERR_UNKNOWN_LEVEL;
6456 /****************************************************************************
6457 ****************************************************************************/
6459 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6461 POLICY_HND *handle = &q_u->handle;
6462 uint32 level = q_u->level;
6463 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6464 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6465 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6466 uint32 command = q_u->command;
6469 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6472 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6476 /* check the level */
6479 return control_printer(handle, command, p);
6481 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6482 if (!W_ERROR_IS_OK(result))
6485 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6488 return update_printer_sec(handle, level, info, p,
6491 return publish_or_unpublish_printer(p, handle, info);
6493 return WERR_UNKNOWN_LEVEL;
6497 /****************************************************************************
6498 ****************************************************************************/
6500 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6502 POLICY_HND *handle = &q_u->handle;
6503 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6506 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6510 if (Printer->notify.client_connected==True) {
6513 if ( Printer->printer_type == SPLHND_SERVER)
6515 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6516 !get_printer_snum(p, handle, &snum, NULL) )
6519 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6522 Printer->notify.flags=0;
6523 Printer->notify.options=0;
6524 Printer->notify.localmachine[0]='\0';
6525 Printer->notify.printerlocal=0;
6526 if (Printer->notify.option)
6527 free_spool_notify_option(&Printer->notify.option);
6528 Printer->notify.client_connected=False;
6533 /****************************************************************************
6534 ****************************************************************************/
6536 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6538 /* that's an [in out] buffer */
6540 if (!q_u->buffer && (q_u->offered!=0)) {
6541 return WERR_INVALID_PARAM;
6544 rpcbuf_move(q_u->buffer, &r_u->buffer);
6547 return WERR_INVALID_PARAM; /* this is what a NT server
6548 returns for AddJob. AddJob
6549 must fail on non-local
6553 /****************************************************************************
6554 ****************************************************************************/
6556 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6557 int position, int snum,
6558 const NT_PRINTER_INFO_LEVEL *ntprinter)
6562 t=gmtime(&queue->time);
6564 job_info->jobid=queue->job;
6565 init_unistr(&job_info->printername, lp_servicename(snum));
6566 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6567 init_unistr(&job_info->username, queue->fs_user);
6568 init_unistr(&job_info->document, queue->fs_file);
6569 init_unistr(&job_info->datatype, "RAW");
6570 init_unistr(&job_info->text_status, "");
6571 job_info->status=nt_printj_status(queue->status);
6572 job_info->priority=queue->priority;
6573 job_info->position=position;
6574 job_info->totalpages=queue->page_count;
6575 job_info->pagesprinted=0;
6577 make_systemtime(&job_info->submitted, t);
6580 /****************************************************************************
6581 ****************************************************************************/
6583 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6584 int position, int snum,
6585 const NT_PRINTER_INFO_LEVEL *ntprinter,
6586 DEVICEMODE *devmode)
6590 t=gmtime(&queue->time);
6592 job_info->jobid=queue->job;
6594 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6596 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6597 init_unistr(&job_info->username, queue->fs_user);
6598 init_unistr(&job_info->document, queue->fs_file);
6599 init_unistr(&job_info->notifyname, queue->fs_user);
6600 init_unistr(&job_info->datatype, "RAW");
6601 init_unistr(&job_info->printprocessor, "winprint");
6602 init_unistr(&job_info->parameters, "");
6603 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6604 init_unistr(&job_info->text_status, "");
6606 /* and here the security descriptor */
6608 job_info->status=nt_printj_status(queue->status);
6609 job_info->priority=queue->priority;
6610 job_info->position=position;
6611 job_info->starttime=0;
6612 job_info->untiltime=0;
6613 job_info->totalpages=queue->page_count;
6614 job_info->size=queue->size;
6615 make_systemtime(&(job_info->submitted), t);
6616 job_info->timeelapsed=0;
6617 job_info->pagesprinted=0;
6619 job_info->devmode = devmode;
6624 /****************************************************************************
6625 Enumjobs at level 1.
6626 ****************************************************************************/
6628 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6629 const NT_PRINTER_INFO_LEVEL *ntprinter,
6630 RPC_BUFFER *buffer, uint32 offered,
6631 uint32 *needed, uint32 *returned)
6635 WERROR result = WERR_OK;
6637 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6643 for (i=0; i<*returned; i++)
6644 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6646 /* check the required size. */
6647 for (i=0; i<*returned; i++)
6648 (*needed) += spoolss_size_job_info_1(&info[i]);
6650 if (*needed > offered) {
6651 result = WERR_INSUFFICIENT_BUFFER;
6655 if (!rpcbuf_alloc_size(buffer, *needed)) {
6656 result = WERR_NOMEM;
6660 /* fill the buffer with the structures */
6661 for (i=0; i<*returned; i++)
6662 smb_io_job_info_1("", buffer, &info[i], 0);
6668 if ( !W_ERROR_IS_OK(result) )
6674 /****************************************************************************
6675 Enumjobs at level 2.
6676 ****************************************************************************/
6678 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6679 const NT_PRINTER_INFO_LEVEL *ntprinter,
6680 RPC_BUFFER *buffer, uint32 offered,
6681 uint32 *needed, uint32 *returned)
6683 JOB_INFO_2 *info = NULL;
6685 WERROR result = WERR_OK;
6686 DEVICEMODE *devmode = NULL;
6688 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6693 /* this should not be a failure condition if the devmode is NULL */
6695 devmode = construct_dev_mode(lp_const_servicename(snum));
6697 for (i=0; i<*returned; i++)
6698 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6700 /* check the required size. */
6701 for (i=0; i<*returned; i++)
6702 (*needed) += spoolss_size_job_info_2(&info[i]);
6704 if (*needed > offered) {
6705 result = WERR_INSUFFICIENT_BUFFER;
6709 if (!rpcbuf_alloc_size(buffer, *needed)) {
6710 result = WERR_NOMEM;
6714 /* fill the buffer with the structures */
6715 for (i=0; i<*returned; i++)
6716 smb_io_job_info_2("", buffer, &info[i], 0);
6719 free_devmode(devmode);
6722 if ( !W_ERROR_IS_OK(result) )
6729 /****************************************************************************
6731 ****************************************************************************/
6733 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6735 POLICY_HND *handle = &q_u->handle;
6736 uint32 level = q_u->level;
6737 RPC_BUFFER *buffer = NULL;
6738 uint32 offered = q_u->offered;
6739 uint32 *needed = &r_u->needed;
6740 uint32 *returned = &r_u->returned;
6742 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6744 print_status_struct prt_status;
6745 print_queue_struct *queue=NULL;
6747 /* that's an [in out] buffer */
6749 if (!q_u->buffer && (offered!=0)) {
6750 return WERR_INVALID_PARAM;
6753 rpcbuf_move(q_u->buffer, &r_u->buffer);
6754 buffer = r_u->buffer;
6756 DEBUG(4,("_spoolss_enumjobs\n"));
6761 /* lookup the printer snum and tdb entry */
6763 if (!get_printer_snum(p, handle, &snum, NULL))
6766 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6767 if ( !W_ERROR_IS_OK(wret) )
6770 *returned = print_queue_status(snum, &queue, &prt_status);
6771 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6773 if (*returned == 0) {
6775 free_a_printer(&ntprinter, 2);
6781 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6784 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6788 wret = WERR_UNKNOWN_LEVEL;
6793 free_a_printer( &ntprinter, 2 );
6797 /****************************************************************************
6798 ****************************************************************************/
6800 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6805 /****************************************************************************
6806 ****************************************************************************/
6808 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6810 POLICY_HND *handle = &q_u->handle;
6811 uint32 jobid = q_u->jobid;
6812 uint32 command = q_u->command;
6815 WERROR errcode = WERR_BADFUNC;
6817 if (!get_printer_snum(p, handle, &snum, NULL)) {
6821 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6822 return WERR_INVALID_PRINTER_NAME;
6826 case JOB_CONTROL_CANCEL:
6827 case JOB_CONTROL_DELETE:
6828 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6832 case JOB_CONTROL_PAUSE:
6833 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6837 case JOB_CONTROL_RESTART:
6838 case JOB_CONTROL_RESUME:
6839 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6844 return WERR_UNKNOWN_LEVEL;
6850 /****************************************************************************
6851 Enumerates all printer drivers at level 1.
6852 ****************************************************************************/
6854 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6859 fstring *list = NULL;
6860 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6861 DRIVER_INFO_1 *driver_info_1=NULL;
6862 WERROR result = WERR_OK;
6866 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6868 ndrivers=get_ntdrivers(&list, architecture, version);
6869 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6871 if(ndrivers == -1) {
6872 SAFE_FREE(driver_info_1);
6877 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6878 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6884 for (i=0; i<ndrivers; i++) {
6886 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6887 ZERO_STRUCT(driver);
6888 status = get_a_printer_driver(&driver, 3, list[i],
6889 architecture, version);
6890 if (!W_ERROR_IS_OK(status)) {
6892 SAFE_FREE(driver_info_1);
6895 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6896 free_a_printer_driver(driver, 3);
6899 *returned+=ndrivers;
6903 /* check the required size. */
6904 for (i=0; i<*returned; i++) {
6905 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6906 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6909 if (*needed > offered) {
6910 result = WERR_INSUFFICIENT_BUFFER;
6914 if (!rpcbuf_alloc_size(buffer, *needed)) {
6915 result = WERR_NOMEM;
6919 /* fill the buffer with the driver structures */
6920 for (i=0; i<*returned; i++) {
6921 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6922 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6926 SAFE_FREE(driver_info_1);
6928 if ( !W_ERROR_IS_OK(result) )
6934 /****************************************************************************
6935 Enumerates all printer drivers at level 2.
6936 ****************************************************************************/
6938 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6943 fstring *list = NULL;
6944 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6945 DRIVER_INFO_2 *driver_info_2=NULL;
6946 WERROR result = WERR_OK;
6950 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6952 ndrivers=get_ntdrivers(&list, architecture, version);
6953 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6955 if(ndrivers == -1) {
6956 SAFE_FREE(driver_info_2);
6961 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6962 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6968 for (i=0; i<ndrivers; i++) {
6971 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6972 ZERO_STRUCT(driver);
6973 status = get_a_printer_driver(&driver, 3, list[i],
6974 architecture, version);
6975 if (!W_ERROR_IS_OK(status)) {
6977 SAFE_FREE(driver_info_2);
6980 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6981 free_a_printer_driver(driver, 3);
6984 *returned+=ndrivers;
6988 /* check the required size. */
6989 for (i=0; i<*returned; i++) {
6990 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6991 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6994 if (*needed > offered) {
6995 result = WERR_INSUFFICIENT_BUFFER;
6999 if (!rpcbuf_alloc_size(buffer, *needed)) {
7000 result = WERR_NOMEM;
7004 /* fill the buffer with the form structures */
7005 for (i=0; i<*returned; i++) {
7006 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7007 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7011 SAFE_FREE(driver_info_2);
7013 if ( !W_ERROR_IS_OK(result) )
7019 /****************************************************************************
7020 Enumerates all printer drivers at level 3.
7021 ****************************************************************************/
7023 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7028 fstring *list = NULL;
7029 DRIVER_INFO_3 *driver_info_3=NULL;
7030 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7031 WERROR result = WERR_OK;
7035 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7037 ndrivers=get_ntdrivers(&list, architecture, version);
7038 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7040 if(ndrivers == -1) {
7041 SAFE_FREE(driver_info_3);
7046 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7047 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7053 for (i=0; i<ndrivers; i++) {
7056 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7057 ZERO_STRUCT(driver);
7058 status = get_a_printer_driver(&driver, 3, list[i],
7059 architecture, version);
7060 if (!W_ERROR_IS_OK(status)) {
7062 SAFE_FREE(driver_info_3);
7065 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7066 free_a_printer_driver(driver, 3);
7069 *returned+=ndrivers;
7073 /* check the required size. */
7074 for (i=0; i<*returned; i++) {
7075 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7076 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7079 if (*needed > offered) {
7080 result = WERR_INSUFFICIENT_BUFFER;
7084 if (!rpcbuf_alloc_size(buffer, *needed)) {
7085 result = WERR_NOMEM;
7089 /* fill the buffer with the driver structures */
7090 for (i=0; i<*returned; i++) {
7091 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7092 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7096 for (i=0; i<*returned; i++) {
7097 SAFE_FREE(driver_info_3[i].dependentfiles);
7100 SAFE_FREE(driver_info_3);
7102 if ( !W_ERROR_IS_OK(result) )
7108 /****************************************************************************
7109 Enumerates all printer drivers.
7110 ****************************************************************************/
7112 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7114 uint32 level = q_u->level;
7115 RPC_BUFFER *buffer = NULL;
7116 uint32 offered = q_u->offered;
7117 uint32 *needed = &r_u->needed;
7118 uint32 *returned = &r_u->returned;
7121 fstring architecture;
7123 /* that's an [in out] buffer */
7125 if (!q_u->buffer && (offered!=0)) {
7126 return WERR_INVALID_PARAM;
7129 rpcbuf_move(q_u->buffer, &r_u->buffer);
7130 buffer = r_u->buffer;
7132 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7137 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7138 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7140 if ( !is_myname_or_ipaddr( servername ) )
7141 return WERR_UNKNOWN_PRINTER_DRIVER;
7145 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7147 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7149 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7151 return WERR_UNKNOWN_LEVEL;
7155 /****************************************************************************
7156 ****************************************************************************/
7158 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7160 form->flag=list->flag;
7161 init_unistr(&form->name, list->name);
7162 form->width=list->width;
7163 form->length=list->length;
7164 form->left=list->left;
7165 form->top=list->top;
7166 form->right=list->right;
7167 form->bottom=list->bottom;
7170 /****************************************************************************
7171 ****************************************************************************/
7173 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7175 uint32 level = q_u->level;
7176 RPC_BUFFER *buffer = NULL;
7177 uint32 offered = q_u->offered;
7178 uint32 *needed = &r_u->needed;
7179 uint32 *numofforms = &r_u->numofforms;
7180 uint32 numbuiltinforms;
7182 nt_forms_struct *list=NULL;
7183 nt_forms_struct *builtinlist=NULL;
7188 /* that's an [in out] buffer */
7190 if (!q_u->buffer && (offered!=0) ) {
7191 return WERR_INVALID_PARAM;
7194 rpcbuf_move(q_u->buffer, &r_u->buffer);
7195 buffer = r_u->buffer;
7197 DEBUG(4,("_spoolss_enumforms\n"));
7198 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7199 DEBUGADD(5,("Info level [%d]\n", level));
7201 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7202 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7203 *numofforms = get_ntforms(&list);
7204 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7205 *numofforms += numbuiltinforms;
7207 if (*numofforms == 0) {
7208 SAFE_FREE(builtinlist);
7210 return WERR_NO_MORE_ITEMS;
7215 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7216 SAFE_FREE(builtinlist);
7222 /* construct the list of form structures */
7223 for (i=0; i<numbuiltinforms; i++) {
7224 DEBUGADD(6,("Filling form number [%d]\n",i));
7225 fill_form_1(&forms_1[i], &builtinlist[i]);
7228 SAFE_FREE(builtinlist);
7230 for (; i<*numofforms; i++) {
7231 DEBUGADD(6,("Filling form number [%d]\n",i));
7232 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7237 /* check the required size. */
7238 for (i=0; i<numbuiltinforms; i++) {
7239 DEBUGADD(6,("adding form [%d]'s size\n",i));
7240 buffer_size += spoolss_size_form_1(&forms_1[i]);
7242 for (; i<*numofforms; i++) {
7243 DEBUGADD(6,("adding form [%d]'s size\n",i));
7244 buffer_size += spoolss_size_form_1(&forms_1[i]);
7247 *needed=buffer_size;
7249 if (*needed > offered) {
7252 return WERR_INSUFFICIENT_BUFFER;
7255 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7261 /* fill the buffer with the form structures */
7262 for (i=0; i<numbuiltinforms; i++) {
7263 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7264 smb_io_form_1("", buffer, &forms_1[i], 0);
7266 for (; i<*numofforms; i++) {
7267 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7268 smb_io_form_1("", buffer, &forms_1[i], 0);
7277 SAFE_FREE(builtinlist);
7278 return WERR_UNKNOWN_LEVEL;
7282 /****************************************************************************
7283 ****************************************************************************/
7285 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7287 uint32 level = q_u->level;
7288 UNISTR2 *uni_formname = &q_u->formname;
7289 RPC_BUFFER *buffer = NULL;
7290 uint32 offered = q_u->offered;
7291 uint32 *needed = &r_u->needed;
7293 nt_forms_struct *list=NULL;
7294 nt_forms_struct builtin_form;
7299 int numofforms=0, i=0;
7301 /* that's an [in out] buffer */
7303 if (!q_u->buffer && (offered!=0)) {
7304 return WERR_INVALID_PARAM;
7307 rpcbuf_move(q_u->buffer, &r_u->buffer);
7308 buffer = r_u->buffer;
7310 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7312 DEBUG(4,("_spoolss_getform\n"));
7313 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7314 DEBUGADD(5,("Info level [%d]\n", level));
7316 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7317 if (!foundBuiltin) {
7318 numofforms = get_ntforms(&list);
7319 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7321 if (numofforms == 0)
7328 fill_form_1(&form_1, &builtin_form);
7331 /* Check if the requested name is in the list of form structures */
7332 for (i=0; i<numofforms; i++) {
7334 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7336 if (strequal(form_name, list[i].name)) {
7337 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7338 fill_form_1(&form_1, &list[i]);
7344 if (i == numofforms) {
7348 /* check the required size. */
7350 *needed=spoolss_size_form_1(&form_1);
7352 if (*needed > offered)
7353 return WERR_INSUFFICIENT_BUFFER;
7355 if (!rpcbuf_alloc_size(buffer, buffer_size))
7358 /* fill the buffer with the form structures */
7359 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7360 smb_io_form_1("", buffer, &form_1, 0);
7366 return WERR_UNKNOWN_LEVEL;
7370 /****************************************************************************
7371 ****************************************************************************/
7373 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7375 init_unistr(&port->port_name, name);
7378 /****************************************************************************
7379 TODO: This probably needs distinguish between TCP/IP and Local ports
7381 ****************************************************************************/
7383 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7385 init_unistr(&port->port_name, name);
7386 init_unistr(&port->monitor_name, "Local Monitor");
7387 init_unistr(&port->description, SPL_LOCAL_PORT );
7388 port->port_type=PORT_TYPE_WRITE;
7393 /****************************************************************************
7394 wrapper around the enumer ports command
7395 ****************************************************************************/
7397 WERROR enumports_hook( int *count, char ***lines )
7399 char *cmd = lp_enumports_cmd();
7409 /* if no hook then just fill in the default port */
7412 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7413 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7418 /* we have a valid enumport command */
7420 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7422 DEBUG(10,("Running [%s]\n", command));
7423 ret = smbrun(command, &fd);
7424 DEBUG(10,("Returned [%d]\n", ret));
7429 return WERR_ACCESS_DENIED;
7433 qlines = fd_lines_load(fd, &numlines, 0);
7434 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7444 /****************************************************************************
7446 ****************************************************************************/
7448 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7450 PORT_INFO_1 *ports=NULL;
7452 WERROR result = WERR_OK;
7453 char **qlines = NULL;
7456 result = enumports_hook( &numlines, &qlines );
7457 if (!W_ERROR_IS_OK(result)) {
7458 file_lines_free(qlines);
7463 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7464 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7465 dos_errstr(WERR_NOMEM)));
7466 file_lines_free(qlines);
7470 for (i=0; i<numlines; i++) {
7471 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7472 fill_port_1(&ports[i], qlines[i]);
7475 file_lines_free(qlines);
7477 *returned = numlines;
7479 /* check the required size. */
7480 for (i=0; i<*returned; i++) {
7481 DEBUGADD(6,("adding port [%d]'s size\n", i));
7482 *needed += spoolss_size_port_info_1(&ports[i]);
7485 if (*needed > offered) {
7486 result = WERR_INSUFFICIENT_BUFFER;
7490 if (!rpcbuf_alloc_size(buffer, *needed)) {
7491 result = WERR_NOMEM;
7495 /* fill the buffer with the ports structures */
7496 for (i=0; i<*returned; i++) {
7497 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7498 smb_io_port_1("", buffer, &ports[i], 0);
7504 if ( !W_ERROR_IS_OK(result) )
7510 /****************************************************************************
7512 ****************************************************************************/
7514 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7516 PORT_INFO_2 *ports=NULL;
7518 WERROR result = WERR_OK;
7519 char **qlines = NULL;
7522 result = enumports_hook( &numlines, &qlines );
7523 if ( !W_ERROR_IS_OK(result)) {
7524 file_lines_free(qlines);
7529 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7530 file_lines_free(qlines);
7534 for (i=0; i<numlines; i++) {
7535 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7536 fill_port_2(&(ports[i]), qlines[i]);
7540 file_lines_free(qlines);
7542 *returned = numlines;
7544 /* check the required size. */
7545 for (i=0; i<*returned; i++) {
7546 DEBUGADD(6,("adding port [%d]'s size\n", i));
7547 *needed += spoolss_size_port_info_2(&ports[i]);
7550 if (*needed > offered) {
7551 result = WERR_INSUFFICIENT_BUFFER;
7555 if (!rpcbuf_alloc_size(buffer, *needed)) {
7556 result = WERR_NOMEM;
7560 /* fill the buffer with the ports structures */
7561 for (i=0; i<*returned; i++) {
7562 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7563 smb_io_port_2("", buffer, &ports[i], 0);
7569 if ( !W_ERROR_IS_OK(result) )
7575 /****************************************************************************
7577 ****************************************************************************/
7579 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7581 uint32 level = q_u->level;
7582 RPC_BUFFER *buffer = NULL;
7583 uint32 offered = q_u->offered;
7584 uint32 *needed = &r_u->needed;
7585 uint32 *returned = &r_u->returned;
7587 /* that's an [in out] buffer */
7589 if (!q_u->buffer && (offered!=0)) {
7590 return WERR_INVALID_PARAM;
7593 rpcbuf_move(q_u->buffer, &r_u->buffer);
7594 buffer = r_u->buffer;
7596 DEBUG(4,("_spoolss_enumports\n"));
7603 return enumports_level_1(buffer, offered, needed, returned);
7605 return enumports_level_2(buffer, offered, needed, returned);
7607 return WERR_UNKNOWN_LEVEL;
7611 /****************************************************************************
7612 ****************************************************************************/
7614 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7615 const SPOOL_PRINTER_INFO_LEVEL *info,
7616 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7617 uint32 user_switch, const SPOOL_USER_CTR *user,
7620 NT_PRINTER_INFO_LEVEL *printer = NULL;
7623 WERROR err = WERR_OK;
7625 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7626 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7630 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7631 if (!convert_printer_info(info, printer, 2)) {
7632 free_a_printer(&printer, 2);
7636 /* check to see if the printer already exists */
7638 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7639 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7640 printer->info_2->sharename));
7641 free_a_printer(&printer, 2);
7642 return WERR_PRINTER_ALREADY_EXISTS;
7645 /* FIXME!!! smbd should check to see if the driver is installed before
7646 trying to add a printer like this --jerry */
7648 if (*lp_addprinter_cmd() ) {
7649 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7650 free_a_printer(&printer,2);
7651 return WERR_ACCESS_DENIED;
7654 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7655 "smb.conf parameter \"addprinter command\" is defined. This"
7656 "parameter must exist for this call to succeed\n",
7657 printer->info_2->sharename ));
7660 /* use our primary netbios name since get_a_printer() will convert
7661 it to what the client expects on a case by case basis */
7663 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7664 printer->info_2->sharename);
7667 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7668 free_a_printer(&printer,2);
7669 return WERR_ACCESS_DENIED;
7672 /* you must be a printer admin to add a new printer */
7673 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7674 free_a_printer(&printer,2);
7675 return WERR_ACCESS_DENIED;
7679 * Do sanity check on the requested changes for Samba.
7682 if (!check_printer_ok(printer->info_2, snum)) {
7683 free_a_printer(&printer,2);
7684 return WERR_INVALID_PARAM;
7688 * When a printer is created, the drivername bound to the printer is used
7689 * to lookup previously saved driver initialization info, which is then
7690 * bound to the new printer, simulating what happens in the Windows arch.
7695 set_driver_init(printer, 2);
7699 /* A valid devmode was included, convert and link it
7701 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7703 if (!convert_devicemode(printer->info_2->printername, devmode,
7704 &printer->info_2->devmode))
7708 /* write the ASCII on disk */
7709 err = mod_a_printer(printer, 2);
7710 if (!W_ERROR_IS_OK(err)) {
7711 free_a_printer(&printer,2);
7715 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7716 /* Handle open failed - remove addition. */
7717 del_a_printer(printer->info_2->sharename);
7718 free_a_printer(&printer,2);
7719 return WERR_ACCESS_DENIED;
7722 update_c_setprinter(False);
7723 free_a_printer(&printer,2);
7728 /****************************************************************************
7729 ****************************************************************************/
7731 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7733 UNISTR2 *uni_srv_name = q_u->server_name;
7734 uint32 level = q_u->level;
7735 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7736 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7737 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7738 uint32 user_switch = q_u->user_switch;
7739 SPOOL_USER_CTR *user = &q_u->user_ctr;
7740 POLICY_HND *handle = &r_u->handle;
7744 /* we don't handle yet */
7745 /* but I know what to do ... */
7746 return WERR_UNKNOWN_LEVEL;
7748 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7750 user_switch, user, handle);
7752 return WERR_UNKNOWN_LEVEL;
7756 /****************************************************************************
7757 ****************************************************************************/
7759 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7761 uint32 level = q_u->level;
7762 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7763 WERROR err = WERR_OK;
7764 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7765 fstring driver_name;
7768 ZERO_STRUCT(driver);
7770 if (!convert_printer_driver_info(info, &driver, level)) {
7775 DEBUG(5,("Cleaning driver's information\n"));
7776 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7777 if (!W_ERROR_IS_OK(err))
7780 DEBUG(5,("Moving driver to final destination\n"));
7781 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7785 if (add_a_printer_driver(driver, level)!=0) {
7786 err = WERR_ACCESS_DENIED;
7791 * I think this is where he DrvUpgradePrinter() hook would be
7792 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7793 * server. Right now, we just need to send ourselves a message
7794 * to update each printer bound to this driver. --jerry
7797 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7798 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7803 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7804 * decide if the driver init data should be deleted. The rules are:
7805 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7806 * 2) delete init data only if there is no 2k/Xp driver
7807 * 3) always delete init data
7808 * The generalized rule is always use init data from the highest order driver.
7809 * It is necessary to follow the driver install by an initialization step to
7810 * finish off this process.
7813 version = driver.info_3->cversion;
7814 else if (level == 6)
7815 version = driver.info_6->version;
7820 * 9x printer driver - never delete init data
7823 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7828 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7829 * there is no 2k/Xp driver init data for this driver name.
7833 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7835 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7837 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7839 if (!del_driver_init(driver_name))
7840 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7843 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7845 free_a_printer_driver(driver1,3);
7846 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7853 * 2k or Xp printer driver - always delete init data
7856 if (!del_driver_init(driver_name))
7857 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7861 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7867 free_a_printer_driver(driver, level);
7871 /********************************************************************
7872 * spoolss_addprinterdriverex
7873 ********************************************************************/
7875 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7877 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7878 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7881 * we only support the semantics of AddPrinterDriver()
7882 * i.e. only copy files that are newer than existing ones
7885 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7886 return WERR_ACCESS_DENIED;
7888 ZERO_STRUCT(q_u_local);
7889 ZERO_STRUCT(r_u_local);
7891 /* just pass the information off to _spoolss_addprinterdriver() */
7892 q_u_local.server_name_ptr = q_u->server_name_ptr;
7893 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7894 q_u_local.level = q_u->level;
7895 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7897 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7900 /****************************************************************************
7901 ****************************************************************************/
7903 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7905 init_unistr(&info->name, name);
7908 /****************************************************************************
7909 ****************************************************************************/
7911 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7917 const char *short_archi;
7918 DRIVER_DIRECTORY_1 *info=NULL;
7919 WERROR result = WERR_OK;
7921 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7922 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7924 /* check for beginning double '\'s and that the server
7927 pservername = servername;
7928 if ( *pservername == '\\' && strlen(servername)>2 ) {
7932 if ( !is_myname_or_ipaddr( pservername ) )
7933 return WERR_INVALID_PARAM;
7935 if (!(short_archi = get_short_archi(long_archi)))
7936 return WERR_INVALID_ENVIRONMENT;
7938 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7941 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7943 DEBUG(4,("printer driver directory: [%s]\n", path));
7945 fill_driverdir_1(info, path);
7947 *needed += spoolss_size_driverdir_info_1(info);
7949 if (*needed > offered) {
7950 result = WERR_INSUFFICIENT_BUFFER;
7954 if (!rpcbuf_alloc_size(buffer, *needed)) {
7955 result = WERR_NOMEM;
7959 smb_io_driverdir_1("", buffer, info, 0);
7967 /****************************************************************************
7968 ****************************************************************************/
7970 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7972 UNISTR2 *name = &q_u->name;
7973 UNISTR2 *uni_environment = &q_u->environment;
7974 uint32 level = q_u->level;
7975 RPC_BUFFER *buffer = NULL;
7976 uint32 offered = q_u->offered;
7977 uint32 *needed = &r_u->needed;
7979 /* that's an [in out] buffer */
7981 if (!q_u->buffer && (offered!=0)) {
7982 return WERR_INVALID_PARAM;
7985 rpcbuf_move(q_u->buffer, &r_u->buffer);
7986 buffer = r_u->buffer;
7988 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7994 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7996 return WERR_UNKNOWN_LEVEL;
8000 /****************************************************************************
8001 ****************************************************************************/
8003 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8005 POLICY_HND *handle = &q_u->handle;
8006 uint32 idx = q_u->index;
8007 uint32 in_value_len = q_u->valuesize;
8008 uint32 in_data_len = q_u->datasize;
8009 uint32 *out_max_value_len = &r_u->valuesize;
8010 uint16 **out_value = &r_u->value;
8011 uint32 *out_value_len = &r_u->realvaluesize;
8012 uint32 *out_type = &r_u->type;
8013 uint32 *out_max_data_len = &r_u->datasize;
8014 uint8 **data_out = &r_u->data;
8015 uint32 *out_data_len = &r_u->realdatasize;
8017 NT_PRINTER_INFO_LEVEL *printer = NULL;
8019 uint32 biggest_valuesize;
8020 uint32 biggest_datasize;
8022 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8025 REGISTRY_VALUE *val = NULL;
8026 NT_PRINTER_DATA *p_data;
8027 int i, key_index, num_values;
8032 *out_max_data_len = 0;
8036 DEBUG(5,("spoolss_enumprinterdata\n"));
8039 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8043 if (!get_printer_snum(p,handle, &snum, NULL))
8046 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8047 if (!W_ERROR_IS_OK(result))
8050 p_data = printer->info_2->data;
8051 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8056 * The NT machine wants to know the biggest size of value and data
8058 * cf: MSDN EnumPrinterData remark section
8061 if ( !in_value_len && !in_data_len && (key_index != -1) )
8063 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8065 biggest_valuesize = 0;
8066 biggest_datasize = 0;
8068 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8070 for ( i=0; i<num_values; i++ )
8072 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8074 name_length = strlen(val->valuename);
8075 if ( strlen(val->valuename) > biggest_valuesize )
8076 biggest_valuesize = name_length;
8078 if ( val->size > biggest_datasize )
8079 biggest_datasize = val->size;
8081 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8085 /* the value is an UNICODE string but real_value_size is the length
8086 in bytes including the trailing 0 */
8088 *out_value_len = 2 * (1+biggest_valuesize);
8089 *out_data_len = biggest_datasize;
8091 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8097 * the value len is wrong in NT sp3
8098 * that's the number of bytes not the number of unicode chars
8101 if ( key_index != -1 )
8102 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8107 /* out_value should default to "" or else NT4 has
8108 problems unmarshalling the response */
8110 *out_max_value_len=(in_value_len/sizeof(uint16));
8112 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8114 result = WERR_NOMEM;
8118 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8120 /* the data is counted in bytes */
8122 *out_max_data_len = in_data_len;
8123 *out_data_len = in_data_len;
8125 /* only allocate when given a non-zero data_len */
8127 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8129 result = WERR_NOMEM;
8133 result = WERR_NO_MORE_ITEMS;
8139 * - counted in bytes in the request
8140 * - counted in UNICODE chars in the max reply
8141 * - counted in bytes in the real size
8143 * take a pause *before* coding not *during* coding
8147 *out_max_value_len=(in_value_len/sizeof(uint16));
8148 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8150 result = WERR_NOMEM;
8154 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8158 *out_type = regval_type( val );
8160 /* data - counted in bytes */
8162 *out_max_data_len = in_data_len;
8163 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8165 result = WERR_NOMEM;
8168 data_len = regval_size(val);
8170 memcpy( *data_out, regval_data_p(val), data_len );
8171 *out_data_len = data_len;
8175 free_a_printer(&printer, 2);
8179 /****************************************************************************
8180 ****************************************************************************/
8182 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8184 POLICY_HND *handle = &q_u->handle;
8185 UNISTR2 *value = &q_u->value;
8186 uint32 type = q_u->type;
8187 uint8 *data = q_u->data;
8188 uint32 real_len = q_u->real_len;
8190 NT_PRINTER_INFO_LEVEL *printer = NULL;
8192 WERROR status = WERR_OK;
8193 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8196 DEBUG(5,("spoolss_setprinterdata\n"));
8199 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8203 if ( Printer->printer_type == SPLHND_SERVER ) {
8204 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8205 return WERR_INVALID_PARAM;
8208 if (!get_printer_snum(p,handle, &snum, NULL))
8212 * Access check : NT returns "access denied" if you make a
8213 * SetPrinterData call without the necessary privildge.
8214 * we were originally returning OK if nothing changed
8215 * which made Win2k issue **a lot** of SetPrinterData
8216 * when connecting to a printer --jerry
8219 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8221 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8222 status = WERR_ACCESS_DENIED;
8226 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8227 if (!W_ERROR_IS_OK(status))
8230 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8233 * When client side code sets a magic printer data key, detect it and save
8234 * the current printer data and the magic key's data (its the DEVMODE) for
8235 * future printer/driver initializations.
8237 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8239 /* Set devmode and printer initialization info */
8240 status = save_driver_init( printer, 2, data, real_len );
8242 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8246 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8247 type, data, real_len );
8248 if ( W_ERROR_IS_OK(status) )
8249 status = mod_a_printer(printer, 2);
8253 free_a_printer(&printer, 2);
8258 /****************************************************************************
8259 ****************************************************************************/
8261 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8263 POLICY_HND *handle = &q_u->handle;
8264 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8267 DEBUG(5,("_spoolss_resetprinter\n"));
8270 * All we do is to check to see if the handle and queue is valid.
8271 * This call really doesn't mean anything to us because we only
8272 * support RAW printing. --jerry
8276 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8280 if (!get_printer_snum(p,handle, &snum, NULL))
8284 /* blindly return success */
8289 /****************************************************************************
8290 ****************************************************************************/
8292 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8294 POLICY_HND *handle = &q_u->handle;
8295 UNISTR2 *value = &q_u->valuename;
8297 NT_PRINTER_INFO_LEVEL *printer = NULL;
8299 WERROR status = WERR_OK;
8300 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8303 DEBUG(5,("spoolss_deleteprinterdata\n"));
8306 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8310 if (!get_printer_snum(p, handle, &snum, NULL))
8313 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8314 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8315 return WERR_ACCESS_DENIED;
8318 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8319 if (!W_ERROR_IS_OK(status))
8322 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8324 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8326 if ( W_ERROR_IS_OK(status) )
8327 mod_a_printer( printer, 2 );
8329 free_a_printer(&printer, 2);
8334 /****************************************************************************
8335 ****************************************************************************/
8337 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8339 POLICY_HND *handle = &q_u->handle;
8340 FORM *form = &q_u->form;
8341 nt_forms_struct tmpForm;
8343 WERROR status = WERR_OK;
8344 NT_PRINTER_INFO_LEVEL *printer = NULL;
8347 nt_forms_struct *list=NULL;
8348 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8350 DEBUG(5,("spoolss_addform\n"));
8353 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8358 /* forms can be added on printer of on the print server handle */
8360 if ( Printer->printer_type == SPLHND_PRINTER )
8362 if (!get_printer_snum(p,handle, &snum, NULL))
8365 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8366 if (!W_ERROR_IS_OK(status))
8370 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8371 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8372 status = WERR_ACCESS_DENIED;
8376 /* can't add if builtin */
8378 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8379 status = WERR_ALREADY_EXISTS;
8383 count = get_ntforms(&list);
8385 if(!add_a_form(&list, form, &count)) {
8386 status = WERR_NOMEM;
8390 write_ntforms(&list, count);
8393 * ChangeID must always be set if this is a printer
8396 if ( Printer->printer_type == SPLHND_PRINTER )
8397 status = mod_a_printer(printer, 2);
8401 free_a_printer(&printer, 2);
8407 /****************************************************************************
8408 ****************************************************************************/
8410 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8412 POLICY_HND *handle = &q_u->handle;
8413 UNISTR2 *form_name = &q_u->name;
8414 nt_forms_struct tmpForm;
8416 nt_forms_struct *list=NULL;
8417 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8419 WERROR status = WERR_OK;
8420 NT_PRINTER_INFO_LEVEL *printer = NULL;
8422 DEBUG(5,("spoolss_deleteform\n"));
8425 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8429 /* forms can be deleted on printer of on the print server handle */
8431 if ( Printer->printer_type == SPLHND_PRINTER )
8433 if (!get_printer_snum(p,handle, &snum, NULL))
8436 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8437 if (!W_ERROR_IS_OK(status))
8441 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8442 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8443 status = WERR_ACCESS_DENIED;
8447 /* can't delete if builtin */
8449 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8450 status = WERR_INVALID_PARAM;
8454 count = get_ntforms(&list);
8456 if ( !delete_a_form(&list, form_name, &count, &status ))
8460 * ChangeID must always be set if this is a printer
8463 if ( Printer->printer_type == SPLHND_PRINTER )
8464 status = mod_a_printer(printer, 2);
8468 free_a_printer(&printer, 2);
8474 /****************************************************************************
8475 ****************************************************************************/
8477 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8479 POLICY_HND *handle = &q_u->handle;
8480 FORM *form = &q_u->form;
8481 nt_forms_struct tmpForm;
8483 WERROR status = WERR_OK;
8484 NT_PRINTER_INFO_LEVEL *printer = NULL;
8487 nt_forms_struct *list=NULL;
8488 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8490 DEBUG(5,("spoolss_setform\n"));
8493 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8497 /* forms can be modified on printer of on the print server handle */
8499 if ( Printer->printer_type == SPLHND_PRINTER )
8501 if (!get_printer_snum(p,handle, &snum, NULL))
8504 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8505 if (!W_ERROR_IS_OK(status))
8509 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8510 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8511 status = WERR_ACCESS_DENIED;
8515 /* can't set if builtin */
8516 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8517 status = WERR_INVALID_PARAM;
8521 count = get_ntforms(&list);
8522 update_a_form(&list, form, count);
8523 write_ntforms(&list, count);
8526 * ChangeID must always be set if this is a printer
8529 if ( Printer->printer_type == SPLHND_PRINTER )
8530 status = mod_a_printer(printer, 2);
8535 free_a_printer(&printer, 2);
8541 /****************************************************************************
8542 enumprintprocessors level 1.
8543 ****************************************************************************/
8545 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8547 PRINTPROCESSOR_1 *info_1=NULL;
8548 WERROR result = WERR_OK;
8550 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8555 init_unistr(&info_1->name, "winprint");
8557 *needed += spoolss_size_printprocessor_info_1(info_1);
8559 if (*needed > offered) {
8560 result = WERR_INSUFFICIENT_BUFFER;
8564 if (!rpcbuf_alloc_size(buffer, *needed)) {
8565 result = WERR_NOMEM;
8569 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8574 if ( !W_ERROR_IS_OK(result) )
8580 /****************************************************************************
8581 ****************************************************************************/
8583 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8585 uint32 level = q_u->level;
8586 RPC_BUFFER *buffer = NULL;
8587 uint32 offered = q_u->offered;
8588 uint32 *needed = &r_u->needed;
8589 uint32 *returned = &r_u->returned;
8591 /* that's an [in out] buffer */
8593 if (!q_u->buffer && (offered!=0)) {
8594 return WERR_INVALID_PARAM;
8597 rpcbuf_move(q_u->buffer, &r_u->buffer);
8598 buffer = r_u->buffer;
8600 DEBUG(5,("spoolss_enumprintprocessors\n"));
8603 * Enumerate the print processors ...
8605 * Just reply with "winprint", to keep NT happy
8606 * and I can use my nice printer checker.
8614 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8616 return WERR_UNKNOWN_LEVEL;
8620 /****************************************************************************
8621 enumprintprocdatatypes level 1.
8622 ****************************************************************************/
8624 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8626 PRINTPROCDATATYPE_1 *info_1=NULL;
8627 WERROR result = WERR_NOMEM;
8629 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8634 init_unistr(&info_1->name, "RAW");
8636 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8638 if (*needed > offered) {
8639 result = WERR_INSUFFICIENT_BUFFER;
8643 if (!rpcbuf_alloc_size(buffer, *needed)) {
8644 result = WERR_NOMEM;
8648 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8653 if ( !W_ERROR_IS_OK(result) )
8659 /****************************************************************************
8660 ****************************************************************************/
8662 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8664 uint32 level = q_u->level;
8665 RPC_BUFFER *buffer = NULL;
8666 uint32 offered = q_u->offered;
8667 uint32 *needed = &r_u->needed;
8668 uint32 *returned = &r_u->returned;
8670 /* that's an [in out] buffer */
8672 if (!q_u->buffer && (offered!=0)) {
8673 return WERR_INVALID_PARAM;
8676 rpcbuf_move(q_u->buffer, &r_u->buffer);
8677 buffer = r_u->buffer;
8679 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8686 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8688 return WERR_UNKNOWN_LEVEL;
8692 /****************************************************************************
8693 enumprintmonitors level 1.
8694 ****************************************************************************/
8696 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8698 PRINTMONITOR_1 *info_1;
8699 WERROR result = WERR_OK;
8702 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8707 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8708 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8710 for ( i=0; i<*returned; i++ ) {
8711 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8714 if (*needed > offered) {
8715 result = WERR_INSUFFICIENT_BUFFER;
8719 if (!rpcbuf_alloc_size(buffer, *needed)) {
8720 result = WERR_NOMEM;
8724 for ( i=0; i<*returned; i++ ) {
8725 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8731 if ( !W_ERROR_IS_OK(result) )
8737 /****************************************************************************
8738 enumprintmonitors level 2.
8739 ****************************************************************************/
8741 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8743 PRINTMONITOR_2 *info_2;
8744 WERROR result = WERR_OK;
8747 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8752 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8753 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8754 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8756 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8757 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8758 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8760 for ( i=0; i<*returned; i++ ) {
8761 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8764 if (*needed > offered) {
8765 result = WERR_INSUFFICIENT_BUFFER;
8769 if (!rpcbuf_alloc_size(buffer, *needed)) {
8770 result = WERR_NOMEM;
8774 for ( i=0; i<*returned; i++ ) {
8775 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8781 if ( !W_ERROR_IS_OK(result) )
8787 /****************************************************************************
8788 ****************************************************************************/
8790 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8792 uint32 level = q_u->level;
8793 RPC_BUFFER *buffer = NULL;
8794 uint32 offered = q_u->offered;
8795 uint32 *needed = &r_u->needed;
8796 uint32 *returned = &r_u->returned;
8798 /* that's an [in out] buffer */
8800 if (!q_u->buffer && (offered!=0)) {
8801 return WERR_INVALID_PARAM;
8804 rpcbuf_move(q_u->buffer, &r_u->buffer);
8805 buffer = r_u->buffer;
8807 DEBUG(5,("spoolss_enumprintmonitors\n"));
8810 * Enumerate the print monitors ...
8812 * Just reply with "Local Port", to keep NT happy
8813 * and I can use my nice printer checker.
8821 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8823 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8825 return WERR_UNKNOWN_LEVEL;
8829 /****************************************************************************
8830 ****************************************************************************/
8832 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8833 NT_PRINTER_INFO_LEVEL *ntprinter,
8834 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8839 JOB_INFO_1 *info_1=NULL;
8840 WERROR result = WERR_OK;
8842 info_1=SMB_MALLOC_P(JOB_INFO_1);
8844 if (info_1 == NULL) {
8848 for (i=0; i<count && found==False; i++) {
8849 if ((*queue)[i].job==(int)jobid)
8855 /* NT treats not found as bad param... yet another bad choice */
8856 return WERR_INVALID_PARAM;
8859 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8861 *needed += spoolss_size_job_info_1(info_1);
8863 if (*needed > offered) {
8864 result = WERR_INSUFFICIENT_BUFFER;
8868 if (!rpcbuf_alloc_size(buffer, *needed)) {
8869 result = WERR_NOMEM;
8873 smb_io_job_info_1("", buffer, info_1, 0);
8881 /****************************************************************************
8882 ****************************************************************************/
8884 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8885 NT_PRINTER_INFO_LEVEL *ntprinter,
8886 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8893 DEVICEMODE *devmode = NULL;
8894 NT_DEVICEMODE *nt_devmode = NULL;
8896 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8899 ZERO_STRUCTP(info_2);
8901 for ( i=0; i<count && found==False; i++ )
8903 if ((*queue)[i].job == (int)jobid)
8908 /* NT treats not found as bad param... yet another bad
8910 result = WERR_INVALID_PARAM;
8915 * if the print job does not have a DEVMODE associated with it,
8916 * just use the one for the printer. A NULL devicemode is not
8917 * a failure condition
8920 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8921 devmode = construct_dev_mode(lp_const_servicename(snum));
8923 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8924 ZERO_STRUCTP( devmode );
8925 convert_nt_devicemode( devmode, nt_devmode );
8929 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8931 *needed += spoolss_size_job_info_2(info_2);
8933 if (*needed > offered) {
8934 result = WERR_INSUFFICIENT_BUFFER;
8938 if (!rpcbuf_alloc_size(buffer, *needed)) {
8939 result = WERR_NOMEM;
8943 smb_io_job_info_2("", buffer, info_2, 0);
8948 /* Cleanup allocated memory */
8950 free_job_info_2(info_2); /* Also frees devmode */
8956 /****************************************************************************
8957 ****************************************************************************/
8959 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8961 POLICY_HND *handle = &q_u->handle;
8962 uint32 jobid = q_u->jobid;
8963 uint32 level = q_u->level;
8964 RPC_BUFFER *buffer = NULL;
8965 uint32 offered = q_u->offered;
8966 uint32 *needed = &r_u->needed;
8967 WERROR wstatus = WERR_OK;
8968 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8971 print_queue_struct *queue = NULL;
8972 print_status_struct prt_status;
8974 /* that's an [in out] buffer */
8976 if (!q_u->buffer && (offered!=0)) {
8977 return WERR_INVALID_PARAM;
8980 rpcbuf_move(q_u->buffer, &r_u->buffer);
8981 buffer = r_u->buffer;
8983 DEBUG(5,("spoolss_getjob\n"));
8987 if (!get_printer_snum(p, handle, &snum, NULL))
8990 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8991 if ( !W_ERROR_IS_OK(wstatus) )
8994 count = print_queue_status(snum, &queue, &prt_status);
8996 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8997 count, prt_status.status, prt_status.message));
9001 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9002 buffer, offered, needed);
9005 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9006 buffer, offered, needed);
9009 wstatus = WERR_UNKNOWN_LEVEL;
9014 free_a_printer( &ntprinter, 2 );
9019 /********************************************************************
9020 spoolss_getprinterdataex
9022 From MSDN documentation of GetPrinterDataEx: pass request
9023 to GetPrinterData if key is "PrinterDriverData".
9024 ********************************************************************/
9026 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9028 POLICY_HND *handle = &q_u->handle;
9029 uint32 in_size = q_u->size;
9030 uint32 *type = &r_u->type;
9031 uint32 *out_size = &r_u->size;
9032 uint8 **data = &r_u->data;
9033 uint32 *needed = &r_u->needed;
9034 fstring keyname, valuename;
9036 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9038 NT_PRINTER_INFO_LEVEL *printer = NULL;
9040 WERROR status = WERR_OK;
9042 DEBUG(4,("_spoolss_getprinterdataex\n"));
9044 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
9045 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
9047 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9048 keyname, valuename));
9050 /* in case of problem, return some default values */
9054 *out_size = in_size;
9057 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9058 status = WERR_BADFID;
9062 /* Is the handle to a printer or to the server? */
9064 if (Printer->printer_type == SPLHND_SERVER) {
9065 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9066 status = WERR_INVALID_PARAM;
9070 if ( !get_printer_snum(p,handle, &snum, NULL) )
9073 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9074 if ( !W_ERROR_IS_OK(status) )
9077 /* check to see if the keyname is valid */
9078 if ( !strlen(keyname) ) {
9079 status = WERR_INVALID_PARAM;
9083 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9084 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9085 free_a_printer( &printer, 2 );
9086 status = WERR_BADFILE;
9090 /* When given a new keyname, we should just create it */
9092 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9094 if (*needed > *out_size)
9095 status = WERR_MORE_DATA;
9098 if ( !W_ERROR_IS_OK(status) )
9100 DEBUG(5, ("error: allocating %d\n", *out_size));
9102 /* reply this param doesn't exist */
9106 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9107 status = WERR_NOMEM;
9117 free_a_printer( &printer, 2 );
9122 /********************************************************************
9123 * spoolss_setprinterdataex
9124 ********************************************************************/
9126 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9128 POLICY_HND *handle = &q_u->handle;
9129 uint32 type = q_u->type;
9130 uint8 *data = q_u->data;
9131 uint32 real_len = q_u->real_len;
9133 NT_PRINTER_INFO_LEVEL *printer = NULL;
9135 WERROR status = WERR_OK;
9136 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9141 DEBUG(4,("_spoolss_setprinterdataex\n"));
9143 /* From MSDN documentation of SetPrinterDataEx: pass request to
9144 SetPrinterData if key is "PrinterDriverData" */
9147 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9151 if ( Printer->printer_type == SPLHND_SERVER ) {
9152 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9153 return WERR_INVALID_PARAM;
9156 if ( !get_printer_snum(p,handle, &snum, NULL) )
9160 * Access check : NT returns "access denied" if you make a
9161 * SetPrinterData call without the necessary privildge.
9162 * we were originally returning OK if nothing changed
9163 * which made Win2k issue **a lot** of SetPrinterData
9164 * when connecting to a printer --jerry
9167 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9169 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9170 return WERR_ACCESS_DENIED;
9173 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9174 if (!W_ERROR_IS_OK(status))
9177 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9178 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9180 /* check for OID in valuename */
9182 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9188 /* save the registry data */
9190 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9192 if ( W_ERROR_IS_OK(status) )
9194 /* save the OID if one was specified */
9196 fstrcat( keyname, "\\" );
9197 fstrcat( keyname, SPOOL_OID_KEY );
9200 * I'm not checking the status here on purpose. Don't know
9201 * if this is right, but I'm returning the status from the
9202 * previous set_printer_dataex() call. I have no idea if
9203 * this is right. --jerry
9206 set_printer_dataex( printer, keyname, valuename,
9207 REG_SZ, (uint8 *)oid_string,
9208 strlen(oid_string)+1 );
9211 status = mod_a_printer(printer, 2);
9214 free_a_printer(&printer, 2);
9220 /********************************************************************
9221 * spoolss_deleteprinterdataex
9222 ********************************************************************/
9224 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9226 POLICY_HND *handle = &q_u->handle;
9227 UNISTR2 *value = &q_u->valuename;
9228 UNISTR2 *key = &q_u->keyname;
9230 NT_PRINTER_INFO_LEVEL *printer = NULL;
9232 WERROR status = WERR_OK;
9233 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9234 pstring valuename, keyname;
9236 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9239 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9243 if (!get_printer_snum(p, handle, &snum, NULL))
9246 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9247 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9248 return WERR_ACCESS_DENIED;
9251 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9252 if (!W_ERROR_IS_OK(status))
9255 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9256 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9258 status = delete_printer_dataex( printer, keyname, valuename );
9260 if ( W_ERROR_IS_OK(status) )
9261 mod_a_printer( printer, 2 );
9263 free_a_printer(&printer, 2);
9268 /********************************************************************
9269 * spoolss_enumprinterkey
9270 ********************************************************************/
9273 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9276 fstring *keynames = NULL;
9277 uint16 *enumkeys = NULL;
9280 POLICY_HND *handle = &q_u->handle;
9281 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9282 NT_PRINTER_DATA *data;
9283 NT_PRINTER_INFO_LEVEL *printer = NULL;
9285 WERROR status = WERR_BADFILE;
9288 DEBUG(4,("_spoolss_enumprinterkey\n"));
9291 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9295 if ( !get_printer_snum(p,handle, &snum, NULL) )
9298 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9299 if (!W_ERROR_IS_OK(status))
9302 /* get the list of subkey names */
9304 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9305 data = printer->info_2->data;
9307 num_keys = get_printer_subkeys( data, key, &keynames );
9309 if ( num_keys == -1 ) {
9310 status = WERR_BADFILE;
9314 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9316 r_u->needed = printerkey_len*2;
9318 if ( q_u->size < r_u->needed ) {
9319 status = WERR_MORE_DATA;
9323 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9324 status = WERR_NOMEM;
9330 if ( q_u->size < r_u->needed )
9331 status = WERR_MORE_DATA;
9334 free_a_printer( &printer, 2 );
9335 SAFE_FREE( keynames );
9340 /********************************************************************
9341 * spoolss_deleteprinterkey
9342 ********************************************************************/
9344 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9346 POLICY_HND *handle = &q_u->handle;
9347 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9349 NT_PRINTER_INFO_LEVEL *printer = NULL;
9353 DEBUG(5,("spoolss_deleteprinterkey\n"));
9356 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9360 /* if keyname == NULL, return error */
9362 if ( !q_u->keyname.buffer )
9363 return WERR_INVALID_PARAM;
9365 if (!get_printer_snum(p, handle, &snum, NULL))
9368 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9369 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9370 return WERR_ACCESS_DENIED;
9373 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9374 if (!W_ERROR_IS_OK(status))
9377 /* delete the key and all subneys */
9379 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9381 status = delete_all_printer_data( printer->info_2, key );
9383 if ( W_ERROR_IS_OK(status) )
9384 status = mod_a_printer(printer, 2);
9386 free_a_printer( &printer, 2 );
9392 /********************************************************************
9393 * spoolss_enumprinterdataex
9394 ********************************************************************/
9396 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9398 POLICY_HND *handle = &q_u->handle;
9399 uint32 in_size = q_u->size;
9402 NT_PRINTER_INFO_LEVEL *printer = NULL;
9403 PRINTER_ENUM_VALUES *enum_values = NULL;
9404 NT_PRINTER_DATA *p_data;
9406 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9411 REGISTRY_VALUE *val;
9416 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9419 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9424 * first check for a keyname of NULL or "". Win2k seems to send
9425 * this a lot and we should send back WERR_INVALID_PARAM
9426 * no need to spend time looking up the printer in this case.
9430 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9431 if ( !strlen(key) ) {
9432 result = WERR_INVALID_PARAM;
9436 /* get the printer off of disk */
9438 if (!get_printer_snum(p,handle, &snum, NULL))
9441 ZERO_STRUCT(printer);
9442 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9443 if (!W_ERROR_IS_OK(result))
9446 /* now look for a match on the key name */
9448 p_data = printer->info_2->data;
9450 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9451 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9453 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9454 result = WERR_INVALID_PARAM;
9461 /* allocate the memory for the array of pointers -- if necessary */
9463 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9466 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9468 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9469 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9470 result = WERR_NOMEM;
9474 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9478 * loop through all params and build the array to pass
9479 * back to the client
9482 for ( i=0; i<num_entries; i++ )
9484 /* lookup the registry value */
9486 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9487 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9491 value_name = regval_name( val );
9492 init_unistr( &enum_values[i].valuename, value_name );
9493 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9494 enum_values[i].type = regval_type( val );
9496 data_len = regval_size( val );
9498 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9500 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9502 result = WERR_NOMEM;
9506 enum_values[i].data_len = data_len;
9508 /* keep track of the size of the array in bytes */
9510 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9513 /* housekeeping information in the reply */
9515 r_u->needed = needed;
9516 r_u->returned = num_entries;
9518 if (needed > in_size) {
9519 result = WERR_MORE_DATA;
9523 /* copy data into the reply */
9525 r_u->ctr.size = r_u->needed;
9526 r_u->ctr.size_of_array = r_u->returned;
9527 r_u->ctr.values = enum_values;
9533 free_a_printer(&printer, 2);
9538 /****************************************************************************
9539 ****************************************************************************/
9541 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9543 init_unistr(&info->name, name);
9546 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9547 UNISTR2 *environment,
9554 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9555 WERROR result = WERR_OK;
9557 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9559 if (!get_short_archi(long_archi))
9560 return WERR_INVALID_ENVIRONMENT;
9562 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9565 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9567 fill_printprocessordirectory_1(info, path);
9569 *needed += spoolss_size_printprocessordirectory_info_1(info);
9571 if (*needed > offered) {
9572 result = WERR_INSUFFICIENT_BUFFER;
9576 if (!rpcbuf_alloc_size(buffer, *needed)) {
9577 result = WERR_INSUFFICIENT_BUFFER;
9581 smb_io_printprocessordirectory_1("", buffer, info, 0);
9589 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9591 uint32 level = q_u->level;
9592 RPC_BUFFER *buffer = NULL;
9593 uint32 offered = q_u->offered;
9594 uint32 *needed = &r_u->needed;
9597 /* that's an [in out] buffer */
9599 if (!q_u->buffer && (offered!=0)) {
9600 return WERR_INVALID_PARAM;
9603 rpcbuf_move(q_u->buffer, &r_u->buffer);
9604 buffer = r_u->buffer;
9606 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9612 result = getprintprocessordirectory_level_1
9613 (&q_u->name, &q_u->environment, buffer, offered, needed);
9616 result = WERR_UNKNOWN_LEVEL;
9622 /*******************************************************************
9623 Streams the monitor UI DLL name in UNICODE
9624 *******************************************************************/
9626 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9627 RPC_BUFFER *out, uint32 *needed )
9629 const char *dllname = "tcpmonui.dll";
9631 *needed = (strlen(dllname)+1) * 2;
9633 if ( rpcbuf_get_size(out) < *needed ) {
9634 return WERR_INSUFFICIENT_BUFFER;
9637 if ( !make_monitorui_buf( out, dllname ) ) {
9644 /*******************************************************************
9645 Create a new TCP/IP port
9646 *******************************************************************/
9648 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9649 RPC_BUFFER *out, uint32 *needed )
9651 NT_PORT_DATA_1 port1;
9654 ZERO_STRUCT( port1 );
9656 /* convert to our internal port data structure */
9658 if ( !convert_port_data_1( &port1, in ) ) {
9662 /* create the device URI and call the add_port_hook() */
9664 switch ( port1.protocol ) {
9665 case PORT_PROTOCOL_DIRECT:
9666 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9669 case PORT_PROTOCOL_LPR:
9670 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9674 return WERR_UNKNOWN_PORT;
9677 return add_port_hook( token, port1.name, device_uri );
9680 /*******************************************************************
9681 *******************************************************************/
9683 struct xcv_api_table xcvtcp_cmds[] = {
9684 { "MonitorUI", xcvtcp_monitorui },
9685 { "AddPort", xcvtcp_addport},
9689 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9690 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9695 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9697 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9698 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9699 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9702 return WERR_BADFUNC;
9705 /*******************************************************************
9706 *******************************************************************/
9707 #if 0 /* don't support management using the "Local Port" monitor */
9709 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9710 RPC_BUFFER *out, uint32 *needed )
9712 const char *dllname = "localui.dll";
9714 *needed = (strlen(dllname)+1) * 2;
9716 if ( rpcbuf_get_size(out) < *needed ) {
9717 return WERR_INSUFFICIENT_BUFFER;
9720 if ( !make_monitorui_buf( out, dllname )) {
9727 /*******************************************************************
9728 *******************************************************************/
9730 struct xcv_api_table xcvlocal_cmds[] = {
9731 { "MonitorUI", xcvlocal_monitorui },
9735 struct xcv_api_table xcvlocal_cmds[] = {
9742 /*******************************************************************
9743 *******************************************************************/
9745 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9746 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9751 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9753 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9754 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9755 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9757 return WERR_BADFUNC;
9760 /*******************************************************************
9761 *******************************************************************/
9763 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9765 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9769 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9773 /* Has to be a handle to the TCP/IP port monitor */
9775 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9776 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9780 /* requires administrative access to the server */
9782 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9783 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9784 return WERR_ACCESS_DENIED;
9787 /* Get the command name. There's numerous commands supported by the
9788 TCPMON interface. */
9790 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9791 q_u->dataname.uni_str_len*2, 0);
9793 /* Allocate the outgoing buffer */
9795 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9797 switch ( Printer->printer_type ) {
9798 case SPLHND_PORTMON_TCP:
9799 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9800 &q_u->indata, &r_u->outdata, &r_u->needed );
9801 case SPLHND_PORTMON_LOCAL:
9802 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9803 &q_u->indata, &r_u->outdata, &r_u->needed );
9806 return WERR_INVALID_PRINT_MONITOR;