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;
5991 /* Check the user has permissions to change the security
5992 descriptor. By experimentation with two NT machines, the user
5993 requires Full Access to the printer to change security
5996 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5997 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5998 result = WERR_ACCESS_DENIED;
6002 /* NT seems to like setting the security descriptor even though
6003 nothing may have actually changed. */
6005 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
6007 if (DEBUGLEVEL >= 10) {
6011 the_acl = old_secdesc_ctr->sd->dacl;
6012 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6013 PRINTERNAME(snum), the_acl->num_aces));
6015 for (i = 0; i < the_acl->num_aces; i++) {
6018 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6020 DEBUG(10, ("%s 0x%08x\n", sid_str,
6021 the_acl->aces[i].access_mask));
6024 the_acl = secdesc_ctr->sd->dacl;
6027 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6028 PRINTERNAME(snum), the_acl->num_aces));
6030 for (i = 0; i < the_acl->num_aces; i++) {
6033 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6035 DEBUG(10, ("%s 0x%08x\n", sid_str,
6036 the_acl->aces[i].access_mask));
6039 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6043 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6044 if (!new_secdesc_ctr) {
6045 result = WERR_NOMEM;
6049 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6054 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6061 /********************************************************************
6062 Canonicalize printer info from a client
6064 ATTN: It does not matter what we set the servername to hear
6065 since we do the necessary work in get_a_printer() to set it to
6066 the correct value based on what the client sent in the
6067 _spoolss_open_printer_ex().
6068 ********************************************************************/
6070 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6072 fstring printername;
6075 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6076 "portname=%s drivername=%s comment=%s location=%s\n",
6077 info->servername, info->printername, info->sharename,
6078 info->portname, info->drivername, info->comment, info->location));
6080 /* we force some elements to "correct" values */
6081 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6082 fstrcpy(info->sharename, lp_servicename(snum));
6084 /* check to see if we allow printername != sharename */
6086 if ( lp_force_printername(snum) ) {
6087 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6088 global_myname(), info->sharename );
6091 /* make sure printername is in \\server\printername format */
6093 fstrcpy( printername, info->printername );
6095 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6096 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6100 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6101 global_myname(), p );
6104 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6105 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6112 /****************************************************************************
6113 ****************************************************************************/
6115 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
6117 char *cmd = lp_addport_cmd();
6121 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6122 BOOL is_print_op = False;
6125 return WERR_ACCESS_DENIED;
6128 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
6131 is_print_op = user_has_privileges( token, &se_printop );
6133 DEBUG(10,("Running [%s]\n", command));
6135 /********* BEGIN SePrintOperatorPrivilege **********/
6140 ret = smbrun(command, &fd);
6145 /********* END SePrintOperatorPrivilege **********/
6147 DEBUGADD(10,("returned [%d]\n", ret));
6152 return WERR_ACCESS_DENIED;
6158 /****************************************************************************
6159 ****************************************************************************/
6161 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6163 char *cmd = lp_addprinter_cmd();
6169 fstring remote_machine = "%m";
6170 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6171 BOOL is_print_op = False;
6173 standard_sub_basic(current_user_info.smb_name,
6174 current_user_info.domain,
6175 remote_machine,sizeof(remote_machine));
6177 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6178 cmd, printer->info_2->printername, printer->info_2->sharename,
6179 printer->info_2->portname, printer->info_2->drivername,
6180 printer->info_2->location, printer->info_2->comment, remote_machine);
6183 is_print_op = user_has_privileges( token, &se_printop );
6185 DEBUG(10,("Running [%s]\n", command));
6187 /********* BEGIN SePrintOperatorPrivilege **********/
6192 if ( (ret = smbrun(command, &fd)) == 0 ) {
6193 /* Tell everyone we updated smb.conf. */
6194 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6200 /********* END SePrintOperatorPrivilege **********/
6202 DEBUGADD(10,("returned [%d]\n", ret));
6210 /* reload our services immediately */
6211 reload_services( False );
6214 /* Get lines and convert them back to dos-codepage */
6215 qlines = fd_lines_load(fd, &numlines, 0);
6216 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6219 /* Set the portname to what the script says the portname should be. */
6220 /* but don't require anything to be return from the script exit a good error code */
6223 /* Set the portname to what the script says the portname should be. */
6224 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6225 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6228 file_lines_free(qlines);
6233 /********************************************************************
6234 * Called by spoolss_api_setprinter
6235 * when updating a printer description.
6236 ********************************************************************/
6238 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6239 const SPOOL_PRINTER_INFO_LEVEL *info,
6240 DEVICEMODE *devmode)
6243 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6244 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6249 DEBUG(8,("update_printer\n"));
6254 result = WERR_BADFID;
6258 if (!get_printer_snum(p, handle, &snum, NULL)) {
6259 result = WERR_BADFID;
6263 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6264 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6265 result = WERR_BADFID;
6269 DEBUGADD(8,("Converting info_2 struct\n"));
6272 * convert_printer_info converts the incoming
6273 * info from the client and overwrites the info
6274 * just read from the tdb in the pointer 'printer'.
6277 if (!convert_printer_info(info, printer, level)) {
6278 result = WERR_NOMEM;
6283 /* we have a valid devmode
6284 convert it and link it*/
6286 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6287 if (!convert_devicemode(printer->info_2->printername, devmode,
6288 &printer->info_2->devmode)) {
6289 result = WERR_NOMEM;
6294 /* Do sanity check on the requested changes for Samba */
6296 if (!check_printer_ok(printer->info_2, snum)) {
6297 result = WERR_INVALID_PARAM;
6301 /* FIXME!!! If the driver has changed we really should verify that
6302 it is installed before doing much else --jerry */
6304 /* Check calling user has permission to update printer description */
6306 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6307 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6308 result = WERR_ACCESS_DENIED;
6312 /* Call addprinter hook */
6313 /* Check changes to see if this is really needed */
6315 if ( *lp_addprinter_cmd()
6316 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6317 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6318 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6319 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6321 /* add_printer_hook() will call reload_services() */
6323 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6324 result = WERR_ACCESS_DENIED;
6330 * When a *new* driver is bound to a printer, the drivername is used to
6331 * lookup previously saved driver initialization info, which is then
6332 * bound to the printer, simulating what happens in the Windows arch.
6334 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6336 if (!set_driver_init(printer, 2))
6338 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6339 printer->info_2->drivername));
6342 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6343 printer->info_2->drivername));
6345 notify_printer_driver(snum, printer->info_2->drivername);
6349 * flag which changes actually occured. This is a small subset of
6350 * all the possible changes. We also have to update things in the
6354 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6355 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6356 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6357 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6359 notify_printer_comment(snum, printer->info_2->comment);
6362 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6363 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6364 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6365 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6367 notify_printer_sharename(snum, printer->info_2->sharename);
6370 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6373 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6376 pname = printer->info_2->printername;
6379 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6380 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6381 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6383 notify_printer_printername( snum, pname );
6386 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6387 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6388 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6389 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6391 notify_printer_port(snum, printer->info_2->portname);
6394 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6395 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6396 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6397 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6399 notify_printer_location(snum, printer->info_2->location);
6402 /* here we need to update some more DsSpooler keys */
6403 /* uNCName, serverName, shortServerName */
6405 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6406 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6407 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6408 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6409 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6411 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6412 global_myname(), printer->info_2->sharename );
6413 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6414 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6415 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6417 /* Update printer info */
6418 result = mod_a_printer(printer, 2);
6421 free_a_printer(&printer, 2);
6422 free_a_printer(&old_printer, 2);
6428 /****************************************************************************
6429 ****************************************************************************/
6430 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6431 const SPOOL_PRINTER_INFO_LEVEL *info)
6434 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6436 Printer_entry *Printer;
6438 if ( lp_security() != SEC_ADS ) {
6439 return WERR_UNKNOWN_LEVEL;
6442 Printer = find_printer_index_by_hnd(p, handle);
6444 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6449 if (!get_printer_snum(p, handle, &snum, NULL))
6452 nt_printer_publish(Printer, snum, info7->action);
6456 return WERR_UNKNOWN_LEVEL;
6459 /****************************************************************************
6460 ****************************************************************************/
6462 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6464 POLICY_HND *handle = &q_u->handle;
6465 uint32 level = q_u->level;
6466 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6467 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6468 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6469 uint32 command = q_u->command;
6472 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6475 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6479 /* check the level */
6482 return control_printer(handle, command, p);
6484 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6485 if (!W_ERROR_IS_OK(result))
6488 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6491 return update_printer_sec(handle, level, info, p,
6494 return publish_or_unpublish_printer(p, handle, info);
6496 return WERR_UNKNOWN_LEVEL;
6500 /****************************************************************************
6501 ****************************************************************************/
6503 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6505 POLICY_HND *handle = &q_u->handle;
6506 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6509 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6513 if (Printer->notify.client_connected==True) {
6516 if ( Printer->printer_type == SPLHND_SERVER)
6518 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6519 !get_printer_snum(p, handle, &snum, NULL) )
6522 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6525 Printer->notify.flags=0;
6526 Printer->notify.options=0;
6527 Printer->notify.localmachine[0]='\0';
6528 Printer->notify.printerlocal=0;
6529 if (Printer->notify.option)
6530 free_spool_notify_option(&Printer->notify.option);
6531 Printer->notify.client_connected=False;
6536 /****************************************************************************
6537 ****************************************************************************/
6539 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6541 /* that's an [in out] buffer */
6543 if (!q_u->buffer && (q_u->offered!=0)) {
6544 return WERR_INVALID_PARAM;
6547 rpcbuf_move(q_u->buffer, &r_u->buffer);
6550 return WERR_INVALID_PARAM; /* this is what a NT server
6551 returns for AddJob. AddJob
6552 must fail on non-local
6556 /****************************************************************************
6557 ****************************************************************************/
6559 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6560 int position, int snum,
6561 const NT_PRINTER_INFO_LEVEL *ntprinter)
6565 t=gmtime(&queue->time);
6567 job_info->jobid=queue->job;
6568 init_unistr(&job_info->printername, lp_servicename(snum));
6569 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6570 init_unistr(&job_info->username, queue->fs_user);
6571 init_unistr(&job_info->document, queue->fs_file);
6572 init_unistr(&job_info->datatype, "RAW");
6573 init_unistr(&job_info->text_status, "");
6574 job_info->status=nt_printj_status(queue->status);
6575 job_info->priority=queue->priority;
6576 job_info->position=position;
6577 job_info->totalpages=queue->page_count;
6578 job_info->pagesprinted=0;
6580 make_systemtime(&job_info->submitted, t);
6583 /****************************************************************************
6584 ****************************************************************************/
6586 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6587 int position, int snum,
6588 const NT_PRINTER_INFO_LEVEL *ntprinter,
6589 DEVICEMODE *devmode)
6593 t=gmtime(&queue->time);
6595 job_info->jobid=queue->job;
6597 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6599 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6600 init_unistr(&job_info->username, queue->fs_user);
6601 init_unistr(&job_info->document, queue->fs_file);
6602 init_unistr(&job_info->notifyname, queue->fs_user);
6603 init_unistr(&job_info->datatype, "RAW");
6604 init_unistr(&job_info->printprocessor, "winprint");
6605 init_unistr(&job_info->parameters, "");
6606 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6607 init_unistr(&job_info->text_status, "");
6609 /* and here the security descriptor */
6611 job_info->status=nt_printj_status(queue->status);
6612 job_info->priority=queue->priority;
6613 job_info->position=position;
6614 job_info->starttime=0;
6615 job_info->untiltime=0;
6616 job_info->totalpages=queue->page_count;
6617 job_info->size=queue->size;
6618 make_systemtime(&(job_info->submitted), t);
6619 job_info->timeelapsed=0;
6620 job_info->pagesprinted=0;
6622 job_info->devmode = devmode;
6627 /****************************************************************************
6628 Enumjobs at level 1.
6629 ****************************************************************************/
6631 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6632 const NT_PRINTER_INFO_LEVEL *ntprinter,
6633 RPC_BUFFER *buffer, uint32 offered,
6634 uint32 *needed, uint32 *returned)
6638 WERROR result = WERR_OK;
6640 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6646 for (i=0; i<*returned; i++)
6647 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6649 /* check the required size. */
6650 for (i=0; i<*returned; i++)
6651 (*needed) += spoolss_size_job_info_1(&info[i]);
6653 if (*needed > offered) {
6654 result = WERR_INSUFFICIENT_BUFFER;
6658 if (!rpcbuf_alloc_size(buffer, *needed)) {
6659 result = WERR_NOMEM;
6663 /* fill the buffer with the structures */
6664 for (i=0; i<*returned; i++)
6665 smb_io_job_info_1("", buffer, &info[i], 0);
6671 if ( !W_ERROR_IS_OK(result) )
6677 /****************************************************************************
6678 Enumjobs at level 2.
6679 ****************************************************************************/
6681 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6682 const NT_PRINTER_INFO_LEVEL *ntprinter,
6683 RPC_BUFFER *buffer, uint32 offered,
6684 uint32 *needed, uint32 *returned)
6686 JOB_INFO_2 *info = NULL;
6688 WERROR result = WERR_OK;
6689 DEVICEMODE *devmode = NULL;
6691 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6696 /* this should not be a failure condition if the devmode is NULL */
6698 devmode = construct_dev_mode(lp_const_servicename(snum));
6700 for (i=0; i<*returned; i++)
6701 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6703 /* check the required size. */
6704 for (i=0; i<*returned; i++)
6705 (*needed) += spoolss_size_job_info_2(&info[i]);
6707 if (*needed > offered) {
6708 result = WERR_INSUFFICIENT_BUFFER;
6712 if (!rpcbuf_alloc_size(buffer, *needed)) {
6713 result = WERR_NOMEM;
6717 /* fill the buffer with the structures */
6718 for (i=0; i<*returned; i++)
6719 smb_io_job_info_2("", buffer, &info[i], 0);
6722 free_devmode(devmode);
6725 if ( !W_ERROR_IS_OK(result) )
6732 /****************************************************************************
6734 ****************************************************************************/
6736 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6738 POLICY_HND *handle = &q_u->handle;
6739 uint32 level = q_u->level;
6740 RPC_BUFFER *buffer = NULL;
6741 uint32 offered = q_u->offered;
6742 uint32 *needed = &r_u->needed;
6743 uint32 *returned = &r_u->returned;
6745 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6747 print_status_struct prt_status;
6748 print_queue_struct *queue=NULL;
6750 /* that's an [in out] buffer */
6752 if (!q_u->buffer && (offered!=0)) {
6753 return WERR_INVALID_PARAM;
6756 rpcbuf_move(q_u->buffer, &r_u->buffer);
6757 buffer = r_u->buffer;
6759 DEBUG(4,("_spoolss_enumjobs\n"));
6764 /* lookup the printer snum and tdb entry */
6766 if (!get_printer_snum(p, handle, &snum, NULL))
6769 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6770 if ( !W_ERROR_IS_OK(wret) )
6773 *returned = print_queue_status(snum, &queue, &prt_status);
6774 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6776 if (*returned == 0) {
6778 free_a_printer(&ntprinter, 2);
6784 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6787 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6791 wret = WERR_UNKNOWN_LEVEL;
6796 free_a_printer( &ntprinter, 2 );
6800 /****************************************************************************
6801 ****************************************************************************/
6803 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6808 /****************************************************************************
6809 ****************************************************************************/
6811 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6813 POLICY_HND *handle = &q_u->handle;
6814 uint32 jobid = q_u->jobid;
6815 uint32 command = q_u->command;
6818 WERROR errcode = WERR_BADFUNC;
6820 if (!get_printer_snum(p, handle, &snum, NULL)) {
6824 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6825 return WERR_INVALID_PRINTER_NAME;
6829 case JOB_CONTROL_CANCEL:
6830 case JOB_CONTROL_DELETE:
6831 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6835 case JOB_CONTROL_PAUSE:
6836 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6840 case JOB_CONTROL_RESTART:
6841 case JOB_CONTROL_RESUME:
6842 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6847 return WERR_UNKNOWN_LEVEL;
6853 /****************************************************************************
6854 Enumerates all printer drivers at level 1.
6855 ****************************************************************************/
6857 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6862 fstring *list = NULL;
6863 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6864 DRIVER_INFO_1 *driver_info_1=NULL;
6865 WERROR result = WERR_OK;
6869 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6871 ndrivers=get_ntdrivers(&list, architecture, version);
6872 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6874 if(ndrivers == -1) {
6875 SAFE_FREE(driver_info_1);
6880 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6881 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6887 for (i=0; i<ndrivers; i++) {
6889 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6890 ZERO_STRUCT(driver);
6891 status = get_a_printer_driver(&driver, 3, list[i],
6892 architecture, version);
6893 if (!W_ERROR_IS_OK(status)) {
6895 SAFE_FREE(driver_info_1);
6898 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6899 free_a_printer_driver(driver, 3);
6902 *returned+=ndrivers;
6906 /* check the required size. */
6907 for (i=0; i<*returned; i++) {
6908 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6909 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6912 if (*needed > offered) {
6913 result = WERR_INSUFFICIENT_BUFFER;
6917 if (!rpcbuf_alloc_size(buffer, *needed)) {
6918 result = WERR_NOMEM;
6922 /* fill the buffer with the driver structures */
6923 for (i=0; i<*returned; i++) {
6924 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6925 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6929 SAFE_FREE(driver_info_1);
6931 if ( !W_ERROR_IS_OK(result) )
6937 /****************************************************************************
6938 Enumerates all printer drivers at level 2.
6939 ****************************************************************************/
6941 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6946 fstring *list = NULL;
6947 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6948 DRIVER_INFO_2 *driver_info_2=NULL;
6949 WERROR result = WERR_OK;
6953 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6955 ndrivers=get_ntdrivers(&list, architecture, version);
6956 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6958 if(ndrivers == -1) {
6959 SAFE_FREE(driver_info_2);
6964 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6965 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6971 for (i=0; i<ndrivers; i++) {
6974 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6975 ZERO_STRUCT(driver);
6976 status = get_a_printer_driver(&driver, 3, list[i],
6977 architecture, version);
6978 if (!W_ERROR_IS_OK(status)) {
6980 SAFE_FREE(driver_info_2);
6983 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6984 free_a_printer_driver(driver, 3);
6987 *returned+=ndrivers;
6991 /* check the required size. */
6992 for (i=0; i<*returned; i++) {
6993 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6994 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6997 if (*needed > offered) {
6998 result = WERR_INSUFFICIENT_BUFFER;
7002 if (!rpcbuf_alloc_size(buffer, *needed)) {
7003 result = WERR_NOMEM;
7007 /* fill the buffer with the form structures */
7008 for (i=0; i<*returned; i++) {
7009 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7010 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7014 SAFE_FREE(driver_info_2);
7016 if ( !W_ERROR_IS_OK(result) )
7022 /****************************************************************************
7023 Enumerates all printer drivers at level 3.
7024 ****************************************************************************/
7026 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7031 fstring *list = NULL;
7032 DRIVER_INFO_3 *driver_info_3=NULL;
7033 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7034 WERROR result = WERR_OK;
7038 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7040 ndrivers=get_ntdrivers(&list, architecture, version);
7041 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7043 if(ndrivers == -1) {
7044 SAFE_FREE(driver_info_3);
7049 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7050 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7056 for (i=0; i<ndrivers; i++) {
7059 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7060 ZERO_STRUCT(driver);
7061 status = get_a_printer_driver(&driver, 3, list[i],
7062 architecture, version);
7063 if (!W_ERROR_IS_OK(status)) {
7065 SAFE_FREE(driver_info_3);
7068 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7069 free_a_printer_driver(driver, 3);
7072 *returned+=ndrivers;
7076 /* check the required size. */
7077 for (i=0; i<*returned; i++) {
7078 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7079 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7082 if (*needed > offered) {
7083 result = WERR_INSUFFICIENT_BUFFER;
7087 if (!rpcbuf_alloc_size(buffer, *needed)) {
7088 result = WERR_NOMEM;
7092 /* fill the buffer with the driver structures */
7093 for (i=0; i<*returned; i++) {
7094 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7095 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7099 for (i=0; i<*returned; i++) {
7100 SAFE_FREE(driver_info_3[i].dependentfiles);
7103 SAFE_FREE(driver_info_3);
7105 if ( !W_ERROR_IS_OK(result) )
7111 /****************************************************************************
7112 Enumerates all printer drivers.
7113 ****************************************************************************/
7115 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7117 uint32 level = q_u->level;
7118 RPC_BUFFER *buffer = NULL;
7119 uint32 offered = q_u->offered;
7120 uint32 *needed = &r_u->needed;
7121 uint32 *returned = &r_u->returned;
7124 fstring architecture;
7126 /* that's an [in out] buffer */
7128 if (!q_u->buffer && (offered!=0)) {
7129 return WERR_INVALID_PARAM;
7132 rpcbuf_move(q_u->buffer, &r_u->buffer);
7133 buffer = r_u->buffer;
7135 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7140 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7141 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7143 if ( !is_myname_or_ipaddr( servername ) )
7144 return WERR_UNKNOWN_PRINTER_DRIVER;
7148 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7150 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7152 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7154 return WERR_UNKNOWN_LEVEL;
7158 /****************************************************************************
7159 ****************************************************************************/
7161 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7163 form->flag=list->flag;
7164 init_unistr(&form->name, list->name);
7165 form->width=list->width;
7166 form->length=list->length;
7167 form->left=list->left;
7168 form->top=list->top;
7169 form->right=list->right;
7170 form->bottom=list->bottom;
7173 /****************************************************************************
7174 ****************************************************************************/
7176 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7178 uint32 level = q_u->level;
7179 RPC_BUFFER *buffer = NULL;
7180 uint32 offered = q_u->offered;
7181 uint32 *needed = &r_u->needed;
7182 uint32 *numofforms = &r_u->numofforms;
7183 uint32 numbuiltinforms;
7185 nt_forms_struct *list=NULL;
7186 nt_forms_struct *builtinlist=NULL;
7191 /* that's an [in out] buffer */
7193 if (!q_u->buffer && (offered!=0) ) {
7194 return WERR_INVALID_PARAM;
7197 rpcbuf_move(q_u->buffer, &r_u->buffer);
7198 buffer = r_u->buffer;
7200 DEBUG(4,("_spoolss_enumforms\n"));
7201 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7202 DEBUGADD(5,("Info level [%d]\n", level));
7204 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7205 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7206 *numofforms = get_ntforms(&list);
7207 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7208 *numofforms += numbuiltinforms;
7210 if (*numofforms == 0) {
7211 SAFE_FREE(builtinlist);
7213 return WERR_NO_MORE_ITEMS;
7218 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7219 SAFE_FREE(builtinlist);
7225 /* construct the list of form structures */
7226 for (i=0; i<numbuiltinforms; i++) {
7227 DEBUGADD(6,("Filling form number [%d]\n",i));
7228 fill_form_1(&forms_1[i], &builtinlist[i]);
7231 SAFE_FREE(builtinlist);
7233 for (; i<*numofforms; i++) {
7234 DEBUGADD(6,("Filling form number [%d]\n",i));
7235 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7240 /* check the required size. */
7241 for (i=0; i<numbuiltinforms; i++) {
7242 DEBUGADD(6,("adding form [%d]'s size\n",i));
7243 buffer_size += spoolss_size_form_1(&forms_1[i]);
7245 for (; i<*numofforms; i++) {
7246 DEBUGADD(6,("adding form [%d]'s size\n",i));
7247 buffer_size += spoolss_size_form_1(&forms_1[i]);
7250 *needed=buffer_size;
7252 if (*needed > offered) {
7255 return WERR_INSUFFICIENT_BUFFER;
7258 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7264 /* fill the buffer with the form structures */
7265 for (i=0; i<numbuiltinforms; i++) {
7266 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7267 smb_io_form_1("", buffer, &forms_1[i], 0);
7269 for (; i<*numofforms; i++) {
7270 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7271 smb_io_form_1("", buffer, &forms_1[i], 0);
7280 SAFE_FREE(builtinlist);
7281 return WERR_UNKNOWN_LEVEL;
7285 /****************************************************************************
7286 ****************************************************************************/
7288 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7290 uint32 level = q_u->level;
7291 UNISTR2 *uni_formname = &q_u->formname;
7292 RPC_BUFFER *buffer = NULL;
7293 uint32 offered = q_u->offered;
7294 uint32 *needed = &r_u->needed;
7296 nt_forms_struct *list=NULL;
7297 nt_forms_struct builtin_form;
7302 int numofforms=0, i=0;
7304 /* that's an [in out] buffer */
7306 if (!q_u->buffer && (offered!=0)) {
7307 return WERR_INVALID_PARAM;
7310 rpcbuf_move(q_u->buffer, &r_u->buffer);
7311 buffer = r_u->buffer;
7313 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7315 DEBUG(4,("_spoolss_getform\n"));
7316 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7317 DEBUGADD(5,("Info level [%d]\n", level));
7319 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7320 if (!foundBuiltin) {
7321 numofforms = get_ntforms(&list);
7322 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7324 if (numofforms == 0)
7331 fill_form_1(&form_1, &builtin_form);
7334 /* Check if the requested name is in the list of form structures */
7335 for (i=0; i<numofforms; i++) {
7337 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7339 if (strequal(form_name, list[i].name)) {
7340 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7341 fill_form_1(&form_1, &list[i]);
7347 if (i == numofforms) {
7351 /* check the required size. */
7353 *needed=spoolss_size_form_1(&form_1);
7355 if (*needed > offered)
7356 return WERR_INSUFFICIENT_BUFFER;
7358 if (!rpcbuf_alloc_size(buffer, buffer_size))
7361 /* fill the buffer with the form structures */
7362 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7363 smb_io_form_1("", buffer, &form_1, 0);
7369 return WERR_UNKNOWN_LEVEL;
7373 /****************************************************************************
7374 ****************************************************************************/
7376 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7378 init_unistr(&port->port_name, name);
7381 /****************************************************************************
7382 TODO: This probably needs distinguish between TCP/IP and Local ports
7384 ****************************************************************************/
7386 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7388 init_unistr(&port->port_name, name);
7389 init_unistr(&port->monitor_name, "Local Monitor");
7390 init_unistr(&port->description, SPL_LOCAL_PORT );
7391 port->port_type=PORT_TYPE_WRITE;
7396 /****************************************************************************
7397 wrapper around the enumer ports command
7398 ****************************************************************************/
7400 WERROR enumports_hook( int *count, char ***lines )
7402 char *cmd = lp_enumports_cmd();
7412 /* if no hook then just fill in the default port */
7415 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7416 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7421 /* we have a valid enumport command */
7423 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7425 DEBUG(10,("Running [%s]\n", command));
7426 ret = smbrun(command, &fd);
7427 DEBUG(10,("Returned [%d]\n", ret));
7432 return WERR_ACCESS_DENIED;
7436 qlines = fd_lines_load(fd, &numlines, 0);
7437 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7447 /****************************************************************************
7449 ****************************************************************************/
7451 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7453 PORT_INFO_1 *ports=NULL;
7455 WERROR result = WERR_OK;
7456 char **qlines = NULL;
7459 result = enumports_hook( &numlines, &qlines );
7460 if (!W_ERROR_IS_OK(result)) {
7461 file_lines_free(qlines);
7466 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7467 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7468 dos_errstr(WERR_NOMEM)));
7469 file_lines_free(qlines);
7473 for (i=0; i<numlines; i++) {
7474 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7475 fill_port_1(&ports[i], qlines[i]);
7478 file_lines_free(qlines);
7480 *returned = numlines;
7482 /* check the required size. */
7483 for (i=0; i<*returned; i++) {
7484 DEBUGADD(6,("adding port [%d]'s size\n", i));
7485 *needed += spoolss_size_port_info_1(&ports[i]);
7488 if (*needed > offered) {
7489 result = WERR_INSUFFICIENT_BUFFER;
7493 if (!rpcbuf_alloc_size(buffer, *needed)) {
7494 result = WERR_NOMEM;
7498 /* fill the buffer with the ports structures */
7499 for (i=0; i<*returned; i++) {
7500 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7501 smb_io_port_1("", buffer, &ports[i], 0);
7507 if ( !W_ERROR_IS_OK(result) )
7513 /****************************************************************************
7515 ****************************************************************************/
7517 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7519 PORT_INFO_2 *ports=NULL;
7521 WERROR result = WERR_OK;
7522 char **qlines = NULL;
7525 result = enumports_hook( &numlines, &qlines );
7526 if ( !W_ERROR_IS_OK(result)) {
7527 file_lines_free(qlines);
7532 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7533 file_lines_free(qlines);
7537 for (i=0; i<numlines; i++) {
7538 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7539 fill_port_2(&(ports[i]), qlines[i]);
7543 file_lines_free(qlines);
7545 *returned = numlines;
7547 /* check the required size. */
7548 for (i=0; i<*returned; i++) {
7549 DEBUGADD(6,("adding port [%d]'s size\n", i));
7550 *needed += spoolss_size_port_info_2(&ports[i]);
7553 if (*needed > offered) {
7554 result = WERR_INSUFFICIENT_BUFFER;
7558 if (!rpcbuf_alloc_size(buffer, *needed)) {
7559 result = WERR_NOMEM;
7563 /* fill the buffer with the ports structures */
7564 for (i=0; i<*returned; i++) {
7565 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7566 smb_io_port_2("", buffer, &ports[i], 0);
7572 if ( !W_ERROR_IS_OK(result) )
7578 /****************************************************************************
7580 ****************************************************************************/
7582 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7584 uint32 level = q_u->level;
7585 RPC_BUFFER *buffer = NULL;
7586 uint32 offered = q_u->offered;
7587 uint32 *needed = &r_u->needed;
7588 uint32 *returned = &r_u->returned;
7590 /* that's an [in out] buffer */
7592 if (!q_u->buffer && (offered!=0)) {
7593 return WERR_INVALID_PARAM;
7596 rpcbuf_move(q_u->buffer, &r_u->buffer);
7597 buffer = r_u->buffer;
7599 DEBUG(4,("_spoolss_enumports\n"));
7606 return enumports_level_1(buffer, offered, needed, returned);
7608 return enumports_level_2(buffer, offered, needed, returned);
7610 return WERR_UNKNOWN_LEVEL;
7614 /****************************************************************************
7615 ****************************************************************************/
7617 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7618 const SPOOL_PRINTER_INFO_LEVEL *info,
7619 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7620 uint32 user_switch, const SPOOL_USER_CTR *user,
7623 NT_PRINTER_INFO_LEVEL *printer = NULL;
7626 WERROR err = WERR_OK;
7628 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7629 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7633 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7634 if (!convert_printer_info(info, printer, 2)) {
7635 free_a_printer(&printer, 2);
7639 /* check to see if the printer already exists */
7641 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7642 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7643 printer->info_2->sharename));
7644 free_a_printer(&printer, 2);
7645 return WERR_PRINTER_ALREADY_EXISTS;
7648 /* FIXME!!! smbd should check to see if the driver is installed before
7649 trying to add a printer like this --jerry */
7651 if (*lp_addprinter_cmd() ) {
7652 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7653 free_a_printer(&printer,2);
7654 return WERR_ACCESS_DENIED;
7657 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7658 "smb.conf parameter \"addprinter command\" is defined. This"
7659 "parameter must exist for this call to succeed\n",
7660 printer->info_2->sharename ));
7663 /* use our primary netbios name since get_a_printer() will convert
7664 it to what the client expects on a case by case basis */
7666 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7667 printer->info_2->sharename);
7670 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7671 free_a_printer(&printer,2);
7672 return WERR_ACCESS_DENIED;
7675 /* you must be a printer admin to add a new printer */
7676 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7677 free_a_printer(&printer,2);
7678 return WERR_ACCESS_DENIED;
7682 * Do sanity check on the requested changes for Samba.
7685 if (!check_printer_ok(printer->info_2, snum)) {
7686 free_a_printer(&printer,2);
7687 return WERR_INVALID_PARAM;
7691 * When a printer is created, the drivername bound to the printer is used
7692 * to lookup previously saved driver initialization info, which is then
7693 * bound to the new printer, simulating what happens in the Windows arch.
7698 set_driver_init(printer, 2);
7702 /* A valid devmode was included, convert and link it
7704 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7706 if (!convert_devicemode(printer->info_2->printername, devmode,
7707 &printer->info_2->devmode))
7711 /* write the ASCII on disk */
7712 err = mod_a_printer(printer, 2);
7713 if (!W_ERROR_IS_OK(err)) {
7714 free_a_printer(&printer,2);
7718 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7719 /* Handle open failed - remove addition. */
7720 del_a_printer(printer->info_2->sharename);
7721 free_a_printer(&printer,2);
7722 return WERR_ACCESS_DENIED;
7725 update_c_setprinter(False);
7726 free_a_printer(&printer,2);
7731 /****************************************************************************
7732 ****************************************************************************/
7734 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7736 UNISTR2 *uni_srv_name = q_u->server_name;
7737 uint32 level = q_u->level;
7738 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7739 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7740 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7741 uint32 user_switch = q_u->user_switch;
7742 SPOOL_USER_CTR *user = &q_u->user_ctr;
7743 POLICY_HND *handle = &r_u->handle;
7747 /* we don't handle yet */
7748 /* but I know what to do ... */
7749 return WERR_UNKNOWN_LEVEL;
7751 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7753 user_switch, user, handle);
7755 return WERR_UNKNOWN_LEVEL;
7759 /****************************************************************************
7760 ****************************************************************************/
7762 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7764 uint32 level = q_u->level;
7765 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7766 WERROR err = WERR_OK;
7767 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7768 fstring driver_name;
7771 ZERO_STRUCT(driver);
7773 if (!convert_printer_driver_info(info, &driver, level)) {
7778 DEBUG(5,("Cleaning driver's information\n"));
7779 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7780 if (!W_ERROR_IS_OK(err))
7783 DEBUG(5,("Moving driver to final destination\n"));
7784 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7788 if (add_a_printer_driver(driver, level)!=0) {
7789 err = WERR_ACCESS_DENIED;
7794 * I think this is where he DrvUpgradePrinter() hook would be
7795 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7796 * server. Right now, we just need to send ourselves a message
7797 * to update each printer bound to this driver. --jerry
7800 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7801 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7806 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7807 * decide if the driver init data should be deleted. The rules are:
7808 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7809 * 2) delete init data only if there is no 2k/Xp driver
7810 * 3) always delete init data
7811 * The generalized rule is always use init data from the highest order driver.
7812 * It is necessary to follow the driver install by an initialization step to
7813 * finish off this process.
7816 version = driver.info_3->cversion;
7817 else if (level == 6)
7818 version = driver.info_6->version;
7823 * 9x printer driver - never delete init data
7826 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7831 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7832 * there is no 2k/Xp driver init data for this driver name.
7836 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7838 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7840 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7842 if (!del_driver_init(driver_name))
7843 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7846 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7848 free_a_printer_driver(driver1,3);
7849 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7856 * 2k or Xp printer driver - always delete init data
7859 if (!del_driver_init(driver_name))
7860 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7864 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7870 free_a_printer_driver(driver, level);
7874 /********************************************************************
7875 * spoolss_addprinterdriverex
7876 ********************************************************************/
7878 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7880 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7881 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7884 * we only support the semantics of AddPrinterDriver()
7885 * i.e. only copy files that are newer than existing ones
7888 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7889 return WERR_ACCESS_DENIED;
7891 ZERO_STRUCT(q_u_local);
7892 ZERO_STRUCT(r_u_local);
7894 /* just pass the information off to _spoolss_addprinterdriver() */
7895 q_u_local.server_name_ptr = q_u->server_name_ptr;
7896 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7897 q_u_local.level = q_u->level;
7898 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7900 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7903 /****************************************************************************
7904 ****************************************************************************/
7906 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7908 init_unistr(&info->name, name);
7911 /****************************************************************************
7912 ****************************************************************************/
7914 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7920 const char *short_archi;
7921 DRIVER_DIRECTORY_1 *info=NULL;
7922 WERROR result = WERR_OK;
7924 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7925 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7927 /* check for beginning double '\'s and that the server
7930 pservername = servername;
7931 if ( *pservername == '\\' && strlen(servername)>2 ) {
7935 if ( !is_myname_or_ipaddr( pservername ) )
7936 return WERR_INVALID_PARAM;
7938 if (!(short_archi = get_short_archi(long_archi)))
7939 return WERR_INVALID_ENVIRONMENT;
7941 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7944 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7946 DEBUG(4,("printer driver directory: [%s]\n", path));
7948 fill_driverdir_1(info, path);
7950 *needed += spoolss_size_driverdir_info_1(info);
7952 if (*needed > offered) {
7953 result = WERR_INSUFFICIENT_BUFFER;
7957 if (!rpcbuf_alloc_size(buffer, *needed)) {
7958 result = WERR_NOMEM;
7962 smb_io_driverdir_1("", buffer, info, 0);
7970 /****************************************************************************
7971 ****************************************************************************/
7973 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7975 UNISTR2 *name = &q_u->name;
7976 UNISTR2 *uni_environment = &q_u->environment;
7977 uint32 level = q_u->level;
7978 RPC_BUFFER *buffer = NULL;
7979 uint32 offered = q_u->offered;
7980 uint32 *needed = &r_u->needed;
7982 /* that's an [in out] buffer */
7984 if (!q_u->buffer && (offered!=0)) {
7985 return WERR_INVALID_PARAM;
7988 rpcbuf_move(q_u->buffer, &r_u->buffer);
7989 buffer = r_u->buffer;
7991 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7997 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7999 return WERR_UNKNOWN_LEVEL;
8003 /****************************************************************************
8004 ****************************************************************************/
8006 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8008 POLICY_HND *handle = &q_u->handle;
8009 uint32 idx = q_u->index;
8010 uint32 in_value_len = q_u->valuesize;
8011 uint32 in_data_len = q_u->datasize;
8012 uint32 *out_max_value_len = &r_u->valuesize;
8013 uint16 **out_value = &r_u->value;
8014 uint32 *out_value_len = &r_u->realvaluesize;
8015 uint32 *out_type = &r_u->type;
8016 uint32 *out_max_data_len = &r_u->datasize;
8017 uint8 **data_out = &r_u->data;
8018 uint32 *out_data_len = &r_u->realdatasize;
8020 NT_PRINTER_INFO_LEVEL *printer = NULL;
8022 uint32 biggest_valuesize;
8023 uint32 biggest_datasize;
8025 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8028 REGISTRY_VALUE *val = NULL;
8029 NT_PRINTER_DATA *p_data;
8030 int i, key_index, num_values;
8035 *out_max_data_len = 0;
8039 DEBUG(5,("spoolss_enumprinterdata\n"));
8042 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8046 if (!get_printer_snum(p,handle, &snum, NULL))
8049 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8050 if (!W_ERROR_IS_OK(result))
8053 p_data = printer->info_2->data;
8054 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8059 * The NT machine wants to know the biggest size of value and data
8061 * cf: MSDN EnumPrinterData remark section
8064 if ( !in_value_len && !in_data_len && (key_index != -1) )
8066 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8068 biggest_valuesize = 0;
8069 biggest_datasize = 0;
8071 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8073 for ( i=0; i<num_values; i++ )
8075 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8077 name_length = strlen(val->valuename);
8078 if ( strlen(val->valuename) > biggest_valuesize )
8079 biggest_valuesize = name_length;
8081 if ( val->size > biggest_datasize )
8082 biggest_datasize = val->size;
8084 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8088 /* the value is an UNICODE string but real_value_size is the length
8089 in bytes including the trailing 0 */
8091 *out_value_len = 2 * (1+biggest_valuesize);
8092 *out_data_len = biggest_datasize;
8094 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8100 * the value len is wrong in NT sp3
8101 * that's the number of bytes not the number of unicode chars
8104 if ( key_index != -1 )
8105 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8110 /* out_value should default to "" or else NT4 has
8111 problems unmarshalling the response */
8113 *out_max_value_len=(in_value_len/sizeof(uint16));
8115 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8117 result = WERR_NOMEM;
8121 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8123 /* the data is counted in bytes */
8125 *out_max_data_len = in_data_len;
8126 *out_data_len = in_data_len;
8128 /* only allocate when given a non-zero data_len */
8130 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8132 result = WERR_NOMEM;
8136 result = WERR_NO_MORE_ITEMS;
8142 * - counted in bytes in the request
8143 * - counted in UNICODE chars in the max reply
8144 * - counted in bytes in the real size
8146 * take a pause *before* coding not *during* coding
8150 *out_max_value_len=(in_value_len/sizeof(uint16));
8151 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8153 result = WERR_NOMEM;
8157 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8161 *out_type = regval_type( val );
8163 /* data - counted in bytes */
8165 *out_max_data_len = in_data_len;
8166 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8168 result = WERR_NOMEM;
8171 data_len = regval_size(val);
8173 memcpy( *data_out, regval_data_p(val), data_len );
8174 *out_data_len = data_len;
8178 free_a_printer(&printer, 2);
8182 /****************************************************************************
8183 ****************************************************************************/
8185 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8187 POLICY_HND *handle = &q_u->handle;
8188 UNISTR2 *value = &q_u->value;
8189 uint32 type = q_u->type;
8190 uint8 *data = q_u->data;
8191 uint32 real_len = q_u->real_len;
8193 NT_PRINTER_INFO_LEVEL *printer = NULL;
8195 WERROR status = WERR_OK;
8196 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8199 DEBUG(5,("spoolss_setprinterdata\n"));
8202 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8206 if ( Printer->printer_type == SPLHND_SERVER ) {
8207 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8208 return WERR_INVALID_PARAM;
8211 if (!get_printer_snum(p,handle, &snum, NULL))
8215 * Access check : NT returns "access denied" if you make a
8216 * SetPrinterData call without the necessary privildge.
8217 * we were originally returning OK if nothing changed
8218 * which made Win2k issue **a lot** of SetPrinterData
8219 * when connecting to a printer --jerry
8222 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8224 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8225 status = WERR_ACCESS_DENIED;
8229 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8230 if (!W_ERROR_IS_OK(status))
8233 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8236 * When client side code sets a magic printer data key, detect it and save
8237 * the current printer data and the magic key's data (its the DEVMODE) for
8238 * future printer/driver initializations.
8240 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8242 /* Set devmode and printer initialization info */
8243 status = save_driver_init( printer, 2, data, real_len );
8245 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8249 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8250 type, data, real_len );
8251 if ( W_ERROR_IS_OK(status) )
8252 status = mod_a_printer(printer, 2);
8256 free_a_printer(&printer, 2);
8261 /****************************************************************************
8262 ****************************************************************************/
8264 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8266 POLICY_HND *handle = &q_u->handle;
8267 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8270 DEBUG(5,("_spoolss_resetprinter\n"));
8273 * All we do is to check to see if the handle and queue is valid.
8274 * This call really doesn't mean anything to us because we only
8275 * support RAW printing. --jerry
8279 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8283 if (!get_printer_snum(p,handle, &snum, NULL))
8287 /* blindly return success */
8292 /****************************************************************************
8293 ****************************************************************************/
8295 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8297 POLICY_HND *handle = &q_u->handle;
8298 UNISTR2 *value = &q_u->valuename;
8300 NT_PRINTER_INFO_LEVEL *printer = NULL;
8302 WERROR status = WERR_OK;
8303 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8306 DEBUG(5,("spoolss_deleteprinterdata\n"));
8309 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8313 if (!get_printer_snum(p, handle, &snum, NULL))
8316 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8317 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8318 return WERR_ACCESS_DENIED;
8321 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8322 if (!W_ERROR_IS_OK(status))
8325 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8327 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8329 if ( W_ERROR_IS_OK(status) )
8330 mod_a_printer( printer, 2 );
8332 free_a_printer(&printer, 2);
8337 /****************************************************************************
8338 ****************************************************************************/
8340 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8342 POLICY_HND *handle = &q_u->handle;
8343 FORM *form = &q_u->form;
8344 nt_forms_struct tmpForm;
8346 WERROR status = WERR_OK;
8347 NT_PRINTER_INFO_LEVEL *printer = NULL;
8350 nt_forms_struct *list=NULL;
8351 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8353 DEBUG(5,("spoolss_addform\n"));
8356 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8361 /* forms can be added on printer of on the print server handle */
8363 if ( Printer->printer_type == SPLHND_PRINTER )
8365 if (!get_printer_snum(p,handle, &snum, NULL))
8368 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8369 if (!W_ERROR_IS_OK(status))
8373 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8374 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8375 status = WERR_ACCESS_DENIED;
8379 /* can't add if builtin */
8381 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8382 status = WERR_ALREADY_EXISTS;
8386 count = get_ntforms(&list);
8388 if(!add_a_form(&list, form, &count)) {
8389 status = WERR_NOMEM;
8393 write_ntforms(&list, count);
8396 * ChangeID must always be set if this is a printer
8399 if ( Printer->printer_type == SPLHND_PRINTER )
8400 status = mod_a_printer(printer, 2);
8404 free_a_printer(&printer, 2);
8410 /****************************************************************************
8411 ****************************************************************************/
8413 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8415 POLICY_HND *handle = &q_u->handle;
8416 UNISTR2 *form_name = &q_u->name;
8417 nt_forms_struct tmpForm;
8419 nt_forms_struct *list=NULL;
8420 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8422 WERROR status = WERR_OK;
8423 NT_PRINTER_INFO_LEVEL *printer = NULL;
8425 DEBUG(5,("spoolss_deleteform\n"));
8428 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8432 /* forms can be deleted on printer of on the print server handle */
8434 if ( Printer->printer_type == SPLHND_PRINTER )
8436 if (!get_printer_snum(p,handle, &snum, NULL))
8439 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8440 if (!W_ERROR_IS_OK(status))
8444 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8445 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8446 status = WERR_ACCESS_DENIED;
8450 /* can't delete if builtin */
8452 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8453 status = WERR_INVALID_PARAM;
8457 count = get_ntforms(&list);
8459 if ( !delete_a_form(&list, form_name, &count, &status ))
8463 * ChangeID must always be set if this is a printer
8466 if ( Printer->printer_type == SPLHND_PRINTER )
8467 status = mod_a_printer(printer, 2);
8471 free_a_printer(&printer, 2);
8477 /****************************************************************************
8478 ****************************************************************************/
8480 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8482 POLICY_HND *handle = &q_u->handle;
8483 FORM *form = &q_u->form;
8484 nt_forms_struct tmpForm;
8486 WERROR status = WERR_OK;
8487 NT_PRINTER_INFO_LEVEL *printer = NULL;
8490 nt_forms_struct *list=NULL;
8491 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8493 DEBUG(5,("spoolss_setform\n"));
8496 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8500 /* forms can be modified on printer of on the print server handle */
8502 if ( Printer->printer_type == SPLHND_PRINTER )
8504 if (!get_printer_snum(p,handle, &snum, NULL))
8507 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8508 if (!W_ERROR_IS_OK(status))
8512 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8513 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8514 status = WERR_ACCESS_DENIED;
8518 /* can't set if builtin */
8519 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8520 status = WERR_INVALID_PARAM;
8524 count = get_ntforms(&list);
8525 update_a_form(&list, form, count);
8526 write_ntforms(&list, count);
8529 * ChangeID must always be set if this is a printer
8532 if ( Printer->printer_type == SPLHND_PRINTER )
8533 status = mod_a_printer(printer, 2);
8538 free_a_printer(&printer, 2);
8544 /****************************************************************************
8545 enumprintprocessors level 1.
8546 ****************************************************************************/
8548 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8550 PRINTPROCESSOR_1 *info_1=NULL;
8551 WERROR result = WERR_OK;
8553 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8558 init_unistr(&info_1->name, "winprint");
8560 *needed += spoolss_size_printprocessor_info_1(info_1);
8562 if (*needed > offered) {
8563 result = WERR_INSUFFICIENT_BUFFER;
8567 if (!rpcbuf_alloc_size(buffer, *needed)) {
8568 result = WERR_NOMEM;
8572 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8577 if ( !W_ERROR_IS_OK(result) )
8583 /****************************************************************************
8584 ****************************************************************************/
8586 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8588 uint32 level = q_u->level;
8589 RPC_BUFFER *buffer = NULL;
8590 uint32 offered = q_u->offered;
8591 uint32 *needed = &r_u->needed;
8592 uint32 *returned = &r_u->returned;
8594 /* that's an [in out] buffer */
8596 if (!q_u->buffer && (offered!=0)) {
8597 return WERR_INVALID_PARAM;
8600 rpcbuf_move(q_u->buffer, &r_u->buffer);
8601 buffer = r_u->buffer;
8603 DEBUG(5,("spoolss_enumprintprocessors\n"));
8606 * Enumerate the print processors ...
8608 * Just reply with "winprint", to keep NT happy
8609 * and I can use my nice printer checker.
8617 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8619 return WERR_UNKNOWN_LEVEL;
8623 /****************************************************************************
8624 enumprintprocdatatypes level 1.
8625 ****************************************************************************/
8627 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8629 PRINTPROCDATATYPE_1 *info_1=NULL;
8630 WERROR result = WERR_NOMEM;
8632 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8637 init_unistr(&info_1->name, "RAW");
8639 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8641 if (*needed > offered) {
8642 result = WERR_INSUFFICIENT_BUFFER;
8646 if (!rpcbuf_alloc_size(buffer, *needed)) {
8647 result = WERR_NOMEM;
8651 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8656 if ( !W_ERROR_IS_OK(result) )
8662 /****************************************************************************
8663 ****************************************************************************/
8665 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8667 uint32 level = q_u->level;
8668 RPC_BUFFER *buffer = NULL;
8669 uint32 offered = q_u->offered;
8670 uint32 *needed = &r_u->needed;
8671 uint32 *returned = &r_u->returned;
8673 /* that's an [in out] buffer */
8675 if (!q_u->buffer && (offered!=0)) {
8676 return WERR_INVALID_PARAM;
8679 rpcbuf_move(q_u->buffer, &r_u->buffer);
8680 buffer = r_u->buffer;
8682 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8689 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8691 return WERR_UNKNOWN_LEVEL;
8695 /****************************************************************************
8696 enumprintmonitors level 1.
8697 ****************************************************************************/
8699 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8701 PRINTMONITOR_1 *info_1;
8702 WERROR result = WERR_OK;
8705 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8710 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8711 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8713 for ( i=0; i<*returned; i++ ) {
8714 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8717 if (*needed > offered) {
8718 result = WERR_INSUFFICIENT_BUFFER;
8722 if (!rpcbuf_alloc_size(buffer, *needed)) {
8723 result = WERR_NOMEM;
8727 for ( i=0; i<*returned; i++ ) {
8728 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8734 if ( !W_ERROR_IS_OK(result) )
8740 /****************************************************************************
8741 enumprintmonitors level 2.
8742 ****************************************************************************/
8744 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8746 PRINTMONITOR_2 *info_2;
8747 WERROR result = WERR_OK;
8750 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8755 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8756 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8757 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8759 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8760 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8761 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8763 for ( i=0; i<*returned; i++ ) {
8764 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8767 if (*needed > offered) {
8768 result = WERR_INSUFFICIENT_BUFFER;
8772 if (!rpcbuf_alloc_size(buffer, *needed)) {
8773 result = WERR_NOMEM;
8777 for ( i=0; i<*returned; i++ ) {
8778 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8784 if ( !W_ERROR_IS_OK(result) )
8790 /****************************************************************************
8791 ****************************************************************************/
8793 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8795 uint32 level = q_u->level;
8796 RPC_BUFFER *buffer = NULL;
8797 uint32 offered = q_u->offered;
8798 uint32 *needed = &r_u->needed;
8799 uint32 *returned = &r_u->returned;
8801 /* that's an [in out] buffer */
8803 if (!q_u->buffer && (offered!=0)) {
8804 return WERR_INVALID_PARAM;
8807 rpcbuf_move(q_u->buffer, &r_u->buffer);
8808 buffer = r_u->buffer;
8810 DEBUG(5,("spoolss_enumprintmonitors\n"));
8813 * Enumerate the print monitors ...
8815 * Just reply with "Local Port", to keep NT happy
8816 * and I can use my nice printer checker.
8824 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8826 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8828 return WERR_UNKNOWN_LEVEL;
8832 /****************************************************************************
8833 ****************************************************************************/
8835 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8836 NT_PRINTER_INFO_LEVEL *ntprinter,
8837 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8842 JOB_INFO_1 *info_1=NULL;
8843 WERROR result = WERR_OK;
8845 info_1=SMB_MALLOC_P(JOB_INFO_1);
8847 if (info_1 == NULL) {
8851 for (i=0; i<count && found==False; i++) {
8852 if ((*queue)[i].job==(int)jobid)
8858 /* NT treats not found as bad param... yet another bad choice */
8859 return WERR_INVALID_PARAM;
8862 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8864 *needed += spoolss_size_job_info_1(info_1);
8866 if (*needed > offered) {
8867 result = WERR_INSUFFICIENT_BUFFER;
8871 if (!rpcbuf_alloc_size(buffer, *needed)) {
8872 result = WERR_NOMEM;
8876 smb_io_job_info_1("", buffer, info_1, 0);
8884 /****************************************************************************
8885 ****************************************************************************/
8887 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8888 NT_PRINTER_INFO_LEVEL *ntprinter,
8889 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8896 DEVICEMODE *devmode = NULL;
8897 NT_DEVICEMODE *nt_devmode = NULL;
8899 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8902 ZERO_STRUCTP(info_2);
8904 for ( i=0; i<count && found==False; i++ )
8906 if ((*queue)[i].job == (int)jobid)
8911 /* NT treats not found as bad param... yet another bad
8913 result = WERR_INVALID_PARAM;
8918 * if the print job does not have a DEVMODE associated with it,
8919 * just use the one for the printer. A NULL devicemode is not
8920 * a failure condition
8923 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8924 devmode = construct_dev_mode(lp_const_servicename(snum));
8926 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8927 ZERO_STRUCTP( devmode );
8928 convert_nt_devicemode( devmode, nt_devmode );
8932 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8934 *needed += spoolss_size_job_info_2(info_2);
8936 if (*needed > offered) {
8937 result = WERR_INSUFFICIENT_BUFFER;
8941 if (!rpcbuf_alloc_size(buffer, *needed)) {
8942 result = WERR_NOMEM;
8946 smb_io_job_info_2("", buffer, info_2, 0);
8951 /* Cleanup allocated memory */
8953 free_job_info_2(info_2); /* Also frees devmode */
8959 /****************************************************************************
8960 ****************************************************************************/
8962 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8964 POLICY_HND *handle = &q_u->handle;
8965 uint32 jobid = q_u->jobid;
8966 uint32 level = q_u->level;
8967 RPC_BUFFER *buffer = NULL;
8968 uint32 offered = q_u->offered;
8969 uint32 *needed = &r_u->needed;
8970 WERROR wstatus = WERR_OK;
8971 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8974 print_queue_struct *queue = NULL;
8975 print_status_struct prt_status;
8977 /* that's an [in out] buffer */
8979 if (!q_u->buffer && (offered!=0)) {
8980 return WERR_INVALID_PARAM;
8983 rpcbuf_move(q_u->buffer, &r_u->buffer);
8984 buffer = r_u->buffer;
8986 DEBUG(5,("spoolss_getjob\n"));
8990 if (!get_printer_snum(p, handle, &snum, NULL))
8993 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8994 if ( !W_ERROR_IS_OK(wstatus) )
8997 count = print_queue_status(snum, &queue, &prt_status);
8999 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9000 count, prt_status.status, prt_status.message));
9004 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9005 buffer, offered, needed);
9008 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9009 buffer, offered, needed);
9012 wstatus = WERR_UNKNOWN_LEVEL;
9017 free_a_printer( &ntprinter, 2 );
9022 /********************************************************************
9023 spoolss_getprinterdataex
9025 From MSDN documentation of GetPrinterDataEx: pass request
9026 to GetPrinterData if key is "PrinterDriverData".
9027 ********************************************************************/
9029 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9031 POLICY_HND *handle = &q_u->handle;
9032 uint32 in_size = q_u->size;
9033 uint32 *type = &r_u->type;
9034 uint32 *out_size = &r_u->size;
9035 uint8 **data = &r_u->data;
9036 uint32 *needed = &r_u->needed;
9037 fstring keyname, valuename;
9039 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9041 NT_PRINTER_INFO_LEVEL *printer = NULL;
9043 WERROR status = WERR_OK;
9045 DEBUG(4,("_spoolss_getprinterdataex\n"));
9047 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
9048 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
9050 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9051 keyname, valuename));
9053 /* in case of problem, return some default values */
9057 *out_size = in_size;
9060 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9061 status = WERR_BADFID;
9065 /* Is the handle to a printer or to the server? */
9067 if (Printer->printer_type == SPLHND_SERVER) {
9068 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9069 status = WERR_INVALID_PARAM;
9073 if ( !get_printer_snum(p,handle, &snum, NULL) )
9076 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9077 if ( !W_ERROR_IS_OK(status) )
9080 /* check to see if the keyname is valid */
9081 if ( !strlen(keyname) ) {
9082 status = WERR_INVALID_PARAM;
9086 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9087 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9088 free_a_printer( &printer, 2 );
9089 status = WERR_BADFILE;
9093 /* When given a new keyname, we should just create it */
9095 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9097 if (*needed > *out_size)
9098 status = WERR_MORE_DATA;
9101 if ( !W_ERROR_IS_OK(status) )
9103 DEBUG(5, ("error: allocating %d\n", *out_size));
9105 /* reply this param doesn't exist */
9109 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9110 status = WERR_NOMEM;
9120 free_a_printer( &printer, 2 );
9125 /********************************************************************
9126 * spoolss_setprinterdataex
9127 ********************************************************************/
9129 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9131 POLICY_HND *handle = &q_u->handle;
9132 uint32 type = q_u->type;
9133 uint8 *data = q_u->data;
9134 uint32 real_len = q_u->real_len;
9136 NT_PRINTER_INFO_LEVEL *printer = NULL;
9138 WERROR status = WERR_OK;
9139 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9144 DEBUG(4,("_spoolss_setprinterdataex\n"));
9146 /* From MSDN documentation of SetPrinterDataEx: pass request to
9147 SetPrinterData if key is "PrinterDriverData" */
9150 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9154 if ( Printer->printer_type == SPLHND_SERVER ) {
9155 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9156 return WERR_INVALID_PARAM;
9159 if ( !get_printer_snum(p,handle, &snum, NULL) )
9163 * Access check : NT returns "access denied" if you make a
9164 * SetPrinterData call without the necessary privildge.
9165 * we were originally returning OK if nothing changed
9166 * which made Win2k issue **a lot** of SetPrinterData
9167 * when connecting to a printer --jerry
9170 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9172 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9173 return WERR_ACCESS_DENIED;
9176 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9177 if (!W_ERROR_IS_OK(status))
9180 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9181 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9183 /* check for OID in valuename */
9185 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9191 /* save the registry data */
9193 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9195 if ( W_ERROR_IS_OK(status) )
9197 /* save the OID if one was specified */
9199 fstrcat( keyname, "\\" );
9200 fstrcat( keyname, SPOOL_OID_KEY );
9203 * I'm not checking the status here on purpose. Don't know
9204 * if this is right, but I'm returning the status from the
9205 * previous set_printer_dataex() call. I have no idea if
9206 * this is right. --jerry
9209 set_printer_dataex( printer, keyname, valuename,
9210 REG_SZ, (uint8 *)oid_string,
9211 strlen(oid_string)+1 );
9214 status = mod_a_printer(printer, 2);
9217 free_a_printer(&printer, 2);
9223 /********************************************************************
9224 * spoolss_deleteprinterdataex
9225 ********************************************************************/
9227 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9229 POLICY_HND *handle = &q_u->handle;
9230 UNISTR2 *value = &q_u->valuename;
9231 UNISTR2 *key = &q_u->keyname;
9233 NT_PRINTER_INFO_LEVEL *printer = NULL;
9235 WERROR status = WERR_OK;
9236 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9237 pstring valuename, keyname;
9239 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9242 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9246 if (!get_printer_snum(p, handle, &snum, NULL))
9249 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9250 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9251 return WERR_ACCESS_DENIED;
9254 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9255 if (!W_ERROR_IS_OK(status))
9258 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9259 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9261 status = delete_printer_dataex( printer, keyname, valuename );
9263 if ( W_ERROR_IS_OK(status) )
9264 mod_a_printer( printer, 2 );
9266 free_a_printer(&printer, 2);
9271 /********************************************************************
9272 * spoolss_enumprinterkey
9273 ********************************************************************/
9276 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9279 fstring *keynames = NULL;
9280 uint16 *enumkeys = NULL;
9283 POLICY_HND *handle = &q_u->handle;
9284 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9285 NT_PRINTER_DATA *data;
9286 NT_PRINTER_INFO_LEVEL *printer = NULL;
9288 WERROR status = WERR_BADFILE;
9291 DEBUG(4,("_spoolss_enumprinterkey\n"));
9294 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9298 if ( !get_printer_snum(p,handle, &snum, NULL) )
9301 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9302 if (!W_ERROR_IS_OK(status))
9305 /* get the list of subkey names */
9307 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9308 data = printer->info_2->data;
9310 num_keys = get_printer_subkeys( data, key, &keynames );
9312 if ( num_keys == -1 ) {
9313 status = WERR_BADFILE;
9317 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9319 r_u->needed = printerkey_len*2;
9321 if ( q_u->size < r_u->needed ) {
9322 status = WERR_MORE_DATA;
9326 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9327 status = WERR_NOMEM;
9333 if ( q_u->size < r_u->needed )
9334 status = WERR_MORE_DATA;
9337 free_a_printer( &printer, 2 );
9338 SAFE_FREE( keynames );
9343 /********************************************************************
9344 * spoolss_deleteprinterkey
9345 ********************************************************************/
9347 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9349 POLICY_HND *handle = &q_u->handle;
9350 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9352 NT_PRINTER_INFO_LEVEL *printer = NULL;
9356 DEBUG(5,("spoolss_deleteprinterkey\n"));
9359 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9363 /* if keyname == NULL, return error */
9365 if ( !q_u->keyname.buffer )
9366 return WERR_INVALID_PARAM;
9368 if (!get_printer_snum(p, handle, &snum, NULL))
9371 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9372 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9373 return WERR_ACCESS_DENIED;
9376 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9377 if (!W_ERROR_IS_OK(status))
9380 /* delete the key and all subneys */
9382 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9384 status = delete_all_printer_data( printer->info_2, key );
9386 if ( W_ERROR_IS_OK(status) )
9387 status = mod_a_printer(printer, 2);
9389 free_a_printer( &printer, 2 );
9395 /********************************************************************
9396 * spoolss_enumprinterdataex
9397 ********************************************************************/
9399 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9401 POLICY_HND *handle = &q_u->handle;
9402 uint32 in_size = q_u->size;
9405 NT_PRINTER_INFO_LEVEL *printer = NULL;
9406 PRINTER_ENUM_VALUES *enum_values = NULL;
9407 NT_PRINTER_DATA *p_data;
9409 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9414 REGISTRY_VALUE *val;
9419 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9422 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9427 * first check for a keyname of NULL or "". Win2k seems to send
9428 * this a lot and we should send back WERR_INVALID_PARAM
9429 * no need to spend time looking up the printer in this case.
9433 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9434 if ( !strlen(key) ) {
9435 result = WERR_INVALID_PARAM;
9439 /* get the printer off of disk */
9441 if (!get_printer_snum(p,handle, &snum, NULL))
9444 ZERO_STRUCT(printer);
9445 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9446 if (!W_ERROR_IS_OK(result))
9449 /* now look for a match on the key name */
9451 p_data = printer->info_2->data;
9453 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9454 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9456 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9457 result = WERR_INVALID_PARAM;
9464 /* allocate the memory for the array of pointers -- if necessary */
9466 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9469 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9471 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9472 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9473 result = WERR_NOMEM;
9477 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9481 * loop through all params and build the array to pass
9482 * back to the client
9485 for ( i=0; i<num_entries; i++ )
9487 /* lookup the registry value */
9489 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9490 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9494 value_name = regval_name( val );
9495 init_unistr( &enum_values[i].valuename, value_name );
9496 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9497 enum_values[i].type = regval_type( val );
9499 data_len = regval_size( val );
9501 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9503 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9505 result = WERR_NOMEM;
9509 enum_values[i].data_len = data_len;
9511 /* keep track of the size of the array in bytes */
9513 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9516 /* housekeeping information in the reply */
9518 r_u->needed = needed;
9519 r_u->returned = num_entries;
9521 if (needed > in_size) {
9522 result = WERR_MORE_DATA;
9526 /* copy data into the reply */
9528 r_u->ctr.size = r_u->needed;
9529 r_u->ctr.size_of_array = r_u->returned;
9530 r_u->ctr.values = enum_values;
9536 free_a_printer(&printer, 2);
9541 /****************************************************************************
9542 ****************************************************************************/
9544 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9546 init_unistr(&info->name, name);
9549 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9550 UNISTR2 *environment,
9557 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9558 WERROR result = WERR_OK;
9560 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9562 if (!get_short_archi(long_archi))
9563 return WERR_INVALID_ENVIRONMENT;
9565 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9568 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9570 fill_printprocessordirectory_1(info, path);
9572 *needed += spoolss_size_printprocessordirectory_info_1(info);
9574 if (*needed > offered) {
9575 result = WERR_INSUFFICIENT_BUFFER;
9579 if (!rpcbuf_alloc_size(buffer, *needed)) {
9580 result = WERR_INSUFFICIENT_BUFFER;
9584 smb_io_printprocessordirectory_1("", buffer, info, 0);
9592 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9594 uint32 level = q_u->level;
9595 RPC_BUFFER *buffer = NULL;
9596 uint32 offered = q_u->offered;
9597 uint32 *needed = &r_u->needed;
9600 /* that's an [in out] buffer */
9602 if (!q_u->buffer && (offered!=0)) {
9603 return WERR_INVALID_PARAM;
9606 rpcbuf_move(q_u->buffer, &r_u->buffer);
9607 buffer = r_u->buffer;
9609 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9615 result = getprintprocessordirectory_level_1
9616 (&q_u->name, &q_u->environment, buffer, offered, needed);
9619 result = WERR_UNKNOWN_LEVEL;
9625 /*******************************************************************
9626 Streams the monitor UI DLL name in UNICODE
9627 *******************************************************************/
9629 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9630 RPC_BUFFER *out, uint32 *needed )
9632 const char *dllname = "tcpmonui.dll";
9634 *needed = (strlen(dllname)+1) * 2;
9636 if ( rpcbuf_get_size(out) < *needed ) {
9637 return WERR_INSUFFICIENT_BUFFER;
9640 if ( !make_monitorui_buf( out, dllname ) ) {
9647 /*******************************************************************
9648 Create a new TCP/IP port
9649 *******************************************************************/
9651 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9652 RPC_BUFFER *out, uint32 *needed )
9654 NT_PORT_DATA_1 port1;
9657 ZERO_STRUCT( port1 );
9659 /* convert to our internal port data structure */
9661 if ( !convert_port_data_1( &port1, in ) ) {
9665 /* create the device URI and call the add_port_hook() */
9667 switch ( port1.protocol ) {
9668 case PORT_PROTOCOL_DIRECT:
9669 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9672 case PORT_PROTOCOL_LPR:
9673 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9677 return WERR_UNKNOWN_PORT;
9680 return add_port_hook( token, port1.name, device_uri );
9683 /*******************************************************************
9684 *******************************************************************/
9686 struct xcv_api_table xcvtcp_cmds[] = {
9687 { "MonitorUI", xcvtcp_monitorui },
9688 { "AddPort", xcvtcp_addport},
9692 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9693 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9698 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9700 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9701 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9702 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9705 return WERR_BADFUNC;
9708 /*******************************************************************
9709 *******************************************************************/
9710 #if 0 /* don't support management using the "Local Port" monitor */
9712 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9713 RPC_BUFFER *out, uint32 *needed )
9715 const char *dllname = "localui.dll";
9717 *needed = (strlen(dllname)+1) * 2;
9719 if ( rpcbuf_get_size(out) < *needed ) {
9720 return WERR_INSUFFICIENT_BUFFER;
9723 if ( !make_monitorui_buf( out, dllname )) {
9730 /*******************************************************************
9731 *******************************************************************/
9733 struct xcv_api_table xcvlocal_cmds[] = {
9734 { "MonitorUI", xcvlocal_monitorui },
9738 struct xcv_api_table xcvlocal_cmds[] = {
9745 /*******************************************************************
9746 *******************************************************************/
9748 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9749 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9754 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9756 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9757 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9758 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9760 return WERR_BADFUNC;
9763 /*******************************************************************
9764 *******************************************************************/
9766 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9768 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9772 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9776 /* Has to be a handle to the TCP/IP port monitor */
9778 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9779 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9783 /* requires administrative access to the server */
9785 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9786 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9787 return WERR_ACCESS_DENIED;
9790 /* Get the command name. There's numerous commands supported by the
9791 TCPMON interface. */
9793 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9794 q_u->dataname.uni_str_len*2, 0);
9796 /* Allocate the outgoing buffer */
9798 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9800 switch ( Printer->printer_type ) {
9801 case SPLHND_PORTMON_TCP:
9802 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9803 &q_u->indata, &r_u->outdata, &r_u->needed );
9804 case SPLHND_PORTMON_LOCAL:
9805 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9806 &q_u->indata, &r_u->outdata, &r_u->needed );
9809 return WERR_INVALID_PRINT_MONITOR;