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((uint8 *)buf + offset, len - offset, "f",
1079 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1081 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1084 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1085 &msg->notify.value[0], &msg->notify.value[1]);
1087 tdb_unpack((uint8 *)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, (uint8 *)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 if (devmode->driverextra) {
1420 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1421 devmode->driverextra);
1422 if (!d->dev_private) {
1426 d->dev_private = NULL;
1431 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1433 if (!new_ctr || !ctr)
1436 DEBUG(8,("copy_devmode_ctr\n"));
1438 new_ctr->size = ctr->size;
1439 new_ctr->devmode_ptr = ctr->devmode_ptr;
1441 if(ctr->devmode_ptr)
1442 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1445 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1447 if (!new_def || !def)
1450 DEBUG(8,("copy_printer_defaults\n"));
1452 new_def->datatype_ptr = def->datatype_ptr;
1454 if (def->datatype_ptr)
1455 copy_unistr2(&new_def->datatype, &def->datatype);
1457 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1459 new_def->access_required = def->access_required;
1462 /********************************************************************
1463 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1464 * SPOOL_Q_OPEN_PRINTER_EX structure
1465 ********************************************************************/
1467 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1469 if (!q_u_ex || !q_u)
1472 DEBUG(8,("convert_to_openprinterex\n"));
1474 if ( q_u->printername ) {
1475 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1476 if (q_u_ex->printername == NULL)
1478 copy_unistr2(q_u_ex->printername, q_u->printername);
1481 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1486 /********************************************************************
1487 * spoolss_open_printer
1489 * called from the spoolss dispatcher
1490 ********************************************************************/
1492 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1494 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1495 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1500 ZERO_STRUCT(q_u_ex);
1501 ZERO_STRUCT(r_u_ex);
1503 /* convert the OpenPrinter() call to OpenPrinterEx() */
1505 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1506 if (!W_ERROR_IS_OK(r_u_ex.status))
1507 return r_u_ex.status;
1509 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1511 /* convert back to OpenPrinter() */
1513 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1518 /********************************************************************
1519 ********************************************************************/
1521 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1523 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1524 POLICY_HND *handle = &r_u->handle;
1528 Printer_entry *Printer=NULL;
1530 if ( !q_u->printername )
1531 return WERR_INVALID_PRINTER_NAME;
1533 /* some sanity check because you can open a printer or a print server */
1534 /* aka: \\server\printer or \\server */
1536 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1538 DEBUGADD(3,("checking name: %s\n",name));
1540 if (!open_printer_hnd(p, handle, name, 0))
1541 return WERR_INVALID_PRINTER_NAME;
1543 Printer=find_printer_index_by_hnd(p, handle);
1545 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1546 "handle we created for printer %s\n", name ));
1547 close_printer_handle(p,handle);
1548 return WERR_INVALID_PRINTER_NAME;
1552 * First case: the user is opening the print server:
1554 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1555 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1557 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1558 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1559 * or if the user is listed in the smb.conf printer admin parameter.
1561 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1562 * client view printer folder, but does not show the MSAPW.
1564 * Note: this test needs code to check access rights here too. Jeremy
1565 * could you look at this?
1567 * Second case: the user is opening a printer:
1568 * NT doesn't let us connect to a printer if the connecting user
1569 * doesn't have print permission.
1571 * Third case: user is opening a Port Monitor
1572 * access checks same as opening a handle to the print server.
1575 switch (Printer->printer_type )
1578 case SPLHND_PORTMON_TCP:
1579 case SPLHND_PORTMON_LOCAL:
1580 /* Printserver handles use global struct... */
1584 /* Map standard access rights to object specific access rights */
1586 se_map_standard(&printer_default->access_required,
1587 &printserver_std_mapping);
1589 /* Deny any object specific bits that don't apply to print
1590 servers (i.e printer and job specific bits) */
1592 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1594 if (printer_default->access_required &
1595 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1596 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1597 close_printer_handle(p, handle);
1598 return WERR_ACCESS_DENIED;
1601 /* Allow admin access */
1603 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1605 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1607 if (!lp_ms_add_printer_wizard()) {
1608 close_printer_handle(p, handle);
1609 return WERR_ACCESS_DENIED;
1612 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1613 and not a printer admin, then fail */
1615 if ((p->pipe_user.ut.uid != 0) &&
1616 !user_has_privileges(p->pipe_user.nt_user_token,
1618 !token_contains_name_in_list(
1619 uidtoname(p->pipe_user.ut.uid), NULL,
1620 p->pipe_user.nt_user_token,
1621 lp_printer_admin(snum))) {
1622 close_printer_handle(p, handle);
1623 return WERR_ACCESS_DENIED;
1626 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1630 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1633 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1634 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1636 /* We fall through to return WERR_OK */
1639 case SPLHND_PRINTER:
1640 /* NT doesn't let us connect to a printer if the connecting user
1641 doesn't have print permission. */
1643 if (!get_printer_snum(p, handle, &snum, NULL)) {
1644 close_printer_handle(p, handle);
1648 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1650 /* map an empty access mask to the minimum access mask */
1651 if (printer_default->access_required == 0x0)
1652 printer_default->access_required = PRINTER_ACCESS_USE;
1655 * If we are not serving the printer driver for this printer,
1656 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1657 * will keep NT clients happy --jerry
1660 if (lp_use_client_driver(snum)
1661 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1663 printer_default->access_required = PRINTER_ACCESS_USE;
1666 /* check smb.conf parameters and the the sec_desc */
1668 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1669 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1670 return WERR_ACCESS_DENIED;
1673 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1674 p->pipe_user.nt_user_token, snum) ||
1675 !print_access_check(&p->pipe_user, snum,
1676 printer_default->access_required)) {
1677 DEBUG(3, ("access DENIED for printer open\n"));
1678 close_printer_handle(p, handle);
1679 return WERR_ACCESS_DENIED;
1682 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1683 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1684 close_printer_handle(p, handle);
1685 return WERR_ACCESS_DENIED;
1688 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1689 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1691 printer_default->access_required = PRINTER_ACCESS_USE;
1693 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1694 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1699 /* sanity check to prevent programmer error */
1703 Printer->access_granted = printer_default->access_required;
1706 * If the client sent a devmode in the OpenPrinter() call, then
1707 * save it here in case we get a job submission on this handle
1710 if ( (Printer->printer_type != SPLHND_SERVER)
1711 && q_u->printer_default.devmode_cont.devmode_ptr )
1713 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1714 &Printer->nt_devmode );
1717 #if 0 /* JERRY -- I'm doubtful this is really effective */
1718 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1719 optimization in Windows 2000 clients --jerry */
1721 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1722 && (RA_WIN2K == get_remote_arch()) )
1724 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1725 sys_usleep( 500000 );
1732 /****************************************************************************
1733 ****************************************************************************/
1735 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1736 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1742 /* allocate memory if needed. Messy because
1743 convert_printer_info is used to update an existing
1744 printer or build a new one */
1746 if ( !printer->info_2 ) {
1747 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1748 if ( !printer->info_2 ) {
1749 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1754 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1755 printer->info_2->setuptime = time(NULL);
1763 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1764 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1770 printer->info_3=NULL;
1771 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1775 printer->info_6=NULL;
1776 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1786 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1787 NT_DEVICEMODE **pp_nt_devmode)
1789 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1792 * Ensure nt_devmode is a valid pointer
1793 * as we will be overwriting it.
1796 if (nt_devmode == NULL) {
1797 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1798 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1802 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1803 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1805 nt_devmode->specversion=devmode->specversion;
1806 nt_devmode->driverversion=devmode->driverversion;
1807 nt_devmode->size=devmode->size;
1808 nt_devmode->fields=devmode->fields;
1809 nt_devmode->orientation=devmode->orientation;
1810 nt_devmode->papersize=devmode->papersize;
1811 nt_devmode->paperlength=devmode->paperlength;
1812 nt_devmode->paperwidth=devmode->paperwidth;
1813 nt_devmode->scale=devmode->scale;
1814 nt_devmode->copies=devmode->copies;
1815 nt_devmode->defaultsource=devmode->defaultsource;
1816 nt_devmode->printquality=devmode->printquality;
1817 nt_devmode->color=devmode->color;
1818 nt_devmode->duplex=devmode->duplex;
1819 nt_devmode->yresolution=devmode->yresolution;
1820 nt_devmode->ttoption=devmode->ttoption;
1821 nt_devmode->collate=devmode->collate;
1823 nt_devmode->logpixels=devmode->logpixels;
1824 nt_devmode->bitsperpel=devmode->bitsperpel;
1825 nt_devmode->pelswidth=devmode->pelswidth;
1826 nt_devmode->pelsheight=devmode->pelsheight;
1827 nt_devmode->displayflags=devmode->displayflags;
1828 nt_devmode->displayfrequency=devmode->displayfrequency;
1829 nt_devmode->icmmethod=devmode->icmmethod;
1830 nt_devmode->icmintent=devmode->icmintent;
1831 nt_devmode->mediatype=devmode->mediatype;
1832 nt_devmode->dithertype=devmode->dithertype;
1833 nt_devmode->reserved1=devmode->reserved1;
1834 nt_devmode->reserved2=devmode->reserved2;
1835 nt_devmode->panningwidth=devmode->panningwidth;
1836 nt_devmode->panningheight=devmode->panningheight;
1839 * Only change private and driverextra if the incoming devmode
1840 * has a new one. JRA.
1843 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1844 SAFE_FREE(nt_devmode->nt_dev_private);
1845 nt_devmode->driverextra=devmode->driverextra;
1846 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1848 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1851 *pp_nt_devmode = nt_devmode;
1856 /********************************************************************
1857 * _spoolss_enddocprinter_internal.
1858 ********************************************************************/
1860 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1862 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1866 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1870 if (!get_printer_snum(p, handle, &snum, NULL))
1873 Printer->document_started=False;
1874 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1875 /* error codes unhandled so far ... */
1880 /********************************************************************
1881 * api_spoolss_closeprinter
1882 ********************************************************************/
1884 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1886 POLICY_HND *handle = &q_u->handle;
1888 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1890 if (Printer && Printer->document_started)
1891 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1893 if (!close_printer_handle(p, handle))
1896 /* clear the returned printer handle. Observed behavior
1897 from Win2k server. Don't think this really matters.
1898 Previous code just copied the value of the closed
1901 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1906 /********************************************************************
1907 * api_spoolss_deleteprinter
1909 ********************************************************************/
1911 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1913 POLICY_HND *handle = &q_u->handle;
1914 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1917 if (Printer && Printer->document_started)
1918 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1920 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1922 result = delete_printer_handle(p, handle);
1924 update_c_setprinter(False);
1929 /*******************************************************************
1930 * static function to lookup the version id corresponding to an
1931 * long architecture string
1932 ******************************************************************/
1934 static int get_version_id (char * arch)
1937 struct table_node archi_table[]= {
1939 {"Windows 4.0", "WIN40", 0 },
1940 {"Windows NT x86", "W32X86", 2 },
1941 {"Windows NT R4000", "W32MIPS", 2 },
1942 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1943 {"Windows NT PowerPC", "W32PPC", 2 },
1944 {"Windows IA64", "IA64", 3 },
1945 {"Windows x64", "x64", 3 },
1949 for (i=0; archi_table[i].long_archi != NULL; i++)
1951 if (strcmp(arch, archi_table[i].long_archi) == 0)
1952 return (archi_table[i].version);
1958 /********************************************************************
1959 * _spoolss_deleteprinterdriver
1960 ********************************************************************/
1962 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1966 NT_PRINTER_DRIVER_INFO_LEVEL info;
1967 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1970 WERROR status_win2k = WERR_ACCESS_DENIED;
1971 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1973 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1974 and not a printer admin, then fail */
1976 if ( (p->pipe_user.ut.uid != 0)
1977 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
1978 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
1979 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
1981 return WERR_ACCESS_DENIED;
1984 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1985 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1987 /* check that we have a valid driver name first */
1989 if ((version=get_version_id(arch)) == -1)
1990 return WERR_INVALID_ENVIRONMENT;
1993 ZERO_STRUCT(info_win2k);
1995 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1997 /* try for Win2k driver if "Windows NT x86" */
1999 if ( version == 2 ) {
2001 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2002 status = WERR_UNKNOWN_PRINTER_DRIVER;
2006 /* otherwise it was a failure */
2008 status = WERR_UNKNOWN_PRINTER_DRIVER;
2014 if (printer_driver_in_use(info.info_3)) {
2015 status = WERR_PRINTER_DRIVER_IN_USE;
2021 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2023 /* if we get to here, we now have 2 driver info structures to remove */
2024 /* remove the Win2k driver first*/
2026 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2027 free_a_printer_driver( info_win2k, 3 );
2029 /* this should not have failed---if it did, report to client */
2030 if ( !W_ERROR_IS_OK(status_win2k) )
2032 status = status_win2k;
2038 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2040 /* if at least one of the deletes succeeded return OK */
2042 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2046 free_a_printer_driver( info, 3 );
2051 /********************************************************************
2052 * spoolss_deleteprinterdriverex
2053 ********************************************************************/
2055 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2059 NT_PRINTER_DRIVER_INFO_LEVEL info;
2060 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2062 uint32 flags = q_u->delete_flags;
2065 WERROR status_win2k = WERR_ACCESS_DENIED;
2066 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2068 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2069 and not a printer admin, then fail */
2071 if ( (p->pipe_user.ut.uid != 0)
2072 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2073 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2074 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2076 return WERR_ACCESS_DENIED;
2079 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2080 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2082 /* check that we have a valid driver name first */
2083 if ((version=get_version_id(arch)) == -1) {
2084 /* this is what NT returns */
2085 return WERR_INVALID_ENVIRONMENT;
2088 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2089 version = q_u->version;
2092 ZERO_STRUCT(info_win2k);
2094 status = get_a_printer_driver(&info, 3, driver, arch, version);
2096 if ( !W_ERROR_IS_OK(status) )
2099 * if the client asked for a specific version,
2100 * or this is something other than Windows NT x86,
2104 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2107 /* try for Win2k driver if "Windows NT x86" */
2110 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2111 status = WERR_UNKNOWN_PRINTER_DRIVER;
2116 if ( printer_driver_in_use(info.info_3) ) {
2117 status = WERR_PRINTER_DRIVER_IN_USE;
2122 * we have a couple of cases to consider.
2123 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2124 * then the delete should fail if **any** files overlap with
2126 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2127 * non-overlapping files
2128 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2129 * is set, the do not delete any files
2130 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2133 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2135 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2137 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2138 /* no idea of the correct error here */
2139 status = WERR_ACCESS_DENIED;
2144 /* also check for W32X86/3 if necessary; maybe we already have? */
2146 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2147 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2150 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2151 /* no idea of the correct error here */
2152 free_a_printer_driver( info_win2k, 3 );
2153 status = WERR_ACCESS_DENIED;
2157 /* if we get to here, we now have 2 driver info structures to remove */
2158 /* remove the Win2k driver first*/
2160 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2161 free_a_printer_driver( info_win2k, 3 );
2163 /* this should not have failed---if it did, report to client */
2165 if ( !W_ERROR_IS_OK(status_win2k) )
2170 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2172 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2175 free_a_printer_driver( info, 3 );
2181 /****************************************************************************
2182 Internal routine for retreiving printerdata
2183 ***************************************************************************/
2185 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2186 const char *key, const char *value, uint32 *type, uint8 **data,
2187 uint32 *needed, uint32 in_size )
2189 REGISTRY_VALUE *val;
2193 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2194 return WERR_BADFILE;
2196 *type = regval_type( val );
2198 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2200 size = regval_size( val );
2202 /* copy the min(in_size, len) */
2205 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2207 /* special case for 0 length values */
2209 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2213 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2222 DEBUG(5,("get_printer_dataex: copy done\n"));
2227 /****************************************************************************
2228 Internal routine for removing printerdata
2229 ***************************************************************************/
2231 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2233 return delete_printer_data( printer->info_2, key, value );
2236 /****************************************************************************
2237 Internal routine for storing printerdata
2238 ***************************************************************************/
2240 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2241 uint32 type, uint8 *data, int real_len )
2243 /* the registry objects enforce uniqueness based on value name */
2245 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2248 /********************************************************************
2249 GetPrinterData on a printer server Handle.
2250 ********************************************************************/
2252 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2256 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2258 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2260 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2266 if (!StrCaseCmp(value, "BeepEnabled")) {
2268 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2270 SIVAL(*data, 0, 0x00);
2275 if (!StrCaseCmp(value, "EventLog")) {
2277 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2279 /* formally was 0x1b */
2280 SIVAL(*data, 0, 0x0);
2285 if (!StrCaseCmp(value, "NetPopup")) {
2287 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2289 SIVAL(*data, 0, 0x00);
2294 if (!StrCaseCmp(value, "MajorVersion")) {
2296 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2299 /* Windows NT 4.0 seems to not allow uploading of drivers
2300 to a server that reports 0x3 as the MajorVersion.
2301 need to investigate more how Win2k gets around this .
2304 if ( RA_WINNT == get_remote_arch() )
2313 if (!StrCaseCmp(value, "MinorVersion")) {
2315 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2323 * uint32 size = 0x114
2325 * uint32 minor = [0|1]
2326 * uint32 build = [2195|2600]
2327 * extra unicode string = e.g. "Service Pack 3"
2329 if (!StrCaseCmp(value, "OSVersion")) {
2333 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2336 SIVAL(*data, 0, *needed); /* size */
2337 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2339 SIVAL(*data, 12, 2195); /* build */
2341 /* leave extra string empty */
2347 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2348 const char *string="C:\\PRINTERS";
2350 *needed = 2*(strlen(string)+1);
2351 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2353 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2355 /* it's done by hand ready to go on the wire */
2356 for (i=0; i<strlen(string); i++) {
2357 (*data)[2*i]=string[i];
2358 (*data)[2*i+1]='\0';
2363 if (!StrCaseCmp(value, "Architecture")) {
2364 const char *string="Windows NT x86";
2366 *needed = 2*(strlen(string)+1);
2367 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2369 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2370 for (i=0; i<strlen(string); i++) {
2371 (*data)[2*i]=string[i];
2372 (*data)[2*i+1]='\0';
2377 if (!StrCaseCmp(value, "DsPresent")) {
2379 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2382 /* only show the publish check box if we are a
2383 memeber of a AD domain */
2385 if ( lp_security() == SEC_ADS )
2386 SIVAL(*data, 0, 0x01);
2388 SIVAL(*data, 0, 0x00);
2394 if (!StrCaseCmp(value, "DNSMachineName")) {
2397 if (!get_mydnsfullname(hostname))
2398 return WERR_BADFILE;
2400 *needed = 2*(strlen(hostname)+1);
2401 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2403 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2404 for (i=0; i<strlen(hostname); i++) {
2405 (*data)[2*i]=hostname[i];
2406 (*data)[2*i+1]='\0';
2412 return WERR_BADFILE;
2415 /********************************************************************
2416 * spoolss_getprinterdata
2417 ********************************************************************/
2419 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2421 POLICY_HND *handle = &q_u->handle;
2422 UNISTR2 *valuename = &q_u->valuename;
2423 uint32 in_size = q_u->size;
2424 uint32 *type = &r_u->type;
2425 uint32 *out_size = &r_u->size;
2426 uint8 **data = &r_u->data;
2427 uint32 *needed = &r_u->needed;
2430 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2431 NT_PRINTER_INFO_LEVEL *printer = NULL;
2435 * Reminder: when it's a string, the length is in BYTES
2436 * even if UNICODE is negociated.
2441 *out_size = in_size;
2443 /* in case of problem, return some default values */
2448 DEBUG(4,("_spoolss_getprinterdata\n"));
2451 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2452 status = WERR_BADFID;
2456 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2458 if ( Printer->printer_type == SPLHND_SERVER )
2459 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2462 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2463 status = WERR_BADFID;
2467 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2468 if ( !W_ERROR_IS_OK(status) )
2471 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2473 if ( strequal(value, "ChangeId") ) {
2475 *needed = sizeof(uint32);
2476 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2477 status = WERR_NOMEM;
2480 SIVAL( *data, 0, printer->info_2->changeid );
2484 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2487 if (*needed > *out_size)
2488 status = WERR_MORE_DATA;
2491 if ( !W_ERROR_IS_OK(status) )
2493 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2495 /* reply this param doesn't exist */
2498 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2500 free_a_printer( &printer, 2 );
2508 /* cleanup & exit */
2511 free_a_printer( &printer, 2 );
2516 /*********************************************************
2517 Connect to the client machine.
2518 **********************************************************/
2520 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2521 struct in_addr *client_ip, const char *remote_machine)
2524 struct cli_state *the_cli;
2525 struct in_addr rm_addr;
2527 if ( is_zero_ip(*client_ip) ) {
2528 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2529 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2533 if ( ismyip( rm_addr )) {
2534 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2538 rm_addr.s_addr = client_ip->s_addr;
2539 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2540 inet_ntoa(*client_ip) ));
2543 /* setup the connection */
2545 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2546 &rm_addr, 0, "IPC$", "IPC",
2550 0, lp_client_signing(), NULL );
2552 if ( !NT_STATUS_IS_OK( ret ) ) {
2553 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2558 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2559 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2560 cli_shutdown(the_cli);
2565 * Ok - we have an anonymous connection to the IPC$ share.
2566 * Now start the NT Domain stuff :-).
2569 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2570 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2571 remote_machine, nt_errstr(ret)));
2572 cli_shutdown(the_cli);
2576 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2578 (*pp_pipe)->cli = the_cli;
2583 /***************************************************************************
2584 Connect to the client.
2585 ****************************************************************************/
2587 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2588 uint32 localprinter, uint32 type,
2589 POLICY_HND *handle, struct in_addr *client_ip)
2594 * If it's the first connection, contact the client
2595 * and connect to the IPC$ share anonymously
2597 if (smb_connections==0) {
2598 fstring unix_printer;
2600 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2602 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2605 message_register(MSG_PRINTER_NOTIFY2,
2606 receive_notify2_message_list, NULL);
2607 /* Tell the connections db we're now interested in printer
2608 * notify messages. */
2609 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2613 * Tell the specific printing tdb we want messages for this printer
2614 * by registering our PID.
2617 if (!print_notify_register_pid(snum))
2618 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2622 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2625 if (!W_ERROR_IS_OK(result))
2626 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2627 dos_errstr(result)));
2629 return (W_ERROR_IS_OK(result));
2632 /********************************************************************
2634 * ReplyFindFirstPrinterChangeNotifyEx
2636 * before replying OK: status=0 a rpc call is made to the workstation
2637 * asking ReplyOpenPrinter
2639 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2640 * called from api_spoolss_rffpcnex
2641 ********************************************************************/
2643 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2645 POLICY_HND *handle = &q_u->handle;
2646 uint32 flags = q_u->flags;
2647 uint32 options = q_u->options;
2648 UNISTR2 *localmachine = &q_u->localmachine;
2649 uint32 printerlocal = q_u->printerlocal;
2651 SPOOL_NOTIFY_OPTION *option = q_u->option;
2652 struct in_addr client_ip;
2654 /* store the notify value in the printer struct */
2656 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2659 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2663 Printer->notify.flags=flags;
2664 Printer->notify.options=options;
2665 Printer->notify.printerlocal=printerlocal;
2667 if (Printer->notify.option)
2668 free_spool_notify_option(&Printer->notify.option);
2670 Printer->notify.option=dup_spool_notify_option(option);
2672 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2673 sizeof(Printer->notify.localmachine)-1);
2675 /* Connect to the client machine and send a ReplyOpenPrinter */
2677 if ( Printer->printer_type == SPLHND_SERVER)
2679 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2680 !get_printer_snum(p, handle, &snum, NULL) )
2683 client_ip.s_addr = inet_addr(p->conn->client_address);
2685 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2686 Printer->notify.printerlocal, 1,
2687 &Printer->notify.client_hnd, &client_ip))
2688 return WERR_SERVER_UNAVAILABLE;
2690 Printer->notify.client_connected=True;
2695 /*******************************************************************
2696 * fill a notify_info_data with the servername
2697 ********************************************************************/
2699 void spoolss_notify_server_name(int snum,
2700 SPOOL_NOTIFY_INFO_DATA *data,
2701 print_queue_struct *queue,
2702 NT_PRINTER_INFO_LEVEL *printer,
2703 TALLOC_CTX *mem_ctx)
2708 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2710 data->notify_data.data.length = len;
2711 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2713 if (!data->notify_data.data.string) {
2714 data->notify_data.data.length = 0;
2718 memcpy(data->notify_data.data.string, temp, len);
2721 /*******************************************************************
2722 * fill a notify_info_data with the printername (not including the servername).
2723 ********************************************************************/
2725 void spoolss_notify_printer_name(int snum,
2726 SPOOL_NOTIFY_INFO_DATA *data,
2727 print_queue_struct *queue,
2728 NT_PRINTER_INFO_LEVEL *printer,
2729 TALLOC_CTX *mem_ctx)
2734 /* the notify name should not contain the \\server\ part */
2735 char *p = strrchr(printer->info_2->printername, '\\');
2738 p = printer->info_2->printername;
2743 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2745 data->notify_data.data.length = len;
2746 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2748 if (!data->notify_data.data.string) {
2749 data->notify_data.data.length = 0;
2753 memcpy(data->notify_data.data.string, temp, len);
2756 /*******************************************************************
2757 * fill a notify_info_data with the servicename
2758 ********************************************************************/
2760 void spoolss_notify_share_name(int snum,
2761 SPOOL_NOTIFY_INFO_DATA *data,
2762 print_queue_struct *queue,
2763 NT_PRINTER_INFO_LEVEL *printer,
2764 TALLOC_CTX *mem_ctx)
2769 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2771 data->notify_data.data.length = len;
2772 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2774 if (!data->notify_data.data.string) {
2775 data->notify_data.data.length = 0;
2779 memcpy(data->notify_data.data.string, temp, len);
2782 /*******************************************************************
2783 * fill a notify_info_data with the port name
2784 ********************************************************************/
2786 void spoolss_notify_port_name(int snum,
2787 SPOOL_NOTIFY_INFO_DATA *data,
2788 print_queue_struct *queue,
2789 NT_PRINTER_INFO_LEVEL *printer,
2790 TALLOC_CTX *mem_ctx)
2795 /* even if it's strange, that's consistant in all the code */
2797 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2799 data->notify_data.data.length = len;
2800 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2802 if (!data->notify_data.data.string) {
2803 data->notify_data.data.length = 0;
2807 memcpy(data->notify_data.data.string, temp, len);
2810 /*******************************************************************
2811 * fill a notify_info_data with the printername
2812 * but it doesn't exist, have to see what to do
2813 ********************************************************************/
2815 void spoolss_notify_driver_name(int snum,
2816 SPOOL_NOTIFY_INFO_DATA *data,
2817 print_queue_struct *queue,
2818 NT_PRINTER_INFO_LEVEL *printer,
2819 TALLOC_CTX *mem_ctx)
2824 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2826 data->notify_data.data.length = len;
2827 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2829 if (!data->notify_data.data.string) {
2830 data->notify_data.data.length = 0;
2834 memcpy(data->notify_data.data.string, temp, len);
2837 /*******************************************************************
2838 * fill a notify_info_data with the comment
2839 ********************************************************************/
2841 void spoolss_notify_comment(int snum,
2842 SPOOL_NOTIFY_INFO_DATA *data,
2843 print_queue_struct *queue,
2844 NT_PRINTER_INFO_LEVEL *printer,
2845 TALLOC_CTX *mem_ctx)
2850 if (*printer->info_2->comment == '\0')
2851 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2853 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2855 data->notify_data.data.length = len;
2856 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2858 if (!data->notify_data.data.string) {
2859 data->notify_data.data.length = 0;
2863 memcpy(data->notify_data.data.string, temp, len);
2866 /*******************************************************************
2867 * fill a notify_info_data with the comment
2868 * location = "Room 1, floor 2, building 3"
2869 ********************************************************************/
2871 void spoolss_notify_location(int snum,
2872 SPOOL_NOTIFY_INFO_DATA *data,
2873 print_queue_struct *queue,
2874 NT_PRINTER_INFO_LEVEL *printer,
2875 TALLOC_CTX *mem_ctx)
2880 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2882 data->notify_data.data.length = len;
2883 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2885 if (!data->notify_data.data.string) {
2886 data->notify_data.data.length = 0;
2890 memcpy(data->notify_data.data.string, temp, len);
2893 /*******************************************************************
2894 * fill a notify_info_data with the device mode
2895 * jfm:xxxx don't to it for know but that's a real problem !!!
2896 ********************************************************************/
2898 static void spoolss_notify_devmode(int snum,
2899 SPOOL_NOTIFY_INFO_DATA *data,
2900 print_queue_struct *queue,
2901 NT_PRINTER_INFO_LEVEL *printer,
2902 TALLOC_CTX *mem_ctx)
2904 /* for a dummy implementation we have to zero the fields */
2905 data->notify_data.data.length = 0;
2906 data->notify_data.data.string = NULL;
2909 /*******************************************************************
2910 * fill a notify_info_data with the separator file name
2911 ********************************************************************/
2913 void spoolss_notify_sepfile(int snum,
2914 SPOOL_NOTIFY_INFO_DATA *data,
2915 print_queue_struct *queue,
2916 NT_PRINTER_INFO_LEVEL *printer,
2917 TALLOC_CTX *mem_ctx)
2922 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2924 data->notify_data.data.length = len;
2925 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2927 if (!data->notify_data.data.string) {
2928 data->notify_data.data.length = 0;
2932 memcpy(data->notify_data.data.string, temp, len);
2935 /*******************************************************************
2936 * fill a notify_info_data with the print processor
2937 * jfm:xxxx return always winprint to indicate we don't do anything to it
2938 ********************************************************************/
2940 void spoolss_notify_print_processor(int snum,
2941 SPOOL_NOTIFY_INFO_DATA *data,
2942 print_queue_struct *queue,
2943 NT_PRINTER_INFO_LEVEL *printer,
2944 TALLOC_CTX *mem_ctx)
2949 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2951 data->notify_data.data.length = len;
2952 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2954 if (!data->notify_data.data.string) {
2955 data->notify_data.data.length = 0;
2959 memcpy(data->notify_data.data.string, temp, len);
2962 /*******************************************************************
2963 * fill a notify_info_data with the print processor options
2964 * jfm:xxxx send an empty string
2965 ********************************************************************/
2967 void spoolss_notify_parameters(int snum,
2968 SPOOL_NOTIFY_INFO_DATA *data,
2969 print_queue_struct *queue,
2970 NT_PRINTER_INFO_LEVEL *printer,
2971 TALLOC_CTX *mem_ctx)
2976 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2978 data->notify_data.data.length = len;
2979 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2981 if (!data->notify_data.data.string) {
2982 data->notify_data.data.length = 0;
2986 memcpy(data->notify_data.data.string, temp, len);
2989 /*******************************************************************
2990 * fill a notify_info_data with the data type
2991 * jfm:xxxx always send RAW as data type
2992 ********************************************************************/
2994 void spoolss_notify_datatype(int snum,
2995 SPOOL_NOTIFY_INFO_DATA *data,
2996 print_queue_struct *queue,
2997 NT_PRINTER_INFO_LEVEL *printer,
2998 TALLOC_CTX *mem_ctx)
3003 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3005 data->notify_data.data.length = len;
3006 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3008 if (!data->notify_data.data.string) {
3009 data->notify_data.data.length = 0;
3013 memcpy(data->notify_data.data.string, temp, len);
3016 /*******************************************************************
3017 * fill a notify_info_data with the security descriptor
3018 * jfm:xxxx send an null pointer to say no security desc
3019 * have to implement security before !
3020 ********************************************************************/
3022 static void spoolss_notify_security_desc(int snum,
3023 SPOOL_NOTIFY_INFO_DATA *data,
3024 print_queue_struct *queue,
3025 NT_PRINTER_INFO_LEVEL *printer,
3026 TALLOC_CTX *mem_ctx)
3028 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3029 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3032 /*******************************************************************
3033 * fill a notify_info_data with the attributes
3034 * jfm:xxxx a samba printer is always shared
3035 ********************************************************************/
3037 void spoolss_notify_attributes(int snum,
3038 SPOOL_NOTIFY_INFO_DATA *data,
3039 print_queue_struct *queue,
3040 NT_PRINTER_INFO_LEVEL *printer,
3041 TALLOC_CTX *mem_ctx)
3043 data->notify_data.value[0] = printer->info_2->attributes;
3044 data->notify_data.value[1] = 0;
3047 /*******************************************************************
3048 * fill a notify_info_data with the priority
3049 ********************************************************************/
3051 static void spoolss_notify_priority(int snum,
3052 SPOOL_NOTIFY_INFO_DATA *data,
3053 print_queue_struct *queue,
3054 NT_PRINTER_INFO_LEVEL *printer,
3055 TALLOC_CTX *mem_ctx)
3057 data->notify_data.value[0] = printer->info_2->priority;
3058 data->notify_data.value[1] = 0;
3061 /*******************************************************************
3062 * fill a notify_info_data with the default priority
3063 ********************************************************************/
3065 static void spoolss_notify_default_priority(int snum,
3066 SPOOL_NOTIFY_INFO_DATA *data,
3067 print_queue_struct *queue,
3068 NT_PRINTER_INFO_LEVEL *printer,
3069 TALLOC_CTX *mem_ctx)
3071 data->notify_data.value[0] = printer->info_2->default_priority;
3072 data->notify_data.value[1] = 0;
3075 /*******************************************************************
3076 * fill a notify_info_data with the start time
3077 ********************************************************************/
3079 static void spoolss_notify_start_time(int snum,
3080 SPOOL_NOTIFY_INFO_DATA *data,
3081 print_queue_struct *queue,
3082 NT_PRINTER_INFO_LEVEL *printer,
3083 TALLOC_CTX *mem_ctx)
3085 data->notify_data.value[0] = printer->info_2->starttime;
3086 data->notify_data.value[1] = 0;
3089 /*******************************************************************
3090 * fill a notify_info_data with the until time
3091 ********************************************************************/
3093 static void spoolss_notify_until_time(int snum,
3094 SPOOL_NOTIFY_INFO_DATA *data,
3095 print_queue_struct *queue,
3096 NT_PRINTER_INFO_LEVEL *printer,
3097 TALLOC_CTX *mem_ctx)
3099 data->notify_data.value[0] = printer->info_2->untiltime;
3100 data->notify_data.value[1] = 0;
3103 /*******************************************************************
3104 * fill a notify_info_data with the status
3105 ********************************************************************/
3107 static void spoolss_notify_status(int snum,
3108 SPOOL_NOTIFY_INFO_DATA *data,
3109 print_queue_struct *queue,
3110 NT_PRINTER_INFO_LEVEL *printer,
3111 TALLOC_CTX *mem_ctx)
3113 print_status_struct status;
3115 print_queue_length(snum, &status);
3116 data->notify_data.value[0]=(uint32) status.status;
3117 data->notify_data.value[1] = 0;
3120 /*******************************************************************
3121 * fill a notify_info_data with the number of jobs queued
3122 ********************************************************************/
3124 void spoolss_notify_cjobs(int snum,
3125 SPOOL_NOTIFY_INFO_DATA *data,
3126 print_queue_struct *queue,
3127 NT_PRINTER_INFO_LEVEL *printer,
3128 TALLOC_CTX *mem_ctx)
3130 data->notify_data.value[0] = print_queue_length(snum, NULL);
3131 data->notify_data.value[1] = 0;
3134 /*******************************************************************
3135 * fill a notify_info_data with the average ppm
3136 ********************************************************************/
3138 static void spoolss_notify_average_ppm(int snum,
3139 SPOOL_NOTIFY_INFO_DATA *data,
3140 print_queue_struct *queue,
3141 NT_PRINTER_INFO_LEVEL *printer,
3142 TALLOC_CTX *mem_ctx)
3144 /* always respond 8 pages per minutes */
3145 /* a little hard ! */
3146 data->notify_data.value[0] = printer->info_2->averageppm;
3147 data->notify_data.value[1] = 0;
3150 /*******************************************************************
3151 * fill a notify_info_data with username
3152 ********************************************************************/
3154 static void spoolss_notify_username(int snum,
3155 SPOOL_NOTIFY_INFO_DATA *data,
3156 print_queue_struct *queue,
3157 NT_PRINTER_INFO_LEVEL *printer,
3158 TALLOC_CTX *mem_ctx)
3163 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3165 data->notify_data.data.length = len;
3166 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3168 if (!data->notify_data.data.string) {
3169 data->notify_data.data.length = 0;
3173 memcpy(data->notify_data.data.string, temp, len);
3176 /*******************************************************************
3177 * fill a notify_info_data with job status
3178 ********************************************************************/
3180 static void spoolss_notify_job_status(int snum,
3181 SPOOL_NOTIFY_INFO_DATA *data,
3182 print_queue_struct *queue,
3183 NT_PRINTER_INFO_LEVEL *printer,
3184 TALLOC_CTX *mem_ctx)
3186 data->notify_data.value[0]=nt_printj_status(queue->status);
3187 data->notify_data.value[1] = 0;
3190 /*******************************************************************
3191 * fill a notify_info_data with job name
3192 ********************************************************************/
3194 static void spoolss_notify_job_name(int snum,
3195 SPOOL_NOTIFY_INFO_DATA *data,
3196 print_queue_struct *queue,
3197 NT_PRINTER_INFO_LEVEL *printer,
3198 TALLOC_CTX *mem_ctx)
3203 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3205 data->notify_data.data.length = len;
3206 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3208 if (!data->notify_data.data.string) {
3209 data->notify_data.data.length = 0;
3213 memcpy(data->notify_data.data.string, temp, len);
3216 /*******************************************************************
3217 * fill a notify_info_data with job status
3218 ********************************************************************/
3220 static void spoolss_notify_job_status_string(int snum,
3221 SPOOL_NOTIFY_INFO_DATA *data,
3222 print_queue_struct *queue,
3223 NT_PRINTER_INFO_LEVEL *printer,
3224 TALLOC_CTX *mem_ctx)
3227 * Now we're returning job status codes we just return a "" here. JRA.
3234 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3237 switch (queue->status) {
3242 p = ""; /* NT provides the paused string */
3251 #endif /* NO LONGER NEEDED. */
3253 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3255 data->notify_data.data.length = len;
3256 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3258 if (!data->notify_data.data.string) {
3259 data->notify_data.data.length = 0;
3263 memcpy(data->notify_data.data.string, temp, len);
3266 /*******************************************************************
3267 * fill a notify_info_data with job time
3268 ********************************************************************/
3270 static void spoolss_notify_job_time(int snum,
3271 SPOOL_NOTIFY_INFO_DATA *data,
3272 print_queue_struct *queue,
3273 NT_PRINTER_INFO_LEVEL *printer,
3274 TALLOC_CTX *mem_ctx)
3276 data->notify_data.value[0]=0x0;
3277 data->notify_data.value[1]=0;
3280 /*******************************************************************
3281 * fill a notify_info_data with job size
3282 ********************************************************************/
3284 static void spoolss_notify_job_size(int snum,
3285 SPOOL_NOTIFY_INFO_DATA *data,
3286 print_queue_struct *queue,
3287 NT_PRINTER_INFO_LEVEL *printer,
3288 TALLOC_CTX *mem_ctx)
3290 data->notify_data.value[0]=queue->size;
3291 data->notify_data.value[1]=0;
3294 /*******************************************************************
3295 * fill a notify_info_data with page info
3296 ********************************************************************/
3297 static void spoolss_notify_total_pages(int snum,
3298 SPOOL_NOTIFY_INFO_DATA *data,
3299 print_queue_struct *queue,
3300 NT_PRINTER_INFO_LEVEL *printer,
3301 TALLOC_CTX *mem_ctx)
3303 data->notify_data.value[0]=queue->page_count;
3304 data->notify_data.value[1]=0;
3307 /*******************************************************************
3308 * fill a notify_info_data with pages printed info.
3309 ********************************************************************/
3310 static void spoolss_notify_pages_printed(int snum,
3311 SPOOL_NOTIFY_INFO_DATA *data,
3312 print_queue_struct *queue,
3313 NT_PRINTER_INFO_LEVEL *printer,
3314 TALLOC_CTX *mem_ctx)
3316 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3317 data->notify_data.value[1]=0;
3320 /*******************************************************************
3321 Fill a notify_info_data with job position.
3322 ********************************************************************/
3324 static void spoolss_notify_job_position(int snum,
3325 SPOOL_NOTIFY_INFO_DATA *data,
3326 print_queue_struct *queue,
3327 NT_PRINTER_INFO_LEVEL *printer,
3328 TALLOC_CTX *mem_ctx)
3330 data->notify_data.value[0]=queue->job;
3331 data->notify_data.value[1]=0;
3334 /*******************************************************************
3335 Fill a notify_info_data with submitted time.
3336 ********************************************************************/
3338 static void spoolss_notify_submitted_time(int snum,
3339 SPOOL_NOTIFY_INFO_DATA *data,
3340 print_queue_struct *queue,
3341 NT_PRINTER_INFO_LEVEL *printer,
3342 TALLOC_CTX *mem_ctx)
3349 t=gmtime(&queue->time);
3351 len = sizeof(SYSTEMTIME);
3353 data->notify_data.data.length = len;
3354 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3356 if (!data->notify_data.data.string) {
3357 data->notify_data.data.length = 0;
3361 make_systemtime(&st, t);
3364 * Systemtime must be linearized as a set of UINT16's.
3365 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3368 p = (char *)data->notify_data.data.string;
3369 SSVAL(p, 0, st.year);
3370 SSVAL(p, 2, st.month);
3371 SSVAL(p, 4, st.dayofweek);
3372 SSVAL(p, 6, st.day);
3373 SSVAL(p, 8, st.hour);
3374 SSVAL(p, 10, st.minute);
3375 SSVAL(p, 12, st.second);
3376 SSVAL(p, 14, st.milliseconds);
3379 struct s_notify_info_data_table
3385 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3386 print_queue_struct *queue,
3387 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3390 /* A table describing the various print notification constants and
3391 whether the notification data is a pointer to a variable sized
3392 buffer, a one value uint32 or a two value uint32. */
3394 static const struct s_notify_info_data_table notify_info_data_table[] =
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3440 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3442 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3443 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3444 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3445 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3448 /*******************************************************************
3449 Return the size of info_data structure.
3450 ********************************************************************/
3452 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3456 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3457 if ( (notify_info_data_table[i].type == type)
3458 && (notify_info_data_table[i].field == field) ) {
3459 switch(notify_info_data_table[i].size) {
3460 case NOTIFY_ONE_VALUE:
3461 case NOTIFY_TWO_VALUE:
3466 /* The only pointer notify data I have seen on
3467 the wire is the submitted time and this has
3468 the notify size set to 4. -tpot */
3470 case NOTIFY_POINTER:
3473 case NOTIFY_SECDESC:
3479 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3484 /*******************************************************************
3485 Return the type of notify_info_data.
3486 ********************************************************************/
3488 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3492 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3493 if (notify_info_data_table[i].type == type &&
3494 notify_info_data_table[i].field == field)
3495 return notify_info_data_table[i].size;
3501 /****************************************************************************
3502 ****************************************************************************/
3504 static BOOL search_notify(uint16 type, uint16 field, int *value)
3508 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3509 if (notify_info_data_table[i].type == type &&
3510 notify_info_data_table[i].field == field &&
3511 notify_info_data_table[i].fn != NULL) {
3520 /****************************************************************************
3521 ****************************************************************************/
3523 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3525 info_data->type = type;
3526 info_data->field = field;
3527 info_data->reserved = 0;
3529 info_data->size = size_of_notify_info_data(type, field);
3530 info_data->enc_type = type_of_notify_info_data(type, field);
3535 /*******************************************************************
3537 * fill a notify_info struct with info asked
3539 ********************************************************************/
3541 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3542 snum, SPOOL_NOTIFY_OPTION_TYPE
3543 *option_type, uint32 id,
3544 TALLOC_CTX *mem_ctx)
3550 SPOOL_NOTIFY_INFO_DATA *current_data;
3551 NT_PRINTER_INFO_LEVEL *printer = NULL;
3552 print_queue_struct *queue=NULL;
3554 type=option_type->type;
3556 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3557 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3558 option_type->count, lp_servicename(snum)));
3560 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3563 for(field_num=0; field_num<option_type->count; field_num++) {
3564 field = option_type->fields[field_num];
3566 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3568 if (!search_notify(type, field, &j) )
3571 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3572 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3573 free_a_printer(&printer, 2);
3577 current_data = &info->data[info->count];
3579 construct_info_data(current_data, type, field, id);
3581 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3582 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3584 notify_info_data_table[j].fn(snum, current_data, queue,
3590 free_a_printer(&printer, 2);
3594 /*******************************************************************
3596 * fill a notify_info struct with info asked
3598 ********************************************************************/
3600 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3601 SPOOL_NOTIFY_INFO *info,
3602 NT_PRINTER_INFO_LEVEL *printer,
3603 int snum, SPOOL_NOTIFY_OPTION_TYPE
3604 *option_type, uint32 id,
3605 TALLOC_CTX *mem_ctx)
3611 SPOOL_NOTIFY_INFO_DATA *current_data;
3613 DEBUG(4,("construct_notify_jobs_info\n"));
3615 type = option_type->type;
3617 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3618 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3619 option_type->count));
3621 for(field_num=0; field_num<option_type->count; field_num++) {
3622 field = option_type->fields[field_num];
3624 if (!search_notify(type, field, &j) )
3627 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3628 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3632 current_data=&(info->data[info->count]);
3634 construct_info_data(current_data, type, field, id);
3635 notify_info_data_table[j].fn(snum, current_data, queue,
3644 * JFM: The enumeration is not that simple, it's even non obvious.
3646 * let's take an example: I want to monitor the PRINTER SERVER for
3647 * the printer's name and the number of jobs currently queued.
3648 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3649 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3651 * I have 3 printers on the back of my server.
3653 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3656 * 1 printer 1 name 1
3657 * 2 printer 1 cjob 1
3658 * 3 printer 2 name 2
3659 * 4 printer 2 cjob 2
3660 * 5 printer 3 name 3
3661 * 6 printer 3 name 3
3663 * that's the print server case, the printer case is even worse.
3666 /*******************************************************************
3668 * enumerate all printers on the printserver
3669 * fill a notify_info struct with info asked
3671 ********************************************************************/
3673 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3674 SPOOL_NOTIFY_INFO *info,
3675 TALLOC_CTX *mem_ctx)
3678 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3679 int n_services=lp_numservices();
3681 SPOOL_NOTIFY_OPTION *option;
3682 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3684 DEBUG(4,("printserver_notify_info\n"));
3689 option=Printer->notify.option;
3694 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3695 sending a ffpcn() request first */
3700 for (i=0; i<option->count; i++) {
3701 option_type=&(option->ctr.type[i]);
3703 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3706 for (snum=0; snum<n_services; snum++)
3708 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3709 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3715 * Debugging information, don't delete.
3718 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3719 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3720 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3722 for (i=0; i<info->count; i++) {
3723 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3724 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3725 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3732 /*******************************************************************
3734 * fill a notify_info struct with info asked
3736 ********************************************************************/
3738 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3739 TALLOC_CTX *mem_ctx)
3742 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3745 SPOOL_NOTIFY_OPTION *option;
3746 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3748 print_queue_struct *queue=NULL;
3749 print_status_struct status;
3751 DEBUG(4,("printer_notify_info\n"));
3756 option=Printer->notify.option;
3762 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3763 sending a ffpcn() request first */
3768 get_printer_snum(p, hnd, &snum, NULL);
3770 for (i=0; i<option->count; i++) {
3771 option_type=&option->ctr.type[i];
3773 switch ( option_type->type ) {
3774 case PRINTER_NOTIFY_TYPE:
3775 if(construct_notify_printer_info(Printer, info, snum,
3781 case JOB_NOTIFY_TYPE: {
3782 NT_PRINTER_INFO_LEVEL *printer = NULL;
3784 count = print_queue_status(snum, &queue, &status);
3786 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3789 for (j=0; j<count; j++) {
3790 construct_notify_jobs_info(&queue[j], info,
3797 free_a_printer(&printer, 2);
3807 * Debugging information, don't delete.
3810 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3811 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3812 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3814 for (i=0; i<info->count; i++) {
3815 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3816 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3817 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3823 /********************************************************************
3825 ********************************************************************/
3827 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3829 POLICY_HND *handle = &q_u->handle;
3830 SPOOL_NOTIFY_INFO *info = &r_u->info;
3832 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3833 WERROR result = WERR_BADFID;
3835 /* we always have a NOTIFY_INFO struct */
3839 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3840 OUR_HANDLE(handle)));
3844 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3847 * We are now using the change value, and
3848 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3849 * I don't have a global notification system, I'm sending back all the
3850 * informations even when _NOTHING_ has changed.
3853 /* We need to keep track of the change value to send back in
3854 RRPCN replies otherwise our updates are ignored. */
3856 Printer->notify.fnpcn = True;
3858 if (Printer->notify.client_connected) {
3859 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3860 Printer->notify.change = q_u->change;
3863 /* just ignore the SPOOL_NOTIFY_OPTION */
3865 switch (Printer->printer_type) {
3867 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3870 case SPLHND_PRINTER:
3871 result = printer_notify_info(p, handle, info, p->mem_ctx);
3875 Printer->notify.fnpcn = False;
3881 /********************************************************************
3882 * construct_printer_info_0
3883 * fill a printer_info_0 struct
3884 ********************************************************************/
3886 static BOOL construct_printer_info_0(Printer_entry *print_hnd,
3887 PRINTER_INFO_0 *printer,
3888 const struct share_params *params)
3892 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3893 counter_printer_0 *session_counter;
3894 uint32 global_counter;
3897 print_status_struct status;
3899 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
3900 lp_const_servicename(params->service))))
3903 count = print_queue_length(params->service, &status);
3905 /* check if we already have a counter for this printer */
3906 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3907 if (session_counter->snum == params->service)
3911 /* it's the first time, add it to the list */
3912 if (session_counter==NULL) {
3913 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3914 free_a_printer(&ntprinter, 2);
3917 ZERO_STRUCTP(session_counter);
3918 session_counter->snum=params->service;
3919 session_counter->counter=0;
3920 DLIST_ADD(counter_list, session_counter);
3924 session_counter->counter++;
3927 * the global_counter should be stored in a TDB as it's common to all the clients
3928 * and should be zeroed on samba startup
3930 global_counter=session_counter->counter;
3932 pstrcpy(chaine,ntprinter->info_2->printername);
3934 init_unistr(&printer->printername, chaine);
3936 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3937 init_unistr(&printer->servername, chaine);
3939 printer->cjobs = count;
3940 printer->total_jobs = 0;
3941 printer->total_bytes = 0;
3943 setuptime = (time_t)ntprinter->info_2->setuptime;
3944 t=gmtime(&setuptime);
3946 printer->year = t->tm_year+1900;
3947 printer->month = t->tm_mon+1;
3948 printer->dayofweek = t->tm_wday;
3949 printer->day = t->tm_mday;
3950 printer->hour = t->tm_hour;
3951 printer->minute = t->tm_min;
3952 printer->second = t->tm_sec;
3953 printer->milliseconds = 0;
3955 printer->global_counter = global_counter;
3956 printer->total_pages = 0;
3958 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3959 printer->major_version = 0x0005; /* NT 5 */
3960 printer->build_version = 0x0893; /* build 2195 */
3962 printer->unknown7 = 0x1;
3963 printer->unknown8 = 0x0;
3964 printer->unknown9 = 0x0;
3965 printer->session_counter = session_counter->counter;
3966 printer->unknown11 = 0x0;
3967 printer->printer_errors = 0x0; /* number of print failure */
3968 printer->unknown13 = 0x0;
3969 printer->unknown14 = 0x1;
3970 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3971 printer->unknown16 = 0x0;
3972 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3973 printer->unknown18 = 0x0;
3974 printer->status = nt_printq_status(status.status);
3975 printer->unknown20 = 0x0;
3976 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3977 printer->unknown22 = 0x0;
3978 printer->unknown23 = 0x6; /* 6 ???*/
3979 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3980 printer->unknown25 = 0;
3981 printer->unknown26 = 0;
3982 printer->unknown27 = 0;
3983 printer->unknown28 = 0;
3984 printer->unknown29 = 0;
3986 free_a_printer(&ntprinter,2);
3990 /********************************************************************
3991 * construct_printer_info_1
3992 * fill a printer_info_1 struct
3993 ********************************************************************/
3994 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags,
3995 PRINTER_INFO_1 *printer,
3996 const struct share_params *params)
4000 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4002 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4003 lp_const_servicename(params->service))))
4006 printer->flags=flags;
4008 if (*ntprinter->info_2->comment == '\0') {
4009 init_unistr(&printer->comment, lp_comment(params->service));
4010 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4011 ntprinter->info_2->drivername,
4012 lp_comment(params->service));
4015 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4016 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4017 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4020 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4022 init_unistr(&printer->description, chaine);
4023 init_unistr(&printer->name, chaine2);
4025 free_a_printer(&ntprinter,2);
4030 /****************************************************************************
4031 Free a DEVMODE struct.
4032 ****************************************************************************/
4034 static void free_dev_mode(DEVICEMODE *dev)
4039 SAFE_FREE(dev->dev_private);
4044 /****************************************************************************
4045 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4046 should be valid upon entry
4047 ****************************************************************************/
4049 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4051 if ( !devmode || !ntdevmode )
4054 init_unistr(&devmode->devicename, ntdevmode->devicename);
4056 init_unistr(&devmode->formname, ntdevmode->formname);
4058 devmode->specversion = ntdevmode->specversion;
4059 devmode->driverversion = ntdevmode->driverversion;
4060 devmode->size = ntdevmode->size;
4061 devmode->driverextra = ntdevmode->driverextra;
4062 devmode->fields = ntdevmode->fields;
4064 devmode->orientation = ntdevmode->orientation;
4065 devmode->papersize = ntdevmode->papersize;
4066 devmode->paperlength = ntdevmode->paperlength;
4067 devmode->paperwidth = ntdevmode->paperwidth;
4068 devmode->scale = ntdevmode->scale;
4069 devmode->copies = ntdevmode->copies;
4070 devmode->defaultsource = ntdevmode->defaultsource;
4071 devmode->printquality = ntdevmode->printquality;
4072 devmode->color = ntdevmode->color;
4073 devmode->duplex = ntdevmode->duplex;
4074 devmode->yresolution = ntdevmode->yresolution;
4075 devmode->ttoption = ntdevmode->ttoption;
4076 devmode->collate = ntdevmode->collate;
4077 devmode->icmmethod = ntdevmode->icmmethod;
4078 devmode->icmintent = ntdevmode->icmintent;
4079 devmode->mediatype = ntdevmode->mediatype;
4080 devmode->dithertype = ntdevmode->dithertype;
4082 if (ntdevmode->nt_dev_private != NULL) {
4083 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4090 /****************************************************************************
4091 Create a DEVMODE struct. Returns malloced memory.
4092 ****************************************************************************/
4094 DEVICEMODE *construct_dev_mode(const char *servicename)
4096 NT_PRINTER_INFO_LEVEL *printer = NULL;
4097 DEVICEMODE *devmode = NULL;
4099 DEBUG(7,("construct_dev_mode\n"));
4101 DEBUGADD(8,("getting printer characteristics\n"));
4103 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4106 if ( !printer->info_2->devmode ) {
4107 DEBUG(5, ("BONG! There was no device mode!\n"));
4111 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4112 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4116 ZERO_STRUCTP(devmode);
4118 DEBUGADD(8,("loading DEVICEMODE\n"));
4120 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4121 free_dev_mode( devmode );
4126 free_a_printer(&printer,2);
4131 /********************************************************************
4132 * construct_printer_info_2
4133 * fill a printer_info_2 struct
4134 ********************************************************************/
4136 static BOOL construct_printer_info_2(Printer_entry *print_hnd,
4137 PRINTER_INFO_2 *printer,
4138 const struct share_params *params)
4141 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4143 print_status_struct status;
4145 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4146 lp_const_servicename(params->service))))
4149 count = print_queue_length(params->service, &status);
4151 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4152 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4153 init_unistr(&printer->sharename, lp_servicename(params->service)); /* sharename */
4154 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4155 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4157 if (*ntprinter->info_2->comment == '\0')
4158 init_unistr(&printer->comment, lp_comment(params->service)); /* comment */
4160 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4162 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4163 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4164 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4165 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4166 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4168 printer->attributes = ntprinter->info_2->attributes;
4170 printer->priority = ntprinter->info_2->priority; /* priority */
4171 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4172 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4173 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4174 printer->status = nt_printq_status(status.status); /* status */
4175 printer->cjobs = count; /* jobs */
4176 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4178 if ( !(printer->devmode = construct_dev_mode(
4179 lp_const_servicename(params->service))) )
4180 DEBUG(8, ("Returning NULL Devicemode!\n"));
4182 printer->secdesc = NULL;
4184 if ( ntprinter->info_2->secdesc_buf
4185 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4187 /* don't use talloc_steal() here unless you do a deep steal of all
4188 the SEC_DESC members */
4190 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4191 ntprinter->info_2->secdesc_buf->sd );
4194 free_a_printer(&ntprinter, 2);
4199 /********************************************************************
4200 * construct_printer_info_3
4201 * fill a printer_info_3 struct
4202 ********************************************************************/
4204 static BOOL construct_printer_info_3(Printer_entry *print_hnd,
4205 PRINTER_INFO_3 **pp_printer,
4206 const struct share_params *params)
4208 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4209 PRINTER_INFO_3 *printer = NULL;
4211 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4212 lp_const_servicename(params->service))))
4216 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4217 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4218 free_a_printer(&ntprinter, 2);
4222 ZERO_STRUCTP(printer);
4224 /* These are the components of the SD we are returning. */
4226 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4227 /* don't use talloc_steal() here unless you do a deep steal of all
4228 the SEC_DESC members */
4230 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4231 ntprinter->info_2->secdesc_buf->sd );
4234 free_a_printer(&ntprinter, 2);
4236 *pp_printer = printer;
4240 /********************************************************************
4241 * construct_printer_info_4
4242 * fill a printer_info_4 struct
4243 ********************************************************************/
4245 static BOOL construct_printer_info_4(Printer_entry *print_hnd,
4246 PRINTER_INFO_4 *printer,
4247 const struct share_params *params)
4249 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4251 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4252 lp_const_servicename(params->service))))
4255 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4256 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4257 printer->attributes = ntprinter->info_2->attributes;
4259 free_a_printer(&ntprinter, 2);
4263 /********************************************************************
4264 * construct_printer_info_5
4265 * fill a printer_info_5 struct
4266 ********************************************************************/
4268 static BOOL construct_printer_info_5(Printer_entry *print_hnd,
4269 PRINTER_INFO_5 *printer,
4270 const struct share_params *params)
4272 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4274 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4275 lp_const_servicename(params->service))))
4278 init_unistr(&printer->printername, ntprinter->info_2->printername);
4279 init_unistr(&printer->portname, ntprinter->info_2->portname);
4280 printer->attributes = ntprinter->info_2->attributes;
4282 /* these two are not used by NT+ according to MSDN */
4284 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4285 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4287 free_a_printer(&ntprinter, 2);
4292 /********************************************************************
4293 * construct_printer_info_6
4294 * fill a printer_info_6 struct
4295 ********************************************************************/
4297 static BOOL construct_printer_info_6(Printer_entry *print_hnd,
4298 PRINTER_INFO_6 *printer,
4299 const struct share_params *params)
4301 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4303 print_status_struct status;
4305 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4306 lp_const_servicename(params->service))))
4309 count = print_queue_length(params->service, &status);
4311 printer->status = nt_printq_status(status.status);
4313 free_a_printer(&ntprinter, 2);
4318 /********************************************************************
4319 * construct_printer_info_7
4320 * fill a printer_info_7 struct
4321 ********************************************************************/
4323 static BOOL construct_printer_info_7(Printer_entry *print_hnd,
4324 PRINTER_INFO_7 *printer,
4325 const struct share_params *params)
4327 char *guid_str = NULL;
4330 if (is_printer_published(print_hnd, params->service, &guid)) {
4331 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4332 strupper_m(guid_str);
4333 init_unistr(&printer->guid, guid_str);
4334 printer->action = SPOOL_DS_PUBLISH;
4336 init_unistr(&printer->guid, "");
4337 printer->action = SPOOL_DS_UNPUBLISH;
4343 /********************************************************************
4344 Spoolss_enumprinters.
4345 ********************************************************************/
4347 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4350 struct share_iterator *shares;
4351 struct share_params *printer;
4352 PRINTER_INFO_1 *printers=NULL;
4353 WERROR result = WERR_OK;
4355 DEBUG(4,("enum_all_printers_info_1\n"));
4357 if (!(shares = share_list_all(NULL))) {
4358 DEBUG(5, ("Could not list printers\n"));
4359 return WERR_ACCESS_DENIED;
4362 while ((printer = next_printer(shares)) != NULL) {
4363 PRINTER_INFO_1 current_prt;
4365 DEBUG(4,("Found a printer in smb.conf: %s\n",
4366 lp_servicename(printer->service)));
4368 if (!construct_printer_info_1(NULL, flags, ¤t_prt,
4373 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1,
4374 *returned +1)) == NULL) {
4375 DEBUG(2,("enum_all_printers_info_1: failed to enlarge "
4376 "printers buffer!\n"));
4378 TALLOC_FREE(shares);
4381 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n",
4384 memcpy(&printers[*returned], ¤t_prt,
4385 sizeof(PRINTER_INFO_1));
4387 TALLOC_FREE(printer);
4390 /* check the required size. */
4391 for (i=0; i<*returned; i++)
4392 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4394 if (*needed > offered) {
4395 result = WERR_INSUFFICIENT_BUFFER;
4399 if (!rpcbuf_alloc_size(buffer, *needed)) {
4400 result = WERR_NOMEM;
4404 /* fill the buffer with the structures */
4405 for (i=0; i<*returned; i++)
4406 smb_io_printer_info_1("", buffer, &printers[i], 0);
4411 SAFE_FREE(printers);
4412 TALLOC_FREE(shares);
4414 if ( !W_ERROR_IS_OK(result) )
4420 /********************************************************************
4421 enum_all_printers_info_1_local.
4422 *********************************************************************/
4424 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4426 DEBUG(4,("enum_all_printers_info_1_local\n"));
4428 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4431 /********************************************************************
4432 enum_all_printers_info_1_name.
4433 *********************************************************************/
4435 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4439 DEBUG(4,("enum_all_printers_info_1_name\n"));
4441 if ((name[0] == '\\') && (name[1] == '\\'))
4444 if (is_myname_or_ipaddr(s)) {
4445 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4448 return WERR_INVALID_NAME;
4451 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4452 /********************************************************************
4453 enum_all_printers_info_1_remote.
4454 *********************************************************************/
4456 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4458 PRINTER_INFO_1 *printer;
4459 fstring printername;
4462 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4463 WERROR result = WERR_OK;
4465 /* JFM: currently it's more a place holder than anything else.
4466 * In the spooler world there is a notion of server registration.
4467 * the print servers are registered on the PDC (in the same domain)
4469 * We should have a TDB here. The registration is done thru an
4470 * undocumented RPC call.
4473 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4478 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4479 slprintf(desc, sizeof(desc)-1,"%s", name);
4480 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4482 init_unistr(&printer->description, desc);
4483 init_unistr(&printer->name, printername);
4484 init_unistr(&printer->comment, comment);
4485 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4487 /* check the required size. */
4488 *needed += spoolss_size_printer_info_1(printer);
4490 if (*needed > offered) {
4491 result = WERR_INSUFFICIENT_BUFFER;
4495 if (!rpcbuf_alloc_size(buffer, *needed)) {
4496 result = WERR_NOMEM;
4500 /* fill the buffer with the structures */
4501 smb_io_printer_info_1("", buffer, printer, 0);
4507 if ( !W_ERROR_IS_OK(result) )
4515 /********************************************************************
4516 enum_all_printers_info_1_network.
4517 *********************************************************************/
4519 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4523 DEBUG(4,("enum_all_printers_info_1_network\n"));
4525 /* If we respond to a enum_printers level 1 on our name with flags
4526 set to PRINTER_ENUM_REMOTE with a list of printers then these
4527 printers incorrectly appear in the APW browse list.
4528 Specifically the printers for the server appear at the workgroup
4529 level where all the other servers in the domain are
4530 listed. Windows responds to this call with a
4531 WERR_CAN_NOT_COMPLETE so we should do the same. */
4533 if (name[0] == '\\' && name[1] == '\\')
4536 if (is_myname_or_ipaddr(s))
4537 return WERR_CAN_NOT_COMPLETE;
4539 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4542 /********************************************************************
4543 * api_spoolss_enumprinters
4545 * called from api_spoolss_enumprinters (see this to understand)
4546 ********************************************************************/
4548 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4551 struct share_iterator *shares;
4552 struct share_params *printer;
4553 PRINTER_INFO_2 *printers=NULL;
4554 WERROR result = WERR_OK;
4558 if (!(shares = share_list_all(NULL))) {
4559 DEBUG(5, ("Could not list printers\n"));
4560 return WERR_ACCESS_DENIED;
4563 while ((printer = next_printer(shares)) != NULL) {
4564 PRINTER_INFO_2 current_prt;
4566 DEBUG(4,("Found a printer in smb.conf: %s\n",
4567 lp_servicename(printer->service)));
4569 if (!construct_printer_info_2(NULL, ¤t_prt,
4573 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2,
4575 DEBUG(2,("enum_all_printers_info_2: failed to enlarge "
4576 "printers buffer!\n"));
4578 TALLOC_FREE(shares);
4582 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n",
4585 memcpy(&printers[*returned], ¤t_prt,
4586 sizeof(PRINTER_INFO_2));
4588 TALLOC_FREE(printer);
4591 /* check the required size. */
4592 for (i=0; i<*returned; i++)
4593 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4595 if (*needed > offered) {
4596 result = WERR_INSUFFICIENT_BUFFER;
4600 if (!rpcbuf_alloc_size(buffer, *needed)) {
4601 result = WERR_NOMEM;
4605 /* fill the buffer with the structures */
4606 for (i=0; i<*returned; i++)
4607 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4612 for (i=0; i<*returned; i++)
4613 free_devmode(printers[i].devmode);
4615 SAFE_FREE(printers);
4616 TALLOC_FREE(shares);
4618 if ( !W_ERROR_IS_OK(result) )
4624 /********************************************************************
4625 * handle enumeration of printers at level 1
4626 ********************************************************************/
4628 static WERROR enumprinters_level1( uint32 flags, fstring name,
4629 RPC_BUFFER *buffer, uint32 offered,
4630 uint32 *needed, uint32 *returned)
4632 /* Not all the flags are equals */
4634 if (flags & PRINTER_ENUM_LOCAL)
4635 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4637 if (flags & PRINTER_ENUM_NAME)
4638 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4640 #if 0 /* JERRY - disabled for now */
4641 if (flags & PRINTER_ENUM_REMOTE)
4642 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4645 if (flags & PRINTER_ENUM_NETWORK)
4646 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4648 return WERR_OK; /* NT4sp5 does that */
4651 /********************************************************************
4652 * handle enumeration of printers at level 2
4653 ********************************************************************/
4655 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4656 RPC_BUFFER *buffer, uint32 offered,
4657 uint32 *needed, uint32 *returned)
4659 char *s = servername;
4661 if (flags & PRINTER_ENUM_LOCAL) {
4662 return enum_all_printers_info_2(buffer, offered, needed, returned);
4665 if (flags & PRINTER_ENUM_NAME) {
4666 if ((servername[0] == '\\') && (servername[1] == '\\'))
4668 if (is_myname_or_ipaddr(s))
4669 return enum_all_printers_info_2(buffer, offered, needed, returned);
4671 return WERR_INVALID_NAME;
4674 if (flags & PRINTER_ENUM_REMOTE)
4675 return WERR_UNKNOWN_LEVEL;
4680 /********************************************************************
4681 * handle enumeration of printers at level 5
4682 ********************************************************************/
4684 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4685 RPC_BUFFER *buffer, uint32 offered,
4686 uint32 *needed, uint32 *returned)
4688 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4692 /********************************************************************
4693 * api_spoolss_enumprinters
4695 * called from api_spoolss_enumprinters (see this to understand)
4696 ********************************************************************/
4698 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4700 uint32 flags = q_u->flags;
4701 UNISTR2 *servername = &q_u->servername;
4702 uint32 level = q_u->level;
4703 RPC_BUFFER *buffer = NULL;
4704 uint32 offered = q_u->offered;
4705 uint32 *needed = &r_u->needed;
4706 uint32 *returned = &r_u->returned;
4710 /* that's an [in out] buffer */
4712 if (!q_u->buffer && (offered!=0)) {
4713 return WERR_INVALID_PARAM;
4716 rpcbuf_move(q_u->buffer, &r_u->buffer);
4717 buffer = r_u->buffer;
4719 DEBUG(4,("_spoolss_enumprinters\n"));
4726 * flags==PRINTER_ENUM_NAME
4727 * if name=="" then enumerates all printers
4728 * if name!="" then enumerate the printer
4729 * flags==PRINTER_ENUM_REMOTE
4730 * name is NULL, enumerate printers
4731 * Level 2: name!="" enumerates printers, name can't be NULL
4732 * Level 3: doesn't exist
4733 * Level 4: does a local registry lookup
4734 * Level 5: same as Level 2
4737 unistr2_to_ascii(name, servername, sizeof(name)-1);
4742 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4744 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4746 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4751 return WERR_UNKNOWN_LEVEL;
4754 /****************************************************************************
4755 ****************************************************************************/
4757 static WERROR getprinter_level_0(Printer_entry *print_hnd,
4758 const struct share_params *params,
4759 RPC_BUFFER *buffer, uint32 offered,
4762 PRINTER_INFO_0 *printer=NULL;
4763 WERROR result = WERR_OK;
4765 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4768 construct_printer_info_0(print_hnd, printer, params);
4770 /* check the required size. */
4771 *needed += spoolss_size_printer_info_0(printer);
4773 if (*needed > offered) {
4774 result = WERR_INSUFFICIENT_BUFFER;
4778 if (!rpcbuf_alloc_size(buffer, *needed)) {
4779 result = WERR_NOMEM;
4783 /* fill the buffer with the structures */
4784 smb_io_printer_info_0("", buffer, printer, 0);
4794 /****************************************************************************
4795 ****************************************************************************/
4797 static WERROR getprinter_level_1(Printer_entry *print_hnd,
4798 const struct share_params *params,
4799 RPC_BUFFER *buffer, uint32 offered,
4802 PRINTER_INFO_1 *printer=NULL;
4803 WERROR result = WERR_OK;
4805 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4808 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer,
4811 /* check the required size. */
4812 *needed += spoolss_size_printer_info_1(printer);
4814 if (*needed > offered) {
4815 result = WERR_INSUFFICIENT_BUFFER;
4819 if (!rpcbuf_alloc_size(buffer, *needed)) {
4820 result = WERR_NOMEM;
4824 /* fill the buffer with the structures */
4825 smb_io_printer_info_1("", buffer, printer, 0);
4834 /****************************************************************************
4835 ****************************************************************************/
4837 static WERROR getprinter_level_2(Printer_entry *print_hnd,
4838 const struct share_params *params,
4839 RPC_BUFFER *buffer, uint32 offered,
4842 PRINTER_INFO_2 *printer=NULL;
4843 WERROR result = WERR_OK;
4845 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4848 construct_printer_info_2(print_hnd, printer, params);
4850 /* check the required size. */
4851 *needed += spoolss_size_printer_info_2(printer);
4853 if (*needed > offered) {
4854 result = WERR_INSUFFICIENT_BUFFER;
4858 if (!rpcbuf_alloc_size(buffer, *needed)) {
4859 result = WERR_NOMEM;
4863 /* fill the buffer with the structures */
4864 if (!smb_io_printer_info_2("", buffer, printer, 0))
4865 result = WERR_NOMEM;
4869 free_printer_info_2(printer);
4874 /****************************************************************************
4875 ****************************************************************************/
4877 static WERROR getprinter_level_3(Printer_entry *print_hnd,
4878 const struct share_params *params,
4879 RPC_BUFFER *buffer, uint32 offered,
4882 PRINTER_INFO_3 *printer=NULL;
4883 WERROR result = WERR_OK;
4885 if (!construct_printer_info_3(print_hnd, &printer, params))
4888 /* check the required size. */
4889 *needed += spoolss_size_printer_info_3(printer);
4891 if (*needed > offered) {
4892 result = WERR_INSUFFICIENT_BUFFER;
4896 if (!rpcbuf_alloc_size(buffer, *needed)) {
4897 result = WERR_NOMEM;
4901 /* fill the buffer with the structures */
4902 smb_io_printer_info_3("", buffer, printer, 0);
4906 free_printer_info_3(printer);
4911 /****************************************************************************
4912 ****************************************************************************/
4914 static WERROR getprinter_level_4(Printer_entry *print_hnd,
4915 const struct share_params *params,
4916 RPC_BUFFER *buffer, uint32 offered,
4919 PRINTER_INFO_4 *printer=NULL;
4920 WERROR result = WERR_OK;
4922 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4925 if (!construct_printer_info_4(print_hnd, printer, params)) {
4930 /* check the required size. */
4931 *needed += spoolss_size_printer_info_4(printer);
4933 if (*needed > offered) {
4934 result = WERR_INSUFFICIENT_BUFFER;
4938 if (!rpcbuf_alloc_size(buffer, *needed)) {
4939 result = WERR_NOMEM;
4943 /* fill the buffer with the structures */
4944 smb_io_printer_info_4("", buffer, printer, 0);
4948 free_printer_info_4(printer);
4953 /****************************************************************************
4954 ****************************************************************************/
4956 static WERROR getprinter_level_5(Printer_entry *print_hnd,
4957 const struct share_params *params,
4958 RPC_BUFFER *buffer, uint32 offered,
4961 PRINTER_INFO_5 *printer=NULL;
4962 WERROR result = WERR_OK;
4964 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4967 if (!construct_printer_info_5(print_hnd, printer, params)) {
4968 free_printer_info_5(printer);
4972 /* check the required size. */
4973 *needed += spoolss_size_printer_info_5(printer);
4975 if (*needed > offered) {
4976 result = WERR_INSUFFICIENT_BUFFER;
4980 if (!rpcbuf_alloc_size(buffer, *needed)) {
4981 result = WERR_NOMEM;
4985 /* fill the buffer with the structures */
4986 smb_io_printer_info_5("", buffer, printer, 0);
4990 free_printer_info_5(printer);
4995 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4996 const struct share_params *params,
4997 RPC_BUFFER *buffer, uint32 offered,
5000 PRINTER_INFO_6 *printer;
5001 WERROR result = WERR_OK;
5003 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5007 if (!construct_printer_info_6(print_hnd, printer, params)) {
5008 free_printer_info_6(printer);
5012 /* check the required size. */
5013 *needed += spoolss_size_printer_info_6(printer);
5015 if (*needed > offered) {
5016 result = WERR_INSUFFICIENT_BUFFER;
5020 if (!rpcbuf_alloc_size(buffer, *needed)) {
5021 result = WERR_NOMEM;
5025 /* fill the buffer with the structures */
5026 smb_io_printer_info_6("", buffer, printer, 0);
5030 free_printer_info_6(printer);
5035 static WERROR getprinter_level_7(Printer_entry *print_hnd,
5036 const struct share_params *params,
5037 RPC_BUFFER *buffer, uint32 offered,
5040 PRINTER_INFO_7 *printer=NULL;
5041 WERROR result = WERR_OK;
5043 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5046 if (!construct_printer_info_7(print_hnd, printer, params))
5049 /* check the required size. */
5050 *needed += spoolss_size_printer_info_7(printer);
5052 if (*needed > offered) {
5053 result = WERR_INSUFFICIENT_BUFFER;
5057 if (!rpcbuf_alloc_size(buffer, *needed)) {
5058 result = WERR_NOMEM;
5063 /* fill the buffer with the structures */
5064 smb_io_printer_info_7("", buffer, printer, 0);
5068 free_printer_info_7(printer);
5073 /****************************************************************************
5074 ****************************************************************************/
5076 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5078 POLICY_HND *handle = &q_u->handle;
5079 uint32 level = q_u->level;
5080 RPC_BUFFER *buffer = NULL;
5081 uint32 offered = q_u->offered;
5082 uint32 *needed = &r_u->needed;
5083 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5084 struct share_params *params;
5088 /* that's an [in out] buffer */
5090 if (!q_u->buffer && (offered!=0)) {
5091 return WERR_INVALID_PARAM;
5094 rpcbuf_move(q_u->buffer, &r_u->buffer);
5095 buffer = r_u->buffer;
5099 if (!get_printer_snum(p, handle, &snum, ¶ms))
5104 return getprinter_level_0(Printer, params, buffer, offered,
5107 return getprinter_level_1(Printer, params, buffer, offered,
5110 return getprinter_level_2(Printer, params, buffer, offered,
5113 return getprinter_level_3(Printer, params, buffer, offered,
5116 return getprinter_level_4(Printer, params, buffer, offered,
5119 return getprinter_level_5(Printer, params, buffer, offered,
5122 return getprinter_level_6(Printer, params, buffer, offered,
5125 return getprinter_level_7(Printer, params, buffer, offered,
5128 return WERR_UNKNOWN_LEVEL;
5131 /********************************************************************
5132 * fill a DRIVER_INFO_1 struct
5133 ********************************************************************/
5135 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5137 init_unistr( &info->name, driver.info_3->name);
5140 /********************************************************************
5141 * construct_printer_driver_info_1
5142 ********************************************************************/
5144 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5146 NT_PRINTER_INFO_LEVEL *printer = NULL;
5147 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5149 ZERO_STRUCT(driver);
5151 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5152 return WERR_INVALID_PRINTER_NAME;
5154 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5155 free_a_printer(&printer, 2);
5156 return WERR_UNKNOWN_PRINTER_DRIVER;
5159 fill_printer_driver_info_1(info, driver, servername, architecture);
5161 free_a_printer(&printer,2);
5166 /********************************************************************
5167 * construct_printer_driver_info_2
5168 * fill a printer_info_2 struct
5169 ********************************************************************/
5171 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5175 info->version=driver.info_3->cversion;
5177 init_unistr( &info->name, driver.info_3->name );
5178 init_unistr( &info->architecture, driver.info_3->environment );
5181 if (strlen(driver.info_3->driverpath)) {
5182 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5183 init_unistr( &info->driverpath, temp );
5185 init_unistr( &info->driverpath, "" );
5187 if (strlen(driver.info_3->datafile)) {
5188 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5189 init_unistr( &info->datafile, temp );
5191 init_unistr( &info->datafile, "" );
5193 if (strlen(driver.info_3->configfile)) {
5194 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5195 init_unistr( &info->configfile, temp );
5197 init_unistr( &info->configfile, "" );
5200 /********************************************************************
5201 * construct_printer_driver_info_2
5202 * fill a printer_info_2 struct
5203 ********************************************************************/
5205 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5207 NT_PRINTER_INFO_LEVEL *printer = NULL;
5208 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5210 ZERO_STRUCT(printer);
5211 ZERO_STRUCT(driver);
5213 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5214 return WERR_INVALID_PRINTER_NAME;
5216 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5217 free_a_printer(&printer, 2);
5218 return WERR_UNKNOWN_PRINTER_DRIVER;
5221 fill_printer_driver_info_2(info, driver, servername);
5223 free_a_printer(&printer,2);
5228 /********************************************************************
5229 * copy a strings array and convert to UNICODE
5231 * convert an array of ascii string to a UNICODE string
5232 ********************************************************************/
5234 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5241 DEBUG(6,("init_unistr_array\n"));
5252 v = ""; /* hack to handle null lists */
5255 /* hack to allow this to be used in places other than when generating
5256 the list of dependent files */
5259 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5263 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5265 /* add one extra unit16 for the second terminating NULL */
5267 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5268 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5275 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5280 /* special case for ""; we need to add both NULL's here */
5282 (*uni_array)[j++]=0x0000;
5283 (*uni_array)[j]=0x0000;
5286 DEBUGADD(6,("last one:done\n"));
5288 /* return size of array in uint16's */
5293 /********************************************************************
5294 * construct_printer_info_3
5295 * fill a printer_info_3 struct
5296 ********************************************************************/
5298 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5304 info->version=driver.info_3->cversion;
5306 init_unistr( &info->name, driver.info_3->name );
5307 init_unistr( &info->architecture, driver.info_3->environment );
5309 if (strlen(driver.info_3->driverpath)) {
5310 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5311 init_unistr( &info->driverpath, temp );
5313 init_unistr( &info->driverpath, "" );
5315 if (strlen(driver.info_3->datafile)) {
5316 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5317 init_unistr( &info->datafile, temp );
5319 init_unistr( &info->datafile, "" );
5321 if (strlen(driver.info_3->configfile)) {
5322 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5323 init_unistr( &info->configfile, temp );
5325 init_unistr( &info->configfile, "" );
5327 if (strlen(driver.info_3->helpfile)) {
5328 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5329 init_unistr( &info->helpfile, temp );
5331 init_unistr( &info->helpfile, "" );
5333 init_unistr( &info->monitorname, driver.info_3->monitorname );
5334 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5336 info->dependentfiles=NULL;
5337 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5340 /********************************************************************
5341 * construct_printer_info_3
5342 * fill a printer_info_3 struct
5343 ********************************************************************/
5345 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5347 NT_PRINTER_INFO_LEVEL *printer = NULL;
5348 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5350 ZERO_STRUCT(driver);
5352 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5353 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5354 if (!W_ERROR_IS_OK(status))
5355 return WERR_INVALID_PRINTER_NAME;
5357 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5358 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5363 * I put this code in during testing. Helpful when commenting out the
5364 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5365 * as win2k always queries the driver using an infor level of 6.
5366 * I've left it in (but ifdef'd out) because I'll probably
5367 * use it in experimentation again in the future. --jerry 22/01/2002
5370 if (!W_ERROR_IS_OK(status)) {
5372 * Is this a W2k client ?
5375 /* Yes - try again with a WinNT driver. */
5377 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5378 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5382 if (!W_ERROR_IS_OK(status)) {
5383 free_a_printer(&printer,2);
5384 return WERR_UNKNOWN_PRINTER_DRIVER;
5392 fill_printer_driver_info_3(info, driver, servername);
5394 free_a_printer(&printer,2);
5399 /********************************************************************
5400 * construct_printer_info_6
5401 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5402 ********************************************************************/
5404 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5410 memset(&nullstr, '\0', sizeof(fstring));
5412 info->version=driver.info_3->cversion;
5414 init_unistr( &info->name, driver.info_3->name );
5415 init_unistr( &info->architecture, driver.info_3->environment );
5417 if (strlen(driver.info_3->driverpath)) {
5418 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5419 init_unistr( &info->driverpath, temp );
5421 init_unistr( &info->driverpath, "" );
5423 if (strlen(driver.info_3->datafile)) {
5424 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5425 init_unistr( &info->datafile, temp );
5427 init_unistr( &info->datafile, "" );
5429 if (strlen(driver.info_3->configfile)) {
5430 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5431 init_unistr( &info->configfile, temp );
5433 init_unistr( &info->configfile, "" );
5435 if (strlen(driver.info_3->helpfile)) {
5436 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5437 init_unistr( &info->helpfile, temp );
5439 init_unistr( &info->helpfile, "" );
5441 init_unistr( &info->monitorname, driver.info_3->monitorname );
5442 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5444 info->dependentfiles = NULL;
5445 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5447 info->previousdrivernames=NULL;
5448 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5450 info->driver_date=0;
5453 info->driver_version_low=0;
5454 info->driver_version_high=0;
5456 init_unistr( &info->mfgname, "");
5457 init_unistr( &info->oem_url, "");
5458 init_unistr( &info->hardware_id, "");
5459 init_unistr( &info->provider, "");
5462 /********************************************************************
5463 * construct_printer_info_6
5464 * fill a printer_info_6 struct
5465 ********************************************************************/
5467 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5468 fstring servername, fstring architecture, uint32 version)
5470 NT_PRINTER_INFO_LEVEL *printer = NULL;
5471 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5474 ZERO_STRUCT(driver);
5476 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5478 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5480 if (!W_ERROR_IS_OK(status))
5481 return WERR_INVALID_PRINTER_NAME;
5483 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5485 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5487 if (!W_ERROR_IS_OK(status))
5490 * Is this a W2k client ?
5494 free_a_printer(&printer,2);
5495 return WERR_UNKNOWN_PRINTER_DRIVER;
5498 /* Yes - try again with a WinNT driver. */
5500 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5501 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5502 if (!W_ERROR_IS_OK(status)) {
5503 free_a_printer(&printer,2);
5504 return WERR_UNKNOWN_PRINTER_DRIVER;
5508 fill_printer_driver_info_6(info, driver, servername);
5510 free_a_printer(&printer,2);
5511 free_a_printer_driver(driver, 3);
5516 /****************************************************************************
5517 ****************************************************************************/
5519 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5521 SAFE_FREE(info->dependentfiles);
5524 /****************************************************************************
5525 ****************************************************************************/
5527 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5529 SAFE_FREE(info->dependentfiles);
5532 /****************************************************************************
5533 ****************************************************************************/
5535 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5537 DRIVER_INFO_1 *info=NULL;
5540 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5543 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5544 if (!W_ERROR_IS_OK(result))
5547 /* check the required size. */
5548 *needed += spoolss_size_printer_driver_info_1(info);
5550 if (*needed > offered) {
5551 result = WERR_INSUFFICIENT_BUFFER;
5555 if (!rpcbuf_alloc_size(buffer, *needed)) {
5556 result = WERR_NOMEM;
5560 /* fill the buffer with the structures */
5561 smb_io_printer_driver_info_1("", buffer, info, 0);
5570 /****************************************************************************
5571 ****************************************************************************/
5573 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5575 DRIVER_INFO_2 *info=NULL;
5578 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5581 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5582 if (!W_ERROR_IS_OK(result))
5585 /* check the required size. */
5586 *needed += spoolss_size_printer_driver_info_2(info);
5588 if (*needed > offered) {
5589 result = WERR_INSUFFICIENT_BUFFER;
5593 if (!rpcbuf_alloc_size(buffer, *needed)) {
5594 result = WERR_NOMEM;
5598 /* fill the buffer with the structures */
5599 smb_io_printer_driver_info_2("", buffer, info, 0);
5608 /****************************************************************************
5609 ****************************************************************************/
5611 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5618 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5619 if (!W_ERROR_IS_OK(result))
5622 /* check the required size. */
5623 *needed += spoolss_size_printer_driver_info_3(&info);
5625 if (*needed > offered) {
5626 result = WERR_INSUFFICIENT_BUFFER;
5630 if (!rpcbuf_alloc_size(buffer, *needed)) {
5631 result = WERR_NOMEM;
5635 /* fill the buffer with the structures */
5636 smb_io_printer_driver_info_3("", buffer, &info, 0);
5639 free_printer_driver_info_3(&info);
5644 /****************************************************************************
5645 ****************************************************************************/
5647 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5654 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5655 if (!W_ERROR_IS_OK(result))
5658 /* check the required size. */
5659 *needed += spoolss_size_printer_driver_info_6(&info);
5661 if (*needed > offered) {
5662 result = WERR_INSUFFICIENT_BUFFER;
5666 if (!rpcbuf_alloc_size(buffer, *needed)) {
5667 result = WERR_NOMEM;
5671 /* fill the buffer with the structures */
5672 smb_io_printer_driver_info_6("", buffer, &info, 0);
5675 free_printer_driver_info_6(&info);
5680 /****************************************************************************
5681 ****************************************************************************/
5683 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5685 POLICY_HND *handle = &q_u->handle;
5686 UNISTR2 *uni_arch = &q_u->architecture;
5687 uint32 level = q_u->level;
5688 uint32 clientmajorversion = q_u->clientmajorversion;
5689 RPC_BUFFER *buffer = NULL;
5690 uint32 offered = q_u->offered;
5691 uint32 *needed = &r_u->needed;
5692 uint32 *servermajorversion = &r_u->servermajorversion;
5693 uint32 *serverminorversion = &r_u->serverminorversion;
5694 Printer_entry *printer;
5697 fstring architecture;
5700 /* that's an [in out] buffer */
5702 if (!q_u->buffer && (offered!=0)) {
5703 return WERR_INVALID_PARAM;
5706 rpcbuf_move(q_u->buffer, &r_u->buffer);
5707 buffer = r_u->buffer;
5709 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5711 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5712 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5713 return WERR_INVALID_PRINTER_NAME;
5717 *servermajorversion = 0;
5718 *serverminorversion = 0;
5720 fstrcpy(servername, get_server_name( printer ));
5721 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5723 if (!get_printer_snum(p, handle, &snum, NULL))
5728 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5730 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5732 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5734 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5737 /* apparently this call is the equivalent of
5738 EnumPrinterDataEx() for the DsDriver key */
5743 return WERR_UNKNOWN_LEVEL;
5746 /****************************************************************************
5747 ****************************************************************************/
5749 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5751 POLICY_HND *handle = &q_u->handle;
5753 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5756 DEBUG(3,("Error in startpageprinter printer handle\n"));
5760 Printer->page_started=True;
5764 /****************************************************************************
5765 ****************************************************************************/
5767 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5769 POLICY_HND *handle = &q_u->handle;
5772 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5775 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5779 if (!get_printer_snum(p, handle, &snum, NULL))
5782 Printer->page_started=False;
5783 print_job_endpage(snum, Printer->jobid);
5788 /********************************************************************
5789 * api_spoolss_getprinter
5790 * called from the spoolss dispatcher
5792 ********************************************************************/
5794 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5796 POLICY_HND *handle = &q_u->handle;
5797 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5798 uint32 *jobid = &r_u->jobid;
5800 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5804 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5807 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5812 * a nice thing with NT is it doesn't listen to what you tell it.
5813 * when asked to send _only_ RAW datas, it tries to send datas
5816 * So I add checks like in NT Server ...
5819 if (info_1->p_datatype != 0) {
5820 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5821 if (strcmp(datatype, "RAW") != 0) {
5823 return WERR_INVALID_DATATYPE;
5827 /* get the share number of the printer */
5828 if (!get_printer_snum(p, handle, &snum, NULL)) {
5832 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5834 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5836 /* An error occured in print_job_start() so return an appropriate
5839 if (Printer->jobid == -1) {
5840 return map_werror_from_unix(errno);
5843 Printer->document_started=True;
5844 (*jobid) = Printer->jobid;
5849 /********************************************************************
5850 * api_spoolss_getprinter
5851 * called from the spoolss dispatcher
5853 ********************************************************************/
5855 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5857 POLICY_HND *handle = &q_u->handle;
5859 return _spoolss_enddocprinter_internal(p, handle);
5862 /****************************************************************************
5863 ****************************************************************************/
5865 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5867 POLICY_HND *handle = &q_u->handle;
5868 uint32 buffer_size = q_u->buffer_size;
5869 uint8 *buffer = q_u->buffer;
5870 uint32 *buffer_written = &q_u->buffer_size2;
5872 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5875 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5876 r_u->buffer_written = q_u->buffer_size2;
5880 if (!get_printer_snum(p, handle, &snum, NULL))
5883 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5884 (SMB_OFF_T)-1, (size_t)buffer_size);
5885 if (*buffer_written == (uint32)-1) {
5886 r_u->buffer_written = 0;
5887 if (errno == ENOSPC)
5888 return WERR_NO_SPOOL_SPACE;
5890 return WERR_ACCESS_DENIED;
5893 r_u->buffer_written = q_u->buffer_size2;
5898 /********************************************************************
5899 * api_spoolss_getprinter
5900 * called from the spoolss dispatcher
5902 ********************************************************************/
5904 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5908 WERROR errcode = WERR_BADFUNC;
5909 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5912 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5916 if (!get_printer_snum(p, handle, &snum, NULL))
5920 case PRINTER_CONTROL_PAUSE:
5921 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5925 case PRINTER_CONTROL_RESUME:
5926 case PRINTER_CONTROL_UNPAUSE:
5927 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5931 case PRINTER_CONTROL_PURGE:
5932 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5937 return WERR_UNKNOWN_LEVEL;
5943 /********************************************************************
5944 * api_spoolss_abortprinter
5945 * From MSDN: "Deletes printer's spool file if printer is configured
5947 ********************************************************************/
5949 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5951 POLICY_HND *handle = &q_u->handle;
5952 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5954 WERROR errcode = WERR_OK;
5957 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5961 if (!get_printer_snum(p, handle, &snum, NULL))
5964 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5969 /********************************************************************
5970 * called by spoolss_api_setprinter
5971 * when updating a printer description
5972 ********************************************************************/
5974 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5975 const SPOOL_PRINTER_INFO_LEVEL *info,
5976 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5978 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5982 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5984 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5985 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5986 OUR_HANDLE(handle)));
5988 result = WERR_BADFID;
5993 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5994 result = WERR_INVALID_PARAM;
5998 /* Check the user has permissions to change the security
5999 descriptor. By experimentation with two NT machines, the user
6000 requires Full Access to the printer to change security
6003 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6004 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6005 result = WERR_ACCESS_DENIED;
6009 /* NT seems to like setting the security descriptor even though
6010 nothing may have actually changed. */
6012 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
6014 if (DEBUGLEVEL >= 10) {
6018 the_acl = old_secdesc_ctr->sd->dacl;
6019 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6020 PRINTERNAME(snum), the_acl->num_aces));
6022 for (i = 0; i < the_acl->num_aces; i++) {
6025 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6027 DEBUG(10, ("%s 0x%08x\n", sid_str,
6028 the_acl->aces[i].access_mask));
6031 the_acl = secdesc_ctr->sd->dacl;
6034 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6035 PRINTERNAME(snum), the_acl->num_aces));
6037 for (i = 0; i < the_acl->num_aces; i++) {
6040 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6042 DEBUG(10, ("%s 0x%08x\n", sid_str,
6043 the_acl->aces[i].access_mask));
6046 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6050 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6051 if (!new_secdesc_ctr) {
6052 result = WERR_NOMEM;
6056 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6061 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6068 /********************************************************************
6069 Canonicalize printer info from a client
6071 ATTN: It does not matter what we set the servername to hear
6072 since we do the necessary work in get_a_printer() to set it to
6073 the correct value based on what the client sent in the
6074 _spoolss_open_printer_ex().
6075 ********************************************************************/
6077 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6079 fstring printername;
6082 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6083 "portname=%s drivername=%s comment=%s location=%s\n",
6084 info->servername, info->printername, info->sharename,
6085 info->portname, info->drivername, info->comment, info->location));
6087 /* we force some elements to "correct" values */
6088 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6089 fstrcpy(info->sharename, lp_servicename(snum));
6091 /* check to see if we allow printername != sharename */
6093 if ( lp_force_printername(snum) ) {
6094 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6095 global_myname(), info->sharename );
6098 /* make sure printername is in \\server\printername format */
6100 fstrcpy( printername, info->printername );
6102 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6103 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6107 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6108 global_myname(), p );
6111 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6112 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6119 /****************************************************************************
6120 ****************************************************************************/
6122 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
6124 char *cmd = lp_addport_cmd();
6128 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6129 BOOL is_print_op = False;
6132 return WERR_ACCESS_DENIED;
6135 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
6138 is_print_op = user_has_privileges( token, &se_printop );
6140 DEBUG(10,("Running [%s]\n", command));
6142 /********* BEGIN SePrintOperatorPrivilege **********/
6147 ret = smbrun(command, &fd);
6152 /********* END SePrintOperatorPrivilege **********/
6154 DEBUGADD(10,("returned [%d]\n", ret));
6159 return WERR_ACCESS_DENIED;
6165 /****************************************************************************
6166 ****************************************************************************/
6168 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6170 char *cmd = lp_addprinter_cmd();
6176 fstring remote_machine = "%m";
6177 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6178 BOOL is_print_op = False;
6180 standard_sub_basic(current_user_info.smb_name,
6181 current_user_info.domain,
6182 remote_machine,sizeof(remote_machine));
6184 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6185 cmd, printer->info_2->printername, printer->info_2->sharename,
6186 printer->info_2->portname, printer->info_2->drivername,
6187 printer->info_2->location, printer->info_2->comment, remote_machine);
6190 is_print_op = user_has_privileges( token, &se_printop );
6192 DEBUG(10,("Running [%s]\n", command));
6194 /********* BEGIN SePrintOperatorPrivilege **********/
6199 if ( (ret = smbrun(command, &fd)) == 0 ) {
6200 /* Tell everyone we updated smb.conf. */
6201 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6207 /********* END SePrintOperatorPrivilege **********/
6209 DEBUGADD(10,("returned [%d]\n", ret));
6217 /* reload our services immediately */
6218 reload_services( False );
6221 /* Get lines and convert them back to dos-codepage */
6222 qlines = fd_lines_load(fd, &numlines, 0);
6223 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6226 /* Set the portname to what the script says the portname should be. */
6227 /* but don't require anything to be return from the script exit a good error code */
6230 /* Set the portname to what the script says the portname should be. */
6231 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6232 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6235 file_lines_free(qlines);
6240 /********************************************************************
6241 * Called by spoolss_api_setprinter
6242 * when updating a printer description.
6243 ********************************************************************/
6245 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6246 const SPOOL_PRINTER_INFO_LEVEL *info,
6247 DEVICEMODE *devmode)
6250 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6251 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6256 DEBUG(8,("update_printer\n"));
6261 result = WERR_BADFID;
6265 if (!get_printer_snum(p, handle, &snum, NULL)) {
6266 result = WERR_BADFID;
6270 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6271 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6272 result = WERR_BADFID;
6276 DEBUGADD(8,("Converting info_2 struct\n"));
6279 * convert_printer_info converts the incoming
6280 * info from the client and overwrites the info
6281 * just read from the tdb in the pointer 'printer'.
6284 if (!convert_printer_info(info, printer, level)) {
6285 result = WERR_NOMEM;
6290 /* we have a valid devmode
6291 convert it and link it*/
6293 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6294 if (!convert_devicemode(printer->info_2->printername, devmode,
6295 &printer->info_2->devmode)) {
6296 result = WERR_NOMEM;
6301 /* Do sanity check on the requested changes for Samba */
6303 if (!check_printer_ok(printer->info_2, snum)) {
6304 result = WERR_INVALID_PARAM;
6308 /* FIXME!!! If the driver has changed we really should verify that
6309 it is installed before doing much else --jerry */
6311 /* Check calling user has permission to update printer description */
6313 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6314 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6315 result = WERR_ACCESS_DENIED;
6319 /* Call addprinter hook */
6320 /* Check changes to see if this is really needed */
6322 if ( *lp_addprinter_cmd()
6323 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6324 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6325 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6326 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6328 /* add_printer_hook() will call reload_services() */
6330 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6331 result = WERR_ACCESS_DENIED;
6337 * When a *new* driver is bound to a printer, the drivername is used to
6338 * lookup previously saved driver initialization info, which is then
6339 * bound to the printer, simulating what happens in the Windows arch.
6341 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6343 if (!set_driver_init(printer, 2))
6345 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6346 printer->info_2->drivername));
6349 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6350 printer->info_2->drivername));
6352 notify_printer_driver(snum, printer->info_2->drivername);
6356 * flag which changes actually occured. This is a small subset of
6357 * all the possible changes. We also have to update things in the
6361 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6362 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6363 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6364 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6366 notify_printer_comment(snum, printer->info_2->comment);
6369 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6370 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6371 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6372 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6374 notify_printer_sharename(snum, printer->info_2->sharename);
6377 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6380 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6383 pname = printer->info_2->printername;
6386 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6387 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6388 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6390 notify_printer_printername( snum, pname );
6393 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6394 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6395 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6396 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6398 notify_printer_port(snum, printer->info_2->portname);
6401 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6402 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6403 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6404 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6406 notify_printer_location(snum, printer->info_2->location);
6409 /* here we need to update some more DsSpooler keys */
6410 /* uNCName, serverName, shortServerName */
6412 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6413 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6414 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6415 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6416 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6418 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6419 global_myname(), printer->info_2->sharename );
6420 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6421 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6422 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6424 /* Update printer info */
6425 result = mod_a_printer(printer, 2);
6428 free_a_printer(&printer, 2);
6429 free_a_printer(&old_printer, 2);
6435 /****************************************************************************
6436 ****************************************************************************/
6437 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6438 const SPOOL_PRINTER_INFO_LEVEL *info)
6441 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6443 Printer_entry *Printer;
6445 if ( lp_security() != SEC_ADS ) {
6446 return WERR_UNKNOWN_LEVEL;
6449 Printer = find_printer_index_by_hnd(p, handle);
6451 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6456 if (!get_printer_snum(p, handle, &snum, NULL))
6459 nt_printer_publish(Printer, snum, info7->action);
6463 return WERR_UNKNOWN_LEVEL;
6466 /****************************************************************************
6467 ****************************************************************************/
6469 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6471 POLICY_HND *handle = &q_u->handle;
6472 uint32 level = q_u->level;
6473 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6474 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6475 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6476 uint32 command = q_u->command;
6479 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6482 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6486 /* check the level */
6489 return control_printer(handle, command, p);
6491 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6492 if (!W_ERROR_IS_OK(result))
6495 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6498 return update_printer_sec(handle, level, info, p,
6501 return publish_or_unpublish_printer(p, handle, info);
6503 return WERR_UNKNOWN_LEVEL;
6507 /****************************************************************************
6508 ****************************************************************************/
6510 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6512 POLICY_HND *handle = &q_u->handle;
6513 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6516 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6520 if (Printer->notify.client_connected==True) {
6523 if ( Printer->printer_type == SPLHND_SERVER)
6525 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6526 !get_printer_snum(p, handle, &snum, NULL) )
6529 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6532 Printer->notify.flags=0;
6533 Printer->notify.options=0;
6534 Printer->notify.localmachine[0]='\0';
6535 Printer->notify.printerlocal=0;
6536 if (Printer->notify.option)
6537 free_spool_notify_option(&Printer->notify.option);
6538 Printer->notify.client_connected=False;
6543 /****************************************************************************
6544 ****************************************************************************/
6546 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6548 /* that's an [in out] buffer */
6550 if (!q_u->buffer && (q_u->offered!=0)) {
6551 return WERR_INVALID_PARAM;
6554 rpcbuf_move(q_u->buffer, &r_u->buffer);
6557 return WERR_INVALID_PARAM; /* this is what a NT server
6558 returns for AddJob. AddJob
6559 must fail on non-local
6563 /****************************************************************************
6564 ****************************************************************************/
6566 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6567 int position, int snum,
6568 const NT_PRINTER_INFO_LEVEL *ntprinter)
6572 t=gmtime(&queue->time);
6574 job_info->jobid=queue->job;
6575 init_unistr(&job_info->printername, lp_servicename(snum));
6576 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6577 init_unistr(&job_info->username, queue->fs_user);
6578 init_unistr(&job_info->document, queue->fs_file);
6579 init_unistr(&job_info->datatype, "RAW");
6580 init_unistr(&job_info->text_status, "");
6581 job_info->status=nt_printj_status(queue->status);
6582 job_info->priority=queue->priority;
6583 job_info->position=position;
6584 job_info->totalpages=queue->page_count;
6585 job_info->pagesprinted=0;
6587 make_systemtime(&job_info->submitted, t);
6590 /****************************************************************************
6591 ****************************************************************************/
6593 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6594 int position, int snum,
6595 const NT_PRINTER_INFO_LEVEL *ntprinter,
6596 DEVICEMODE *devmode)
6600 t=gmtime(&queue->time);
6602 job_info->jobid=queue->job;
6604 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6606 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6607 init_unistr(&job_info->username, queue->fs_user);
6608 init_unistr(&job_info->document, queue->fs_file);
6609 init_unistr(&job_info->notifyname, queue->fs_user);
6610 init_unistr(&job_info->datatype, "RAW");
6611 init_unistr(&job_info->printprocessor, "winprint");
6612 init_unistr(&job_info->parameters, "");
6613 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6614 init_unistr(&job_info->text_status, "");
6616 /* and here the security descriptor */
6618 job_info->status=nt_printj_status(queue->status);
6619 job_info->priority=queue->priority;
6620 job_info->position=position;
6621 job_info->starttime=0;
6622 job_info->untiltime=0;
6623 job_info->totalpages=queue->page_count;
6624 job_info->size=queue->size;
6625 make_systemtime(&(job_info->submitted), t);
6626 job_info->timeelapsed=0;
6627 job_info->pagesprinted=0;
6629 job_info->devmode = devmode;
6634 /****************************************************************************
6635 Enumjobs at level 1.
6636 ****************************************************************************/
6638 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6639 const NT_PRINTER_INFO_LEVEL *ntprinter,
6640 RPC_BUFFER *buffer, uint32 offered,
6641 uint32 *needed, uint32 *returned)
6645 WERROR result = WERR_OK;
6647 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6653 for (i=0; i<*returned; i++)
6654 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6656 /* check the required size. */
6657 for (i=0; i<*returned; i++)
6658 (*needed) += spoolss_size_job_info_1(&info[i]);
6660 if (*needed > offered) {
6661 result = WERR_INSUFFICIENT_BUFFER;
6665 if (!rpcbuf_alloc_size(buffer, *needed)) {
6666 result = WERR_NOMEM;
6670 /* fill the buffer with the structures */
6671 for (i=0; i<*returned; i++)
6672 smb_io_job_info_1("", buffer, &info[i], 0);
6678 if ( !W_ERROR_IS_OK(result) )
6684 /****************************************************************************
6685 Enumjobs at level 2.
6686 ****************************************************************************/
6688 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6689 const NT_PRINTER_INFO_LEVEL *ntprinter,
6690 RPC_BUFFER *buffer, uint32 offered,
6691 uint32 *needed, uint32 *returned)
6693 JOB_INFO_2 *info = NULL;
6695 WERROR result = WERR_OK;
6696 DEVICEMODE *devmode = NULL;
6698 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6703 /* this should not be a failure condition if the devmode is NULL */
6705 devmode = construct_dev_mode(lp_const_servicename(snum));
6707 for (i=0; i<*returned; i++)
6708 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6710 /* check the required size. */
6711 for (i=0; i<*returned; i++)
6712 (*needed) += spoolss_size_job_info_2(&info[i]);
6714 if (*needed > offered) {
6715 result = WERR_INSUFFICIENT_BUFFER;
6719 if (!rpcbuf_alloc_size(buffer, *needed)) {
6720 result = WERR_NOMEM;
6724 /* fill the buffer with the structures */
6725 for (i=0; i<*returned; i++)
6726 smb_io_job_info_2("", buffer, &info[i], 0);
6729 free_devmode(devmode);
6732 if ( !W_ERROR_IS_OK(result) )
6739 /****************************************************************************
6741 ****************************************************************************/
6743 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6745 POLICY_HND *handle = &q_u->handle;
6746 uint32 level = q_u->level;
6747 RPC_BUFFER *buffer = NULL;
6748 uint32 offered = q_u->offered;
6749 uint32 *needed = &r_u->needed;
6750 uint32 *returned = &r_u->returned;
6752 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6754 print_status_struct prt_status;
6755 print_queue_struct *queue=NULL;
6757 /* that's an [in out] buffer */
6759 if (!q_u->buffer && (offered!=0)) {
6760 return WERR_INVALID_PARAM;
6763 rpcbuf_move(q_u->buffer, &r_u->buffer);
6764 buffer = r_u->buffer;
6766 DEBUG(4,("_spoolss_enumjobs\n"));
6771 /* lookup the printer snum and tdb entry */
6773 if (!get_printer_snum(p, handle, &snum, NULL))
6776 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6777 if ( !W_ERROR_IS_OK(wret) )
6780 *returned = print_queue_status(snum, &queue, &prt_status);
6781 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6783 if (*returned == 0) {
6785 free_a_printer(&ntprinter, 2);
6791 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6794 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6798 wret = WERR_UNKNOWN_LEVEL;
6803 free_a_printer( &ntprinter, 2 );
6807 /****************************************************************************
6808 ****************************************************************************/
6810 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6815 /****************************************************************************
6816 ****************************************************************************/
6818 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6820 POLICY_HND *handle = &q_u->handle;
6821 uint32 jobid = q_u->jobid;
6822 uint32 command = q_u->command;
6825 WERROR errcode = WERR_BADFUNC;
6827 if (!get_printer_snum(p, handle, &snum, NULL)) {
6831 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6832 return WERR_INVALID_PRINTER_NAME;
6836 case JOB_CONTROL_CANCEL:
6837 case JOB_CONTROL_DELETE:
6838 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6842 case JOB_CONTROL_PAUSE:
6843 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6847 case JOB_CONTROL_RESTART:
6848 case JOB_CONTROL_RESUME:
6849 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6854 return WERR_UNKNOWN_LEVEL;
6860 /****************************************************************************
6861 Enumerates all printer drivers at level 1.
6862 ****************************************************************************/
6864 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6869 fstring *list = NULL;
6870 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6871 DRIVER_INFO_1 *driver_info_1=NULL;
6872 WERROR result = WERR_OK;
6876 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6878 ndrivers=get_ntdrivers(&list, architecture, version);
6879 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6881 if(ndrivers == -1) {
6882 SAFE_FREE(driver_info_1);
6887 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6888 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6894 for (i=0; i<ndrivers; i++) {
6896 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6897 ZERO_STRUCT(driver);
6898 status = get_a_printer_driver(&driver, 3, list[i],
6899 architecture, version);
6900 if (!W_ERROR_IS_OK(status)) {
6902 SAFE_FREE(driver_info_1);
6905 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6906 free_a_printer_driver(driver, 3);
6909 *returned+=ndrivers;
6913 /* check the required size. */
6914 for (i=0; i<*returned; i++) {
6915 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6916 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6919 if (*needed > offered) {
6920 result = WERR_INSUFFICIENT_BUFFER;
6924 if (!rpcbuf_alloc_size(buffer, *needed)) {
6925 result = WERR_NOMEM;
6929 /* fill the buffer with the driver structures */
6930 for (i=0; i<*returned; i++) {
6931 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6932 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6936 SAFE_FREE(driver_info_1);
6938 if ( !W_ERROR_IS_OK(result) )
6944 /****************************************************************************
6945 Enumerates all printer drivers at level 2.
6946 ****************************************************************************/
6948 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6953 fstring *list = NULL;
6954 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6955 DRIVER_INFO_2 *driver_info_2=NULL;
6956 WERROR result = WERR_OK;
6960 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6962 ndrivers=get_ntdrivers(&list, architecture, version);
6963 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6965 if(ndrivers == -1) {
6966 SAFE_FREE(driver_info_2);
6971 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6972 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6978 for (i=0; i<ndrivers; i++) {
6981 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6982 ZERO_STRUCT(driver);
6983 status = get_a_printer_driver(&driver, 3, list[i],
6984 architecture, version);
6985 if (!W_ERROR_IS_OK(status)) {
6987 SAFE_FREE(driver_info_2);
6990 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6991 free_a_printer_driver(driver, 3);
6994 *returned+=ndrivers;
6998 /* check the required size. */
6999 for (i=0; i<*returned; i++) {
7000 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7001 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7004 if (*needed > offered) {
7005 result = WERR_INSUFFICIENT_BUFFER;
7009 if (!rpcbuf_alloc_size(buffer, *needed)) {
7010 result = WERR_NOMEM;
7014 /* fill the buffer with the form structures */
7015 for (i=0; i<*returned; i++) {
7016 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7017 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7021 SAFE_FREE(driver_info_2);
7023 if ( !W_ERROR_IS_OK(result) )
7029 /****************************************************************************
7030 Enumerates all printer drivers at level 3.
7031 ****************************************************************************/
7033 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7038 fstring *list = NULL;
7039 DRIVER_INFO_3 *driver_info_3=NULL;
7040 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7041 WERROR result = WERR_OK;
7045 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7047 ndrivers=get_ntdrivers(&list, architecture, version);
7048 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7050 if(ndrivers == -1) {
7051 SAFE_FREE(driver_info_3);
7056 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7057 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7063 for (i=0; i<ndrivers; i++) {
7066 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7067 ZERO_STRUCT(driver);
7068 status = get_a_printer_driver(&driver, 3, list[i],
7069 architecture, version);
7070 if (!W_ERROR_IS_OK(status)) {
7072 SAFE_FREE(driver_info_3);
7075 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7076 free_a_printer_driver(driver, 3);
7079 *returned+=ndrivers;
7083 /* check the required size. */
7084 for (i=0; i<*returned; i++) {
7085 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7086 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7089 if (*needed > offered) {
7090 result = WERR_INSUFFICIENT_BUFFER;
7094 if (!rpcbuf_alloc_size(buffer, *needed)) {
7095 result = WERR_NOMEM;
7099 /* fill the buffer with the driver structures */
7100 for (i=0; i<*returned; i++) {
7101 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7102 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7106 for (i=0; i<*returned; i++) {
7107 SAFE_FREE(driver_info_3[i].dependentfiles);
7110 SAFE_FREE(driver_info_3);
7112 if ( !W_ERROR_IS_OK(result) )
7118 /****************************************************************************
7119 Enumerates all printer drivers.
7120 ****************************************************************************/
7122 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7124 uint32 level = q_u->level;
7125 RPC_BUFFER *buffer = NULL;
7126 uint32 offered = q_u->offered;
7127 uint32 *needed = &r_u->needed;
7128 uint32 *returned = &r_u->returned;
7131 fstring architecture;
7133 /* that's an [in out] buffer */
7135 if (!q_u->buffer && (offered!=0)) {
7136 return WERR_INVALID_PARAM;
7139 rpcbuf_move(q_u->buffer, &r_u->buffer);
7140 buffer = r_u->buffer;
7142 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7147 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7148 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7150 if ( !is_myname_or_ipaddr( servername ) )
7151 return WERR_UNKNOWN_PRINTER_DRIVER;
7155 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7157 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7159 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7161 return WERR_UNKNOWN_LEVEL;
7165 /****************************************************************************
7166 ****************************************************************************/
7168 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7170 form->flag=list->flag;
7171 init_unistr(&form->name, list->name);
7172 form->width=list->width;
7173 form->length=list->length;
7174 form->left=list->left;
7175 form->top=list->top;
7176 form->right=list->right;
7177 form->bottom=list->bottom;
7180 /****************************************************************************
7181 ****************************************************************************/
7183 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7185 uint32 level = q_u->level;
7186 RPC_BUFFER *buffer = NULL;
7187 uint32 offered = q_u->offered;
7188 uint32 *needed = &r_u->needed;
7189 uint32 *numofforms = &r_u->numofforms;
7190 uint32 numbuiltinforms;
7192 nt_forms_struct *list=NULL;
7193 nt_forms_struct *builtinlist=NULL;
7198 /* that's an [in out] buffer */
7200 if (!q_u->buffer && (offered!=0) ) {
7201 return WERR_INVALID_PARAM;
7204 rpcbuf_move(q_u->buffer, &r_u->buffer);
7205 buffer = r_u->buffer;
7207 DEBUG(4,("_spoolss_enumforms\n"));
7208 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7209 DEBUGADD(5,("Info level [%d]\n", level));
7211 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7212 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7213 *numofforms = get_ntforms(&list);
7214 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7215 *numofforms += numbuiltinforms;
7217 if (*numofforms == 0) {
7218 SAFE_FREE(builtinlist);
7220 return WERR_NO_MORE_ITEMS;
7225 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7226 SAFE_FREE(builtinlist);
7232 /* construct the list of form structures */
7233 for (i=0; i<numbuiltinforms; i++) {
7234 DEBUGADD(6,("Filling form number [%d]\n",i));
7235 fill_form_1(&forms_1[i], &builtinlist[i]);
7238 SAFE_FREE(builtinlist);
7240 for (; i<*numofforms; i++) {
7241 DEBUGADD(6,("Filling form number [%d]\n",i));
7242 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7247 /* check the required size. */
7248 for (i=0; i<numbuiltinforms; i++) {
7249 DEBUGADD(6,("adding form [%d]'s size\n",i));
7250 buffer_size += spoolss_size_form_1(&forms_1[i]);
7252 for (; i<*numofforms; i++) {
7253 DEBUGADD(6,("adding form [%d]'s size\n",i));
7254 buffer_size += spoolss_size_form_1(&forms_1[i]);
7257 *needed=buffer_size;
7259 if (*needed > offered) {
7262 return WERR_INSUFFICIENT_BUFFER;
7265 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7271 /* fill the buffer with the form structures */
7272 for (i=0; i<numbuiltinforms; i++) {
7273 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7274 smb_io_form_1("", buffer, &forms_1[i], 0);
7276 for (; i<*numofforms; i++) {
7277 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7278 smb_io_form_1("", buffer, &forms_1[i], 0);
7287 SAFE_FREE(builtinlist);
7288 return WERR_UNKNOWN_LEVEL;
7292 /****************************************************************************
7293 ****************************************************************************/
7295 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7297 uint32 level = q_u->level;
7298 UNISTR2 *uni_formname = &q_u->formname;
7299 RPC_BUFFER *buffer = NULL;
7300 uint32 offered = q_u->offered;
7301 uint32 *needed = &r_u->needed;
7303 nt_forms_struct *list=NULL;
7304 nt_forms_struct builtin_form;
7309 int numofforms=0, i=0;
7311 /* that's an [in out] buffer */
7313 if (!q_u->buffer && (offered!=0)) {
7314 return WERR_INVALID_PARAM;
7317 rpcbuf_move(q_u->buffer, &r_u->buffer);
7318 buffer = r_u->buffer;
7320 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7322 DEBUG(4,("_spoolss_getform\n"));
7323 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7324 DEBUGADD(5,("Info level [%d]\n", level));
7326 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7327 if (!foundBuiltin) {
7328 numofforms = get_ntforms(&list);
7329 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7331 if (numofforms == 0)
7338 fill_form_1(&form_1, &builtin_form);
7341 /* Check if the requested name is in the list of form structures */
7342 for (i=0; i<numofforms; i++) {
7344 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7346 if (strequal(form_name, list[i].name)) {
7347 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7348 fill_form_1(&form_1, &list[i]);
7354 if (i == numofforms) {
7358 /* check the required size. */
7360 *needed=spoolss_size_form_1(&form_1);
7362 if (*needed > offered)
7363 return WERR_INSUFFICIENT_BUFFER;
7365 if (!rpcbuf_alloc_size(buffer, buffer_size))
7368 /* fill the buffer with the form structures */
7369 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7370 smb_io_form_1("", buffer, &form_1, 0);
7376 return WERR_UNKNOWN_LEVEL;
7380 /****************************************************************************
7381 ****************************************************************************/
7383 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7385 init_unistr(&port->port_name, name);
7388 /****************************************************************************
7389 TODO: This probably needs distinguish between TCP/IP and Local ports
7391 ****************************************************************************/
7393 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7395 init_unistr(&port->port_name, name);
7396 init_unistr(&port->monitor_name, "Local Monitor");
7397 init_unistr(&port->description, SPL_LOCAL_PORT );
7398 port->port_type=PORT_TYPE_WRITE;
7403 /****************************************************************************
7404 wrapper around the enumer ports command
7405 ****************************************************************************/
7407 WERROR enumports_hook( int *count, char ***lines )
7409 char *cmd = lp_enumports_cmd();
7419 /* if no hook then just fill in the default port */
7422 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7423 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7428 /* we have a valid enumport command */
7430 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7432 DEBUG(10,("Running [%s]\n", command));
7433 ret = smbrun(command, &fd);
7434 DEBUG(10,("Returned [%d]\n", ret));
7439 return WERR_ACCESS_DENIED;
7443 qlines = fd_lines_load(fd, &numlines, 0);
7444 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7454 /****************************************************************************
7456 ****************************************************************************/
7458 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7460 PORT_INFO_1 *ports=NULL;
7462 WERROR result = WERR_OK;
7463 char **qlines = NULL;
7466 result = enumports_hook( &numlines, &qlines );
7467 if (!W_ERROR_IS_OK(result)) {
7468 file_lines_free(qlines);
7473 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7474 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7475 dos_errstr(WERR_NOMEM)));
7476 file_lines_free(qlines);
7480 for (i=0; i<numlines; i++) {
7481 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7482 fill_port_1(&ports[i], qlines[i]);
7485 file_lines_free(qlines);
7487 *returned = numlines;
7489 /* check the required size. */
7490 for (i=0; i<*returned; i++) {
7491 DEBUGADD(6,("adding port [%d]'s size\n", i));
7492 *needed += spoolss_size_port_info_1(&ports[i]);
7495 if (*needed > offered) {
7496 result = WERR_INSUFFICIENT_BUFFER;
7500 if (!rpcbuf_alloc_size(buffer, *needed)) {
7501 result = WERR_NOMEM;
7505 /* fill the buffer with the ports structures */
7506 for (i=0; i<*returned; i++) {
7507 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7508 smb_io_port_1("", buffer, &ports[i], 0);
7514 if ( !W_ERROR_IS_OK(result) )
7520 /****************************************************************************
7522 ****************************************************************************/
7524 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7526 PORT_INFO_2 *ports=NULL;
7528 WERROR result = WERR_OK;
7529 char **qlines = NULL;
7532 result = enumports_hook( &numlines, &qlines );
7533 if ( !W_ERROR_IS_OK(result)) {
7534 file_lines_free(qlines);
7539 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7540 file_lines_free(qlines);
7544 for (i=0; i<numlines; i++) {
7545 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7546 fill_port_2(&(ports[i]), qlines[i]);
7550 file_lines_free(qlines);
7552 *returned = numlines;
7554 /* check the required size. */
7555 for (i=0; i<*returned; i++) {
7556 DEBUGADD(6,("adding port [%d]'s size\n", i));
7557 *needed += spoolss_size_port_info_2(&ports[i]);
7560 if (*needed > offered) {
7561 result = WERR_INSUFFICIENT_BUFFER;
7565 if (!rpcbuf_alloc_size(buffer, *needed)) {
7566 result = WERR_NOMEM;
7570 /* fill the buffer with the ports structures */
7571 for (i=0; i<*returned; i++) {
7572 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7573 smb_io_port_2("", buffer, &ports[i], 0);
7579 if ( !W_ERROR_IS_OK(result) )
7585 /****************************************************************************
7587 ****************************************************************************/
7589 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7591 uint32 level = q_u->level;
7592 RPC_BUFFER *buffer = NULL;
7593 uint32 offered = q_u->offered;
7594 uint32 *needed = &r_u->needed;
7595 uint32 *returned = &r_u->returned;
7597 /* that's an [in out] buffer */
7599 if (!q_u->buffer && (offered!=0)) {
7600 return WERR_INVALID_PARAM;
7603 rpcbuf_move(q_u->buffer, &r_u->buffer);
7604 buffer = r_u->buffer;
7606 DEBUG(4,("_spoolss_enumports\n"));
7613 return enumports_level_1(buffer, offered, needed, returned);
7615 return enumports_level_2(buffer, offered, needed, returned);
7617 return WERR_UNKNOWN_LEVEL;
7621 /****************************************************************************
7622 ****************************************************************************/
7624 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7625 const SPOOL_PRINTER_INFO_LEVEL *info,
7626 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7627 uint32 user_switch, const SPOOL_USER_CTR *user,
7630 NT_PRINTER_INFO_LEVEL *printer = NULL;
7633 WERROR err = WERR_OK;
7635 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7636 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7640 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7641 if (!convert_printer_info(info, printer, 2)) {
7642 free_a_printer(&printer, 2);
7646 /* check to see if the printer already exists */
7648 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7649 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7650 printer->info_2->sharename));
7651 free_a_printer(&printer, 2);
7652 return WERR_PRINTER_ALREADY_EXISTS;
7655 /* FIXME!!! smbd should check to see if the driver is installed before
7656 trying to add a printer like this --jerry */
7658 if (*lp_addprinter_cmd() ) {
7659 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7660 free_a_printer(&printer,2);
7661 return WERR_ACCESS_DENIED;
7664 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7665 "smb.conf parameter \"addprinter command\" is defined. This"
7666 "parameter must exist for this call to succeed\n",
7667 printer->info_2->sharename ));
7670 /* use our primary netbios name since get_a_printer() will convert
7671 it to what the client expects on a case by case basis */
7673 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7674 printer->info_2->sharename);
7677 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7678 free_a_printer(&printer,2);
7679 return WERR_ACCESS_DENIED;
7682 /* you must be a printer admin to add a new printer */
7683 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7684 free_a_printer(&printer,2);
7685 return WERR_ACCESS_DENIED;
7689 * Do sanity check on the requested changes for Samba.
7692 if (!check_printer_ok(printer->info_2, snum)) {
7693 free_a_printer(&printer,2);
7694 return WERR_INVALID_PARAM;
7698 * When a printer is created, the drivername bound to the printer is used
7699 * to lookup previously saved driver initialization info, which is then
7700 * bound to the new printer, simulating what happens in the Windows arch.
7705 set_driver_init(printer, 2);
7709 /* A valid devmode was included, convert and link it
7711 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7713 if (!convert_devicemode(printer->info_2->printername, devmode,
7714 &printer->info_2->devmode))
7718 /* write the ASCII on disk */
7719 err = mod_a_printer(printer, 2);
7720 if (!W_ERROR_IS_OK(err)) {
7721 free_a_printer(&printer,2);
7725 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7726 /* Handle open failed - remove addition. */
7727 del_a_printer(printer->info_2->sharename);
7728 free_a_printer(&printer,2);
7729 return WERR_ACCESS_DENIED;
7732 update_c_setprinter(False);
7733 free_a_printer(&printer,2);
7738 /****************************************************************************
7739 ****************************************************************************/
7741 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7743 UNISTR2 *uni_srv_name = q_u->server_name;
7744 uint32 level = q_u->level;
7745 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7746 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7747 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7748 uint32 user_switch = q_u->user_switch;
7749 SPOOL_USER_CTR *user = &q_u->user_ctr;
7750 POLICY_HND *handle = &r_u->handle;
7754 /* we don't handle yet */
7755 /* but I know what to do ... */
7756 return WERR_UNKNOWN_LEVEL;
7758 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7760 user_switch, user, handle);
7762 return WERR_UNKNOWN_LEVEL;
7766 /****************************************************************************
7767 ****************************************************************************/
7769 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7771 uint32 level = q_u->level;
7772 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7773 WERROR err = WERR_OK;
7774 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7775 fstring driver_name;
7778 ZERO_STRUCT(driver);
7780 if (!convert_printer_driver_info(info, &driver, level)) {
7785 DEBUG(5,("Cleaning driver's information\n"));
7786 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7787 if (!W_ERROR_IS_OK(err))
7790 DEBUG(5,("Moving driver to final destination\n"));
7791 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7795 if (add_a_printer_driver(driver, level)!=0) {
7796 err = WERR_ACCESS_DENIED;
7801 * I think this is where he DrvUpgradePrinter() hook would be
7802 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7803 * server. Right now, we just need to send ourselves a message
7804 * to update each printer bound to this driver. --jerry
7807 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7808 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7813 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7814 * decide if the driver init data should be deleted. The rules are:
7815 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7816 * 2) delete init data only if there is no 2k/Xp driver
7817 * 3) always delete init data
7818 * The generalized rule is always use init data from the highest order driver.
7819 * It is necessary to follow the driver install by an initialization step to
7820 * finish off this process.
7823 version = driver.info_3->cversion;
7824 else if (level == 6)
7825 version = driver.info_6->version;
7830 * 9x printer driver - never delete init data
7833 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7838 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7839 * there is no 2k/Xp driver init data for this driver name.
7843 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7845 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7847 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7849 if (!del_driver_init(driver_name))
7850 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7853 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7855 free_a_printer_driver(driver1,3);
7856 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7863 * 2k or Xp printer driver - always delete init data
7866 if (!del_driver_init(driver_name))
7867 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7871 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7877 free_a_printer_driver(driver, level);
7881 /********************************************************************
7882 * spoolss_addprinterdriverex
7883 ********************************************************************/
7885 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7887 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7888 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7891 * we only support the semantics of AddPrinterDriver()
7892 * i.e. only copy files that are newer than existing ones
7895 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7896 return WERR_ACCESS_DENIED;
7898 ZERO_STRUCT(q_u_local);
7899 ZERO_STRUCT(r_u_local);
7901 /* just pass the information off to _spoolss_addprinterdriver() */
7902 q_u_local.server_name_ptr = q_u->server_name_ptr;
7903 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7904 q_u_local.level = q_u->level;
7905 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7907 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7910 /****************************************************************************
7911 ****************************************************************************/
7913 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7915 init_unistr(&info->name, name);
7918 /****************************************************************************
7919 ****************************************************************************/
7921 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7927 const char *short_archi;
7928 DRIVER_DIRECTORY_1 *info=NULL;
7929 WERROR result = WERR_OK;
7931 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7932 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7934 /* check for beginning double '\'s and that the server
7937 pservername = servername;
7938 if ( *pservername == '\\' && strlen(servername)>2 ) {
7942 if ( !is_myname_or_ipaddr( pservername ) )
7943 return WERR_INVALID_PARAM;
7945 if (!(short_archi = get_short_archi(long_archi)))
7946 return WERR_INVALID_ENVIRONMENT;
7948 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7951 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7953 DEBUG(4,("printer driver directory: [%s]\n", path));
7955 fill_driverdir_1(info, path);
7957 *needed += spoolss_size_driverdir_info_1(info);
7959 if (*needed > offered) {
7960 result = WERR_INSUFFICIENT_BUFFER;
7964 if (!rpcbuf_alloc_size(buffer, *needed)) {
7965 result = WERR_NOMEM;
7969 smb_io_driverdir_1("", buffer, info, 0);
7977 /****************************************************************************
7978 ****************************************************************************/
7980 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7982 UNISTR2 *name = &q_u->name;
7983 UNISTR2 *uni_environment = &q_u->environment;
7984 uint32 level = q_u->level;
7985 RPC_BUFFER *buffer = NULL;
7986 uint32 offered = q_u->offered;
7987 uint32 *needed = &r_u->needed;
7989 /* that's an [in out] buffer */
7991 if (!q_u->buffer && (offered!=0)) {
7992 return WERR_INVALID_PARAM;
7995 rpcbuf_move(q_u->buffer, &r_u->buffer);
7996 buffer = r_u->buffer;
7998 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8004 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8006 return WERR_UNKNOWN_LEVEL;
8010 /****************************************************************************
8011 ****************************************************************************/
8013 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8015 POLICY_HND *handle = &q_u->handle;
8016 uint32 idx = q_u->index;
8017 uint32 in_value_len = q_u->valuesize;
8018 uint32 in_data_len = q_u->datasize;
8019 uint32 *out_max_value_len = &r_u->valuesize;
8020 uint16 **out_value = &r_u->value;
8021 uint32 *out_value_len = &r_u->realvaluesize;
8022 uint32 *out_type = &r_u->type;
8023 uint32 *out_max_data_len = &r_u->datasize;
8024 uint8 **data_out = &r_u->data;
8025 uint32 *out_data_len = &r_u->realdatasize;
8027 NT_PRINTER_INFO_LEVEL *printer = NULL;
8029 uint32 biggest_valuesize;
8030 uint32 biggest_datasize;
8032 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8035 REGISTRY_VALUE *val = NULL;
8036 NT_PRINTER_DATA *p_data;
8037 int i, key_index, num_values;
8042 *out_max_data_len = 0;
8046 DEBUG(5,("spoolss_enumprinterdata\n"));
8049 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8053 if (!get_printer_snum(p,handle, &snum, NULL))
8056 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8057 if (!W_ERROR_IS_OK(result))
8060 p_data = printer->info_2->data;
8061 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8066 * The NT machine wants to know the biggest size of value and data
8068 * cf: MSDN EnumPrinterData remark section
8071 if ( !in_value_len && !in_data_len && (key_index != -1) )
8073 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8075 biggest_valuesize = 0;
8076 biggest_datasize = 0;
8078 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8080 for ( i=0; i<num_values; i++ )
8082 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8084 name_length = strlen(val->valuename);
8085 if ( strlen(val->valuename) > biggest_valuesize )
8086 biggest_valuesize = name_length;
8088 if ( val->size > biggest_datasize )
8089 biggest_datasize = val->size;
8091 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8095 /* the value is an UNICODE string but real_value_size is the length
8096 in bytes including the trailing 0 */
8098 *out_value_len = 2 * (1+biggest_valuesize);
8099 *out_data_len = biggest_datasize;
8101 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8107 * the value len is wrong in NT sp3
8108 * that's the number of bytes not the number of unicode chars
8111 if ( key_index != -1 )
8112 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8117 /* out_value should default to "" or else NT4 has
8118 problems unmarshalling the response */
8120 *out_max_value_len=(in_value_len/sizeof(uint16));
8122 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8124 result = WERR_NOMEM;
8128 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8130 /* the data is counted in bytes */
8132 *out_max_data_len = in_data_len;
8133 *out_data_len = in_data_len;
8135 /* only allocate when given a non-zero data_len */
8137 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8139 result = WERR_NOMEM;
8143 result = WERR_NO_MORE_ITEMS;
8149 * - counted in bytes in the request
8150 * - counted in UNICODE chars in the max reply
8151 * - counted in bytes in the real size
8153 * take a pause *before* coding not *during* coding
8157 *out_max_value_len=(in_value_len/sizeof(uint16));
8158 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8160 result = WERR_NOMEM;
8164 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8168 *out_type = regval_type( val );
8170 /* data - counted in bytes */
8172 *out_max_data_len = in_data_len;
8173 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8175 result = WERR_NOMEM;
8178 data_len = regval_size(val);
8180 memcpy( *data_out, regval_data_p(val), data_len );
8181 *out_data_len = data_len;
8185 free_a_printer(&printer, 2);
8189 /****************************************************************************
8190 ****************************************************************************/
8192 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8194 POLICY_HND *handle = &q_u->handle;
8195 UNISTR2 *value = &q_u->value;
8196 uint32 type = q_u->type;
8197 uint8 *data = q_u->data;
8198 uint32 real_len = q_u->real_len;
8200 NT_PRINTER_INFO_LEVEL *printer = NULL;
8202 WERROR status = WERR_OK;
8203 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8206 DEBUG(5,("spoolss_setprinterdata\n"));
8209 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8213 if ( Printer->printer_type == SPLHND_SERVER ) {
8214 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8215 return WERR_INVALID_PARAM;
8218 if (!get_printer_snum(p,handle, &snum, NULL))
8222 * Access check : NT returns "access denied" if you make a
8223 * SetPrinterData call without the necessary privildge.
8224 * we were originally returning OK if nothing changed
8225 * which made Win2k issue **a lot** of SetPrinterData
8226 * when connecting to a printer --jerry
8229 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8231 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8232 status = WERR_ACCESS_DENIED;
8236 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8237 if (!W_ERROR_IS_OK(status))
8240 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8243 * When client side code sets a magic printer data key, detect it and save
8244 * the current printer data and the magic key's data (its the DEVMODE) for
8245 * future printer/driver initializations.
8247 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8249 /* Set devmode and printer initialization info */
8250 status = save_driver_init( printer, 2, data, real_len );
8252 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8256 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8257 type, data, real_len );
8258 if ( W_ERROR_IS_OK(status) )
8259 status = mod_a_printer(printer, 2);
8263 free_a_printer(&printer, 2);
8268 /****************************************************************************
8269 ****************************************************************************/
8271 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8273 POLICY_HND *handle = &q_u->handle;
8274 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8277 DEBUG(5,("_spoolss_resetprinter\n"));
8280 * All we do is to check to see if the handle and queue is valid.
8281 * This call really doesn't mean anything to us because we only
8282 * support RAW printing. --jerry
8286 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8290 if (!get_printer_snum(p,handle, &snum, NULL))
8294 /* blindly return success */
8299 /****************************************************************************
8300 ****************************************************************************/
8302 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8304 POLICY_HND *handle = &q_u->handle;
8305 UNISTR2 *value = &q_u->valuename;
8307 NT_PRINTER_INFO_LEVEL *printer = NULL;
8309 WERROR status = WERR_OK;
8310 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8313 DEBUG(5,("spoolss_deleteprinterdata\n"));
8316 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8320 if (!get_printer_snum(p, handle, &snum, NULL))
8323 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8324 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8325 return WERR_ACCESS_DENIED;
8328 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8329 if (!W_ERROR_IS_OK(status))
8332 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8334 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8336 if ( W_ERROR_IS_OK(status) )
8337 mod_a_printer( printer, 2 );
8339 free_a_printer(&printer, 2);
8344 /****************************************************************************
8345 ****************************************************************************/
8347 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8349 POLICY_HND *handle = &q_u->handle;
8350 FORM *form = &q_u->form;
8351 nt_forms_struct tmpForm;
8353 WERROR status = WERR_OK;
8354 NT_PRINTER_INFO_LEVEL *printer = NULL;
8357 nt_forms_struct *list=NULL;
8358 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8360 DEBUG(5,("spoolss_addform\n"));
8363 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8368 /* forms can be added on printer of on the print server handle */
8370 if ( Printer->printer_type == SPLHND_PRINTER )
8372 if (!get_printer_snum(p,handle, &snum, NULL))
8375 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8376 if (!W_ERROR_IS_OK(status))
8380 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8381 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8382 status = WERR_ACCESS_DENIED;
8386 /* can't add if builtin */
8388 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8389 status = WERR_ALREADY_EXISTS;
8393 count = get_ntforms(&list);
8395 if(!add_a_form(&list, form, &count)) {
8396 status = WERR_NOMEM;
8400 write_ntforms(&list, count);
8403 * ChangeID must always be set if this is a printer
8406 if ( Printer->printer_type == SPLHND_PRINTER )
8407 status = mod_a_printer(printer, 2);
8411 free_a_printer(&printer, 2);
8417 /****************************************************************************
8418 ****************************************************************************/
8420 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8422 POLICY_HND *handle = &q_u->handle;
8423 UNISTR2 *form_name = &q_u->name;
8424 nt_forms_struct tmpForm;
8426 nt_forms_struct *list=NULL;
8427 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8429 WERROR status = WERR_OK;
8430 NT_PRINTER_INFO_LEVEL *printer = NULL;
8432 DEBUG(5,("spoolss_deleteform\n"));
8435 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8439 /* forms can be deleted on printer of on the print server handle */
8441 if ( Printer->printer_type == SPLHND_PRINTER )
8443 if (!get_printer_snum(p,handle, &snum, NULL))
8446 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8447 if (!W_ERROR_IS_OK(status))
8451 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8452 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8453 status = WERR_ACCESS_DENIED;
8457 /* can't delete if builtin */
8459 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8460 status = WERR_INVALID_PARAM;
8464 count = get_ntforms(&list);
8466 if ( !delete_a_form(&list, form_name, &count, &status ))
8470 * ChangeID must always be set if this is a printer
8473 if ( Printer->printer_type == SPLHND_PRINTER )
8474 status = mod_a_printer(printer, 2);
8478 free_a_printer(&printer, 2);
8484 /****************************************************************************
8485 ****************************************************************************/
8487 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8489 POLICY_HND *handle = &q_u->handle;
8490 FORM *form = &q_u->form;
8491 nt_forms_struct tmpForm;
8493 WERROR status = WERR_OK;
8494 NT_PRINTER_INFO_LEVEL *printer = NULL;
8497 nt_forms_struct *list=NULL;
8498 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8500 DEBUG(5,("spoolss_setform\n"));
8503 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8507 /* forms can be modified on printer of on the print server handle */
8509 if ( Printer->printer_type == SPLHND_PRINTER )
8511 if (!get_printer_snum(p,handle, &snum, NULL))
8514 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8515 if (!W_ERROR_IS_OK(status))
8519 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8520 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8521 status = WERR_ACCESS_DENIED;
8525 /* can't set if builtin */
8526 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8527 status = WERR_INVALID_PARAM;
8531 count = get_ntforms(&list);
8532 update_a_form(&list, form, count);
8533 write_ntforms(&list, count);
8536 * ChangeID must always be set if this is a printer
8539 if ( Printer->printer_type == SPLHND_PRINTER )
8540 status = mod_a_printer(printer, 2);
8545 free_a_printer(&printer, 2);
8551 /****************************************************************************
8552 enumprintprocessors level 1.
8553 ****************************************************************************/
8555 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8557 PRINTPROCESSOR_1 *info_1=NULL;
8558 WERROR result = WERR_OK;
8560 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8565 init_unistr(&info_1->name, "winprint");
8567 *needed += spoolss_size_printprocessor_info_1(info_1);
8569 if (*needed > offered) {
8570 result = WERR_INSUFFICIENT_BUFFER;
8574 if (!rpcbuf_alloc_size(buffer, *needed)) {
8575 result = WERR_NOMEM;
8579 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8584 if ( !W_ERROR_IS_OK(result) )
8590 /****************************************************************************
8591 ****************************************************************************/
8593 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8595 uint32 level = q_u->level;
8596 RPC_BUFFER *buffer = NULL;
8597 uint32 offered = q_u->offered;
8598 uint32 *needed = &r_u->needed;
8599 uint32 *returned = &r_u->returned;
8601 /* that's an [in out] buffer */
8603 if (!q_u->buffer && (offered!=0)) {
8604 return WERR_INVALID_PARAM;
8607 rpcbuf_move(q_u->buffer, &r_u->buffer);
8608 buffer = r_u->buffer;
8610 DEBUG(5,("spoolss_enumprintprocessors\n"));
8613 * Enumerate the print processors ...
8615 * Just reply with "winprint", to keep NT happy
8616 * and I can use my nice printer checker.
8624 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8626 return WERR_UNKNOWN_LEVEL;
8630 /****************************************************************************
8631 enumprintprocdatatypes level 1.
8632 ****************************************************************************/
8634 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8636 PRINTPROCDATATYPE_1 *info_1=NULL;
8637 WERROR result = WERR_OK;
8639 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8644 init_unistr(&info_1->name, "RAW");
8646 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8648 if (*needed > offered) {
8649 result = WERR_INSUFFICIENT_BUFFER;
8653 if (!rpcbuf_alloc_size(buffer, *needed)) {
8654 result = WERR_NOMEM;
8658 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8663 if ( !W_ERROR_IS_OK(result) )
8669 /****************************************************************************
8670 ****************************************************************************/
8672 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8674 uint32 level = q_u->level;
8675 RPC_BUFFER *buffer = NULL;
8676 uint32 offered = q_u->offered;
8677 uint32 *needed = &r_u->needed;
8678 uint32 *returned = &r_u->returned;
8680 /* that's an [in out] buffer */
8682 if (!q_u->buffer && (offered!=0)) {
8683 return WERR_INVALID_PARAM;
8686 rpcbuf_move(q_u->buffer, &r_u->buffer);
8687 buffer = r_u->buffer;
8689 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8696 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8698 return WERR_UNKNOWN_LEVEL;
8702 /****************************************************************************
8703 enumprintmonitors level 1.
8704 ****************************************************************************/
8706 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8708 PRINTMONITOR_1 *info_1;
8709 WERROR result = WERR_OK;
8712 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8717 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8718 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8720 for ( i=0; i<*returned; i++ ) {
8721 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8724 if (*needed > offered) {
8725 result = WERR_INSUFFICIENT_BUFFER;
8729 if (!rpcbuf_alloc_size(buffer, *needed)) {
8730 result = WERR_NOMEM;
8734 for ( i=0; i<*returned; i++ ) {
8735 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8741 if ( !W_ERROR_IS_OK(result) )
8747 /****************************************************************************
8748 enumprintmonitors level 2.
8749 ****************************************************************************/
8751 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8753 PRINTMONITOR_2 *info_2;
8754 WERROR result = WERR_OK;
8757 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8762 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8763 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8764 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8766 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8767 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8768 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8770 for ( i=0; i<*returned; i++ ) {
8771 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8774 if (*needed > offered) {
8775 result = WERR_INSUFFICIENT_BUFFER;
8779 if (!rpcbuf_alloc_size(buffer, *needed)) {
8780 result = WERR_NOMEM;
8784 for ( i=0; i<*returned; i++ ) {
8785 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8791 if ( !W_ERROR_IS_OK(result) )
8797 /****************************************************************************
8798 ****************************************************************************/
8800 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8802 uint32 level = q_u->level;
8803 RPC_BUFFER *buffer = NULL;
8804 uint32 offered = q_u->offered;
8805 uint32 *needed = &r_u->needed;
8806 uint32 *returned = &r_u->returned;
8808 /* that's an [in out] buffer */
8810 if (!q_u->buffer && (offered!=0)) {
8811 return WERR_INVALID_PARAM;
8814 rpcbuf_move(q_u->buffer, &r_u->buffer);
8815 buffer = r_u->buffer;
8817 DEBUG(5,("spoolss_enumprintmonitors\n"));
8820 * Enumerate the print monitors ...
8822 * Just reply with "Local Port", to keep NT happy
8823 * and I can use my nice printer checker.
8831 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8833 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8835 return WERR_UNKNOWN_LEVEL;
8839 /****************************************************************************
8840 ****************************************************************************/
8842 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8843 NT_PRINTER_INFO_LEVEL *ntprinter,
8844 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8849 JOB_INFO_1 *info_1=NULL;
8850 WERROR result = WERR_OK;
8852 info_1=SMB_MALLOC_P(JOB_INFO_1);
8854 if (info_1 == NULL) {
8858 for (i=0; i<count && found==False; i++) {
8859 if ((*queue)[i].job==(int)jobid)
8865 /* NT treats not found as bad param... yet another bad choice */
8866 return WERR_INVALID_PARAM;
8869 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8871 *needed += spoolss_size_job_info_1(info_1);
8873 if (*needed > offered) {
8874 result = WERR_INSUFFICIENT_BUFFER;
8878 if (!rpcbuf_alloc_size(buffer, *needed)) {
8879 result = WERR_NOMEM;
8883 smb_io_job_info_1("", buffer, info_1, 0);
8891 /****************************************************************************
8892 ****************************************************************************/
8894 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8895 NT_PRINTER_INFO_LEVEL *ntprinter,
8896 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8903 DEVICEMODE *devmode = NULL;
8904 NT_DEVICEMODE *nt_devmode = NULL;
8906 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8909 ZERO_STRUCTP(info_2);
8911 for ( i=0; i<count && found==False; i++ )
8913 if ((*queue)[i].job == (int)jobid)
8918 /* NT treats not found as bad param... yet another bad
8920 result = WERR_INVALID_PARAM;
8925 * if the print job does not have a DEVMODE associated with it,
8926 * just use the one for the printer. A NULL devicemode is not
8927 * a failure condition
8930 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8931 devmode = construct_dev_mode(lp_const_servicename(snum));
8933 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8934 ZERO_STRUCTP( devmode );
8935 convert_nt_devicemode( devmode, nt_devmode );
8939 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8941 *needed += spoolss_size_job_info_2(info_2);
8943 if (*needed > offered) {
8944 result = WERR_INSUFFICIENT_BUFFER;
8948 if (!rpcbuf_alloc_size(buffer, *needed)) {
8949 result = WERR_NOMEM;
8953 smb_io_job_info_2("", buffer, info_2, 0);
8958 /* Cleanup allocated memory */
8960 free_job_info_2(info_2); /* Also frees devmode */
8966 /****************************************************************************
8967 ****************************************************************************/
8969 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8971 POLICY_HND *handle = &q_u->handle;
8972 uint32 jobid = q_u->jobid;
8973 uint32 level = q_u->level;
8974 RPC_BUFFER *buffer = NULL;
8975 uint32 offered = q_u->offered;
8976 uint32 *needed = &r_u->needed;
8977 WERROR wstatus = WERR_OK;
8978 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8981 print_queue_struct *queue = NULL;
8982 print_status_struct prt_status;
8984 /* that's an [in out] buffer */
8986 if (!q_u->buffer && (offered!=0)) {
8987 return WERR_INVALID_PARAM;
8990 rpcbuf_move(q_u->buffer, &r_u->buffer);
8991 buffer = r_u->buffer;
8993 DEBUG(5,("spoolss_getjob\n"));
8997 if (!get_printer_snum(p, handle, &snum, NULL))
9000 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9001 if ( !W_ERROR_IS_OK(wstatus) )
9004 count = print_queue_status(snum, &queue, &prt_status);
9006 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9007 count, prt_status.status, prt_status.message));
9011 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9012 buffer, offered, needed);
9015 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9016 buffer, offered, needed);
9019 wstatus = WERR_UNKNOWN_LEVEL;
9024 free_a_printer( &ntprinter, 2 );
9029 /********************************************************************
9030 spoolss_getprinterdataex
9032 From MSDN documentation of GetPrinterDataEx: pass request
9033 to GetPrinterData if key is "PrinterDriverData".
9034 ********************************************************************/
9036 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9038 POLICY_HND *handle = &q_u->handle;
9039 uint32 in_size = q_u->size;
9040 uint32 *type = &r_u->type;
9041 uint32 *out_size = &r_u->size;
9042 uint8 **data = &r_u->data;
9043 uint32 *needed = &r_u->needed;
9044 fstring keyname, valuename;
9046 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9048 NT_PRINTER_INFO_LEVEL *printer = NULL;
9050 WERROR status = WERR_OK;
9052 DEBUG(4,("_spoolss_getprinterdataex\n"));
9054 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
9055 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
9057 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9058 keyname, valuename));
9060 /* in case of problem, return some default values */
9064 *out_size = in_size;
9067 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9068 status = WERR_BADFID;
9072 /* Is the handle to a printer or to the server? */
9074 if (Printer->printer_type == SPLHND_SERVER) {
9075 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9076 status = WERR_INVALID_PARAM;
9080 if ( !get_printer_snum(p,handle, &snum, NULL) )
9083 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9084 if ( !W_ERROR_IS_OK(status) )
9087 /* check to see if the keyname is valid */
9088 if ( !strlen(keyname) ) {
9089 status = WERR_INVALID_PARAM;
9093 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9094 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9095 free_a_printer( &printer, 2 );
9096 status = WERR_BADFILE;
9100 /* When given a new keyname, we should just create it */
9102 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9104 if (*needed > *out_size)
9105 status = WERR_MORE_DATA;
9108 if ( !W_ERROR_IS_OK(status) )
9110 DEBUG(5, ("error: allocating %d\n", *out_size));
9112 /* reply this param doesn't exist */
9116 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9117 status = WERR_NOMEM;
9127 free_a_printer( &printer, 2 );
9132 /********************************************************************
9133 * spoolss_setprinterdataex
9134 ********************************************************************/
9136 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9138 POLICY_HND *handle = &q_u->handle;
9139 uint32 type = q_u->type;
9140 uint8 *data = q_u->data;
9141 uint32 real_len = q_u->real_len;
9143 NT_PRINTER_INFO_LEVEL *printer = NULL;
9145 WERROR status = WERR_OK;
9146 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9151 DEBUG(4,("_spoolss_setprinterdataex\n"));
9153 /* From MSDN documentation of SetPrinterDataEx: pass request to
9154 SetPrinterData if key is "PrinterDriverData" */
9157 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9161 if ( Printer->printer_type == SPLHND_SERVER ) {
9162 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9163 return WERR_INVALID_PARAM;
9166 if ( !get_printer_snum(p,handle, &snum, NULL) )
9170 * Access check : NT returns "access denied" if you make a
9171 * SetPrinterData call without the necessary privildge.
9172 * we were originally returning OK if nothing changed
9173 * which made Win2k issue **a lot** of SetPrinterData
9174 * when connecting to a printer --jerry
9177 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9179 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9180 return WERR_ACCESS_DENIED;
9183 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9184 if (!W_ERROR_IS_OK(status))
9187 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9188 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9190 /* check for OID in valuename */
9192 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9198 /* save the registry data */
9200 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9202 if ( W_ERROR_IS_OK(status) )
9204 /* save the OID if one was specified */
9206 fstrcat( keyname, "\\" );
9207 fstrcat( keyname, SPOOL_OID_KEY );
9210 * I'm not checking the status here on purpose. Don't know
9211 * if this is right, but I'm returning the status from the
9212 * previous set_printer_dataex() call. I have no idea if
9213 * this is right. --jerry
9216 set_printer_dataex( printer, keyname, valuename,
9217 REG_SZ, (uint8 *)oid_string,
9218 strlen(oid_string)+1 );
9221 status = mod_a_printer(printer, 2);
9224 free_a_printer(&printer, 2);
9230 /********************************************************************
9231 * spoolss_deleteprinterdataex
9232 ********************************************************************/
9234 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9236 POLICY_HND *handle = &q_u->handle;
9237 UNISTR2 *value = &q_u->valuename;
9238 UNISTR2 *key = &q_u->keyname;
9240 NT_PRINTER_INFO_LEVEL *printer = NULL;
9242 WERROR status = WERR_OK;
9243 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9244 pstring valuename, keyname;
9246 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9249 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9253 if (!get_printer_snum(p, handle, &snum, NULL))
9256 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9257 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9258 return WERR_ACCESS_DENIED;
9261 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9262 if (!W_ERROR_IS_OK(status))
9265 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9266 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9268 status = delete_printer_dataex( printer, keyname, valuename );
9270 if ( W_ERROR_IS_OK(status) )
9271 mod_a_printer( printer, 2 );
9273 free_a_printer(&printer, 2);
9278 /********************************************************************
9279 * spoolss_enumprinterkey
9280 ********************************************************************/
9283 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9286 fstring *keynames = NULL;
9287 uint16 *enumkeys = NULL;
9290 POLICY_HND *handle = &q_u->handle;
9291 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9292 NT_PRINTER_DATA *data;
9293 NT_PRINTER_INFO_LEVEL *printer = NULL;
9295 WERROR status = WERR_BADFILE;
9298 DEBUG(4,("_spoolss_enumprinterkey\n"));
9301 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9305 if ( !get_printer_snum(p,handle, &snum, NULL) )
9308 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9309 if (!W_ERROR_IS_OK(status))
9312 /* get the list of subkey names */
9314 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9315 data = printer->info_2->data;
9317 num_keys = get_printer_subkeys( data, key, &keynames );
9319 if ( num_keys == -1 ) {
9320 status = WERR_BADFILE;
9324 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9326 r_u->needed = printerkey_len*2;
9328 if ( q_u->size < r_u->needed ) {
9329 status = WERR_MORE_DATA;
9333 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9334 status = WERR_NOMEM;
9340 if ( q_u->size < r_u->needed )
9341 status = WERR_MORE_DATA;
9344 free_a_printer( &printer, 2 );
9345 SAFE_FREE( keynames );
9350 /********************************************************************
9351 * spoolss_deleteprinterkey
9352 ********************************************************************/
9354 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9356 POLICY_HND *handle = &q_u->handle;
9357 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9359 NT_PRINTER_INFO_LEVEL *printer = NULL;
9363 DEBUG(5,("spoolss_deleteprinterkey\n"));
9366 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9370 /* if keyname == NULL, return error */
9372 if ( !q_u->keyname.buffer )
9373 return WERR_INVALID_PARAM;
9375 if (!get_printer_snum(p, handle, &snum, NULL))
9378 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9379 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9380 return WERR_ACCESS_DENIED;
9383 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9384 if (!W_ERROR_IS_OK(status))
9387 /* delete the key and all subneys */
9389 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9391 status = delete_all_printer_data( printer->info_2, key );
9393 if ( W_ERROR_IS_OK(status) )
9394 status = mod_a_printer(printer, 2);
9396 free_a_printer( &printer, 2 );
9402 /********************************************************************
9403 * spoolss_enumprinterdataex
9404 ********************************************************************/
9406 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9408 POLICY_HND *handle = &q_u->handle;
9409 uint32 in_size = q_u->size;
9412 NT_PRINTER_INFO_LEVEL *printer = NULL;
9413 PRINTER_ENUM_VALUES *enum_values = NULL;
9414 NT_PRINTER_DATA *p_data;
9416 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9421 REGISTRY_VALUE *val;
9426 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9429 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9434 * first check for a keyname of NULL or "". Win2k seems to send
9435 * this a lot and we should send back WERR_INVALID_PARAM
9436 * no need to spend time looking up the printer in this case.
9440 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9441 if ( !strlen(key) ) {
9442 result = WERR_INVALID_PARAM;
9446 /* get the printer off of disk */
9448 if (!get_printer_snum(p,handle, &snum, NULL))
9451 ZERO_STRUCT(printer);
9452 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9453 if (!W_ERROR_IS_OK(result))
9456 /* now look for a match on the key name */
9458 p_data = printer->info_2->data;
9460 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9461 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9463 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9464 result = WERR_INVALID_PARAM;
9471 /* allocate the memory for the array of pointers -- if necessary */
9473 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9476 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9478 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9479 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9480 result = WERR_NOMEM;
9484 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9488 * loop through all params and build the array to pass
9489 * back to the client
9492 for ( i=0; i<num_entries; i++ )
9494 /* lookup the registry value */
9496 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9497 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9501 value_name = regval_name( val );
9502 init_unistr( &enum_values[i].valuename, value_name );
9503 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9504 enum_values[i].type = regval_type( val );
9506 data_len = regval_size( val );
9508 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9510 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9512 result = WERR_NOMEM;
9516 enum_values[i].data_len = data_len;
9518 /* keep track of the size of the array in bytes */
9520 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9523 /* housekeeping information in the reply */
9525 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9526 * the hand marshalled container size is a multiple
9527 * of 4 bytes for RPC alignment.
9531 needed += 4-(needed % 4);
9534 r_u->needed = needed;
9535 r_u->returned = num_entries;
9537 if (needed > in_size) {
9538 result = WERR_MORE_DATA;
9542 /* copy data into the reply */
9544 r_u->ctr.size = r_u->needed;
9546 r_u->ctr.size_of_array = r_u->returned;
9547 r_u->ctr.values = enum_values;
9553 free_a_printer(&printer, 2);
9558 /****************************************************************************
9559 ****************************************************************************/
9561 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9563 init_unistr(&info->name, name);
9566 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9567 UNISTR2 *environment,
9574 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9575 WERROR result = WERR_OK;
9577 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9579 if (!get_short_archi(long_archi))
9580 return WERR_INVALID_ENVIRONMENT;
9582 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9585 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9587 fill_printprocessordirectory_1(info, path);
9589 *needed += spoolss_size_printprocessordirectory_info_1(info);
9591 if (*needed > offered) {
9592 result = WERR_INSUFFICIENT_BUFFER;
9596 if (!rpcbuf_alloc_size(buffer, *needed)) {
9597 result = WERR_INSUFFICIENT_BUFFER;
9601 smb_io_printprocessordirectory_1("", buffer, info, 0);
9609 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9611 uint32 level = q_u->level;
9612 RPC_BUFFER *buffer = NULL;
9613 uint32 offered = q_u->offered;
9614 uint32 *needed = &r_u->needed;
9617 /* that's an [in out] buffer */
9619 if (!q_u->buffer && (offered!=0)) {
9620 return WERR_INVALID_PARAM;
9623 rpcbuf_move(q_u->buffer, &r_u->buffer);
9624 buffer = r_u->buffer;
9626 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9632 result = getprintprocessordirectory_level_1
9633 (&q_u->name, &q_u->environment, buffer, offered, needed);
9636 result = WERR_UNKNOWN_LEVEL;
9642 /*******************************************************************
9643 Streams the monitor UI DLL name in UNICODE
9644 *******************************************************************/
9646 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9647 RPC_BUFFER *out, uint32 *needed )
9649 const char *dllname = "tcpmonui.dll";
9651 *needed = (strlen(dllname)+1) * 2;
9653 if ( rpcbuf_get_size(out) < *needed ) {
9654 return WERR_INSUFFICIENT_BUFFER;
9657 if ( !make_monitorui_buf( out, dllname ) ) {
9664 /*******************************************************************
9665 Create a new TCP/IP port
9666 *******************************************************************/
9668 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9669 RPC_BUFFER *out, uint32 *needed )
9671 NT_PORT_DATA_1 port1;
9674 ZERO_STRUCT( port1 );
9676 /* convert to our internal port data structure */
9678 if ( !convert_port_data_1( &port1, in ) ) {
9682 /* create the device URI and call the add_port_hook() */
9684 switch ( port1.protocol ) {
9685 case PORT_PROTOCOL_DIRECT:
9686 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9689 case PORT_PROTOCOL_LPR:
9690 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9694 return WERR_UNKNOWN_PORT;
9697 return add_port_hook( token, port1.name, device_uri );
9700 /*******************************************************************
9701 *******************************************************************/
9703 struct xcv_api_table xcvtcp_cmds[] = {
9704 { "MonitorUI", xcvtcp_monitorui },
9705 { "AddPort", xcvtcp_addport},
9709 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9710 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9715 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9717 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9718 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9719 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9722 return WERR_BADFUNC;
9725 /*******************************************************************
9726 *******************************************************************/
9727 #if 0 /* don't support management using the "Local Port" monitor */
9729 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9730 RPC_BUFFER *out, uint32 *needed )
9732 const char *dllname = "localui.dll";
9734 *needed = (strlen(dllname)+1) * 2;
9736 if ( rpcbuf_get_size(out) < *needed ) {
9737 return WERR_INSUFFICIENT_BUFFER;
9740 if ( !make_monitorui_buf( out, dllname )) {
9747 /*******************************************************************
9748 *******************************************************************/
9750 struct xcv_api_table xcvlocal_cmds[] = {
9751 { "MonitorUI", xcvlocal_monitorui },
9755 struct xcv_api_table xcvlocal_cmds[] = {
9762 /*******************************************************************
9763 *******************************************************************/
9765 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9766 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9771 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9773 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9774 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9775 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9777 return WERR_BADFUNC;
9780 /*******************************************************************
9781 *******************************************************************/
9783 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9785 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9789 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9793 /* Has to be a handle to the TCP/IP port monitor */
9795 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9796 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9800 /* requires administrative access to the server */
9802 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9803 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9804 return WERR_ACCESS_DENIED;
9807 /* Get the command name. There's numerous commands supported by the
9808 TCPMON interface. */
9810 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9811 q_u->dataname.uni_str_len*2, 0);
9813 /* Allocate the outgoing buffer */
9815 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9817 switch ( Printer->printer_type ) {
9818 case SPLHND_PORTMON_TCP:
9819 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9820 &q_u->indata, &r_u->outdata, &r_u->needed );
9821 case SPLHND_PORTMON_LOCAL:
9822 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9823 &q_u->indata, &r_u->outdata, &r_u->needed );
9826 return WERR_INVALID_PRINT_MONITOR;