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,
1113 size_t msg_count, i;
1114 char *buf = (char *)msg;
1117 SPOOLSS_NOTIFY_MSG notify;
1118 SPOOLSS_NOTIFY_MSG_CTR messages;
1122 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1126 msg_count = IVAL(buf, 0);
1129 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1131 if (msg_count == 0) {
1132 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1136 /* initialize the container */
1138 ZERO_STRUCT( messages );
1139 notify_msg_ctr_init( &messages );
1142 * build message groups for each printer identified
1143 * in a change_notify msg. Remember that a PCN message
1144 * includes the handle returned for the srv_spoolss_replyopenprinter()
1145 * call. Therefore messages are grouped according to printer handle.
1148 for ( i=0; i<msg_count; i++ ) {
1149 struct timeval msg_tv;
1151 if (msg_ptr + 4 - buf > len) {
1152 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1156 msg_len = IVAL(msg_ptr,0);
1159 if (msg_ptr + msg_len - buf > len) {
1160 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1164 /* unpack messages */
1166 ZERO_STRUCT( notify );
1167 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1170 /* add to correct list in container */
1172 notify_msg_ctr_addmsg( &messages, ¬ify );
1174 /* free memory that might have been allocated by notify2_unpack_msg() */
1176 if ( notify.len != 0 )
1177 SAFE_FREE( notify.notify.data );
1180 /* process each group of messages */
1182 num_groups = notify_msg_ctr_numgroups( &messages );
1183 for ( i=0; i<num_groups; i++ )
1184 send_notify2_changes( &messages, i );
1189 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1191 notify_msg_ctr_destroy( &messages );
1196 /********************************************************************
1197 Send a message to ourself about new driver being installed
1198 so we can upgrade the information for each printer bound to this
1200 ********************************************************************/
1202 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1204 int len = strlen(drivername);
1209 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1212 message_send_pid(pid_to_procid(sys_getpid()),
1213 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1218 /**********************************************************************
1219 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1220 over all printers, upgrading ones as necessary
1221 **********************************************************************/
1223 void do_drv_upgrade_printer(int msg_type, struct process_id src,
1224 void *buf, size_t len, void *private_data)
1228 int n_services = lp_numservices();
1230 len = MIN(len,sizeof(drivername)-1);
1231 strncpy(drivername, (const char *)buf, len);
1233 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1235 /* Iterate the printer list */
1237 for (snum=0; snum<n_services; snum++)
1239 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1242 NT_PRINTER_INFO_LEVEL *printer = NULL;
1244 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1245 if (!W_ERROR_IS_OK(result))
1248 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1250 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1252 /* all we care about currently is the change_id */
1254 result = mod_a_printer(printer, 2);
1255 if (!W_ERROR_IS_OK(result)) {
1256 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1257 dos_errstr(result)));
1261 free_a_printer(&printer, 2);
1268 /********************************************************************
1269 Update the cache for all printq's with a registered client
1271 ********************************************************************/
1273 void update_monitored_printq_cache( void )
1275 Printer_entry *printer = printers_list;
1278 /* loop through all printers and update the cache where
1279 client_connected == True */
1282 if ( (printer->printer_type == SPLHND_PRINTER)
1283 && printer->notify.client_connected )
1285 snum = print_queue_snum(printer->sharename);
1286 print_queue_status( snum, NULL, NULL );
1289 printer = printer->next;
1294 /********************************************************************
1295 Send a message to ourself about new driver being installed
1296 so we can upgrade the information for each printer bound to this
1298 ********************************************************************/
1300 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1302 int len = strlen(drivername);
1307 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1310 message_send_pid(pid_to_procid(sys_getpid()),
1311 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1316 /**********************************************************************
1317 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1318 over all printers, resetting printer data as neessary
1319 **********************************************************************/
1321 void reset_all_printerdata(int msg_type, struct process_id src,
1322 void *buf, size_t len, void *private_data)
1326 int n_services = lp_numservices();
1328 len = MIN( len, sizeof(drivername)-1 );
1329 strncpy( drivername, (const char *)buf, len );
1331 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1333 /* Iterate the printer list */
1335 for ( snum=0; snum<n_services; snum++ )
1337 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1340 NT_PRINTER_INFO_LEVEL *printer = NULL;
1342 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1343 if ( !W_ERROR_IS_OK(result) )
1347 * if the printer is bound to the driver,
1348 * then reset to the new driver initdata
1351 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1353 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1355 if ( !set_driver_init(printer, 2) ) {
1356 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1357 printer->info_2->printername, printer->info_2->drivername));
1360 result = mod_a_printer( printer, 2 );
1361 if ( !W_ERROR_IS_OK(result) ) {
1362 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1363 get_dos_error_msg(result)));
1367 free_a_printer( &printer, 2 );
1376 /********************************************************************
1377 Copy routines used by convert_to_openprinterex()
1378 *******************************************************************/
1380 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1388 DEBUG (8,("dup_devmode\n"));
1390 /* bulk copy first */
1392 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1396 /* dup the pointer members separately */
1398 len = unistrlen(devmode->devicename.buffer);
1400 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1401 if (!d->devicename.buffer) {
1404 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1409 len = unistrlen(devmode->formname.buffer);
1411 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1412 if (!d->devicename.buffer) {
1415 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1419 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1420 devmode->driverextra);
1421 if (!d->dev_private) {
1427 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1429 if (!new_ctr || !ctr)
1432 DEBUG(8,("copy_devmode_ctr\n"));
1434 new_ctr->size = ctr->size;
1435 new_ctr->devmode_ptr = ctr->devmode_ptr;
1437 if(ctr->devmode_ptr)
1438 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1441 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1443 if (!new_def || !def)
1446 DEBUG(8,("copy_printer_defaults\n"));
1448 new_def->datatype_ptr = def->datatype_ptr;
1450 if (def->datatype_ptr)
1451 copy_unistr2(&new_def->datatype, &def->datatype);
1453 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1455 new_def->access_required = def->access_required;
1458 /********************************************************************
1459 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1460 * SPOOL_Q_OPEN_PRINTER_EX structure
1461 ********************************************************************/
1463 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1465 if (!q_u_ex || !q_u)
1468 DEBUG(8,("convert_to_openprinterex\n"));
1470 if ( q_u->printername ) {
1471 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1472 if (q_u_ex->printername == NULL)
1474 copy_unistr2(q_u_ex->printername, q_u->printername);
1477 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1482 /********************************************************************
1483 * spoolss_open_printer
1485 * called from the spoolss dispatcher
1486 ********************************************************************/
1488 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1490 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1491 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1496 ZERO_STRUCT(q_u_ex);
1497 ZERO_STRUCT(r_u_ex);
1499 /* convert the OpenPrinter() call to OpenPrinterEx() */
1501 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1502 if (!W_ERROR_IS_OK(r_u_ex.status))
1503 return r_u_ex.status;
1505 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1507 /* convert back to OpenPrinter() */
1509 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1514 /********************************************************************
1515 ********************************************************************/
1517 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1519 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1520 POLICY_HND *handle = &r_u->handle;
1524 Printer_entry *Printer=NULL;
1526 if ( !q_u->printername )
1527 return WERR_INVALID_PRINTER_NAME;
1529 /* some sanity check because you can open a printer or a print server */
1530 /* aka: \\server\printer or \\server */
1532 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1534 DEBUGADD(3,("checking name: %s\n",name));
1536 if (!open_printer_hnd(p, handle, name, 0))
1537 return WERR_INVALID_PRINTER_NAME;
1539 Printer=find_printer_index_by_hnd(p, handle);
1541 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1542 "handle we created for printer %s\n", name ));
1543 close_printer_handle(p,handle);
1544 return WERR_INVALID_PRINTER_NAME;
1548 * First case: the user is opening the print server:
1550 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1551 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1553 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1554 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1555 * or if the user is listed in the smb.conf printer admin parameter.
1557 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1558 * client view printer folder, but does not show the MSAPW.
1560 * Note: this test needs code to check access rights here too. Jeremy
1561 * could you look at this?
1563 * Second case: the user is opening a printer:
1564 * NT doesn't let us connect to a printer if the connecting user
1565 * doesn't have print permission.
1567 * Third case: user is opening a Port Monitor
1568 * access checks same as opening a handle to the print server.
1571 switch (Printer->printer_type )
1574 case SPLHND_PORTMON_TCP:
1575 case SPLHND_PORTMON_LOCAL:
1576 /* Printserver handles use global struct... */
1580 /* Map standard access rights to object specific access rights */
1582 se_map_standard(&printer_default->access_required,
1583 &printserver_std_mapping);
1585 /* Deny any object specific bits that don't apply to print
1586 servers (i.e printer and job specific bits) */
1588 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1590 if (printer_default->access_required &
1591 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1592 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1593 close_printer_handle(p, handle);
1594 return WERR_ACCESS_DENIED;
1597 /* Allow admin access */
1599 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1601 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1603 if (!lp_ms_add_printer_wizard()) {
1604 close_printer_handle(p, handle);
1605 return WERR_ACCESS_DENIED;
1608 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1609 and not a printer admin, then fail */
1611 if ((p->pipe_user.ut.uid != 0) &&
1612 !user_has_privileges(p->pipe_user.nt_user_token,
1614 !token_contains_name_in_list(
1615 uidtoname(p->pipe_user.ut.uid), NULL,
1616 p->pipe_user.nt_user_token,
1617 lp_printer_admin(snum))) {
1618 close_printer_handle(p, handle);
1619 return WERR_ACCESS_DENIED;
1622 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1626 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1629 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1630 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1632 /* We fall through to return WERR_OK */
1635 case SPLHND_PRINTER:
1636 /* NT doesn't let us connect to a printer if the connecting user
1637 doesn't have print permission. */
1639 if (!get_printer_snum(p, handle, &snum, NULL)) {
1640 close_printer_handle(p, handle);
1644 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1646 /* map an empty access mask to the minimum access mask */
1647 if (printer_default->access_required == 0x0)
1648 printer_default->access_required = PRINTER_ACCESS_USE;
1651 * If we are not serving the printer driver for this printer,
1652 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1653 * will keep NT clients happy --jerry
1656 if (lp_use_client_driver(snum)
1657 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1659 printer_default->access_required = PRINTER_ACCESS_USE;
1662 /* check smb.conf parameters and the the sec_desc */
1664 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1665 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1666 return WERR_ACCESS_DENIED;
1669 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1670 p->pipe_user.nt_user_token, snum) ||
1671 !print_access_check(&p->pipe_user, snum,
1672 printer_default->access_required)) {
1673 DEBUG(3, ("access DENIED for printer open\n"));
1674 close_printer_handle(p, handle);
1675 return WERR_ACCESS_DENIED;
1678 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1679 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1680 close_printer_handle(p, handle);
1681 return WERR_ACCESS_DENIED;
1684 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1685 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1687 printer_default->access_required = PRINTER_ACCESS_USE;
1689 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1690 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1695 /* sanity check to prevent programmer error */
1699 Printer->access_granted = printer_default->access_required;
1702 * If the client sent a devmode in the OpenPrinter() call, then
1703 * save it here in case we get a job submission on this handle
1706 if ( (Printer->printer_type != SPLHND_SERVER)
1707 && q_u->printer_default.devmode_cont.devmode_ptr )
1709 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1710 &Printer->nt_devmode );
1713 #if 0 /* JERRY -- I'm doubtful this is really effective */
1714 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1715 optimization in Windows 2000 clients --jerry */
1717 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1718 && (RA_WIN2K == get_remote_arch()) )
1720 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1721 sys_usleep( 500000 );
1728 /****************************************************************************
1729 ****************************************************************************/
1731 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1732 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1738 /* allocate memory if needed. Messy because
1739 convert_printer_info is used to update an existing
1740 printer or build a new one */
1742 if ( !printer->info_2 ) {
1743 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1744 if ( !printer->info_2 ) {
1745 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1750 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1751 printer->info_2->setuptime = time(NULL);
1759 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1760 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1766 printer->info_3=NULL;
1767 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1771 printer->info_6=NULL;
1772 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1782 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1783 NT_DEVICEMODE **pp_nt_devmode)
1785 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1788 * Ensure nt_devmode is a valid pointer
1789 * as we will be overwriting it.
1792 if (nt_devmode == NULL) {
1793 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1794 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1798 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1799 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1801 nt_devmode->specversion=devmode->specversion;
1802 nt_devmode->driverversion=devmode->driverversion;
1803 nt_devmode->size=devmode->size;
1804 nt_devmode->fields=devmode->fields;
1805 nt_devmode->orientation=devmode->orientation;
1806 nt_devmode->papersize=devmode->papersize;
1807 nt_devmode->paperlength=devmode->paperlength;
1808 nt_devmode->paperwidth=devmode->paperwidth;
1809 nt_devmode->scale=devmode->scale;
1810 nt_devmode->copies=devmode->copies;
1811 nt_devmode->defaultsource=devmode->defaultsource;
1812 nt_devmode->printquality=devmode->printquality;
1813 nt_devmode->color=devmode->color;
1814 nt_devmode->duplex=devmode->duplex;
1815 nt_devmode->yresolution=devmode->yresolution;
1816 nt_devmode->ttoption=devmode->ttoption;
1817 nt_devmode->collate=devmode->collate;
1819 nt_devmode->logpixels=devmode->logpixels;
1820 nt_devmode->bitsperpel=devmode->bitsperpel;
1821 nt_devmode->pelswidth=devmode->pelswidth;
1822 nt_devmode->pelsheight=devmode->pelsheight;
1823 nt_devmode->displayflags=devmode->displayflags;
1824 nt_devmode->displayfrequency=devmode->displayfrequency;
1825 nt_devmode->icmmethod=devmode->icmmethod;
1826 nt_devmode->icmintent=devmode->icmintent;
1827 nt_devmode->mediatype=devmode->mediatype;
1828 nt_devmode->dithertype=devmode->dithertype;
1829 nt_devmode->reserved1=devmode->reserved1;
1830 nt_devmode->reserved2=devmode->reserved2;
1831 nt_devmode->panningwidth=devmode->panningwidth;
1832 nt_devmode->panningheight=devmode->panningheight;
1835 * Only change private and driverextra if the incoming devmode
1836 * has a new one. JRA.
1839 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1840 SAFE_FREE(nt_devmode->nt_dev_private);
1841 nt_devmode->driverextra=devmode->driverextra;
1842 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1844 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1847 *pp_nt_devmode = nt_devmode;
1852 /********************************************************************
1853 * _spoolss_enddocprinter_internal.
1854 ********************************************************************/
1856 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1858 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1862 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1866 if (!get_printer_snum(p, handle, &snum, NULL))
1869 Printer->document_started=False;
1870 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1871 /* error codes unhandled so far ... */
1876 /********************************************************************
1877 * api_spoolss_closeprinter
1878 ********************************************************************/
1880 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1882 POLICY_HND *handle = &q_u->handle;
1884 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1886 if (Printer && Printer->document_started)
1887 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1889 if (!close_printer_handle(p, handle))
1892 /* clear the returned printer handle. Observed behavior
1893 from Win2k server. Don't think this really matters.
1894 Previous code just copied the value of the closed
1897 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1902 /********************************************************************
1903 * api_spoolss_deleteprinter
1905 ********************************************************************/
1907 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1909 POLICY_HND *handle = &q_u->handle;
1910 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1913 if (Printer && Printer->document_started)
1914 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1916 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1918 result = delete_printer_handle(p, handle);
1920 update_c_setprinter(False);
1925 /*******************************************************************
1926 * static function to lookup the version id corresponding to an
1927 * long architecture string
1928 ******************************************************************/
1930 static int get_version_id (char * arch)
1933 struct table_node archi_table[]= {
1935 {"Windows 4.0", "WIN40", 0 },
1936 {"Windows NT x86", "W32X86", 2 },
1937 {"Windows NT R4000", "W32MIPS", 2 },
1938 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1939 {"Windows NT PowerPC", "W32PPC", 2 },
1940 {"Windows IA64", "IA64", 3 },
1941 {"Windows x64", "x64", 3 },
1945 for (i=0; archi_table[i].long_archi != NULL; i++)
1947 if (strcmp(arch, archi_table[i].long_archi) == 0)
1948 return (archi_table[i].version);
1954 /********************************************************************
1955 * _spoolss_deleteprinterdriver
1956 ********************************************************************/
1958 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1962 NT_PRINTER_DRIVER_INFO_LEVEL info;
1963 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1966 WERROR status_win2k = WERR_ACCESS_DENIED;
1967 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1969 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1970 and not a printer admin, then fail */
1972 if ( (p->pipe_user.ut.uid != 0)
1973 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
1974 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
1975 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
1977 return WERR_ACCESS_DENIED;
1980 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1981 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1983 /* check that we have a valid driver name first */
1985 if ((version=get_version_id(arch)) == -1)
1986 return WERR_INVALID_ENVIRONMENT;
1989 ZERO_STRUCT(info_win2k);
1991 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1993 /* try for Win2k driver if "Windows NT x86" */
1995 if ( version == 2 ) {
1997 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1998 status = WERR_UNKNOWN_PRINTER_DRIVER;
2002 /* otherwise it was a failure */
2004 status = WERR_UNKNOWN_PRINTER_DRIVER;
2010 if (printer_driver_in_use(info.info_3)) {
2011 status = WERR_PRINTER_DRIVER_IN_USE;
2017 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2019 /* if we get to here, we now have 2 driver info structures to remove */
2020 /* remove the Win2k driver first*/
2022 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2023 free_a_printer_driver( info_win2k, 3 );
2025 /* this should not have failed---if it did, report to client */
2026 if ( !W_ERROR_IS_OK(status_win2k) )
2028 status = status_win2k;
2034 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2036 /* if at least one of the deletes succeeded return OK */
2038 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2042 free_a_printer_driver( info, 3 );
2047 /********************************************************************
2048 * spoolss_deleteprinterdriverex
2049 ********************************************************************/
2051 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2055 NT_PRINTER_DRIVER_INFO_LEVEL info;
2056 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2058 uint32 flags = q_u->delete_flags;
2061 WERROR status_win2k = WERR_ACCESS_DENIED;
2062 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2064 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2065 and not a printer admin, then fail */
2067 if ( (p->pipe_user.ut.uid != 0)
2068 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2069 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2070 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2072 return WERR_ACCESS_DENIED;
2075 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2076 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2078 /* check that we have a valid driver name first */
2079 if ((version=get_version_id(arch)) == -1) {
2080 /* this is what NT returns */
2081 return WERR_INVALID_ENVIRONMENT;
2084 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2085 version = q_u->version;
2088 ZERO_STRUCT(info_win2k);
2090 status = get_a_printer_driver(&info, 3, driver, arch, version);
2092 if ( !W_ERROR_IS_OK(status) )
2095 * if the client asked for a specific version,
2096 * or this is something other than Windows NT x86,
2100 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2103 /* try for Win2k driver if "Windows NT x86" */
2106 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2107 status = WERR_UNKNOWN_PRINTER_DRIVER;
2112 if ( printer_driver_in_use(info.info_3) ) {
2113 status = WERR_PRINTER_DRIVER_IN_USE;
2118 * we have a couple of cases to consider.
2119 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2120 * then the delete should fail if **any** files overlap with
2122 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2123 * non-overlapping files
2124 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2125 * is set, the do not delete any files
2126 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2129 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2131 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2133 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2134 /* no idea of the correct error here */
2135 status = WERR_ACCESS_DENIED;
2140 /* also check for W32X86/3 if necessary; maybe we already have? */
2142 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2143 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2146 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2147 /* no idea of the correct error here */
2148 free_a_printer_driver( info_win2k, 3 );
2149 status = WERR_ACCESS_DENIED;
2153 /* if we get to here, we now have 2 driver info structures to remove */
2154 /* remove the Win2k driver first*/
2156 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2157 free_a_printer_driver( info_win2k, 3 );
2159 /* this should not have failed---if it did, report to client */
2161 if ( !W_ERROR_IS_OK(status_win2k) )
2166 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2168 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2171 free_a_printer_driver( info, 3 );
2177 /****************************************************************************
2178 Internal routine for retreiving printerdata
2179 ***************************************************************************/
2181 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2182 const char *key, const char *value, uint32 *type, uint8 **data,
2183 uint32 *needed, uint32 in_size )
2185 REGISTRY_VALUE *val;
2189 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2190 return WERR_BADFILE;
2192 *type = regval_type( val );
2194 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2196 size = regval_size( val );
2198 /* copy the min(in_size, len) */
2201 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2203 /* special case for 0 length values */
2205 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2209 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2218 DEBUG(5,("get_printer_dataex: copy done\n"));
2223 /****************************************************************************
2224 Internal routine for removing printerdata
2225 ***************************************************************************/
2227 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2229 return delete_printer_data( printer->info_2, key, value );
2232 /****************************************************************************
2233 Internal routine for storing printerdata
2234 ***************************************************************************/
2236 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2237 uint32 type, uint8 *data, int real_len )
2239 /* the registry objects enforce uniqueness based on value name */
2241 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2244 /********************************************************************
2245 GetPrinterData on a printer server Handle.
2246 ********************************************************************/
2248 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2252 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2254 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2256 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2262 if (!StrCaseCmp(value, "BeepEnabled")) {
2264 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2266 SIVAL(*data, 0, 0x00);
2271 if (!StrCaseCmp(value, "EventLog")) {
2273 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2275 /* formally was 0x1b */
2276 SIVAL(*data, 0, 0x0);
2281 if (!StrCaseCmp(value, "NetPopup")) {
2283 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2285 SIVAL(*data, 0, 0x00);
2290 if (!StrCaseCmp(value, "MajorVersion")) {
2292 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2295 /* Windows NT 4.0 seems to not allow uploading of drivers
2296 to a server that reports 0x3 as the MajorVersion.
2297 need to investigate more how Win2k gets around this .
2300 if ( RA_WINNT == get_remote_arch() )
2309 if (!StrCaseCmp(value, "MinorVersion")) {
2311 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2319 * uint32 size = 0x114
2321 * uint32 minor = [0|1]
2322 * uint32 build = [2195|2600]
2323 * extra unicode string = e.g. "Service Pack 3"
2325 if (!StrCaseCmp(value, "OSVersion")) {
2329 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2332 SIVAL(*data, 0, *needed); /* size */
2333 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2335 SIVAL(*data, 12, 2195); /* build */
2337 /* leave extra string empty */
2343 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2344 const char *string="C:\\PRINTERS";
2346 *needed = 2*(strlen(string)+1);
2347 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2349 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2351 /* it's done by hand ready to go on the wire */
2352 for (i=0; i<strlen(string); i++) {
2353 (*data)[2*i]=string[i];
2354 (*data)[2*i+1]='\0';
2359 if (!StrCaseCmp(value, "Architecture")) {
2360 const char *string="Windows NT x86";
2362 *needed = 2*(strlen(string)+1);
2363 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2365 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2366 for (i=0; i<strlen(string); i++) {
2367 (*data)[2*i]=string[i];
2368 (*data)[2*i+1]='\0';
2373 if (!StrCaseCmp(value, "DsPresent")) {
2375 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2378 /* only show the publish check box if we are a
2379 memeber of a AD domain */
2381 if ( lp_security() == SEC_ADS )
2382 SIVAL(*data, 0, 0x01);
2384 SIVAL(*data, 0, 0x00);
2390 if (!StrCaseCmp(value, "DNSMachineName")) {
2393 if (!get_mydnsfullname(hostname))
2394 return WERR_BADFILE;
2396 *needed = 2*(strlen(hostname)+1);
2397 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2399 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2400 for (i=0; i<strlen(hostname); i++) {
2401 (*data)[2*i]=hostname[i];
2402 (*data)[2*i+1]='\0';
2408 return WERR_BADFILE;
2411 /********************************************************************
2412 * spoolss_getprinterdata
2413 ********************************************************************/
2415 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2417 POLICY_HND *handle = &q_u->handle;
2418 UNISTR2 *valuename = &q_u->valuename;
2419 uint32 in_size = q_u->size;
2420 uint32 *type = &r_u->type;
2421 uint32 *out_size = &r_u->size;
2422 uint8 **data = &r_u->data;
2423 uint32 *needed = &r_u->needed;
2426 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2427 NT_PRINTER_INFO_LEVEL *printer = NULL;
2431 * Reminder: when it's a string, the length is in BYTES
2432 * even if UNICODE is negociated.
2437 *out_size = in_size;
2439 /* in case of problem, return some default values */
2444 DEBUG(4,("_spoolss_getprinterdata\n"));
2447 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2448 status = WERR_BADFID;
2452 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2454 if ( Printer->printer_type == SPLHND_SERVER )
2455 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2458 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2459 status = WERR_BADFID;
2463 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2464 if ( !W_ERROR_IS_OK(status) )
2467 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2469 if ( strequal(value, "ChangeId") ) {
2471 *needed = sizeof(uint32);
2472 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2473 status = WERR_NOMEM;
2476 SIVAL( *data, 0, printer->info_2->changeid );
2480 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2483 if (*needed > *out_size)
2484 status = WERR_MORE_DATA;
2487 if ( !W_ERROR_IS_OK(status) )
2489 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2491 /* reply this param doesn't exist */
2494 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2496 free_a_printer( &printer, 2 );
2505 /* cleanup & exit */
2508 free_a_printer( &printer, 2 );
2513 /*********************************************************
2514 Connect to the client machine.
2515 **********************************************************/
2517 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2518 struct in_addr *client_ip, const char *remote_machine)
2521 struct cli_state *the_cli;
2522 struct in_addr rm_addr;
2524 if ( is_zero_ip(*client_ip) ) {
2525 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2526 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2530 if ( ismyip( rm_addr )) {
2531 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2535 rm_addr.s_addr = client_ip->s_addr;
2536 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2537 inet_ntoa(*client_ip) ));
2540 /* setup the connection */
2542 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2543 &rm_addr, 0, "IPC$", "IPC",
2547 0, lp_client_signing(), NULL );
2549 if ( !NT_STATUS_IS_OK( ret ) ) {
2550 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2555 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2556 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2557 cli_shutdown(the_cli);
2562 * Ok - we have an anonymous connection to the IPC$ share.
2563 * Now start the NT Domain stuff :-).
2566 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2567 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2568 remote_machine, nt_errstr(ret)));
2569 cli_shutdown(the_cli);
2573 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2575 (*pp_pipe)->cli = the_cli;
2580 /***************************************************************************
2581 Connect to the client.
2582 ****************************************************************************/
2584 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2585 uint32 localprinter, uint32 type,
2586 POLICY_HND *handle, struct in_addr *client_ip)
2591 * If it's the first connection, contact the client
2592 * and connect to the IPC$ share anonymously
2594 if (smb_connections==0) {
2595 fstring unix_printer;
2597 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2599 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2602 message_register(MSG_PRINTER_NOTIFY2,
2603 receive_notify2_message_list, NULL);
2604 /* Tell the connections db we're now interested in printer
2605 * notify messages. */
2606 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2610 * Tell the specific printing tdb we want messages for this printer
2611 * by registering our PID.
2614 if (!print_notify_register_pid(snum))
2615 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2619 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2622 if (!W_ERROR_IS_OK(result))
2623 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2624 dos_errstr(result)));
2626 return (W_ERROR_IS_OK(result));
2629 /********************************************************************
2631 * ReplyFindFirstPrinterChangeNotifyEx
2633 * before replying OK: status=0 a rpc call is made to the workstation
2634 * asking ReplyOpenPrinter
2636 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2637 * called from api_spoolss_rffpcnex
2638 ********************************************************************/
2640 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2642 POLICY_HND *handle = &q_u->handle;
2643 uint32 flags = q_u->flags;
2644 uint32 options = q_u->options;
2645 UNISTR2 *localmachine = &q_u->localmachine;
2646 uint32 printerlocal = q_u->printerlocal;
2648 SPOOL_NOTIFY_OPTION *option = q_u->option;
2649 struct in_addr client_ip;
2651 /* store the notify value in the printer struct */
2653 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2656 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2660 Printer->notify.flags=flags;
2661 Printer->notify.options=options;
2662 Printer->notify.printerlocal=printerlocal;
2664 if (Printer->notify.option)
2665 free_spool_notify_option(&Printer->notify.option);
2667 Printer->notify.option=dup_spool_notify_option(option);
2669 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2670 sizeof(Printer->notify.localmachine)-1);
2672 /* Connect to the client machine and send a ReplyOpenPrinter */
2674 if ( Printer->printer_type == SPLHND_SERVER)
2676 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2677 !get_printer_snum(p, handle, &snum, NULL) )
2680 client_ip.s_addr = inet_addr(p->conn->client_address);
2682 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2683 Printer->notify.printerlocal, 1,
2684 &Printer->notify.client_hnd, &client_ip))
2685 return WERR_SERVER_UNAVAILABLE;
2687 Printer->notify.client_connected=True;
2692 /*******************************************************************
2693 * fill a notify_info_data with the servername
2694 ********************************************************************/
2696 void spoolss_notify_server_name(int snum,
2697 SPOOL_NOTIFY_INFO_DATA *data,
2698 print_queue_struct *queue,
2699 NT_PRINTER_INFO_LEVEL *printer,
2700 TALLOC_CTX *mem_ctx)
2705 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2707 data->notify_data.data.length = len;
2708 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2710 if (!data->notify_data.data.string) {
2711 data->notify_data.data.length = 0;
2715 memcpy(data->notify_data.data.string, temp, len);
2718 /*******************************************************************
2719 * fill a notify_info_data with the printername (not including the servername).
2720 ********************************************************************/
2722 void spoolss_notify_printer_name(int snum,
2723 SPOOL_NOTIFY_INFO_DATA *data,
2724 print_queue_struct *queue,
2725 NT_PRINTER_INFO_LEVEL *printer,
2726 TALLOC_CTX *mem_ctx)
2731 /* the notify name should not contain the \\server\ part */
2732 char *p = strrchr(printer->info_2->printername, '\\');
2735 p = printer->info_2->printername;
2740 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2742 data->notify_data.data.length = len;
2743 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2745 if (!data->notify_data.data.string) {
2746 data->notify_data.data.length = 0;
2750 memcpy(data->notify_data.data.string, temp, len);
2753 /*******************************************************************
2754 * fill a notify_info_data with the servicename
2755 ********************************************************************/
2757 void spoolss_notify_share_name(int snum,
2758 SPOOL_NOTIFY_INFO_DATA *data,
2759 print_queue_struct *queue,
2760 NT_PRINTER_INFO_LEVEL *printer,
2761 TALLOC_CTX *mem_ctx)
2766 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2768 data->notify_data.data.length = len;
2769 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2771 if (!data->notify_data.data.string) {
2772 data->notify_data.data.length = 0;
2776 memcpy(data->notify_data.data.string, temp, len);
2779 /*******************************************************************
2780 * fill a notify_info_data with the port name
2781 ********************************************************************/
2783 void spoolss_notify_port_name(int snum,
2784 SPOOL_NOTIFY_INFO_DATA *data,
2785 print_queue_struct *queue,
2786 NT_PRINTER_INFO_LEVEL *printer,
2787 TALLOC_CTX *mem_ctx)
2792 /* even if it's strange, that's consistant in all the code */
2794 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2796 data->notify_data.data.length = len;
2797 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2799 if (!data->notify_data.data.string) {
2800 data->notify_data.data.length = 0;
2804 memcpy(data->notify_data.data.string, temp, len);
2807 /*******************************************************************
2808 * fill a notify_info_data with the printername
2809 * but it doesn't exist, have to see what to do
2810 ********************************************************************/
2812 void spoolss_notify_driver_name(int snum,
2813 SPOOL_NOTIFY_INFO_DATA *data,
2814 print_queue_struct *queue,
2815 NT_PRINTER_INFO_LEVEL *printer,
2816 TALLOC_CTX *mem_ctx)
2821 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2823 data->notify_data.data.length = len;
2824 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2826 if (!data->notify_data.data.string) {
2827 data->notify_data.data.length = 0;
2831 memcpy(data->notify_data.data.string, temp, len);
2834 /*******************************************************************
2835 * fill a notify_info_data with the comment
2836 ********************************************************************/
2838 void spoolss_notify_comment(int snum,
2839 SPOOL_NOTIFY_INFO_DATA *data,
2840 print_queue_struct *queue,
2841 NT_PRINTER_INFO_LEVEL *printer,
2842 TALLOC_CTX *mem_ctx)
2847 if (*printer->info_2->comment == '\0')
2848 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2850 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2852 data->notify_data.data.length = len;
2853 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2855 if (!data->notify_data.data.string) {
2856 data->notify_data.data.length = 0;
2860 memcpy(data->notify_data.data.string, temp, len);
2863 /*******************************************************************
2864 * fill a notify_info_data with the comment
2865 * location = "Room 1, floor 2, building 3"
2866 ********************************************************************/
2868 void spoolss_notify_location(int snum,
2869 SPOOL_NOTIFY_INFO_DATA *data,
2870 print_queue_struct *queue,
2871 NT_PRINTER_INFO_LEVEL *printer,
2872 TALLOC_CTX *mem_ctx)
2877 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2879 data->notify_data.data.length = len;
2880 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2882 if (!data->notify_data.data.string) {
2883 data->notify_data.data.length = 0;
2887 memcpy(data->notify_data.data.string, temp, len);
2890 /*******************************************************************
2891 * fill a notify_info_data with the device mode
2892 * jfm:xxxx don't to it for know but that's a real problem !!!
2893 ********************************************************************/
2895 static void spoolss_notify_devmode(int snum,
2896 SPOOL_NOTIFY_INFO_DATA *data,
2897 print_queue_struct *queue,
2898 NT_PRINTER_INFO_LEVEL *printer,
2899 TALLOC_CTX *mem_ctx)
2901 /* for a dummy implementation we have to zero the fields */
2902 data->notify_data.data.length = 0;
2903 data->notify_data.data.string = NULL;
2906 /*******************************************************************
2907 * fill a notify_info_data with the separator file name
2908 ********************************************************************/
2910 void spoolss_notify_sepfile(int snum,
2911 SPOOL_NOTIFY_INFO_DATA *data,
2912 print_queue_struct *queue,
2913 NT_PRINTER_INFO_LEVEL *printer,
2914 TALLOC_CTX *mem_ctx)
2919 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2921 data->notify_data.data.length = len;
2922 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2924 if (!data->notify_data.data.string) {
2925 data->notify_data.data.length = 0;
2929 memcpy(data->notify_data.data.string, temp, len);
2932 /*******************************************************************
2933 * fill a notify_info_data with the print processor
2934 * jfm:xxxx return always winprint to indicate we don't do anything to it
2935 ********************************************************************/
2937 void spoolss_notify_print_processor(int snum,
2938 SPOOL_NOTIFY_INFO_DATA *data,
2939 print_queue_struct *queue,
2940 NT_PRINTER_INFO_LEVEL *printer,
2941 TALLOC_CTX *mem_ctx)
2946 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2948 data->notify_data.data.length = len;
2949 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2951 if (!data->notify_data.data.string) {
2952 data->notify_data.data.length = 0;
2956 memcpy(data->notify_data.data.string, temp, len);
2959 /*******************************************************************
2960 * fill a notify_info_data with the print processor options
2961 * jfm:xxxx send an empty string
2962 ********************************************************************/
2964 void spoolss_notify_parameters(int snum,
2965 SPOOL_NOTIFY_INFO_DATA *data,
2966 print_queue_struct *queue,
2967 NT_PRINTER_INFO_LEVEL *printer,
2968 TALLOC_CTX *mem_ctx)
2973 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2975 data->notify_data.data.length = len;
2976 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2978 if (!data->notify_data.data.string) {
2979 data->notify_data.data.length = 0;
2983 memcpy(data->notify_data.data.string, temp, len);
2986 /*******************************************************************
2987 * fill a notify_info_data with the data type
2988 * jfm:xxxx always send RAW as data type
2989 ********************************************************************/
2991 void spoolss_notify_datatype(int snum,
2992 SPOOL_NOTIFY_INFO_DATA *data,
2993 print_queue_struct *queue,
2994 NT_PRINTER_INFO_LEVEL *printer,
2995 TALLOC_CTX *mem_ctx)
3000 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3002 data->notify_data.data.length = len;
3003 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3005 if (!data->notify_data.data.string) {
3006 data->notify_data.data.length = 0;
3010 memcpy(data->notify_data.data.string, temp, len);
3013 /*******************************************************************
3014 * fill a notify_info_data with the security descriptor
3015 * jfm:xxxx send an null pointer to say no security desc
3016 * have to implement security before !
3017 ********************************************************************/
3019 static void spoolss_notify_security_desc(int snum,
3020 SPOOL_NOTIFY_INFO_DATA *data,
3021 print_queue_struct *queue,
3022 NT_PRINTER_INFO_LEVEL *printer,
3023 TALLOC_CTX *mem_ctx)
3025 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3026 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3029 /*******************************************************************
3030 * fill a notify_info_data with the attributes
3031 * jfm:xxxx a samba printer is always shared
3032 ********************************************************************/
3034 void spoolss_notify_attributes(int snum,
3035 SPOOL_NOTIFY_INFO_DATA *data,
3036 print_queue_struct *queue,
3037 NT_PRINTER_INFO_LEVEL *printer,
3038 TALLOC_CTX *mem_ctx)
3040 data->notify_data.value[0] = printer->info_2->attributes;
3041 data->notify_data.value[1] = 0;
3044 /*******************************************************************
3045 * fill a notify_info_data with the priority
3046 ********************************************************************/
3048 static void spoolss_notify_priority(int snum,
3049 SPOOL_NOTIFY_INFO_DATA *data,
3050 print_queue_struct *queue,
3051 NT_PRINTER_INFO_LEVEL *printer,
3052 TALLOC_CTX *mem_ctx)
3054 data->notify_data.value[0] = printer->info_2->priority;
3055 data->notify_data.value[1] = 0;
3058 /*******************************************************************
3059 * fill a notify_info_data with the default priority
3060 ********************************************************************/
3062 static void spoolss_notify_default_priority(int snum,
3063 SPOOL_NOTIFY_INFO_DATA *data,
3064 print_queue_struct *queue,
3065 NT_PRINTER_INFO_LEVEL *printer,
3066 TALLOC_CTX *mem_ctx)
3068 data->notify_data.value[0] = printer->info_2->default_priority;
3069 data->notify_data.value[1] = 0;
3072 /*******************************************************************
3073 * fill a notify_info_data with the start time
3074 ********************************************************************/
3076 static void spoolss_notify_start_time(int snum,
3077 SPOOL_NOTIFY_INFO_DATA *data,
3078 print_queue_struct *queue,
3079 NT_PRINTER_INFO_LEVEL *printer,
3080 TALLOC_CTX *mem_ctx)
3082 data->notify_data.value[0] = printer->info_2->starttime;
3083 data->notify_data.value[1] = 0;
3086 /*******************************************************************
3087 * fill a notify_info_data with the until time
3088 ********************************************************************/
3090 static void spoolss_notify_until_time(int snum,
3091 SPOOL_NOTIFY_INFO_DATA *data,
3092 print_queue_struct *queue,
3093 NT_PRINTER_INFO_LEVEL *printer,
3094 TALLOC_CTX *mem_ctx)
3096 data->notify_data.value[0] = printer->info_2->untiltime;
3097 data->notify_data.value[1] = 0;
3100 /*******************************************************************
3101 * fill a notify_info_data with the status
3102 ********************************************************************/
3104 static void spoolss_notify_status(int snum,
3105 SPOOL_NOTIFY_INFO_DATA *data,
3106 print_queue_struct *queue,
3107 NT_PRINTER_INFO_LEVEL *printer,
3108 TALLOC_CTX *mem_ctx)
3110 print_status_struct status;
3112 print_queue_length(snum, &status);
3113 data->notify_data.value[0]=(uint32) status.status;
3114 data->notify_data.value[1] = 0;
3117 /*******************************************************************
3118 * fill a notify_info_data with the number of jobs queued
3119 ********************************************************************/
3121 void spoolss_notify_cjobs(int snum,
3122 SPOOL_NOTIFY_INFO_DATA *data,
3123 print_queue_struct *queue,
3124 NT_PRINTER_INFO_LEVEL *printer,
3125 TALLOC_CTX *mem_ctx)
3127 data->notify_data.value[0] = print_queue_length(snum, NULL);
3128 data->notify_data.value[1] = 0;
3131 /*******************************************************************
3132 * fill a notify_info_data with the average ppm
3133 ********************************************************************/
3135 static void spoolss_notify_average_ppm(int snum,
3136 SPOOL_NOTIFY_INFO_DATA *data,
3137 print_queue_struct *queue,
3138 NT_PRINTER_INFO_LEVEL *printer,
3139 TALLOC_CTX *mem_ctx)
3141 /* always respond 8 pages per minutes */
3142 /* a little hard ! */
3143 data->notify_data.value[0] = printer->info_2->averageppm;
3144 data->notify_data.value[1] = 0;
3147 /*******************************************************************
3148 * fill a notify_info_data with username
3149 ********************************************************************/
3151 static void spoolss_notify_username(int snum,
3152 SPOOL_NOTIFY_INFO_DATA *data,
3153 print_queue_struct *queue,
3154 NT_PRINTER_INFO_LEVEL *printer,
3155 TALLOC_CTX *mem_ctx)
3160 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3162 data->notify_data.data.length = len;
3163 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3165 if (!data->notify_data.data.string) {
3166 data->notify_data.data.length = 0;
3170 memcpy(data->notify_data.data.string, temp, len);
3173 /*******************************************************************
3174 * fill a notify_info_data with job status
3175 ********************************************************************/
3177 static void spoolss_notify_job_status(int snum,
3178 SPOOL_NOTIFY_INFO_DATA *data,
3179 print_queue_struct *queue,
3180 NT_PRINTER_INFO_LEVEL *printer,
3181 TALLOC_CTX *mem_ctx)
3183 data->notify_data.value[0]=nt_printj_status(queue->status);
3184 data->notify_data.value[1] = 0;
3187 /*******************************************************************
3188 * fill a notify_info_data with job name
3189 ********************************************************************/
3191 static void spoolss_notify_job_name(int snum,
3192 SPOOL_NOTIFY_INFO_DATA *data,
3193 print_queue_struct *queue,
3194 NT_PRINTER_INFO_LEVEL *printer,
3195 TALLOC_CTX *mem_ctx)
3200 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3202 data->notify_data.data.length = len;
3203 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3205 if (!data->notify_data.data.string) {
3206 data->notify_data.data.length = 0;
3210 memcpy(data->notify_data.data.string, temp, len);
3213 /*******************************************************************
3214 * fill a notify_info_data with job status
3215 ********************************************************************/
3217 static void spoolss_notify_job_status_string(int snum,
3218 SPOOL_NOTIFY_INFO_DATA *data,
3219 print_queue_struct *queue,
3220 NT_PRINTER_INFO_LEVEL *printer,
3221 TALLOC_CTX *mem_ctx)
3224 * Now we're returning job status codes we just return a "" here. JRA.
3231 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3234 switch (queue->status) {
3239 p = ""; /* NT provides the paused string */
3248 #endif /* NO LONGER NEEDED. */
3250 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3252 data->notify_data.data.length = len;
3253 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3255 if (!data->notify_data.data.string) {
3256 data->notify_data.data.length = 0;
3260 memcpy(data->notify_data.data.string, temp, len);
3263 /*******************************************************************
3264 * fill a notify_info_data with job time
3265 ********************************************************************/
3267 static void spoolss_notify_job_time(int snum,
3268 SPOOL_NOTIFY_INFO_DATA *data,
3269 print_queue_struct *queue,
3270 NT_PRINTER_INFO_LEVEL *printer,
3271 TALLOC_CTX *mem_ctx)
3273 data->notify_data.value[0]=0x0;
3274 data->notify_data.value[1]=0;
3277 /*******************************************************************
3278 * fill a notify_info_data with job size
3279 ********************************************************************/
3281 static void spoolss_notify_job_size(int snum,
3282 SPOOL_NOTIFY_INFO_DATA *data,
3283 print_queue_struct *queue,
3284 NT_PRINTER_INFO_LEVEL *printer,
3285 TALLOC_CTX *mem_ctx)
3287 data->notify_data.value[0]=queue->size;
3288 data->notify_data.value[1]=0;
3291 /*******************************************************************
3292 * fill a notify_info_data with page info
3293 ********************************************************************/
3294 static void spoolss_notify_total_pages(int snum,
3295 SPOOL_NOTIFY_INFO_DATA *data,
3296 print_queue_struct *queue,
3297 NT_PRINTER_INFO_LEVEL *printer,
3298 TALLOC_CTX *mem_ctx)
3300 data->notify_data.value[0]=queue->page_count;
3301 data->notify_data.value[1]=0;
3304 /*******************************************************************
3305 * fill a notify_info_data with pages printed info.
3306 ********************************************************************/
3307 static void spoolss_notify_pages_printed(int snum,
3308 SPOOL_NOTIFY_INFO_DATA *data,
3309 print_queue_struct *queue,
3310 NT_PRINTER_INFO_LEVEL *printer,
3311 TALLOC_CTX *mem_ctx)
3313 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3314 data->notify_data.value[1]=0;
3317 /*******************************************************************
3318 Fill a notify_info_data with job position.
3319 ********************************************************************/
3321 static void spoolss_notify_job_position(int snum,
3322 SPOOL_NOTIFY_INFO_DATA *data,
3323 print_queue_struct *queue,
3324 NT_PRINTER_INFO_LEVEL *printer,
3325 TALLOC_CTX *mem_ctx)
3327 data->notify_data.value[0]=queue->job;
3328 data->notify_data.value[1]=0;
3331 /*******************************************************************
3332 Fill a notify_info_data with submitted time.
3333 ********************************************************************/
3335 static void spoolss_notify_submitted_time(int snum,
3336 SPOOL_NOTIFY_INFO_DATA *data,
3337 print_queue_struct *queue,
3338 NT_PRINTER_INFO_LEVEL *printer,
3339 TALLOC_CTX *mem_ctx)
3346 t=gmtime(&queue->time);
3348 len = sizeof(SYSTEMTIME);
3350 data->notify_data.data.length = len;
3351 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3353 if (!data->notify_data.data.string) {
3354 data->notify_data.data.length = 0;
3358 make_systemtime(&st, t);
3361 * Systemtime must be linearized as a set of UINT16's.
3362 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3365 p = (char *)data->notify_data.data.string;
3366 SSVAL(p, 0, st.year);
3367 SSVAL(p, 2, st.month);
3368 SSVAL(p, 4, st.dayofweek);
3369 SSVAL(p, 6, st.day);
3370 SSVAL(p, 8, st.hour);
3371 SSVAL(p, 10, st.minute);
3372 SSVAL(p, 12, st.second);
3373 SSVAL(p, 14, st.milliseconds);
3376 struct s_notify_info_data_table
3382 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3383 print_queue_struct *queue,
3384 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3387 /* A table describing the various print notification constants and
3388 whether the notification data is a pointer to a variable sized
3389 buffer, a one value uint32 or a two value uint32. */
3391 static const struct s_notify_info_data_table notify_info_data_table[] =
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3440 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3442 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3445 /*******************************************************************
3446 Return the size of info_data structure.
3447 ********************************************************************/
3449 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3453 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3454 if ( (notify_info_data_table[i].type == type)
3455 && (notify_info_data_table[i].field == field) ) {
3456 switch(notify_info_data_table[i].size) {
3457 case NOTIFY_ONE_VALUE:
3458 case NOTIFY_TWO_VALUE:
3463 /* The only pointer notify data I have seen on
3464 the wire is the submitted time and this has
3465 the notify size set to 4. -tpot */
3467 case NOTIFY_POINTER:
3470 case NOTIFY_SECDESC:
3476 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3481 /*******************************************************************
3482 Return the type of notify_info_data.
3483 ********************************************************************/
3485 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3489 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3490 if (notify_info_data_table[i].type == type &&
3491 notify_info_data_table[i].field == field)
3492 return notify_info_data_table[i].size;
3498 /****************************************************************************
3499 ****************************************************************************/
3501 static BOOL search_notify(uint16 type, uint16 field, int *value)
3505 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3506 if (notify_info_data_table[i].type == type &&
3507 notify_info_data_table[i].field == field &&
3508 notify_info_data_table[i].fn != NULL) {
3517 /****************************************************************************
3518 ****************************************************************************/
3520 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3522 info_data->type = type;
3523 info_data->field = field;
3524 info_data->reserved = 0;
3526 info_data->size = size_of_notify_info_data(type, field);
3527 info_data->enc_type = type_of_notify_info_data(type, field);
3532 /*******************************************************************
3534 * fill a notify_info struct with info asked
3536 ********************************************************************/
3538 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3539 snum, SPOOL_NOTIFY_OPTION_TYPE
3540 *option_type, uint32 id,
3541 TALLOC_CTX *mem_ctx)
3547 SPOOL_NOTIFY_INFO_DATA *current_data;
3548 NT_PRINTER_INFO_LEVEL *printer = NULL;
3549 print_queue_struct *queue=NULL;
3551 type=option_type->type;
3553 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3554 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3555 option_type->count, lp_servicename(snum)));
3557 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3560 for(field_num=0; field_num<option_type->count; field_num++) {
3561 field = option_type->fields[field_num];
3563 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3565 if (!search_notify(type, field, &j) )
3568 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3569 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3570 free_a_printer(&printer, 2);
3574 current_data = &info->data[info->count];
3576 construct_info_data(current_data, type, field, id);
3578 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3579 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3581 notify_info_data_table[j].fn(snum, current_data, queue,
3587 free_a_printer(&printer, 2);
3591 /*******************************************************************
3593 * fill a notify_info struct with info asked
3595 ********************************************************************/
3597 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3598 SPOOL_NOTIFY_INFO *info,
3599 NT_PRINTER_INFO_LEVEL *printer,
3600 int snum, SPOOL_NOTIFY_OPTION_TYPE
3601 *option_type, uint32 id,
3602 TALLOC_CTX *mem_ctx)
3608 SPOOL_NOTIFY_INFO_DATA *current_data;
3610 DEBUG(4,("construct_notify_jobs_info\n"));
3612 type = option_type->type;
3614 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3615 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3616 option_type->count));
3618 for(field_num=0; field_num<option_type->count; field_num++) {
3619 field = option_type->fields[field_num];
3621 if (!search_notify(type, field, &j) )
3624 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3625 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3629 current_data=&(info->data[info->count]);
3631 construct_info_data(current_data, type, field, id);
3632 notify_info_data_table[j].fn(snum, current_data, queue,
3641 * JFM: The enumeration is not that simple, it's even non obvious.
3643 * let's take an example: I want to monitor the PRINTER SERVER for
3644 * the printer's name and the number of jobs currently queued.
3645 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3646 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3648 * I have 3 printers on the back of my server.
3650 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3653 * 1 printer 1 name 1
3654 * 2 printer 1 cjob 1
3655 * 3 printer 2 name 2
3656 * 4 printer 2 cjob 2
3657 * 5 printer 3 name 3
3658 * 6 printer 3 name 3
3660 * that's the print server case, the printer case is even worse.
3663 /*******************************************************************
3665 * enumerate all printers on the printserver
3666 * fill a notify_info struct with info asked
3668 ********************************************************************/
3670 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3671 SPOOL_NOTIFY_INFO *info,
3672 TALLOC_CTX *mem_ctx)
3675 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3676 int n_services=lp_numservices();
3678 SPOOL_NOTIFY_OPTION *option;
3679 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3681 DEBUG(4,("printserver_notify_info\n"));
3686 option=Printer->notify.option;
3691 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3692 sending a ffpcn() request first */
3697 for (i=0; i<option->count; i++) {
3698 option_type=&(option->ctr.type[i]);
3700 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3703 for (snum=0; snum<n_services; snum++)
3705 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3706 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3712 * Debugging information, don't delete.
3715 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3716 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3717 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3719 for (i=0; i<info->count; i++) {
3720 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3721 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3722 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3729 /*******************************************************************
3731 * fill a notify_info struct with info asked
3733 ********************************************************************/
3735 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3736 TALLOC_CTX *mem_ctx)
3739 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3742 SPOOL_NOTIFY_OPTION *option;
3743 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3745 print_queue_struct *queue=NULL;
3746 print_status_struct status;
3748 DEBUG(4,("printer_notify_info\n"));
3753 option=Printer->notify.option;
3759 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3760 sending a ffpcn() request first */
3765 get_printer_snum(p, hnd, &snum, NULL);
3767 for (i=0; i<option->count; i++) {
3768 option_type=&option->ctr.type[i];
3770 switch ( option_type->type ) {
3771 case PRINTER_NOTIFY_TYPE:
3772 if(construct_notify_printer_info(Printer, info, snum,
3778 case JOB_NOTIFY_TYPE: {
3779 NT_PRINTER_INFO_LEVEL *printer = NULL;
3781 count = print_queue_status(snum, &queue, &status);
3783 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3786 for (j=0; j<count; j++) {
3787 construct_notify_jobs_info(&queue[j], info,
3794 free_a_printer(&printer, 2);
3804 * Debugging information, don't delete.
3807 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3808 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3809 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3811 for (i=0; i<info->count; i++) {
3812 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3813 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3814 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3820 /********************************************************************
3822 ********************************************************************/
3824 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3826 POLICY_HND *handle = &q_u->handle;
3827 SPOOL_NOTIFY_INFO *info = &r_u->info;
3829 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3830 WERROR result = WERR_BADFID;
3832 /* we always have a NOTIFY_INFO struct */
3836 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3837 OUR_HANDLE(handle)));
3841 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3844 * We are now using the change value, and
3845 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3846 * I don't have a global notification system, I'm sending back all the
3847 * informations even when _NOTHING_ has changed.
3850 /* We need to keep track of the change value to send back in
3851 RRPCN replies otherwise our updates are ignored. */
3853 Printer->notify.fnpcn = True;
3855 if (Printer->notify.client_connected) {
3856 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3857 Printer->notify.change = q_u->change;
3860 /* just ignore the SPOOL_NOTIFY_OPTION */
3862 switch (Printer->printer_type) {
3864 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3867 case SPLHND_PRINTER:
3868 result = printer_notify_info(p, handle, info, p->mem_ctx);
3872 Printer->notify.fnpcn = False;
3878 /********************************************************************
3879 * construct_printer_info_0
3880 * fill a printer_info_0 struct
3881 ********************************************************************/
3883 static BOOL construct_printer_info_0(Printer_entry *print_hnd,
3884 PRINTER_INFO_0 *printer,
3885 const struct share_params *params)
3889 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3890 counter_printer_0 *session_counter;
3891 uint32 global_counter;
3894 print_status_struct status;
3896 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
3897 lp_const_servicename(params->service))))
3900 count = print_queue_length(params->service, &status);
3902 /* check if we already have a counter for this printer */
3903 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3904 if (session_counter->snum == params->service)
3908 /* it's the first time, add it to the list */
3909 if (session_counter==NULL) {
3910 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3911 free_a_printer(&ntprinter, 2);
3914 ZERO_STRUCTP(session_counter);
3915 session_counter->snum=params->service;
3916 session_counter->counter=0;
3917 DLIST_ADD(counter_list, session_counter);
3921 session_counter->counter++;
3924 * the global_counter should be stored in a TDB as it's common to all the clients
3925 * and should be zeroed on samba startup
3927 global_counter=session_counter->counter;
3929 pstrcpy(chaine,ntprinter->info_2->printername);
3931 init_unistr(&printer->printername, chaine);
3933 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3934 init_unistr(&printer->servername, chaine);
3936 printer->cjobs = count;
3937 printer->total_jobs = 0;
3938 printer->total_bytes = 0;
3940 setuptime = (time_t)ntprinter->info_2->setuptime;
3941 t=gmtime(&setuptime);
3943 printer->year = t->tm_year+1900;
3944 printer->month = t->tm_mon+1;
3945 printer->dayofweek = t->tm_wday;
3946 printer->day = t->tm_mday;
3947 printer->hour = t->tm_hour;
3948 printer->minute = t->tm_min;
3949 printer->second = t->tm_sec;
3950 printer->milliseconds = 0;
3952 printer->global_counter = global_counter;
3953 printer->total_pages = 0;
3955 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3956 printer->major_version = 0x0005; /* NT 5 */
3957 printer->build_version = 0x0893; /* build 2195 */
3959 printer->unknown7 = 0x1;
3960 printer->unknown8 = 0x0;
3961 printer->unknown9 = 0x0;
3962 printer->session_counter = session_counter->counter;
3963 printer->unknown11 = 0x0;
3964 printer->printer_errors = 0x0; /* number of print failure */
3965 printer->unknown13 = 0x0;
3966 printer->unknown14 = 0x1;
3967 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3968 printer->unknown16 = 0x0;
3969 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3970 printer->unknown18 = 0x0;
3971 printer->status = nt_printq_status(status.status);
3972 printer->unknown20 = 0x0;
3973 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3974 printer->unknown22 = 0x0;
3975 printer->unknown23 = 0x6; /* 6 ???*/
3976 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3977 printer->unknown25 = 0;
3978 printer->unknown26 = 0;
3979 printer->unknown27 = 0;
3980 printer->unknown28 = 0;
3981 printer->unknown29 = 0;
3983 free_a_printer(&ntprinter,2);
3987 /********************************************************************
3988 * construct_printer_info_1
3989 * fill a printer_info_1 struct
3990 ********************************************************************/
3991 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags,
3992 PRINTER_INFO_1 *printer,
3993 const struct share_params *params)
3997 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3999 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4000 lp_const_servicename(params->service))))
4003 printer->flags=flags;
4005 if (*ntprinter->info_2->comment == '\0') {
4006 init_unistr(&printer->comment, lp_comment(params->service));
4007 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4008 ntprinter->info_2->drivername,
4009 lp_comment(params->service));
4012 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4013 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4014 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4017 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4019 init_unistr(&printer->description, chaine);
4020 init_unistr(&printer->name, chaine2);
4022 free_a_printer(&ntprinter,2);
4027 /****************************************************************************
4028 Free a DEVMODE struct.
4029 ****************************************************************************/
4031 static void free_dev_mode(DEVICEMODE *dev)
4036 SAFE_FREE(dev->dev_private);
4041 /****************************************************************************
4042 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4043 should be valid upon entry
4044 ****************************************************************************/
4046 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4048 if ( !devmode || !ntdevmode )
4051 init_unistr(&devmode->devicename, ntdevmode->devicename);
4053 init_unistr(&devmode->formname, ntdevmode->formname);
4055 devmode->specversion = ntdevmode->specversion;
4056 devmode->driverversion = ntdevmode->driverversion;
4057 devmode->size = ntdevmode->size;
4058 devmode->driverextra = ntdevmode->driverextra;
4059 devmode->fields = ntdevmode->fields;
4061 devmode->orientation = ntdevmode->orientation;
4062 devmode->papersize = ntdevmode->papersize;
4063 devmode->paperlength = ntdevmode->paperlength;
4064 devmode->paperwidth = ntdevmode->paperwidth;
4065 devmode->scale = ntdevmode->scale;
4066 devmode->copies = ntdevmode->copies;
4067 devmode->defaultsource = ntdevmode->defaultsource;
4068 devmode->printquality = ntdevmode->printquality;
4069 devmode->color = ntdevmode->color;
4070 devmode->duplex = ntdevmode->duplex;
4071 devmode->yresolution = ntdevmode->yresolution;
4072 devmode->ttoption = ntdevmode->ttoption;
4073 devmode->collate = ntdevmode->collate;
4074 devmode->icmmethod = ntdevmode->icmmethod;
4075 devmode->icmintent = ntdevmode->icmintent;
4076 devmode->mediatype = ntdevmode->mediatype;
4077 devmode->dithertype = ntdevmode->dithertype;
4079 if (ntdevmode->nt_dev_private != NULL) {
4080 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4087 /****************************************************************************
4088 Create a DEVMODE struct. Returns malloced memory.
4089 ****************************************************************************/
4091 DEVICEMODE *construct_dev_mode(const char *servicename)
4093 NT_PRINTER_INFO_LEVEL *printer = NULL;
4094 DEVICEMODE *devmode = NULL;
4096 DEBUG(7,("construct_dev_mode\n"));
4098 DEBUGADD(8,("getting printer characteristics\n"));
4100 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4103 if ( !printer->info_2->devmode ) {
4104 DEBUG(5, ("BONG! There was no device mode!\n"));
4108 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4109 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4113 ZERO_STRUCTP(devmode);
4115 DEBUGADD(8,("loading DEVICEMODE\n"));
4117 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4118 free_dev_mode( devmode );
4123 free_a_printer(&printer,2);
4128 /********************************************************************
4129 * construct_printer_info_2
4130 * fill a printer_info_2 struct
4131 ********************************************************************/
4133 static BOOL construct_printer_info_2(Printer_entry *print_hnd,
4134 PRINTER_INFO_2 *printer,
4135 const struct share_params *params)
4138 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4140 print_status_struct status;
4142 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4143 lp_const_servicename(params->service))))
4146 count = print_queue_length(params->service, &status);
4148 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4149 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4150 init_unistr(&printer->sharename, lp_servicename(params->service)); /* sharename */
4151 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4152 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4154 if (*ntprinter->info_2->comment == '\0')
4155 init_unistr(&printer->comment, lp_comment(params->service)); /* comment */
4157 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4159 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4160 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4161 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4162 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4163 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4165 printer->attributes = ntprinter->info_2->attributes;
4167 printer->priority = ntprinter->info_2->priority; /* priority */
4168 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4169 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4170 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4171 printer->status = nt_printq_status(status.status); /* status */
4172 printer->cjobs = count; /* jobs */
4173 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4175 if ( !(printer->devmode = construct_dev_mode(
4176 lp_const_servicename(params->service))) )
4177 DEBUG(8, ("Returning NULL Devicemode!\n"));
4179 printer->secdesc = NULL;
4181 if ( ntprinter->info_2->secdesc_buf
4182 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4184 /* don't use talloc_steal() here unless you do a deep steal of all
4185 the SEC_DESC members */
4187 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4188 ntprinter->info_2->secdesc_buf->sd );
4191 free_a_printer(&ntprinter, 2);
4196 /********************************************************************
4197 * construct_printer_info_3
4198 * fill a printer_info_3 struct
4199 ********************************************************************/
4201 static BOOL construct_printer_info_3(Printer_entry *print_hnd,
4202 PRINTER_INFO_3 **pp_printer,
4203 const struct share_params *params)
4205 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4206 PRINTER_INFO_3 *printer = NULL;
4208 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4209 lp_const_servicename(params->service))))
4213 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4214 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4215 free_a_printer(&ntprinter, 2);
4219 ZERO_STRUCTP(printer);
4221 /* These are the components of the SD we are returning. */
4223 printer->flags = 0x4;
4225 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4226 /* don't use talloc_steal() here unless you do a deep steal of all
4227 the SEC_DESC members */
4229 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4230 ntprinter->info_2->secdesc_buf->sd );
4233 free_a_printer(&ntprinter, 2);
4235 *pp_printer = printer;
4239 /********************************************************************
4240 * construct_printer_info_4
4241 * fill a printer_info_4 struct
4242 ********************************************************************/
4244 static BOOL construct_printer_info_4(Printer_entry *print_hnd,
4245 PRINTER_INFO_4 *printer,
4246 const struct share_params *params)
4248 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4250 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4251 lp_const_servicename(params->service))))
4254 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4255 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4256 printer->attributes = ntprinter->info_2->attributes;
4258 free_a_printer(&ntprinter, 2);
4262 /********************************************************************
4263 * construct_printer_info_5
4264 * fill a printer_info_5 struct
4265 ********************************************************************/
4267 static BOOL construct_printer_info_5(Printer_entry *print_hnd,
4268 PRINTER_INFO_5 *printer,
4269 const struct share_params *params)
4271 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4273 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4274 lp_const_servicename(params->service))))
4277 init_unistr(&printer->printername, ntprinter->info_2->printername);
4278 init_unistr(&printer->portname, ntprinter->info_2->portname);
4279 printer->attributes = ntprinter->info_2->attributes;
4281 /* these two are not used by NT+ according to MSDN */
4283 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4284 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4286 free_a_printer(&ntprinter, 2);
4291 /********************************************************************
4292 * construct_printer_info_6
4293 * fill a printer_info_6 struct
4294 ********************************************************************/
4296 static BOOL construct_printer_info_6(Printer_entry *print_hnd,
4297 PRINTER_INFO_6 *printer,
4298 const struct share_params *params)
4300 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4302 print_status_struct status;
4304 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4305 lp_const_servicename(params->service))))
4308 count = print_queue_length(params->service, &status);
4310 printer->status = nt_printq_status(status.status);
4312 free_a_printer(&ntprinter, 2);
4317 /********************************************************************
4318 * construct_printer_info_7
4319 * fill a printer_info_7 struct
4320 ********************************************************************/
4322 static BOOL construct_printer_info_7(Printer_entry *print_hnd,
4323 PRINTER_INFO_7 *printer,
4324 const struct share_params *params)
4326 char *guid_str = NULL;
4329 if (is_printer_published(print_hnd, params->service, &guid)) {
4330 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4331 strupper_m(guid_str);
4332 init_unistr(&printer->guid, guid_str);
4333 printer->action = SPOOL_DS_PUBLISH;
4335 init_unistr(&printer->guid, "");
4336 printer->action = SPOOL_DS_UNPUBLISH;
4342 /********************************************************************
4343 Spoolss_enumprinters.
4344 ********************************************************************/
4346 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4349 struct share_iterator *shares;
4350 struct share_params *printer;
4351 PRINTER_INFO_1 *printers=NULL;
4352 WERROR result = WERR_OK;
4354 DEBUG(4,("enum_all_printers_info_1\n"));
4356 if (!(shares = share_list_all(NULL))) {
4357 DEBUG(5, ("Could not list printers\n"));
4358 return WERR_ACCESS_DENIED;
4361 while ((printer = next_printer(shares)) != NULL) {
4362 PRINTER_INFO_1 current_prt;
4364 DEBUG(4,("Found a printer in smb.conf: %s\n",
4365 lp_servicename(printer->service)));
4367 if (!construct_printer_info_1(NULL, flags, ¤t_prt,
4372 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1,
4373 *returned +1)) == NULL) {
4374 DEBUG(2,("enum_all_printers_info_1: failed to enlarge "
4375 "printers buffer!\n"));
4377 TALLOC_FREE(shares);
4380 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n",
4383 memcpy(&printers[*returned], ¤t_prt,
4384 sizeof(PRINTER_INFO_1));
4386 TALLOC_FREE(printer);
4389 /* check the required size. */
4390 for (i=0; i<*returned; i++)
4391 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4393 if (*needed > offered) {
4394 result = WERR_INSUFFICIENT_BUFFER;
4398 if (!rpcbuf_alloc_size(buffer, *needed)) {
4399 result = WERR_NOMEM;
4403 /* fill the buffer with the structures */
4404 for (i=0; i<*returned; i++)
4405 smb_io_printer_info_1("", buffer, &printers[i], 0);
4410 SAFE_FREE(printers);
4411 TALLOC_FREE(shares);
4413 if ( !W_ERROR_IS_OK(result) )
4419 /********************************************************************
4420 enum_all_printers_info_1_local.
4421 *********************************************************************/
4423 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4425 DEBUG(4,("enum_all_printers_info_1_local\n"));
4427 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4430 /********************************************************************
4431 enum_all_printers_info_1_name.
4432 *********************************************************************/
4434 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4438 DEBUG(4,("enum_all_printers_info_1_name\n"));
4440 if ((name[0] == '\\') && (name[1] == '\\'))
4443 if (is_myname_or_ipaddr(s)) {
4444 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4447 return WERR_INVALID_NAME;
4450 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4451 /********************************************************************
4452 enum_all_printers_info_1_remote.
4453 *********************************************************************/
4455 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4457 PRINTER_INFO_1 *printer;
4458 fstring printername;
4461 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4462 WERROR result = WERR_OK;
4464 /* JFM: currently it's more a place holder than anything else.
4465 * In the spooler world there is a notion of server registration.
4466 * the print servers are registered on the PDC (in the same domain)
4468 * We should have a TDB here. The registration is done thru an
4469 * undocumented RPC call.
4472 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4477 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4478 slprintf(desc, sizeof(desc)-1,"%s", name);
4479 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4481 init_unistr(&printer->description, desc);
4482 init_unistr(&printer->name, printername);
4483 init_unistr(&printer->comment, comment);
4484 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4486 /* check the required size. */
4487 *needed += spoolss_size_printer_info_1(printer);
4489 if (*needed > offered) {
4490 result = WERR_INSUFFICIENT_BUFFER;
4494 if (!rpcbuf_alloc_size(buffer, *needed)) {
4495 result = WERR_NOMEM;
4499 /* fill the buffer with the structures */
4500 smb_io_printer_info_1("", buffer, printer, 0);
4506 if ( !W_ERROR_IS_OK(result) )
4514 /********************************************************************
4515 enum_all_printers_info_1_network.
4516 *********************************************************************/
4518 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4522 DEBUG(4,("enum_all_printers_info_1_network\n"));
4524 /* If we respond to a enum_printers level 1 on our name with flags
4525 set to PRINTER_ENUM_REMOTE with a list of printers then these
4526 printers incorrectly appear in the APW browse list.
4527 Specifically the printers for the server appear at the workgroup
4528 level where all the other servers in the domain are
4529 listed. Windows responds to this call with a
4530 WERR_CAN_NOT_COMPLETE so we should do the same. */
4532 if (name[0] == '\\' && name[1] == '\\')
4535 if (is_myname_or_ipaddr(s))
4536 return WERR_CAN_NOT_COMPLETE;
4538 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4541 /********************************************************************
4542 * api_spoolss_enumprinters
4544 * called from api_spoolss_enumprinters (see this to understand)
4545 ********************************************************************/
4547 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4550 struct share_iterator *shares;
4551 struct share_params *printer;
4552 PRINTER_INFO_2 *printers=NULL;
4553 WERROR result = WERR_OK;
4557 if (!(shares = share_list_all(NULL))) {
4558 DEBUG(5, ("Could not list printers\n"));
4559 return WERR_ACCESS_DENIED;
4562 while ((printer = next_printer(shares)) != NULL) {
4563 PRINTER_INFO_2 current_prt;
4565 DEBUG(4,("Found a printer in smb.conf: %s\n",
4566 lp_servicename(printer->service)));
4568 if (!construct_printer_info_2(NULL, ¤t_prt,
4572 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2,
4574 DEBUG(2,("enum_all_printers_info_2: failed to enlarge "
4575 "printers buffer!\n"));
4577 TALLOC_FREE(shares);
4581 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n",
4584 memcpy(&printers[*returned], ¤t_prt,
4585 sizeof(PRINTER_INFO_2));
4587 TALLOC_FREE(printer);
4590 /* check the required size. */
4591 for (i=0; i<*returned; i++)
4592 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4594 if (*needed > offered) {
4595 result = WERR_INSUFFICIENT_BUFFER;
4599 if (!rpcbuf_alloc_size(buffer, *needed)) {
4600 result = WERR_NOMEM;
4604 /* fill the buffer with the structures */
4605 for (i=0; i<*returned; i++)
4606 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4611 for (i=0; i<*returned; i++)
4612 free_devmode(printers[i].devmode);
4614 SAFE_FREE(printers);
4615 TALLOC_FREE(shares);
4617 if ( !W_ERROR_IS_OK(result) )
4623 /********************************************************************
4624 * handle enumeration of printers at level 1
4625 ********************************************************************/
4627 static WERROR enumprinters_level1( uint32 flags, fstring name,
4628 RPC_BUFFER *buffer, uint32 offered,
4629 uint32 *needed, uint32 *returned)
4631 /* Not all the flags are equals */
4633 if (flags & PRINTER_ENUM_LOCAL)
4634 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4636 if (flags & PRINTER_ENUM_NAME)
4637 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4639 #if 0 /* JERRY - disabled for now */
4640 if (flags & PRINTER_ENUM_REMOTE)
4641 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4644 if (flags & PRINTER_ENUM_NETWORK)
4645 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4647 return WERR_OK; /* NT4sp5 does that */
4650 /********************************************************************
4651 * handle enumeration of printers at level 2
4652 ********************************************************************/
4654 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4655 RPC_BUFFER *buffer, uint32 offered,
4656 uint32 *needed, uint32 *returned)
4658 char *s = servername;
4660 if (flags & PRINTER_ENUM_LOCAL) {
4661 return enum_all_printers_info_2(buffer, offered, needed, returned);
4664 if (flags & PRINTER_ENUM_NAME) {
4665 if ((servername[0] == '\\') && (servername[1] == '\\'))
4667 if (is_myname_or_ipaddr(s))
4668 return enum_all_printers_info_2(buffer, offered, needed, returned);
4670 return WERR_INVALID_NAME;
4673 if (flags & PRINTER_ENUM_REMOTE)
4674 return WERR_UNKNOWN_LEVEL;
4679 /********************************************************************
4680 * handle enumeration of printers at level 5
4681 ********************************************************************/
4683 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4684 RPC_BUFFER *buffer, uint32 offered,
4685 uint32 *needed, uint32 *returned)
4687 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4691 /********************************************************************
4692 * api_spoolss_enumprinters
4694 * called from api_spoolss_enumprinters (see this to understand)
4695 ********************************************************************/
4697 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4699 uint32 flags = q_u->flags;
4700 UNISTR2 *servername = &q_u->servername;
4701 uint32 level = q_u->level;
4702 RPC_BUFFER *buffer = NULL;
4703 uint32 offered = q_u->offered;
4704 uint32 *needed = &r_u->needed;
4705 uint32 *returned = &r_u->returned;
4709 /* that's an [in out] buffer */
4711 if (!q_u->buffer && (offered!=0)) {
4712 return WERR_INVALID_PARAM;
4715 rpcbuf_move(q_u->buffer, &r_u->buffer);
4716 buffer = r_u->buffer;
4718 DEBUG(4,("_spoolss_enumprinters\n"));
4725 * flags==PRINTER_ENUM_NAME
4726 * if name=="" then enumerates all printers
4727 * if name!="" then enumerate the printer
4728 * flags==PRINTER_ENUM_REMOTE
4729 * name is NULL, enumerate printers
4730 * Level 2: name!="" enumerates printers, name can't be NULL
4731 * Level 3: doesn't exist
4732 * Level 4: does a local registry lookup
4733 * Level 5: same as Level 2
4736 unistr2_to_ascii(name, servername, sizeof(name)-1);
4741 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4743 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4745 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4750 return WERR_UNKNOWN_LEVEL;
4753 /****************************************************************************
4754 ****************************************************************************/
4756 static WERROR getprinter_level_0(Printer_entry *print_hnd,
4757 const struct share_params *params,
4758 RPC_BUFFER *buffer, uint32 offered,
4761 PRINTER_INFO_0 *printer=NULL;
4762 WERROR result = WERR_OK;
4764 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4767 construct_printer_info_0(print_hnd, printer, params);
4769 /* check the required size. */
4770 *needed += spoolss_size_printer_info_0(printer);
4772 if (*needed > offered) {
4773 result = WERR_INSUFFICIENT_BUFFER;
4777 if (!rpcbuf_alloc_size(buffer, *needed)) {
4778 result = WERR_NOMEM;
4782 /* fill the buffer with the structures */
4783 smb_io_printer_info_0("", buffer, printer, 0);
4793 /****************************************************************************
4794 ****************************************************************************/
4796 static WERROR getprinter_level_1(Printer_entry *print_hnd,
4797 const struct share_params *params,
4798 RPC_BUFFER *buffer, uint32 offered,
4801 PRINTER_INFO_1 *printer=NULL;
4802 WERROR result = WERR_OK;
4804 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4807 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer,
4810 /* check the required size. */
4811 *needed += spoolss_size_printer_info_1(printer);
4813 if (*needed > offered) {
4814 result = WERR_INSUFFICIENT_BUFFER;
4818 if (!rpcbuf_alloc_size(buffer, *needed)) {
4819 result = WERR_NOMEM;
4823 /* fill the buffer with the structures */
4824 smb_io_printer_info_1("", buffer, printer, 0);
4833 /****************************************************************************
4834 ****************************************************************************/
4836 static WERROR getprinter_level_2(Printer_entry *print_hnd,
4837 const struct share_params *params,
4838 RPC_BUFFER *buffer, uint32 offered,
4841 PRINTER_INFO_2 *printer=NULL;
4842 WERROR result = WERR_OK;
4844 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4847 construct_printer_info_2(print_hnd, printer, params);
4849 /* check the required size. */
4850 *needed += spoolss_size_printer_info_2(printer);
4852 if (*needed > offered) {
4853 result = WERR_INSUFFICIENT_BUFFER;
4857 if (!rpcbuf_alloc_size(buffer, *needed)) {
4858 result = WERR_NOMEM;
4862 /* fill the buffer with the structures */
4863 if (!smb_io_printer_info_2("", buffer, printer, 0))
4864 result = WERR_NOMEM;
4868 free_printer_info_2(printer);
4873 /****************************************************************************
4874 ****************************************************************************/
4876 static WERROR getprinter_level_3(Printer_entry *print_hnd,
4877 const struct share_params *params,
4878 RPC_BUFFER *buffer, uint32 offered,
4881 PRINTER_INFO_3 *printer=NULL;
4882 WERROR result = WERR_OK;
4884 if (!construct_printer_info_3(print_hnd, &printer, params))
4887 /* check the required size. */
4888 *needed += spoolss_size_printer_info_3(printer);
4890 if (*needed > offered) {
4891 result = WERR_INSUFFICIENT_BUFFER;
4895 if (!rpcbuf_alloc_size(buffer, *needed)) {
4896 result = WERR_NOMEM;
4900 /* fill the buffer with the structures */
4901 smb_io_printer_info_3("", buffer, printer, 0);
4905 free_printer_info_3(printer);
4910 /****************************************************************************
4911 ****************************************************************************/
4913 static WERROR getprinter_level_4(Printer_entry *print_hnd,
4914 const struct share_params *params,
4915 RPC_BUFFER *buffer, uint32 offered,
4918 PRINTER_INFO_4 *printer=NULL;
4919 WERROR result = WERR_OK;
4921 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4924 if (!construct_printer_info_4(print_hnd, printer, params)) {
4929 /* check the required size. */
4930 *needed += spoolss_size_printer_info_4(printer);
4932 if (*needed > offered) {
4933 result = WERR_INSUFFICIENT_BUFFER;
4937 if (!rpcbuf_alloc_size(buffer, *needed)) {
4938 result = WERR_NOMEM;
4942 /* fill the buffer with the structures */
4943 smb_io_printer_info_4("", buffer, printer, 0);
4947 free_printer_info_4(printer);
4952 /****************************************************************************
4953 ****************************************************************************/
4955 static WERROR getprinter_level_5(Printer_entry *print_hnd,
4956 const struct share_params *params,
4957 RPC_BUFFER *buffer, uint32 offered,
4960 PRINTER_INFO_5 *printer=NULL;
4961 WERROR result = WERR_OK;
4963 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4966 if (!construct_printer_info_5(print_hnd, printer, params)) {
4967 free_printer_info_5(printer);
4971 /* check the required size. */
4972 *needed += spoolss_size_printer_info_5(printer);
4974 if (*needed > offered) {
4975 result = WERR_INSUFFICIENT_BUFFER;
4979 if (!rpcbuf_alloc_size(buffer, *needed)) {
4980 result = WERR_NOMEM;
4984 /* fill the buffer with the structures */
4985 smb_io_printer_info_5("", buffer, printer, 0);
4989 free_printer_info_5(printer);
4994 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4995 const struct share_params *params,
4996 RPC_BUFFER *buffer, uint32 offered,
4999 PRINTER_INFO_6 *printer;
5000 WERROR result = WERR_OK;
5002 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5006 if (!construct_printer_info_6(print_hnd, printer, params)) {
5007 free_printer_info_6(printer);
5011 /* check the required size. */
5012 *needed += spoolss_size_printer_info_6(printer);
5014 if (*needed > offered) {
5015 result = WERR_INSUFFICIENT_BUFFER;
5019 if (!rpcbuf_alloc_size(buffer, *needed)) {
5020 result = WERR_NOMEM;
5024 /* fill the buffer with the structures */
5025 smb_io_printer_info_6("", buffer, printer, 0);
5029 free_printer_info_6(printer);
5034 static WERROR getprinter_level_7(Printer_entry *print_hnd,
5035 const struct share_params *params,
5036 RPC_BUFFER *buffer, uint32 offered,
5039 PRINTER_INFO_7 *printer=NULL;
5040 WERROR result = WERR_OK;
5042 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5045 if (!construct_printer_info_7(print_hnd, printer, params))
5048 /* check the required size. */
5049 *needed += spoolss_size_printer_info_7(printer);
5051 if (*needed > offered) {
5052 result = WERR_INSUFFICIENT_BUFFER;
5056 if (!rpcbuf_alloc_size(buffer, *needed)) {
5057 result = WERR_NOMEM;
5062 /* fill the buffer with the structures */
5063 smb_io_printer_info_7("", buffer, printer, 0);
5067 free_printer_info_7(printer);
5072 /****************************************************************************
5073 ****************************************************************************/
5075 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5077 POLICY_HND *handle = &q_u->handle;
5078 uint32 level = q_u->level;
5079 RPC_BUFFER *buffer = NULL;
5080 uint32 offered = q_u->offered;
5081 uint32 *needed = &r_u->needed;
5082 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5083 struct share_params *params;
5087 /* that's an [in out] buffer */
5089 if (!q_u->buffer && (offered!=0)) {
5090 return WERR_INVALID_PARAM;
5093 rpcbuf_move(q_u->buffer, &r_u->buffer);
5094 buffer = r_u->buffer;
5098 if (!get_printer_snum(p, handle, &snum, ¶ms))
5103 return getprinter_level_0(Printer, params, buffer, offered,
5106 return getprinter_level_1(Printer, params, buffer, offered,
5109 return getprinter_level_2(Printer, params, buffer, offered,
5112 return getprinter_level_3(Printer, params, buffer, offered,
5115 return getprinter_level_4(Printer, params, buffer, offered,
5118 return getprinter_level_5(Printer, params, buffer, offered,
5121 return getprinter_level_6(Printer, params, buffer, offered,
5124 return getprinter_level_7(Printer, params, buffer, offered,
5127 return WERR_UNKNOWN_LEVEL;
5130 /********************************************************************
5131 * fill a DRIVER_INFO_1 struct
5132 ********************************************************************/
5134 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5136 init_unistr( &info->name, driver.info_3->name);
5139 /********************************************************************
5140 * construct_printer_driver_info_1
5141 ********************************************************************/
5143 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5145 NT_PRINTER_INFO_LEVEL *printer = NULL;
5146 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5148 ZERO_STRUCT(driver);
5150 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5151 return WERR_INVALID_PRINTER_NAME;
5153 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5154 free_a_printer(&printer, 2);
5155 return WERR_UNKNOWN_PRINTER_DRIVER;
5158 fill_printer_driver_info_1(info, driver, servername, architecture);
5160 free_a_printer(&printer,2);
5165 /********************************************************************
5166 * construct_printer_driver_info_2
5167 * fill a printer_info_2 struct
5168 ********************************************************************/
5170 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5174 info->version=driver.info_3->cversion;
5176 init_unistr( &info->name, driver.info_3->name );
5177 init_unistr( &info->architecture, driver.info_3->environment );
5180 if (strlen(driver.info_3->driverpath)) {
5181 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5182 init_unistr( &info->driverpath, temp );
5184 init_unistr( &info->driverpath, "" );
5186 if (strlen(driver.info_3->datafile)) {
5187 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5188 init_unistr( &info->datafile, temp );
5190 init_unistr( &info->datafile, "" );
5192 if (strlen(driver.info_3->configfile)) {
5193 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5194 init_unistr( &info->configfile, temp );
5196 init_unistr( &info->configfile, "" );
5199 /********************************************************************
5200 * construct_printer_driver_info_2
5201 * fill a printer_info_2 struct
5202 ********************************************************************/
5204 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5206 NT_PRINTER_INFO_LEVEL *printer = NULL;
5207 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5209 ZERO_STRUCT(printer);
5210 ZERO_STRUCT(driver);
5212 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5213 return WERR_INVALID_PRINTER_NAME;
5215 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5216 free_a_printer(&printer, 2);
5217 return WERR_UNKNOWN_PRINTER_DRIVER;
5220 fill_printer_driver_info_2(info, driver, servername);
5222 free_a_printer(&printer,2);
5227 /********************************************************************
5228 * copy a strings array and convert to UNICODE
5230 * convert an array of ascii string to a UNICODE string
5231 ********************************************************************/
5233 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5240 DEBUG(6,("init_unistr_array\n"));
5251 v = ""; /* hack to handle null lists */
5254 /* hack to allow this to be used in places other than when generating
5255 the list of dependent files */
5258 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5262 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5264 /* add one extra unit16 for the second terminating NULL */
5266 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5267 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5274 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5279 /* special case for ""; we need to add both NULL's here */
5281 (*uni_array)[j++]=0x0000;
5282 (*uni_array)[j]=0x0000;
5285 DEBUGADD(6,("last one:done\n"));
5287 /* return size of array in uint16's */
5292 /********************************************************************
5293 * construct_printer_info_3
5294 * fill a printer_info_3 struct
5295 ********************************************************************/
5297 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5303 info->version=driver.info_3->cversion;
5305 init_unistr( &info->name, driver.info_3->name );
5306 init_unistr( &info->architecture, driver.info_3->environment );
5308 if (strlen(driver.info_3->driverpath)) {
5309 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5310 init_unistr( &info->driverpath, temp );
5312 init_unistr( &info->driverpath, "" );
5314 if (strlen(driver.info_3->datafile)) {
5315 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5316 init_unistr( &info->datafile, temp );
5318 init_unistr( &info->datafile, "" );
5320 if (strlen(driver.info_3->configfile)) {
5321 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5322 init_unistr( &info->configfile, temp );
5324 init_unistr( &info->configfile, "" );
5326 if (strlen(driver.info_3->helpfile)) {
5327 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5328 init_unistr( &info->helpfile, temp );
5330 init_unistr( &info->helpfile, "" );
5332 init_unistr( &info->monitorname, driver.info_3->monitorname );
5333 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5335 info->dependentfiles=NULL;
5336 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5339 /********************************************************************
5340 * construct_printer_info_3
5341 * fill a printer_info_3 struct
5342 ********************************************************************/
5344 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5346 NT_PRINTER_INFO_LEVEL *printer = NULL;
5347 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5349 ZERO_STRUCT(driver);
5351 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5352 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5353 if (!W_ERROR_IS_OK(status))
5354 return WERR_INVALID_PRINTER_NAME;
5356 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5357 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5362 * I put this code in during testing. Helpful when commenting out the
5363 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5364 * as win2k always queries the driver using an infor level of 6.
5365 * I've left it in (but ifdef'd out) because I'll probably
5366 * use it in experimentation again in the future. --jerry 22/01/2002
5369 if (!W_ERROR_IS_OK(status)) {
5371 * Is this a W2k client ?
5374 /* Yes - try again with a WinNT driver. */
5376 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5377 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5381 if (!W_ERROR_IS_OK(status)) {
5382 free_a_printer(&printer,2);
5383 return WERR_UNKNOWN_PRINTER_DRIVER;
5391 fill_printer_driver_info_3(info, driver, servername);
5393 free_a_printer(&printer,2);
5398 /********************************************************************
5399 * construct_printer_info_6
5400 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5401 ********************************************************************/
5403 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5409 memset(&nullstr, '\0', sizeof(fstring));
5411 info->version=driver.info_3->cversion;
5413 init_unistr( &info->name, driver.info_3->name );
5414 init_unistr( &info->architecture, driver.info_3->environment );
5416 if (strlen(driver.info_3->driverpath)) {
5417 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5418 init_unistr( &info->driverpath, temp );
5420 init_unistr( &info->driverpath, "" );
5422 if (strlen(driver.info_3->datafile)) {
5423 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5424 init_unistr( &info->datafile, temp );
5426 init_unistr( &info->datafile, "" );
5428 if (strlen(driver.info_3->configfile)) {
5429 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5430 init_unistr( &info->configfile, temp );
5432 init_unistr( &info->configfile, "" );
5434 if (strlen(driver.info_3->helpfile)) {
5435 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5436 init_unistr( &info->helpfile, temp );
5438 init_unistr( &info->helpfile, "" );
5440 init_unistr( &info->monitorname, driver.info_3->monitorname );
5441 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5443 info->dependentfiles = NULL;
5444 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5446 info->previousdrivernames=NULL;
5447 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5449 info->driver_date=0;
5452 info->driver_version_low=0;
5453 info->driver_version_high=0;
5455 init_unistr( &info->mfgname, "");
5456 init_unistr( &info->oem_url, "");
5457 init_unistr( &info->hardware_id, "");
5458 init_unistr( &info->provider, "");
5461 /********************************************************************
5462 * construct_printer_info_6
5463 * fill a printer_info_6 struct
5464 ********************************************************************/
5466 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5467 fstring servername, fstring architecture, uint32 version)
5469 NT_PRINTER_INFO_LEVEL *printer = NULL;
5470 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5473 ZERO_STRUCT(driver);
5475 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5477 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5479 if (!W_ERROR_IS_OK(status))
5480 return WERR_INVALID_PRINTER_NAME;
5482 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5484 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5486 if (!W_ERROR_IS_OK(status))
5489 * Is this a W2k client ?
5493 free_a_printer(&printer,2);
5494 return WERR_UNKNOWN_PRINTER_DRIVER;
5497 /* Yes - try again with a WinNT driver. */
5499 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5500 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5501 if (!W_ERROR_IS_OK(status)) {
5502 free_a_printer(&printer,2);
5503 return WERR_UNKNOWN_PRINTER_DRIVER;
5507 fill_printer_driver_info_6(info, driver, servername);
5509 free_a_printer(&printer,2);
5510 free_a_printer_driver(driver, 3);
5515 /****************************************************************************
5516 ****************************************************************************/
5518 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5520 SAFE_FREE(info->dependentfiles);
5523 /****************************************************************************
5524 ****************************************************************************/
5526 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5528 SAFE_FREE(info->dependentfiles);
5531 /****************************************************************************
5532 ****************************************************************************/
5534 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5536 DRIVER_INFO_1 *info=NULL;
5539 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5542 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5543 if (!W_ERROR_IS_OK(result))
5546 /* check the required size. */
5547 *needed += spoolss_size_printer_driver_info_1(info);
5549 if (*needed > offered) {
5550 result = WERR_INSUFFICIENT_BUFFER;
5554 if (!rpcbuf_alloc_size(buffer, *needed)) {
5555 result = WERR_NOMEM;
5559 /* fill the buffer with the structures */
5560 smb_io_printer_driver_info_1("", buffer, info, 0);
5569 /****************************************************************************
5570 ****************************************************************************/
5572 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5574 DRIVER_INFO_2 *info=NULL;
5577 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5580 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5581 if (!W_ERROR_IS_OK(result))
5584 /* check the required size. */
5585 *needed += spoolss_size_printer_driver_info_2(info);
5587 if (*needed > offered) {
5588 result = WERR_INSUFFICIENT_BUFFER;
5592 if (!rpcbuf_alloc_size(buffer, *needed)) {
5593 result = WERR_NOMEM;
5597 /* fill the buffer with the structures */
5598 smb_io_printer_driver_info_2("", buffer, info, 0);
5607 /****************************************************************************
5608 ****************************************************************************/
5610 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5617 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5618 if (!W_ERROR_IS_OK(result))
5621 /* check the required size. */
5622 *needed += spoolss_size_printer_driver_info_3(&info);
5624 if (*needed > offered) {
5625 result = WERR_INSUFFICIENT_BUFFER;
5629 if (!rpcbuf_alloc_size(buffer, *needed)) {
5630 result = WERR_NOMEM;
5634 /* fill the buffer with the structures */
5635 smb_io_printer_driver_info_3("", buffer, &info, 0);
5638 free_printer_driver_info_3(&info);
5643 /****************************************************************************
5644 ****************************************************************************/
5646 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5653 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5654 if (!W_ERROR_IS_OK(result))
5657 /* check the required size. */
5658 *needed += spoolss_size_printer_driver_info_6(&info);
5660 if (*needed > offered) {
5661 result = WERR_INSUFFICIENT_BUFFER;
5665 if (!rpcbuf_alloc_size(buffer, *needed)) {
5666 result = WERR_NOMEM;
5670 /* fill the buffer with the structures */
5671 smb_io_printer_driver_info_6("", buffer, &info, 0);
5674 free_printer_driver_info_6(&info);
5679 /****************************************************************************
5680 ****************************************************************************/
5682 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5684 POLICY_HND *handle = &q_u->handle;
5685 UNISTR2 *uni_arch = &q_u->architecture;
5686 uint32 level = q_u->level;
5687 uint32 clientmajorversion = q_u->clientmajorversion;
5688 RPC_BUFFER *buffer = NULL;
5689 uint32 offered = q_u->offered;
5690 uint32 *needed = &r_u->needed;
5691 uint32 *servermajorversion = &r_u->servermajorversion;
5692 uint32 *serverminorversion = &r_u->serverminorversion;
5693 Printer_entry *printer;
5696 fstring architecture;
5699 /* that's an [in out] buffer */
5701 if (!q_u->buffer && (offered!=0)) {
5702 return WERR_INVALID_PARAM;
5705 rpcbuf_move(q_u->buffer, &r_u->buffer);
5706 buffer = r_u->buffer;
5708 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5710 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5711 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5712 return WERR_INVALID_PRINTER_NAME;
5716 *servermajorversion = 0;
5717 *serverminorversion = 0;
5719 fstrcpy(servername, get_server_name( printer ));
5720 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5722 if (!get_printer_snum(p, handle, &snum, NULL))
5727 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5729 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5731 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5733 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5736 /* apparently this call is the equivalent of
5737 EnumPrinterDataEx() for the DsDriver key */
5742 return WERR_UNKNOWN_LEVEL;
5745 /****************************************************************************
5746 ****************************************************************************/
5748 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5750 POLICY_HND *handle = &q_u->handle;
5752 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5755 DEBUG(3,("Error in startpageprinter printer handle\n"));
5759 Printer->page_started=True;
5763 /****************************************************************************
5764 ****************************************************************************/
5766 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5768 POLICY_HND *handle = &q_u->handle;
5771 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5774 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5778 if (!get_printer_snum(p, handle, &snum, NULL))
5781 Printer->page_started=False;
5782 print_job_endpage(snum, Printer->jobid);
5787 /********************************************************************
5788 * api_spoolss_getprinter
5789 * called from the spoolss dispatcher
5791 ********************************************************************/
5793 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5795 POLICY_HND *handle = &q_u->handle;
5796 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5797 uint32 *jobid = &r_u->jobid;
5799 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5803 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5806 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5811 * a nice thing with NT is it doesn't listen to what you tell it.
5812 * when asked to send _only_ RAW datas, it tries to send datas
5815 * So I add checks like in NT Server ...
5818 if (info_1->p_datatype != 0) {
5819 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5820 if (strcmp(datatype, "RAW") != 0) {
5822 return WERR_INVALID_DATATYPE;
5826 /* get the share number of the printer */
5827 if (!get_printer_snum(p, handle, &snum, NULL)) {
5831 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5833 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5835 /* An error occured in print_job_start() so return an appropriate
5838 if (Printer->jobid == -1) {
5839 return map_werror_from_unix(errno);
5842 Printer->document_started=True;
5843 (*jobid) = Printer->jobid;
5848 /********************************************************************
5849 * api_spoolss_getprinter
5850 * called from the spoolss dispatcher
5852 ********************************************************************/
5854 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5856 POLICY_HND *handle = &q_u->handle;
5858 return _spoolss_enddocprinter_internal(p, handle);
5861 /****************************************************************************
5862 ****************************************************************************/
5864 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5866 POLICY_HND *handle = &q_u->handle;
5867 uint32 buffer_size = q_u->buffer_size;
5868 uint8 *buffer = q_u->buffer;
5869 uint32 *buffer_written = &q_u->buffer_size2;
5871 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5874 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5875 r_u->buffer_written = q_u->buffer_size2;
5879 if (!get_printer_snum(p, handle, &snum, NULL))
5882 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5883 (SMB_OFF_T)-1, (size_t)buffer_size);
5884 if (*buffer_written == (uint32)-1) {
5885 r_u->buffer_written = 0;
5886 if (errno == ENOSPC)
5887 return WERR_NO_SPOOL_SPACE;
5889 return WERR_ACCESS_DENIED;
5892 r_u->buffer_written = q_u->buffer_size2;
5897 /********************************************************************
5898 * api_spoolss_getprinter
5899 * called from the spoolss dispatcher
5901 ********************************************************************/
5903 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5907 WERROR errcode = WERR_BADFUNC;
5908 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5911 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5915 if (!get_printer_snum(p, handle, &snum, NULL))
5919 case PRINTER_CONTROL_PAUSE:
5920 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5924 case PRINTER_CONTROL_RESUME:
5925 case PRINTER_CONTROL_UNPAUSE:
5926 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5930 case PRINTER_CONTROL_PURGE:
5931 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5936 return WERR_UNKNOWN_LEVEL;
5942 /********************************************************************
5943 * api_spoolss_abortprinter
5944 * From MSDN: "Deletes printer's spool file if printer is configured
5946 ********************************************************************/
5948 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5950 POLICY_HND *handle = &q_u->handle;
5951 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5953 WERROR errcode = WERR_OK;
5956 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5960 if (!get_printer_snum(p, handle, &snum, NULL))
5963 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5968 /********************************************************************
5969 * called by spoolss_api_setprinter
5970 * when updating a printer description
5971 ********************************************************************/
5973 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5974 const SPOOL_PRINTER_INFO_LEVEL *info,
5975 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5977 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5981 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5983 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5984 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5985 OUR_HANDLE(handle)));
5987 result = WERR_BADFID;
5992 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5993 result = WERR_INVALID_PARAM;
5997 /* Check the user has permissions to change the security
5998 descriptor. By experimentation with two NT machines, the user
5999 requires Full Access to the printer to change security
6002 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6003 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6004 result = WERR_ACCESS_DENIED;
6008 /* NT seems to like setting the security descriptor even though
6009 nothing may have actually changed. */
6011 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
6013 if (DEBUGLEVEL >= 10) {
6017 the_acl = old_secdesc_ctr->sd->dacl;
6018 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6019 PRINTERNAME(snum), the_acl->num_aces));
6021 for (i = 0; i < the_acl->num_aces; i++) {
6024 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6026 DEBUG(10, ("%s 0x%08x\n", sid_str,
6027 the_acl->aces[i].access_mask));
6030 the_acl = secdesc_ctr->sd->dacl;
6033 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6034 PRINTERNAME(snum), the_acl->num_aces));
6036 for (i = 0; i < the_acl->num_aces; i++) {
6039 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6041 DEBUG(10, ("%s 0x%08x\n", sid_str,
6042 the_acl->aces[i].access_mask));
6045 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6049 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6050 if (!new_secdesc_ctr) {
6051 result = WERR_NOMEM;
6055 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6060 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6067 /********************************************************************
6068 Canonicalize printer info from a client
6070 ATTN: It does not matter what we set the servername to hear
6071 since we do the necessary work in get_a_printer() to set it to
6072 the correct value based on what the client sent in the
6073 _spoolss_open_printer_ex().
6074 ********************************************************************/
6076 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6078 fstring printername;
6081 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6082 "portname=%s drivername=%s comment=%s location=%s\n",
6083 info->servername, info->printername, info->sharename,
6084 info->portname, info->drivername, info->comment, info->location));
6086 /* we force some elements to "correct" values */
6087 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6088 fstrcpy(info->sharename, lp_servicename(snum));
6090 /* check to see if we allow printername != sharename */
6092 if ( lp_force_printername(snum) ) {
6093 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6094 global_myname(), info->sharename );
6097 /* make sure printername is in \\server\printername format */
6099 fstrcpy( printername, info->printername );
6101 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6102 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6106 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6107 global_myname(), p );
6110 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6111 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6118 /****************************************************************************
6119 ****************************************************************************/
6121 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
6123 char *cmd = lp_addport_cmd();
6127 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6128 BOOL is_print_op = False;
6131 return WERR_ACCESS_DENIED;
6134 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
6137 is_print_op = user_has_privileges( token, &se_printop );
6139 DEBUG(10,("Running [%s]\n", command));
6141 /********* BEGIN SePrintOperatorPrivilege **********/
6146 ret = smbrun(command, &fd);
6151 /********* END SePrintOperatorPrivilege **********/
6153 DEBUGADD(10,("returned [%d]\n", ret));
6158 return WERR_ACCESS_DENIED;
6164 /****************************************************************************
6165 ****************************************************************************/
6167 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6169 char *cmd = lp_addprinter_cmd();
6175 fstring remote_machine = "%m";
6176 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6177 BOOL is_print_op = False;
6179 standard_sub_basic(current_user_info.smb_name,
6180 current_user_info.domain,
6181 remote_machine,sizeof(remote_machine));
6183 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6184 cmd, printer->info_2->printername, printer->info_2->sharename,
6185 printer->info_2->portname, printer->info_2->drivername,
6186 printer->info_2->location, printer->info_2->comment, remote_machine);
6189 is_print_op = user_has_privileges( token, &se_printop );
6191 DEBUG(10,("Running [%s]\n", command));
6193 /********* BEGIN SePrintOperatorPrivilege **********/
6198 if ( (ret = smbrun(command, &fd)) == 0 ) {
6199 /* Tell everyone we updated smb.conf. */
6200 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6206 /********* END SePrintOperatorPrivilege **********/
6208 DEBUGADD(10,("returned [%d]\n", ret));
6216 /* reload our services immediately */
6217 reload_services( False );
6220 /* Get lines and convert them back to dos-codepage */
6221 qlines = fd_lines_load(fd, &numlines, 0);
6222 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6225 /* Set the portname to what the script says the portname should be. */
6226 /* but don't require anything to be return from the script exit a good error code */
6229 /* Set the portname to what the script says the portname should be. */
6230 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6231 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6234 file_lines_free(qlines);
6239 /********************************************************************
6240 * Called by spoolss_api_setprinter
6241 * when updating a printer description.
6242 ********************************************************************/
6244 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6245 const SPOOL_PRINTER_INFO_LEVEL *info,
6246 DEVICEMODE *devmode)
6249 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6250 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6255 DEBUG(8,("update_printer\n"));
6260 result = WERR_BADFID;
6264 if (!get_printer_snum(p, handle, &snum, NULL)) {
6265 result = WERR_BADFID;
6269 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6270 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6271 result = WERR_BADFID;
6275 DEBUGADD(8,("Converting info_2 struct\n"));
6278 * convert_printer_info converts the incoming
6279 * info from the client and overwrites the info
6280 * just read from the tdb in the pointer 'printer'.
6283 if (!convert_printer_info(info, printer, level)) {
6284 result = WERR_NOMEM;
6289 /* we have a valid devmode
6290 convert it and link it*/
6292 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6293 if (!convert_devicemode(printer->info_2->printername, devmode,
6294 &printer->info_2->devmode)) {
6295 result = WERR_NOMEM;
6300 /* Do sanity check on the requested changes for Samba */
6302 if (!check_printer_ok(printer->info_2, snum)) {
6303 result = WERR_INVALID_PARAM;
6307 /* FIXME!!! If the driver has changed we really should verify that
6308 it is installed before doing much else --jerry */
6310 /* Check calling user has permission to update printer description */
6312 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6313 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6314 result = WERR_ACCESS_DENIED;
6318 /* Call addprinter hook */
6319 /* Check changes to see if this is really needed */
6321 if ( *lp_addprinter_cmd()
6322 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6323 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6324 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6325 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6327 /* add_printer_hook() will call reload_services() */
6329 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6330 result = WERR_ACCESS_DENIED;
6336 * When a *new* driver is bound to a printer, the drivername is used to
6337 * lookup previously saved driver initialization info, which is then
6338 * bound to the printer, simulating what happens in the Windows arch.
6340 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6342 if (!set_driver_init(printer, 2))
6344 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6345 printer->info_2->drivername));
6348 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6349 printer->info_2->drivername));
6351 notify_printer_driver(snum, printer->info_2->drivername);
6355 * flag which changes actually occured. This is a small subset of
6356 * all the possible changes. We also have to update things in the
6360 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6361 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6362 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6363 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6365 notify_printer_comment(snum, printer->info_2->comment);
6368 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6369 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6370 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6371 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6373 notify_printer_sharename(snum, printer->info_2->sharename);
6376 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6379 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6382 pname = printer->info_2->printername;
6385 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6386 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6387 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6389 notify_printer_printername( snum, pname );
6392 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6393 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6394 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6395 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6397 notify_printer_port(snum, printer->info_2->portname);
6400 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6401 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6402 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6403 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6405 notify_printer_location(snum, printer->info_2->location);
6408 /* here we need to update some more DsSpooler keys */
6409 /* uNCName, serverName, shortServerName */
6411 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6412 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6413 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6414 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6415 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6417 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6418 global_myname(), printer->info_2->sharename );
6419 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6420 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6421 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6423 /* Update printer info */
6424 result = mod_a_printer(printer, 2);
6427 free_a_printer(&printer, 2);
6428 free_a_printer(&old_printer, 2);
6434 /****************************************************************************
6435 ****************************************************************************/
6436 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6437 const SPOOL_PRINTER_INFO_LEVEL *info)
6440 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6442 Printer_entry *Printer;
6444 if ( lp_security() != SEC_ADS ) {
6445 return WERR_UNKNOWN_LEVEL;
6448 Printer = find_printer_index_by_hnd(p, handle);
6450 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6455 if (!get_printer_snum(p, handle, &snum, NULL))
6458 nt_printer_publish(Printer, snum, info7->action);
6462 return WERR_UNKNOWN_LEVEL;
6465 /****************************************************************************
6466 ****************************************************************************/
6468 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6470 POLICY_HND *handle = &q_u->handle;
6471 uint32 level = q_u->level;
6472 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6473 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6474 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6475 uint32 command = q_u->command;
6478 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6481 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6485 /* check the level */
6488 return control_printer(handle, command, p);
6490 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6491 if (!W_ERROR_IS_OK(result))
6494 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6497 return update_printer_sec(handle, level, info, p,
6500 return publish_or_unpublish_printer(p, handle, info);
6502 return WERR_UNKNOWN_LEVEL;
6506 /****************************************************************************
6507 ****************************************************************************/
6509 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6511 POLICY_HND *handle = &q_u->handle;
6512 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6515 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6519 if (Printer->notify.client_connected==True) {
6522 if ( Printer->printer_type == SPLHND_SERVER)
6524 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6525 !get_printer_snum(p, handle, &snum, NULL) )
6528 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6531 Printer->notify.flags=0;
6532 Printer->notify.options=0;
6533 Printer->notify.localmachine[0]='\0';
6534 Printer->notify.printerlocal=0;
6535 if (Printer->notify.option)
6536 free_spool_notify_option(&Printer->notify.option);
6537 Printer->notify.client_connected=False;
6542 /****************************************************************************
6543 ****************************************************************************/
6545 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6547 /* that's an [in out] buffer */
6549 if (!q_u->buffer && (q_u->offered!=0)) {
6550 return WERR_INVALID_PARAM;
6553 rpcbuf_move(q_u->buffer, &r_u->buffer);
6556 return WERR_INVALID_PARAM; /* this is what a NT server
6557 returns for AddJob. AddJob
6558 must fail on non-local
6562 /****************************************************************************
6563 ****************************************************************************/
6565 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6566 int position, int snum,
6567 const NT_PRINTER_INFO_LEVEL *ntprinter)
6571 t=gmtime(&queue->time);
6573 job_info->jobid=queue->job;
6574 init_unistr(&job_info->printername, lp_servicename(snum));
6575 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6576 init_unistr(&job_info->username, queue->fs_user);
6577 init_unistr(&job_info->document, queue->fs_file);
6578 init_unistr(&job_info->datatype, "RAW");
6579 init_unistr(&job_info->text_status, "");
6580 job_info->status=nt_printj_status(queue->status);
6581 job_info->priority=queue->priority;
6582 job_info->position=position;
6583 job_info->totalpages=queue->page_count;
6584 job_info->pagesprinted=0;
6586 make_systemtime(&job_info->submitted, t);
6589 /****************************************************************************
6590 ****************************************************************************/
6592 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6593 int position, int snum,
6594 const NT_PRINTER_INFO_LEVEL *ntprinter,
6595 DEVICEMODE *devmode)
6599 t=gmtime(&queue->time);
6601 job_info->jobid=queue->job;
6603 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6605 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6606 init_unistr(&job_info->username, queue->fs_user);
6607 init_unistr(&job_info->document, queue->fs_file);
6608 init_unistr(&job_info->notifyname, queue->fs_user);
6609 init_unistr(&job_info->datatype, "RAW");
6610 init_unistr(&job_info->printprocessor, "winprint");
6611 init_unistr(&job_info->parameters, "");
6612 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6613 init_unistr(&job_info->text_status, "");
6615 /* and here the security descriptor */
6617 job_info->status=nt_printj_status(queue->status);
6618 job_info->priority=queue->priority;
6619 job_info->position=position;
6620 job_info->starttime=0;
6621 job_info->untiltime=0;
6622 job_info->totalpages=queue->page_count;
6623 job_info->size=queue->size;
6624 make_systemtime(&(job_info->submitted), t);
6625 job_info->timeelapsed=0;
6626 job_info->pagesprinted=0;
6628 job_info->devmode = devmode;
6633 /****************************************************************************
6634 Enumjobs at level 1.
6635 ****************************************************************************/
6637 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6638 const NT_PRINTER_INFO_LEVEL *ntprinter,
6639 RPC_BUFFER *buffer, uint32 offered,
6640 uint32 *needed, uint32 *returned)
6644 WERROR result = WERR_OK;
6646 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6652 for (i=0; i<*returned; i++)
6653 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6655 /* check the required size. */
6656 for (i=0; i<*returned; i++)
6657 (*needed) += spoolss_size_job_info_1(&info[i]);
6659 if (*needed > offered) {
6660 result = WERR_INSUFFICIENT_BUFFER;
6664 if (!rpcbuf_alloc_size(buffer, *needed)) {
6665 result = WERR_NOMEM;
6669 /* fill the buffer with the structures */
6670 for (i=0; i<*returned; i++)
6671 smb_io_job_info_1("", buffer, &info[i], 0);
6677 if ( !W_ERROR_IS_OK(result) )
6683 /****************************************************************************
6684 Enumjobs at level 2.
6685 ****************************************************************************/
6687 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6688 const NT_PRINTER_INFO_LEVEL *ntprinter,
6689 RPC_BUFFER *buffer, uint32 offered,
6690 uint32 *needed, uint32 *returned)
6692 JOB_INFO_2 *info = NULL;
6694 WERROR result = WERR_OK;
6695 DEVICEMODE *devmode = NULL;
6697 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6702 /* this should not be a failure condition if the devmode is NULL */
6704 devmode = construct_dev_mode(lp_const_servicename(snum));
6706 for (i=0; i<*returned; i++)
6707 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6709 /* check the required size. */
6710 for (i=0; i<*returned; i++)
6711 (*needed) += spoolss_size_job_info_2(&info[i]);
6713 if (*needed > offered) {
6714 result = WERR_INSUFFICIENT_BUFFER;
6718 if (!rpcbuf_alloc_size(buffer, *needed)) {
6719 result = WERR_NOMEM;
6723 /* fill the buffer with the structures */
6724 for (i=0; i<*returned; i++)
6725 smb_io_job_info_2("", buffer, &info[i], 0);
6728 free_devmode(devmode);
6731 if ( !W_ERROR_IS_OK(result) )
6738 /****************************************************************************
6740 ****************************************************************************/
6742 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6744 POLICY_HND *handle = &q_u->handle;
6745 uint32 level = q_u->level;
6746 RPC_BUFFER *buffer = NULL;
6747 uint32 offered = q_u->offered;
6748 uint32 *needed = &r_u->needed;
6749 uint32 *returned = &r_u->returned;
6751 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6753 print_status_struct prt_status;
6754 print_queue_struct *queue=NULL;
6756 /* that's an [in out] buffer */
6758 if (!q_u->buffer && (offered!=0)) {
6759 return WERR_INVALID_PARAM;
6762 rpcbuf_move(q_u->buffer, &r_u->buffer);
6763 buffer = r_u->buffer;
6765 DEBUG(4,("_spoolss_enumjobs\n"));
6770 /* lookup the printer snum and tdb entry */
6772 if (!get_printer_snum(p, handle, &snum, NULL))
6775 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6776 if ( !W_ERROR_IS_OK(wret) )
6779 *returned = print_queue_status(snum, &queue, &prt_status);
6780 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6782 if (*returned == 0) {
6784 free_a_printer(&ntprinter, 2);
6790 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6793 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6797 wret = WERR_UNKNOWN_LEVEL;
6802 free_a_printer( &ntprinter, 2 );
6806 /****************************************************************************
6807 ****************************************************************************/
6809 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6814 /****************************************************************************
6815 ****************************************************************************/
6817 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6819 POLICY_HND *handle = &q_u->handle;
6820 uint32 jobid = q_u->jobid;
6821 uint32 command = q_u->command;
6824 WERROR errcode = WERR_BADFUNC;
6826 if (!get_printer_snum(p, handle, &snum, NULL)) {
6830 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6831 return WERR_INVALID_PRINTER_NAME;
6835 case JOB_CONTROL_CANCEL:
6836 case JOB_CONTROL_DELETE:
6837 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6841 case JOB_CONTROL_PAUSE:
6842 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6846 case JOB_CONTROL_RESTART:
6847 case JOB_CONTROL_RESUME:
6848 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6853 return WERR_UNKNOWN_LEVEL;
6859 /****************************************************************************
6860 Enumerates all printer drivers at level 1.
6861 ****************************************************************************/
6863 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6868 fstring *list = NULL;
6869 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6870 DRIVER_INFO_1 *driver_info_1=NULL;
6871 WERROR result = WERR_OK;
6875 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6877 ndrivers=get_ntdrivers(&list, architecture, version);
6878 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6880 if(ndrivers == -1) {
6881 SAFE_FREE(driver_info_1);
6886 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6887 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6893 for (i=0; i<ndrivers; i++) {
6895 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6896 ZERO_STRUCT(driver);
6897 status = get_a_printer_driver(&driver, 3, list[i],
6898 architecture, version);
6899 if (!W_ERROR_IS_OK(status)) {
6901 SAFE_FREE(driver_info_1);
6904 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6905 free_a_printer_driver(driver, 3);
6908 *returned+=ndrivers;
6912 /* check the required size. */
6913 for (i=0; i<*returned; i++) {
6914 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6915 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6918 if (*needed > offered) {
6919 result = WERR_INSUFFICIENT_BUFFER;
6923 if (!rpcbuf_alloc_size(buffer, *needed)) {
6924 result = WERR_NOMEM;
6928 /* fill the buffer with the driver structures */
6929 for (i=0; i<*returned; i++) {
6930 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6931 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6935 SAFE_FREE(driver_info_1);
6937 if ( !W_ERROR_IS_OK(result) )
6943 /****************************************************************************
6944 Enumerates all printer drivers at level 2.
6945 ****************************************************************************/
6947 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6952 fstring *list = NULL;
6953 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6954 DRIVER_INFO_2 *driver_info_2=NULL;
6955 WERROR result = WERR_OK;
6959 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6961 ndrivers=get_ntdrivers(&list, architecture, version);
6962 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6964 if(ndrivers == -1) {
6965 SAFE_FREE(driver_info_2);
6970 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6971 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6977 for (i=0; i<ndrivers; i++) {
6980 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6981 ZERO_STRUCT(driver);
6982 status = get_a_printer_driver(&driver, 3, list[i],
6983 architecture, version);
6984 if (!W_ERROR_IS_OK(status)) {
6986 SAFE_FREE(driver_info_2);
6989 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6990 free_a_printer_driver(driver, 3);
6993 *returned+=ndrivers;
6997 /* check the required size. */
6998 for (i=0; i<*returned; i++) {
6999 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7000 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7003 if (*needed > offered) {
7004 result = WERR_INSUFFICIENT_BUFFER;
7008 if (!rpcbuf_alloc_size(buffer, *needed)) {
7009 result = WERR_NOMEM;
7013 /* fill the buffer with the form structures */
7014 for (i=0; i<*returned; i++) {
7015 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7016 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7020 SAFE_FREE(driver_info_2);
7022 if ( !W_ERROR_IS_OK(result) )
7028 /****************************************************************************
7029 Enumerates all printer drivers at level 3.
7030 ****************************************************************************/
7032 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7037 fstring *list = NULL;
7038 DRIVER_INFO_3 *driver_info_3=NULL;
7039 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7040 WERROR result = WERR_OK;
7044 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7046 ndrivers=get_ntdrivers(&list, architecture, version);
7047 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7049 if(ndrivers == -1) {
7050 SAFE_FREE(driver_info_3);
7055 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7056 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7062 for (i=0; i<ndrivers; i++) {
7065 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7066 ZERO_STRUCT(driver);
7067 status = get_a_printer_driver(&driver, 3, list[i],
7068 architecture, version);
7069 if (!W_ERROR_IS_OK(status)) {
7071 SAFE_FREE(driver_info_3);
7074 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7075 free_a_printer_driver(driver, 3);
7078 *returned+=ndrivers;
7082 /* check the required size. */
7083 for (i=0; i<*returned; i++) {
7084 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7085 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7088 if (*needed > offered) {
7089 result = WERR_INSUFFICIENT_BUFFER;
7093 if (!rpcbuf_alloc_size(buffer, *needed)) {
7094 result = WERR_NOMEM;
7098 /* fill the buffer with the driver structures */
7099 for (i=0; i<*returned; i++) {
7100 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7101 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7105 for (i=0; i<*returned; i++) {
7106 SAFE_FREE(driver_info_3[i].dependentfiles);
7109 SAFE_FREE(driver_info_3);
7111 if ( !W_ERROR_IS_OK(result) )
7117 /****************************************************************************
7118 Enumerates all printer drivers.
7119 ****************************************************************************/
7121 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7123 uint32 level = q_u->level;
7124 RPC_BUFFER *buffer = NULL;
7125 uint32 offered = q_u->offered;
7126 uint32 *needed = &r_u->needed;
7127 uint32 *returned = &r_u->returned;
7130 fstring architecture;
7132 /* that's an [in out] buffer */
7134 if (!q_u->buffer && (offered!=0)) {
7135 return WERR_INVALID_PARAM;
7138 rpcbuf_move(q_u->buffer, &r_u->buffer);
7139 buffer = r_u->buffer;
7141 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7146 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7147 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7149 if ( !is_myname_or_ipaddr( servername ) )
7150 return WERR_UNKNOWN_PRINTER_DRIVER;
7154 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7156 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7158 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7160 return WERR_UNKNOWN_LEVEL;
7164 /****************************************************************************
7165 ****************************************************************************/
7167 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7169 form->flag=list->flag;
7170 init_unistr(&form->name, list->name);
7171 form->width=list->width;
7172 form->length=list->length;
7173 form->left=list->left;
7174 form->top=list->top;
7175 form->right=list->right;
7176 form->bottom=list->bottom;
7179 /****************************************************************************
7180 ****************************************************************************/
7182 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7184 uint32 level = q_u->level;
7185 RPC_BUFFER *buffer = NULL;
7186 uint32 offered = q_u->offered;
7187 uint32 *needed = &r_u->needed;
7188 uint32 *numofforms = &r_u->numofforms;
7189 uint32 numbuiltinforms;
7191 nt_forms_struct *list=NULL;
7192 nt_forms_struct *builtinlist=NULL;
7197 /* that's an [in out] buffer */
7199 if (!q_u->buffer && (offered!=0) ) {
7200 return WERR_INVALID_PARAM;
7203 rpcbuf_move(q_u->buffer, &r_u->buffer);
7204 buffer = r_u->buffer;
7206 DEBUG(4,("_spoolss_enumforms\n"));
7207 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7208 DEBUGADD(5,("Info level [%d]\n", level));
7210 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7211 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7212 *numofforms = get_ntforms(&list);
7213 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7214 *numofforms += numbuiltinforms;
7216 if (*numofforms == 0) {
7217 SAFE_FREE(builtinlist);
7219 return WERR_NO_MORE_ITEMS;
7224 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7225 SAFE_FREE(builtinlist);
7231 /* construct the list of form structures */
7232 for (i=0; i<numbuiltinforms; i++) {
7233 DEBUGADD(6,("Filling form number [%d]\n",i));
7234 fill_form_1(&forms_1[i], &builtinlist[i]);
7237 SAFE_FREE(builtinlist);
7239 for (; i<*numofforms; i++) {
7240 DEBUGADD(6,("Filling form number [%d]\n",i));
7241 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7246 /* check the required size. */
7247 for (i=0; i<numbuiltinforms; i++) {
7248 DEBUGADD(6,("adding form [%d]'s size\n",i));
7249 buffer_size += spoolss_size_form_1(&forms_1[i]);
7251 for (; i<*numofforms; i++) {
7252 DEBUGADD(6,("adding form [%d]'s size\n",i));
7253 buffer_size += spoolss_size_form_1(&forms_1[i]);
7256 *needed=buffer_size;
7258 if (*needed > offered) {
7261 return WERR_INSUFFICIENT_BUFFER;
7264 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7270 /* fill the buffer with the form structures */
7271 for (i=0; i<numbuiltinforms; i++) {
7272 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7273 smb_io_form_1("", buffer, &forms_1[i], 0);
7275 for (; i<*numofforms; i++) {
7276 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7277 smb_io_form_1("", buffer, &forms_1[i], 0);
7286 SAFE_FREE(builtinlist);
7287 return WERR_UNKNOWN_LEVEL;
7291 /****************************************************************************
7292 ****************************************************************************/
7294 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7296 uint32 level = q_u->level;
7297 UNISTR2 *uni_formname = &q_u->formname;
7298 RPC_BUFFER *buffer = NULL;
7299 uint32 offered = q_u->offered;
7300 uint32 *needed = &r_u->needed;
7302 nt_forms_struct *list=NULL;
7303 nt_forms_struct builtin_form;
7308 int numofforms=0, i=0;
7310 /* that's an [in out] buffer */
7312 if (!q_u->buffer && (offered!=0)) {
7313 return WERR_INVALID_PARAM;
7316 rpcbuf_move(q_u->buffer, &r_u->buffer);
7317 buffer = r_u->buffer;
7319 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7321 DEBUG(4,("_spoolss_getform\n"));
7322 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7323 DEBUGADD(5,("Info level [%d]\n", level));
7325 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7326 if (!foundBuiltin) {
7327 numofforms = get_ntforms(&list);
7328 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7330 if (numofforms == 0)
7337 fill_form_1(&form_1, &builtin_form);
7340 /* Check if the requested name is in the list of form structures */
7341 for (i=0; i<numofforms; i++) {
7343 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7345 if (strequal(form_name, list[i].name)) {
7346 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7347 fill_form_1(&form_1, &list[i]);
7353 if (i == numofforms) {
7357 /* check the required size. */
7359 *needed=spoolss_size_form_1(&form_1);
7361 if (*needed > offered)
7362 return WERR_INSUFFICIENT_BUFFER;
7364 if (!rpcbuf_alloc_size(buffer, buffer_size))
7367 /* fill the buffer with the form structures */
7368 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7369 smb_io_form_1("", buffer, &form_1, 0);
7375 return WERR_UNKNOWN_LEVEL;
7379 /****************************************************************************
7380 ****************************************************************************/
7382 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7384 init_unistr(&port->port_name, name);
7387 /****************************************************************************
7388 TODO: This probably needs distinguish between TCP/IP and Local ports
7390 ****************************************************************************/
7392 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7394 init_unistr(&port->port_name, name);
7395 init_unistr(&port->monitor_name, "Local Monitor");
7396 init_unistr(&port->description, SPL_LOCAL_PORT );
7397 port->port_type=PORT_TYPE_WRITE;
7402 /****************************************************************************
7403 wrapper around the enumer ports command
7404 ****************************************************************************/
7406 WERROR enumports_hook( int *count, char ***lines )
7408 char *cmd = lp_enumports_cmd();
7418 /* if no hook then just fill in the default port */
7421 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7422 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7427 /* we have a valid enumport command */
7429 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7431 DEBUG(10,("Running [%s]\n", command));
7432 ret = smbrun(command, &fd);
7433 DEBUG(10,("Returned [%d]\n", ret));
7438 return WERR_ACCESS_DENIED;
7442 qlines = fd_lines_load(fd, &numlines, 0);
7443 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7453 /****************************************************************************
7455 ****************************************************************************/
7457 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7459 PORT_INFO_1 *ports=NULL;
7461 WERROR result = WERR_OK;
7462 char **qlines = NULL;
7465 result = enumports_hook( &numlines, &qlines );
7466 if (!W_ERROR_IS_OK(result)) {
7467 file_lines_free(qlines);
7472 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7473 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7474 dos_errstr(WERR_NOMEM)));
7475 file_lines_free(qlines);
7479 for (i=0; i<numlines; i++) {
7480 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7481 fill_port_1(&ports[i], qlines[i]);
7484 file_lines_free(qlines);
7486 *returned = numlines;
7488 /* check the required size. */
7489 for (i=0; i<*returned; i++) {
7490 DEBUGADD(6,("adding port [%d]'s size\n", i));
7491 *needed += spoolss_size_port_info_1(&ports[i]);
7494 if (*needed > offered) {
7495 result = WERR_INSUFFICIENT_BUFFER;
7499 if (!rpcbuf_alloc_size(buffer, *needed)) {
7500 result = WERR_NOMEM;
7504 /* fill the buffer with the ports structures */
7505 for (i=0; i<*returned; i++) {
7506 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7507 smb_io_port_1("", buffer, &ports[i], 0);
7513 if ( !W_ERROR_IS_OK(result) )
7519 /****************************************************************************
7521 ****************************************************************************/
7523 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7525 PORT_INFO_2 *ports=NULL;
7527 WERROR result = WERR_OK;
7528 char **qlines = NULL;
7531 result = enumports_hook( &numlines, &qlines );
7532 if ( !W_ERROR_IS_OK(result)) {
7533 file_lines_free(qlines);
7538 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7539 file_lines_free(qlines);
7543 for (i=0; i<numlines; i++) {
7544 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7545 fill_port_2(&(ports[i]), qlines[i]);
7549 file_lines_free(qlines);
7551 *returned = numlines;
7553 /* check the required size. */
7554 for (i=0; i<*returned; i++) {
7555 DEBUGADD(6,("adding port [%d]'s size\n", i));
7556 *needed += spoolss_size_port_info_2(&ports[i]);
7559 if (*needed > offered) {
7560 result = WERR_INSUFFICIENT_BUFFER;
7564 if (!rpcbuf_alloc_size(buffer, *needed)) {
7565 result = WERR_NOMEM;
7569 /* fill the buffer with the ports structures */
7570 for (i=0; i<*returned; i++) {
7571 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7572 smb_io_port_2("", buffer, &ports[i], 0);
7578 if ( !W_ERROR_IS_OK(result) )
7584 /****************************************************************************
7586 ****************************************************************************/
7588 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7590 uint32 level = q_u->level;
7591 RPC_BUFFER *buffer = NULL;
7592 uint32 offered = q_u->offered;
7593 uint32 *needed = &r_u->needed;
7594 uint32 *returned = &r_u->returned;
7596 /* that's an [in out] buffer */
7598 if (!q_u->buffer && (offered!=0)) {
7599 return WERR_INVALID_PARAM;
7602 rpcbuf_move(q_u->buffer, &r_u->buffer);
7603 buffer = r_u->buffer;
7605 DEBUG(4,("_spoolss_enumports\n"));
7612 return enumports_level_1(buffer, offered, needed, returned);
7614 return enumports_level_2(buffer, offered, needed, returned);
7616 return WERR_UNKNOWN_LEVEL;
7620 /****************************************************************************
7621 ****************************************************************************/
7623 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7624 const SPOOL_PRINTER_INFO_LEVEL *info,
7625 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7626 uint32 user_switch, const SPOOL_USER_CTR *user,
7629 NT_PRINTER_INFO_LEVEL *printer = NULL;
7632 WERROR err = WERR_OK;
7634 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7635 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7639 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7640 if (!convert_printer_info(info, printer, 2)) {
7641 free_a_printer(&printer, 2);
7645 /* check to see if the printer already exists */
7647 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7648 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7649 printer->info_2->sharename));
7650 free_a_printer(&printer, 2);
7651 return WERR_PRINTER_ALREADY_EXISTS;
7654 /* FIXME!!! smbd should check to see if the driver is installed before
7655 trying to add a printer like this --jerry */
7657 if (*lp_addprinter_cmd() ) {
7658 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7659 free_a_printer(&printer,2);
7660 return WERR_ACCESS_DENIED;
7663 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7664 "smb.conf parameter \"addprinter command\" is defined. This"
7665 "parameter must exist for this call to succeed\n",
7666 printer->info_2->sharename ));
7669 /* use our primary netbios name since get_a_printer() will convert
7670 it to what the client expects on a case by case basis */
7672 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7673 printer->info_2->sharename);
7676 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7677 free_a_printer(&printer,2);
7678 return WERR_ACCESS_DENIED;
7681 /* you must be a printer admin to add a new printer */
7682 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7683 free_a_printer(&printer,2);
7684 return WERR_ACCESS_DENIED;
7688 * Do sanity check on the requested changes for Samba.
7691 if (!check_printer_ok(printer->info_2, snum)) {
7692 free_a_printer(&printer,2);
7693 return WERR_INVALID_PARAM;
7697 * When a printer is created, the drivername bound to the printer is used
7698 * to lookup previously saved driver initialization info, which is then
7699 * bound to the new printer, simulating what happens in the Windows arch.
7704 set_driver_init(printer, 2);
7708 /* A valid devmode was included, convert and link it
7710 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7712 if (!convert_devicemode(printer->info_2->printername, devmode,
7713 &printer->info_2->devmode))
7717 /* write the ASCII on disk */
7718 err = mod_a_printer(printer, 2);
7719 if (!W_ERROR_IS_OK(err)) {
7720 free_a_printer(&printer,2);
7724 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7725 /* Handle open failed - remove addition. */
7726 del_a_printer(printer->info_2->sharename);
7727 free_a_printer(&printer,2);
7728 return WERR_ACCESS_DENIED;
7731 update_c_setprinter(False);
7732 free_a_printer(&printer,2);
7737 /****************************************************************************
7738 ****************************************************************************/
7740 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7742 UNISTR2 *uni_srv_name = q_u->server_name;
7743 uint32 level = q_u->level;
7744 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7745 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7746 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7747 uint32 user_switch = q_u->user_switch;
7748 SPOOL_USER_CTR *user = &q_u->user_ctr;
7749 POLICY_HND *handle = &r_u->handle;
7753 /* we don't handle yet */
7754 /* but I know what to do ... */
7755 return WERR_UNKNOWN_LEVEL;
7757 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7759 user_switch, user, handle);
7761 return WERR_UNKNOWN_LEVEL;
7765 /****************************************************************************
7766 ****************************************************************************/
7768 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7770 uint32 level = q_u->level;
7771 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7772 WERROR err = WERR_OK;
7773 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7774 fstring driver_name;
7777 ZERO_STRUCT(driver);
7779 if (!convert_printer_driver_info(info, &driver, level)) {
7784 DEBUG(5,("Cleaning driver's information\n"));
7785 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7786 if (!W_ERROR_IS_OK(err))
7789 DEBUG(5,("Moving driver to final destination\n"));
7790 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7794 if (add_a_printer_driver(driver, level)!=0) {
7795 err = WERR_ACCESS_DENIED;
7800 * I think this is where he DrvUpgradePrinter() hook would be
7801 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7802 * server. Right now, we just need to send ourselves a message
7803 * to update each printer bound to this driver. --jerry
7806 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7807 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7812 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7813 * decide if the driver init data should be deleted. The rules are:
7814 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7815 * 2) delete init data only if there is no 2k/Xp driver
7816 * 3) always delete init data
7817 * The generalized rule is always use init data from the highest order driver.
7818 * It is necessary to follow the driver install by an initialization step to
7819 * finish off this process.
7822 version = driver.info_3->cversion;
7823 else if (level == 6)
7824 version = driver.info_6->version;
7829 * 9x printer driver - never delete init data
7832 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7837 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7838 * there is no 2k/Xp driver init data for this driver name.
7842 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7844 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7846 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7848 if (!del_driver_init(driver_name))
7849 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7852 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7854 free_a_printer_driver(driver1,3);
7855 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7862 * 2k or Xp printer driver - always delete init data
7865 if (!del_driver_init(driver_name))
7866 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7870 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7876 free_a_printer_driver(driver, level);
7880 /********************************************************************
7881 * spoolss_addprinterdriverex
7882 ********************************************************************/
7884 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7886 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7887 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7890 * we only support the semantics of AddPrinterDriver()
7891 * i.e. only copy files that are newer than existing ones
7894 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7895 return WERR_ACCESS_DENIED;
7897 ZERO_STRUCT(q_u_local);
7898 ZERO_STRUCT(r_u_local);
7900 /* just pass the information off to _spoolss_addprinterdriver() */
7901 q_u_local.server_name_ptr = q_u->server_name_ptr;
7902 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7903 q_u_local.level = q_u->level;
7904 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7906 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7909 /****************************************************************************
7910 ****************************************************************************/
7912 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7914 init_unistr(&info->name, name);
7917 /****************************************************************************
7918 ****************************************************************************/
7920 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7926 const char *short_archi;
7927 DRIVER_DIRECTORY_1 *info=NULL;
7928 WERROR result = WERR_OK;
7930 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7931 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7933 /* check for beginning double '\'s and that the server
7936 pservername = servername;
7937 if ( *pservername == '\\' && strlen(servername)>2 ) {
7941 if ( !is_myname_or_ipaddr( pservername ) )
7942 return WERR_INVALID_PARAM;
7944 if (!(short_archi = get_short_archi(long_archi)))
7945 return WERR_INVALID_ENVIRONMENT;
7947 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7950 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7952 DEBUG(4,("printer driver directory: [%s]\n", path));
7954 fill_driverdir_1(info, path);
7956 *needed += spoolss_size_driverdir_info_1(info);
7958 if (*needed > offered) {
7959 result = WERR_INSUFFICIENT_BUFFER;
7963 if (!rpcbuf_alloc_size(buffer, *needed)) {
7964 result = WERR_NOMEM;
7968 smb_io_driverdir_1("", buffer, info, 0);
7976 /****************************************************************************
7977 ****************************************************************************/
7979 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7981 UNISTR2 *name = &q_u->name;
7982 UNISTR2 *uni_environment = &q_u->environment;
7983 uint32 level = q_u->level;
7984 RPC_BUFFER *buffer = NULL;
7985 uint32 offered = q_u->offered;
7986 uint32 *needed = &r_u->needed;
7988 /* that's an [in out] buffer */
7990 if (!q_u->buffer && (offered!=0)) {
7991 return WERR_INVALID_PARAM;
7994 rpcbuf_move(q_u->buffer, &r_u->buffer);
7995 buffer = r_u->buffer;
7997 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8003 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8005 return WERR_UNKNOWN_LEVEL;
8009 /****************************************************************************
8010 ****************************************************************************/
8012 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8014 POLICY_HND *handle = &q_u->handle;
8015 uint32 idx = q_u->index;
8016 uint32 in_value_len = q_u->valuesize;
8017 uint32 in_data_len = q_u->datasize;
8018 uint32 *out_max_value_len = &r_u->valuesize;
8019 uint16 **out_value = &r_u->value;
8020 uint32 *out_value_len = &r_u->realvaluesize;
8021 uint32 *out_type = &r_u->type;
8022 uint32 *out_max_data_len = &r_u->datasize;
8023 uint8 **data_out = &r_u->data;
8024 uint32 *out_data_len = &r_u->realdatasize;
8026 NT_PRINTER_INFO_LEVEL *printer = NULL;
8028 uint32 biggest_valuesize;
8029 uint32 biggest_datasize;
8031 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8034 REGISTRY_VALUE *val = NULL;
8035 NT_PRINTER_DATA *p_data;
8036 int i, key_index, num_values;
8041 *out_max_data_len = 0;
8045 DEBUG(5,("spoolss_enumprinterdata\n"));
8048 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8052 if (!get_printer_snum(p,handle, &snum, NULL))
8055 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8056 if (!W_ERROR_IS_OK(result))
8059 p_data = printer->info_2->data;
8060 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8065 * The NT machine wants to know the biggest size of value and data
8067 * cf: MSDN EnumPrinterData remark section
8070 if ( !in_value_len && !in_data_len && (key_index != -1) )
8072 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8074 biggest_valuesize = 0;
8075 biggest_datasize = 0;
8077 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8079 for ( i=0; i<num_values; i++ )
8081 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8083 name_length = strlen(val->valuename);
8084 if ( strlen(val->valuename) > biggest_valuesize )
8085 biggest_valuesize = name_length;
8087 if ( val->size > biggest_datasize )
8088 biggest_datasize = val->size;
8090 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8094 /* the value is an UNICODE string but real_value_size is the length
8095 in bytes including the trailing 0 */
8097 *out_value_len = 2 * (1+biggest_valuesize);
8098 *out_data_len = biggest_datasize;
8100 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8106 * the value len is wrong in NT sp3
8107 * that's the number of bytes not the number of unicode chars
8110 if ( key_index != -1 )
8111 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8116 /* out_value should default to "" or else NT4 has
8117 problems unmarshalling the response */
8119 *out_max_value_len=(in_value_len/sizeof(uint16));
8121 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8123 result = WERR_NOMEM;
8127 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8129 /* the data is counted in bytes */
8131 *out_max_data_len = in_data_len;
8132 *out_data_len = in_data_len;
8134 /* only allocate when given a non-zero data_len */
8136 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8138 result = WERR_NOMEM;
8142 result = WERR_NO_MORE_ITEMS;
8148 * - counted in bytes in the request
8149 * - counted in UNICODE chars in the max reply
8150 * - counted in bytes in the real size
8152 * take a pause *before* coding not *during* coding
8156 *out_max_value_len=(in_value_len/sizeof(uint16));
8157 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8159 result = WERR_NOMEM;
8163 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8167 *out_type = regval_type( val );
8169 /* data - counted in bytes */
8171 *out_max_data_len = in_data_len;
8172 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8174 result = WERR_NOMEM;
8177 data_len = regval_size(val);
8179 memcpy( *data_out, regval_data_p(val), data_len );
8180 *out_data_len = data_len;
8184 free_a_printer(&printer, 2);
8188 /****************************************************************************
8189 ****************************************************************************/
8191 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8193 POLICY_HND *handle = &q_u->handle;
8194 UNISTR2 *value = &q_u->value;
8195 uint32 type = q_u->type;
8196 uint8 *data = q_u->data;
8197 uint32 real_len = q_u->real_len;
8199 NT_PRINTER_INFO_LEVEL *printer = NULL;
8201 WERROR status = WERR_OK;
8202 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8205 DEBUG(5,("spoolss_setprinterdata\n"));
8208 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8212 if ( Printer->printer_type == SPLHND_SERVER ) {
8213 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8214 return WERR_INVALID_PARAM;
8217 if (!get_printer_snum(p,handle, &snum, NULL))
8221 * Access check : NT returns "access denied" if you make a
8222 * SetPrinterData call without the necessary privildge.
8223 * we were originally returning OK if nothing changed
8224 * which made Win2k issue **a lot** of SetPrinterData
8225 * when connecting to a printer --jerry
8228 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8230 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8231 status = WERR_ACCESS_DENIED;
8235 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8236 if (!W_ERROR_IS_OK(status))
8239 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8242 * When client side code sets a magic printer data key, detect it and save
8243 * the current printer data and the magic key's data (its the DEVMODE) for
8244 * future printer/driver initializations.
8246 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8248 /* Set devmode and printer initialization info */
8249 status = save_driver_init( printer, 2, data, real_len );
8251 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8255 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8256 type, data, real_len );
8257 if ( W_ERROR_IS_OK(status) )
8258 status = mod_a_printer(printer, 2);
8262 free_a_printer(&printer, 2);
8267 /****************************************************************************
8268 ****************************************************************************/
8270 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8272 POLICY_HND *handle = &q_u->handle;
8273 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8276 DEBUG(5,("_spoolss_resetprinter\n"));
8279 * All we do is to check to see if the handle and queue is valid.
8280 * This call really doesn't mean anything to us because we only
8281 * support RAW printing. --jerry
8285 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8289 if (!get_printer_snum(p,handle, &snum, NULL))
8293 /* blindly return success */
8298 /****************************************************************************
8299 ****************************************************************************/
8301 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8303 POLICY_HND *handle = &q_u->handle;
8304 UNISTR2 *value = &q_u->valuename;
8306 NT_PRINTER_INFO_LEVEL *printer = NULL;
8308 WERROR status = WERR_OK;
8309 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8312 DEBUG(5,("spoolss_deleteprinterdata\n"));
8315 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8319 if (!get_printer_snum(p, handle, &snum, NULL))
8322 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8323 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8324 return WERR_ACCESS_DENIED;
8327 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8328 if (!W_ERROR_IS_OK(status))
8331 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8333 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8335 if ( W_ERROR_IS_OK(status) )
8336 mod_a_printer( printer, 2 );
8338 free_a_printer(&printer, 2);
8343 /****************************************************************************
8344 ****************************************************************************/
8346 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8348 POLICY_HND *handle = &q_u->handle;
8349 FORM *form = &q_u->form;
8350 nt_forms_struct tmpForm;
8352 WERROR status = WERR_OK;
8353 NT_PRINTER_INFO_LEVEL *printer = NULL;
8356 nt_forms_struct *list=NULL;
8357 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8359 DEBUG(5,("spoolss_addform\n"));
8362 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8367 /* forms can be added on printer of on the print server handle */
8369 if ( Printer->printer_type == SPLHND_PRINTER )
8371 if (!get_printer_snum(p,handle, &snum, NULL))
8374 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8375 if (!W_ERROR_IS_OK(status))
8379 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8380 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8381 status = WERR_ACCESS_DENIED;
8385 /* can't add if builtin */
8387 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8388 status = WERR_ALREADY_EXISTS;
8392 count = get_ntforms(&list);
8394 if(!add_a_form(&list, form, &count)) {
8395 status = WERR_NOMEM;
8399 write_ntforms(&list, count);
8402 * ChangeID must always be set if this is a printer
8405 if ( Printer->printer_type == SPLHND_PRINTER )
8406 status = mod_a_printer(printer, 2);
8410 free_a_printer(&printer, 2);
8416 /****************************************************************************
8417 ****************************************************************************/
8419 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8421 POLICY_HND *handle = &q_u->handle;
8422 UNISTR2 *form_name = &q_u->name;
8423 nt_forms_struct tmpForm;
8425 nt_forms_struct *list=NULL;
8426 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8428 WERROR status = WERR_OK;
8429 NT_PRINTER_INFO_LEVEL *printer = NULL;
8431 DEBUG(5,("spoolss_deleteform\n"));
8434 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8438 /* forms can be deleted on printer of on the print server handle */
8440 if ( Printer->printer_type == SPLHND_PRINTER )
8442 if (!get_printer_snum(p,handle, &snum, NULL))
8445 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8446 if (!W_ERROR_IS_OK(status))
8450 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8451 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8452 status = WERR_ACCESS_DENIED;
8456 /* can't delete if builtin */
8458 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8459 status = WERR_INVALID_PARAM;
8463 count = get_ntforms(&list);
8465 if ( !delete_a_form(&list, form_name, &count, &status ))
8469 * ChangeID must always be set if this is a printer
8472 if ( Printer->printer_type == SPLHND_PRINTER )
8473 status = mod_a_printer(printer, 2);
8477 free_a_printer(&printer, 2);
8483 /****************************************************************************
8484 ****************************************************************************/
8486 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8488 POLICY_HND *handle = &q_u->handle;
8489 FORM *form = &q_u->form;
8490 nt_forms_struct tmpForm;
8492 WERROR status = WERR_OK;
8493 NT_PRINTER_INFO_LEVEL *printer = NULL;
8496 nt_forms_struct *list=NULL;
8497 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8499 DEBUG(5,("spoolss_setform\n"));
8502 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8506 /* forms can be modified on printer of on the print server handle */
8508 if ( Printer->printer_type == SPLHND_PRINTER )
8510 if (!get_printer_snum(p,handle, &snum, NULL))
8513 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8514 if (!W_ERROR_IS_OK(status))
8518 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8519 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8520 status = WERR_ACCESS_DENIED;
8524 /* can't set if builtin */
8525 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8526 status = WERR_INVALID_PARAM;
8530 count = get_ntforms(&list);
8531 update_a_form(&list, form, count);
8532 write_ntforms(&list, count);
8535 * ChangeID must always be set if this is a printer
8538 if ( Printer->printer_type == SPLHND_PRINTER )
8539 status = mod_a_printer(printer, 2);
8544 free_a_printer(&printer, 2);
8550 /****************************************************************************
8551 enumprintprocessors level 1.
8552 ****************************************************************************/
8554 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8556 PRINTPROCESSOR_1 *info_1=NULL;
8557 WERROR result = WERR_OK;
8559 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8564 init_unistr(&info_1->name, "winprint");
8566 *needed += spoolss_size_printprocessor_info_1(info_1);
8568 if (*needed > offered) {
8569 result = WERR_INSUFFICIENT_BUFFER;
8573 if (!rpcbuf_alloc_size(buffer, *needed)) {
8574 result = WERR_NOMEM;
8578 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8583 if ( !W_ERROR_IS_OK(result) )
8589 /****************************************************************************
8590 ****************************************************************************/
8592 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8594 uint32 level = q_u->level;
8595 RPC_BUFFER *buffer = NULL;
8596 uint32 offered = q_u->offered;
8597 uint32 *needed = &r_u->needed;
8598 uint32 *returned = &r_u->returned;
8600 /* that's an [in out] buffer */
8602 if (!q_u->buffer && (offered!=0)) {
8603 return WERR_INVALID_PARAM;
8606 rpcbuf_move(q_u->buffer, &r_u->buffer);
8607 buffer = r_u->buffer;
8609 DEBUG(5,("spoolss_enumprintprocessors\n"));
8612 * Enumerate the print processors ...
8614 * Just reply with "winprint", to keep NT happy
8615 * and I can use my nice printer checker.
8623 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8625 return WERR_UNKNOWN_LEVEL;
8629 /****************************************************************************
8630 enumprintprocdatatypes level 1.
8631 ****************************************************************************/
8633 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8635 PRINTPROCDATATYPE_1 *info_1=NULL;
8636 WERROR result = WERR_NOMEM;
8638 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8643 init_unistr(&info_1->name, "RAW");
8645 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8647 if (*needed > offered) {
8648 result = WERR_INSUFFICIENT_BUFFER;
8652 if (!rpcbuf_alloc_size(buffer, *needed)) {
8653 result = WERR_NOMEM;
8657 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8662 if ( !W_ERROR_IS_OK(result) )
8668 /****************************************************************************
8669 ****************************************************************************/
8671 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8673 uint32 level = q_u->level;
8674 RPC_BUFFER *buffer = NULL;
8675 uint32 offered = q_u->offered;
8676 uint32 *needed = &r_u->needed;
8677 uint32 *returned = &r_u->returned;
8679 /* that's an [in out] buffer */
8681 if (!q_u->buffer && (offered!=0)) {
8682 return WERR_INVALID_PARAM;
8685 rpcbuf_move(q_u->buffer, &r_u->buffer);
8686 buffer = r_u->buffer;
8688 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8695 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8697 return WERR_UNKNOWN_LEVEL;
8701 /****************************************************************************
8702 enumprintmonitors level 1.
8703 ****************************************************************************/
8705 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8707 PRINTMONITOR_1 *info_1;
8708 WERROR result = WERR_OK;
8711 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8716 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8717 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8719 for ( i=0; i<*returned; i++ ) {
8720 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8723 if (*needed > offered) {
8724 result = WERR_INSUFFICIENT_BUFFER;
8728 if (!rpcbuf_alloc_size(buffer, *needed)) {
8729 result = WERR_NOMEM;
8733 for ( i=0; i<*returned; i++ ) {
8734 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8740 if ( !W_ERROR_IS_OK(result) )
8746 /****************************************************************************
8747 enumprintmonitors level 2.
8748 ****************************************************************************/
8750 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8752 PRINTMONITOR_2 *info_2;
8753 WERROR result = WERR_OK;
8756 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8761 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8762 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8763 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8765 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8766 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8767 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8769 for ( i=0; i<*returned; i++ ) {
8770 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8773 if (*needed > offered) {
8774 result = WERR_INSUFFICIENT_BUFFER;
8778 if (!rpcbuf_alloc_size(buffer, *needed)) {
8779 result = WERR_NOMEM;
8783 for ( i=0; i<*returned; i++ ) {
8784 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8790 if ( !W_ERROR_IS_OK(result) )
8796 /****************************************************************************
8797 ****************************************************************************/
8799 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8801 uint32 level = q_u->level;
8802 RPC_BUFFER *buffer = NULL;
8803 uint32 offered = q_u->offered;
8804 uint32 *needed = &r_u->needed;
8805 uint32 *returned = &r_u->returned;
8807 /* that's an [in out] buffer */
8809 if (!q_u->buffer && (offered!=0)) {
8810 return WERR_INVALID_PARAM;
8813 rpcbuf_move(q_u->buffer, &r_u->buffer);
8814 buffer = r_u->buffer;
8816 DEBUG(5,("spoolss_enumprintmonitors\n"));
8819 * Enumerate the print monitors ...
8821 * Just reply with "Local Port", to keep NT happy
8822 * and I can use my nice printer checker.
8830 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8832 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8834 return WERR_UNKNOWN_LEVEL;
8838 /****************************************************************************
8839 ****************************************************************************/
8841 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8842 NT_PRINTER_INFO_LEVEL *ntprinter,
8843 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8848 JOB_INFO_1 *info_1=NULL;
8849 WERROR result = WERR_OK;
8851 info_1=SMB_MALLOC_P(JOB_INFO_1);
8853 if (info_1 == NULL) {
8857 for (i=0; i<count && found==False; i++) {
8858 if ((*queue)[i].job==(int)jobid)
8864 /* NT treats not found as bad param... yet another bad choice */
8865 return WERR_INVALID_PARAM;
8868 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8870 *needed += spoolss_size_job_info_1(info_1);
8872 if (*needed > offered) {
8873 result = WERR_INSUFFICIENT_BUFFER;
8877 if (!rpcbuf_alloc_size(buffer, *needed)) {
8878 result = WERR_NOMEM;
8882 smb_io_job_info_1("", buffer, info_1, 0);
8890 /****************************************************************************
8891 ****************************************************************************/
8893 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8894 NT_PRINTER_INFO_LEVEL *ntprinter,
8895 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8902 DEVICEMODE *devmode = NULL;
8903 NT_DEVICEMODE *nt_devmode = NULL;
8905 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8908 ZERO_STRUCTP(info_2);
8910 for ( i=0; i<count && found==False; i++ )
8912 if ((*queue)[i].job == (int)jobid)
8917 /* NT treats not found as bad param... yet another bad
8919 result = WERR_INVALID_PARAM;
8924 * if the print job does not have a DEVMODE associated with it,
8925 * just use the one for the printer. A NULL devicemode is not
8926 * a failure condition
8929 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8930 devmode = construct_dev_mode(lp_const_servicename(snum));
8932 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8933 ZERO_STRUCTP( devmode );
8934 convert_nt_devicemode( devmode, nt_devmode );
8938 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8940 *needed += spoolss_size_job_info_2(info_2);
8942 if (*needed > offered) {
8943 result = WERR_INSUFFICIENT_BUFFER;
8947 if (!rpcbuf_alloc_size(buffer, *needed)) {
8948 result = WERR_NOMEM;
8952 smb_io_job_info_2("", buffer, info_2, 0);
8957 /* Cleanup allocated memory */
8959 free_job_info_2(info_2); /* Also frees devmode */
8965 /****************************************************************************
8966 ****************************************************************************/
8968 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8970 POLICY_HND *handle = &q_u->handle;
8971 uint32 jobid = q_u->jobid;
8972 uint32 level = q_u->level;
8973 RPC_BUFFER *buffer = NULL;
8974 uint32 offered = q_u->offered;
8975 uint32 *needed = &r_u->needed;
8976 WERROR wstatus = WERR_OK;
8977 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8980 print_queue_struct *queue = NULL;
8981 print_status_struct prt_status;
8983 /* that's an [in out] buffer */
8985 if (!q_u->buffer && (offered!=0)) {
8986 return WERR_INVALID_PARAM;
8989 rpcbuf_move(q_u->buffer, &r_u->buffer);
8990 buffer = r_u->buffer;
8992 DEBUG(5,("spoolss_getjob\n"));
8996 if (!get_printer_snum(p, handle, &snum, NULL))
8999 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9000 if ( !W_ERROR_IS_OK(wstatus) )
9003 count = print_queue_status(snum, &queue, &prt_status);
9005 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9006 count, prt_status.status, prt_status.message));
9010 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9011 buffer, offered, needed);
9014 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9015 buffer, offered, needed);
9018 wstatus = WERR_UNKNOWN_LEVEL;
9023 free_a_printer( &ntprinter, 2 );
9028 /********************************************************************
9029 spoolss_getprinterdataex
9031 From MSDN documentation of GetPrinterDataEx: pass request
9032 to GetPrinterData if key is "PrinterDriverData".
9033 ********************************************************************/
9035 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9037 POLICY_HND *handle = &q_u->handle;
9038 uint32 in_size = q_u->size;
9039 uint32 *type = &r_u->type;
9040 uint32 *out_size = &r_u->size;
9041 uint8 **data = &r_u->data;
9042 uint32 *needed = &r_u->needed;
9043 fstring keyname, valuename;
9045 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9047 NT_PRINTER_INFO_LEVEL *printer = NULL;
9049 WERROR status = WERR_OK;
9051 DEBUG(4,("_spoolss_getprinterdataex\n"));
9053 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
9054 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
9056 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9057 keyname, valuename));
9059 /* in case of problem, return some default values */
9063 *out_size = in_size;
9066 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9067 status = WERR_BADFID;
9071 /* Is the handle to a printer or to the server? */
9073 if (Printer->printer_type == SPLHND_SERVER) {
9074 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9075 status = WERR_INVALID_PARAM;
9079 if ( !get_printer_snum(p,handle, &snum, NULL) )
9082 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9083 if ( !W_ERROR_IS_OK(status) )
9086 /* check to see if the keyname is valid */
9087 if ( !strlen(keyname) ) {
9088 status = WERR_INVALID_PARAM;
9092 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9093 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9094 free_a_printer( &printer, 2 );
9095 status = WERR_BADFILE;
9099 /* When given a new keyname, we should just create it */
9101 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9103 if (*needed > *out_size)
9104 status = WERR_MORE_DATA;
9107 if ( !W_ERROR_IS_OK(status) )
9109 DEBUG(5, ("error: allocating %d\n", *out_size));
9111 /* reply this param doesn't exist */
9115 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9116 status = WERR_NOMEM;
9126 free_a_printer( &printer, 2 );
9131 /********************************************************************
9132 * spoolss_setprinterdataex
9133 ********************************************************************/
9135 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9137 POLICY_HND *handle = &q_u->handle;
9138 uint32 type = q_u->type;
9139 uint8 *data = q_u->data;
9140 uint32 real_len = q_u->real_len;
9142 NT_PRINTER_INFO_LEVEL *printer = NULL;
9144 WERROR status = WERR_OK;
9145 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9150 DEBUG(4,("_spoolss_setprinterdataex\n"));
9152 /* From MSDN documentation of SetPrinterDataEx: pass request to
9153 SetPrinterData if key is "PrinterDriverData" */
9156 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9160 if ( Printer->printer_type == SPLHND_SERVER ) {
9161 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9162 return WERR_INVALID_PARAM;
9165 if ( !get_printer_snum(p,handle, &snum, NULL) )
9169 * Access check : NT returns "access denied" if you make a
9170 * SetPrinterData call without the necessary privildge.
9171 * we were originally returning OK if nothing changed
9172 * which made Win2k issue **a lot** of SetPrinterData
9173 * when connecting to a printer --jerry
9176 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9178 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9179 return WERR_ACCESS_DENIED;
9182 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9183 if (!W_ERROR_IS_OK(status))
9186 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9187 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9189 /* check for OID in valuename */
9191 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9197 /* save the registry data */
9199 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9201 if ( W_ERROR_IS_OK(status) )
9203 /* save the OID if one was specified */
9205 fstrcat( keyname, "\\" );
9206 fstrcat( keyname, SPOOL_OID_KEY );
9209 * I'm not checking the status here on purpose. Don't know
9210 * if this is right, but I'm returning the status from the
9211 * previous set_printer_dataex() call. I have no idea if
9212 * this is right. --jerry
9215 set_printer_dataex( printer, keyname, valuename,
9216 REG_SZ, (uint8 *)oid_string,
9217 strlen(oid_string)+1 );
9220 status = mod_a_printer(printer, 2);
9223 free_a_printer(&printer, 2);
9229 /********************************************************************
9230 * spoolss_deleteprinterdataex
9231 ********************************************************************/
9233 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9235 POLICY_HND *handle = &q_u->handle;
9236 UNISTR2 *value = &q_u->valuename;
9237 UNISTR2 *key = &q_u->keyname;
9239 NT_PRINTER_INFO_LEVEL *printer = NULL;
9241 WERROR status = WERR_OK;
9242 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9243 pstring valuename, keyname;
9245 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9248 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9252 if (!get_printer_snum(p, handle, &snum, NULL))
9255 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9256 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9257 return WERR_ACCESS_DENIED;
9260 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9261 if (!W_ERROR_IS_OK(status))
9264 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9265 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9267 status = delete_printer_dataex( printer, keyname, valuename );
9269 if ( W_ERROR_IS_OK(status) )
9270 mod_a_printer( printer, 2 );
9272 free_a_printer(&printer, 2);
9277 /********************************************************************
9278 * spoolss_enumprinterkey
9279 ********************************************************************/
9282 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9285 fstring *keynames = NULL;
9286 uint16 *enumkeys = NULL;
9289 POLICY_HND *handle = &q_u->handle;
9290 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9291 NT_PRINTER_DATA *data;
9292 NT_PRINTER_INFO_LEVEL *printer = NULL;
9294 WERROR status = WERR_BADFILE;
9297 DEBUG(4,("_spoolss_enumprinterkey\n"));
9300 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9304 if ( !get_printer_snum(p,handle, &snum, NULL) )
9307 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9308 if (!W_ERROR_IS_OK(status))
9311 /* get the list of subkey names */
9313 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9314 data = printer->info_2->data;
9316 num_keys = get_printer_subkeys( data, key, &keynames );
9318 if ( num_keys == -1 ) {
9319 status = WERR_BADFILE;
9323 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9325 r_u->needed = printerkey_len*2;
9327 if ( q_u->size < r_u->needed ) {
9328 status = WERR_MORE_DATA;
9332 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9333 status = WERR_NOMEM;
9339 if ( q_u->size < r_u->needed )
9340 status = WERR_MORE_DATA;
9343 free_a_printer( &printer, 2 );
9344 SAFE_FREE( keynames );
9349 /********************************************************************
9350 * spoolss_deleteprinterkey
9351 ********************************************************************/
9353 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9355 POLICY_HND *handle = &q_u->handle;
9356 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9358 NT_PRINTER_INFO_LEVEL *printer = NULL;
9362 DEBUG(5,("spoolss_deleteprinterkey\n"));
9365 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9369 /* if keyname == NULL, return error */
9371 if ( !q_u->keyname.buffer )
9372 return WERR_INVALID_PARAM;
9374 if (!get_printer_snum(p, handle, &snum, NULL))
9377 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9378 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9379 return WERR_ACCESS_DENIED;
9382 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9383 if (!W_ERROR_IS_OK(status))
9386 /* delete the key and all subneys */
9388 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9390 status = delete_all_printer_data( printer->info_2, key );
9392 if ( W_ERROR_IS_OK(status) )
9393 status = mod_a_printer(printer, 2);
9395 free_a_printer( &printer, 2 );
9401 /********************************************************************
9402 * spoolss_enumprinterdataex
9403 ********************************************************************/
9405 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9407 POLICY_HND *handle = &q_u->handle;
9408 uint32 in_size = q_u->size;
9411 NT_PRINTER_INFO_LEVEL *printer = NULL;
9412 PRINTER_ENUM_VALUES *enum_values = NULL;
9413 NT_PRINTER_DATA *p_data;
9415 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9420 REGISTRY_VALUE *val;
9425 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9428 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9433 * first check for a keyname of NULL or "". Win2k seems to send
9434 * this a lot and we should send back WERR_INVALID_PARAM
9435 * no need to spend time looking up the printer in this case.
9439 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9440 if ( !strlen(key) ) {
9441 result = WERR_INVALID_PARAM;
9445 /* get the printer off of disk */
9447 if (!get_printer_snum(p,handle, &snum, NULL))
9450 ZERO_STRUCT(printer);
9451 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9452 if (!W_ERROR_IS_OK(result))
9455 /* now look for a match on the key name */
9457 p_data = printer->info_2->data;
9459 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9460 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9462 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9463 result = WERR_INVALID_PARAM;
9470 /* allocate the memory for the array of pointers -- if necessary */
9472 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9475 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9477 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9478 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9479 result = WERR_NOMEM;
9483 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9487 * loop through all params and build the array to pass
9488 * back to the client
9491 for ( i=0; i<num_entries; i++ )
9493 /* lookup the registry value */
9495 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9496 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9500 value_name = regval_name( val );
9501 init_unistr( &enum_values[i].valuename, value_name );
9502 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9503 enum_values[i].type = regval_type( val );
9505 data_len = regval_size( val );
9507 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9509 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9511 result = WERR_NOMEM;
9515 enum_values[i].data_len = data_len;
9517 /* keep track of the size of the array in bytes */
9519 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9522 /* housekeeping information in the reply */
9524 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9525 * the hand marshalled container size is a multiple
9526 * of 4 bytes for RPC alignment.
9530 needed += 4-(needed % 4);
9533 r_u->needed = needed;
9534 r_u->returned = num_entries;
9536 if (needed > in_size) {
9537 result = WERR_MORE_DATA;
9541 /* copy data into the reply */
9543 r_u->ctr.size = r_u->needed;
9545 r_u->ctr.size_of_array = r_u->returned;
9546 r_u->ctr.values = enum_values;
9552 free_a_printer(&printer, 2);
9557 /****************************************************************************
9558 ****************************************************************************/
9560 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9562 init_unistr(&info->name, name);
9565 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9566 UNISTR2 *environment,
9573 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9574 WERROR result = WERR_OK;
9576 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9578 if (!get_short_archi(long_archi))
9579 return WERR_INVALID_ENVIRONMENT;
9581 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9584 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9586 fill_printprocessordirectory_1(info, path);
9588 *needed += spoolss_size_printprocessordirectory_info_1(info);
9590 if (*needed > offered) {
9591 result = WERR_INSUFFICIENT_BUFFER;
9595 if (!rpcbuf_alloc_size(buffer, *needed)) {
9596 result = WERR_INSUFFICIENT_BUFFER;
9600 smb_io_printprocessordirectory_1("", buffer, info, 0);
9608 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9610 uint32 level = q_u->level;
9611 RPC_BUFFER *buffer = NULL;
9612 uint32 offered = q_u->offered;
9613 uint32 *needed = &r_u->needed;
9616 /* that's an [in out] buffer */
9618 if (!q_u->buffer && (offered!=0)) {
9619 return WERR_INVALID_PARAM;
9622 rpcbuf_move(q_u->buffer, &r_u->buffer);
9623 buffer = r_u->buffer;
9625 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9631 result = getprintprocessordirectory_level_1
9632 (&q_u->name, &q_u->environment, buffer, offered, needed);
9635 result = WERR_UNKNOWN_LEVEL;
9641 /*******************************************************************
9642 Streams the monitor UI DLL name in UNICODE
9643 *******************************************************************/
9645 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9646 RPC_BUFFER *out, uint32 *needed )
9648 const char *dllname = "tcpmonui.dll";
9650 *needed = (strlen(dllname)+1) * 2;
9652 if ( rpcbuf_get_size(out) < *needed ) {
9653 return WERR_INSUFFICIENT_BUFFER;
9656 if ( !make_monitorui_buf( out, dllname ) ) {
9663 /*******************************************************************
9664 Create a new TCP/IP port
9665 *******************************************************************/
9667 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9668 RPC_BUFFER *out, uint32 *needed )
9670 NT_PORT_DATA_1 port1;
9673 ZERO_STRUCT( port1 );
9675 /* convert to our internal port data structure */
9677 if ( !convert_port_data_1( &port1, in ) ) {
9681 /* create the device URI and call the add_port_hook() */
9683 switch ( port1.protocol ) {
9684 case PORT_PROTOCOL_DIRECT:
9685 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9688 case PORT_PROTOCOL_LPR:
9689 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9693 return WERR_UNKNOWN_PORT;
9696 return add_port_hook( token, port1.name, device_uri );
9699 /*******************************************************************
9700 *******************************************************************/
9702 struct xcv_api_table xcvtcp_cmds[] = {
9703 { "MonitorUI", xcvtcp_monitorui },
9704 { "AddPort", xcvtcp_addport},
9708 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9709 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9714 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9716 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9717 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9718 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9721 return WERR_BADFUNC;
9724 /*******************************************************************
9725 *******************************************************************/
9726 #if 0 /* don't support management using the "Local Port" monitor */
9728 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9729 RPC_BUFFER *out, uint32 *needed )
9731 const char *dllname = "localui.dll";
9733 *needed = (strlen(dllname)+1) * 2;
9735 if ( rpcbuf_get_size(out) < *needed ) {
9736 return WERR_INSUFFICIENT_BUFFER;
9739 if ( !make_monitorui_buf( out, dllname )) {
9746 /*******************************************************************
9747 *******************************************************************/
9749 struct xcv_api_table xcvlocal_cmds[] = {
9750 { "MonitorUI", xcvlocal_monitorui },
9754 struct xcv_api_table xcvlocal_cmds[] = {
9761 /*******************************************************************
9762 *******************************************************************/
9764 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9765 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9770 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9772 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9773 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9774 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9776 return WERR_BADFUNC;
9779 /*******************************************************************
9780 *******************************************************************/
9782 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9784 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9788 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9792 /* Has to be a handle to the TCP/IP port monitor */
9794 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9795 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9799 /* requires administrative access to the server */
9801 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9802 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9803 return WERR_ACCESS_DENIED;
9806 /* Get the command name. There's numerous commands supported by the
9807 TCPMON interface. */
9809 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9810 q_u->dataname.uni_str_len*2, 0);
9812 /* Allocate the outgoing buffer */
9814 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9816 switch ( Printer->printer_type ) {
9817 case SPLHND_PORTMON_TCP:
9818 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9819 &q_u->indata, &r_u->outdata, &r_u->needed );
9820 case SPLHND_PORTMON_LOCAL:
9821 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9822 &q_u->indata, &r_u->outdata, &r_u->needed );
9825 return WERR_INVALID_PRINT_MONITOR;