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 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1420 devmode->driverextra);
1421 if (!d->dev_private) {
1427 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1429 if (!new_ctr || !ctr)
1432 DEBUG(8,("copy_devmode_ctr\n"));
1434 new_ctr->size = ctr->size;
1435 new_ctr->devmode_ptr = ctr->devmode_ptr;
1437 if(ctr->devmode_ptr)
1438 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1441 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1443 if (!new_def || !def)
1446 DEBUG(8,("copy_printer_defaults\n"));
1448 new_def->datatype_ptr = def->datatype_ptr;
1450 if (def->datatype_ptr)
1451 copy_unistr2(&new_def->datatype, &def->datatype);
1453 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1455 new_def->access_required = def->access_required;
1458 /********************************************************************
1459 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1460 * SPOOL_Q_OPEN_PRINTER_EX structure
1461 ********************************************************************/
1463 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1465 if (!q_u_ex || !q_u)
1468 DEBUG(8,("convert_to_openprinterex\n"));
1470 if ( q_u->printername ) {
1471 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1472 if (q_u_ex->printername == NULL)
1474 copy_unistr2(q_u_ex->printername, q_u->printername);
1477 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1482 /********************************************************************
1483 * spoolss_open_printer
1485 * called from the spoolss dispatcher
1486 ********************************************************************/
1488 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1490 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1491 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1496 ZERO_STRUCT(q_u_ex);
1497 ZERO_STRUCT(r_u_ex);
1499 /* convert the OpenPrinter() call to OpenPrinterEx() */
1501 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1502 if (!W_ERROR_IS_OK(r_u_ex.status))
1503 return r_u_ex.status;
1505 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1507 /* convert back to OpenPrinter() */
1509 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1514 /********************************************************************
1515 ********************************************************************/
1517 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1519 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1520 POLICY_HND *handle = &r_u->handle;
1524 Printer_entry *Printer=NULL;
1526 if ( !q_u->printername )
1527 return WERR_INVALID_PRINTER_NAME;
1529 /* some sanity check because you can open a printer or a print server */
1530 /* aka: \\server\printer or \\server */
1532 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1534 DEBUGADD(3,("checking name: %s\n",name));
1536 if (!open_printer_hnd(p, handle, name, 0))
1537 return WERR_INVALID_PRINTER_NAME;
1539 Printer=find_printer_index_by_hnd(p, handle);
1541 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1542 "handle we created for printer %s\n", name ));
1543 close_printer_handle(p,handle);
1544 return WERR_INVALID_PRINTER_NAME;
1548 * First case: the user is opening the print server:
1550 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1551 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1553 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1554 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1555 * or if the user is listed in the smb.conf printer admin parameter.
1557 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1558 * client view printer folder, but does not show the MSAPW.
1560 * Note: this test needs code to check access rights here too. Jeremy
1561 * could you look at this?
1563 * Second case: the user is opening a printer:
1564 * NT doesn't let us connect to a printer if the connecting user
1565 * doesn't have print permission.
1567 * Third case: user is opening a Port Monitor
1568 * access checks same as opening a handle to the print server.
1571 switch (Printer->printer_type )
1574 case SPLHND_PORTMON_TCP:
1575 case SPLHND_PORTMON_LOCAL:
1576 /* Printserver handles use global struct... */
1580 /* Map standard access rights to object specific access rights */
1582 se_map_standard(&printer_default->access_required,
1583 &printserver_std_mapping);
1585 /* Deny any object specific bits that don't apply to print
1586 servers (i.e printer and job specific bits) */
1588 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1590 if (printer_default->access_required &
1591 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1592 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1593 close_printer_handle(p, handle);
1594 return WERR_ACCESS_DENIED;
1597 /* Allow admin access */
1599 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1601 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1603 if (!lp_ms_add_printer_wizard()) {
1604 close_printer_handle(p, handle);
1605 return WERR_ACCESS_DENIED;
1608 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1609 and not a printer admin, then fail */
1611 if ((p->pipe_user.ut.uid != 0) &&
1612 !user_has_privileges(p->pipe_user.nt_user_token,
1614 !token_contains_name_in_list(
1615 uidtoname(p->pipe_user.ut.uid), NULL,
1616 p->pipe_user.nt_user_token,
1617 lp_printer_admin(snum))) {
1618 close_printer_handle(p, handle);
1619 return WERR_ACCESS_DENIED;
1622 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1626 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1629 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1630 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1632 /* We fall through to return WERR_OK */
1635 case SPLHND_PRINTER:
1636 /* NT doesn't let us connect to a printer if the connecting user
1637 doesn't have print permission. */
1639 if (!get_printer_snum(p, handle, &snum, NULL)) {
1640 close_printer_handle(p, handle);
1644 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1646 /* map an empty access mask to the minimum access mask */
1647 if (printer_default->access_required == 0x0)
1648 printer_default->access_required = PRINTER_ACCESS_USE;
1651 * If we are not serving the printer driver for this printer,
1652 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1653 * will keep NT clients happy --jerry
1656 if (lp_use_client_driver(snum)
1657 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1659 printer_default->access_required = PRINTER_ACCESS_USE;
1662 /* check smb.conf parameters and the the sec_desc */
1664 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1665 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1666 return WERR_ACCESS_DENIED;
1669 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1670 p->pipe_user.nt_user_token, snum) ||
1671 !print_access_check(&p->pipe_user, snum,
1672 printer_default->access_required)) {
1673 DEBUG(3, ("access DENIED for printer open\n"));
1674 close_printer_handle(p, handle);
1675 return WERR_ACCESS_DENIED;
1678 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1679 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1680 close_printer_handle(p, handle);
1681 return WERR_ACCESS_DENIED;
1684 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1685 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1687 printer_default->access_required = PRINTER_ACCESS_USE;
1689 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1690 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1695 /* sanity check to prevent programmer error */
1699 Printer->access_granted = printer_default->access_required;
1702 * If the client sent a devmode in the OpenPrinter() call, then
1703 * save it here in case we get a job submission on this handle
1706 if ( (Printer->printer_type != SPLHND_SERVER)
1707 && q_u->printer_default.devmode_cont.devmode_ptr )
1709 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1710 &Printer->nt_devmode );
1713 #if 0 /* JERRY -- I'm doubtful this is really effective */
1714 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1715 optimization in Windows 2000 clients --jerry */
1717 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1718 && (RA_WIN2K == get_remote_arch()) )
1720 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1721 sys_usleep( 500000 );
1728 /****************************************************************************
1729 ****************************************************************************/
1731 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1732 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1738 /* allocate memory if needed. Messy because
1739 convert_printer_info is used to update an existing
1740 printer or build a new one */
1742 if ( !printer->info_2 ) {
1743 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1744 if ( !printer->info_2 ) {
1745 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1750 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1751 printer->info_2->setuptime = time(NULL);
1759 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1760 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1766 printer->info_3=NULL;
1767 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1771 printer->info_6=NULL;
1772 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1782 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1783 NT_DEVICEMODE **pp_nt_devmode)
1785 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1788 * Ensure nt_devmode is a valid pointer
1789 * as we will be overwriting it.
1792 if (nt_devmode == NULL) {
1793 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1794 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1798 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1799 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1801 nt_devmode->specversion=devmode->specversion;
1802 nt_devmode->driverversion=devmode->driverversion;
1803 nt_devmode->size=devmode->size;
1804 nt_devmode->fields=devmode->fields;
1805 nt_devmode->orientation=devmode->orientation;
1806 nt_devmode->papersize=devmode->papersize;
1807 nt_devmode->paperlength=devmode->paperlength;
1808 nt_devmode->paperwidth=devmode->paperwidth;
1809 nt_devmode->scale=devmode->scale;
1810 nt_devmode->copies=devmode->copies;
1811 nt_devmode->defaultsource=devmode->defaultsource;
1812 nt_devmode->printquality=devmode->printquality;
1813 nt_devmode->color=devmode->color;
1814 nt_devmode->duplex=devmode->duplex;
1815 nt_devmode->yresolution=devmode->yresolution;
1816 nt_devmode->ttoption=devmode->ttoption;
1817 nt_devmode->collate=devmode->collate;
1819 nt_devmode->logpixels=devmode->logpixels;
1820 nt_devmode->bitsperpel=devmode->bitsperpel;
1821 nt_devmode->pelswidth=devmode->pelswidth;
1822 nt_devmode->pelsheight=devmode->pelsheight;
1823 nt_devmode->displayflags=devmode->displayflags;
1824 nt_devmode->displayfrequency=devmode->displayfrequency;
1825 nt_devmode->icmmethod=devmode->icmmethod;
1826 nt_devmode->icmintent=devmode->icmintent;
1827 nt_devmode->mediatype=devmode->mediatype;
1828 nt_devmode->dithertype=devmode->dithertype;
1829 nt_devmode->reserved1=devmode->reserved1;
1830 nt_devmode->reserved2=devmode->reserved2;
1831 nt_devmode->panningwidth=devmode->panningwidth;
1832 nt_devmode->panningheight=devmode->panningheight;
1835 * Only change private and driverextra if the incoming devmode
1836 * has a new one. JRA.
1839 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1840 SAFE_FREE(nt_devmode->nt_dev_private);
1841 nt_devmode->driverextra=devmode->driverextra;
1842 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1844 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1847 *pp_nt_devmode = nt_devmode;
1852 /********************************************************************
1853 * _spoolss_enddocprinter_internal.
1854 ********************************************************************/
1856 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1858 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1862 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1866 if (!get_printer_snum(p, handle, &snum, NULL))
1869 Printer->document_started=False;
1870 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1871 /* error codes unhandled so far ... */
1876 /********************************************************************
1877 * api_spoolss_closeprinter
1878 ********************************************************************/
1880 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1882 POLICY_HND *handle = &q_u->handle;
1884 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1886 if (Printer && Printer->document_started)
1887 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1889 if (!close_printer_handle(p, handle))
1892 /* clear the returned printer handle. Observed behavior
1893 from Win2k server. Don't think this really matters.
1894 Previous code just copied the value of the closed
1897 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1902 /********************************************************************
1903 * api_spoolss_deleteprinter
1905 ********************************************************************/
1907 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1909 POLICY_HND *handle = &q_u->handle;
1910 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1913 if (Printer && Printer->document_started)
1914 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1916 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1918 result = delete_printer_handle(p, handle);
1920 update_c_setprinter(False);
1925 /*******************************************************************
1926 * static function to lookup the version id corresponding to an
1927 * long architecture string
1928 ******************************************************************/
1930 static int get_version_id (char * arch)
1933 struct table_node archi_table[]= {
1935 {"Windows 4.0", "WIN40", 0 },
1936 {"Windows NT x86", "W32X86", 2 },
1937 {"Windows NT R4000", "W32MIPS", 2 },
1938 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1939 {"Windows NT PowerPC", "W32PPC", 2 },
1940 {"Windows IA64", "IA64", 3 },
1941 {"Windows x64", "x64", 3 },
1945 for (i=0; archi_table[i].long_archi != NULL; i++)
1947 if (strcmp(arch, archi_table[i].long_archi) == 0)
1948 return (archi_table[i].version);
1954 /********************************************************************
1955 * _spoolss_deleteprinterdriver
1956 ********************************************************************/
1958 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1962 NT_PRINTER_DRIVER_INFO_LEVEL info;
1963 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1966 WERROR status_win2k = WERR_ACCESS_DENIED;
1967 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1969 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1970 and not a printer admin, then fail */
1972 if ( (p->pipe_user.ut.uid != 0)
1973 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
1974 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
1975 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
1977 return WERR_ACCESS_DENIED;
1980 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1981 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1983 /* check that we have a valid driver name first */
1985 if ((version=get_version_id(arch)) == -1)
1986 return WERR_INVALID_ENVIRONMENT;
1989 ZERO_STRUCT(info_win2k);
1991 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1993 /* try for Win2k driver if "Windows NT x86" */
1995 if ( version == 2 ) {
1997 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1998 status = WERR_UNKNOWN_PRINTER_DRIVER;
2002 /* otherwise it was a failure */
2004 status = WERR_UNKNOWN_PRINTER_DRIVER;
2010 if (printer_driver_in_use(info.info_3)) {
2011 status = WERR_PRINTER_DRIVER_IN_USE;
2017 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2019 /* if we get to here, we now have 2 driver info structures to remove */
2020 /* remove the Win2k driver first*/
2022 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2023 free_a_printer_driver( info_win2k, 3 );
2025 /* this should not have failed---if it did, report to client */
2026 if ( !W_ERROR_IS_OK(status_win2k) )
2028 status = status_win2k;
2034 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2036 /* if at least one of the deletes succeeded return OK */
2038 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2042 free_a_printer_driver( info, 3 );
2047 /********************************************************************
2048 * spoolss_deleteprinterdriverex
2049 ********************************************************************/
2051 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2055 NT_PRINTER_DRIVER_INFO_LEVEL info;
2056 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2058 uint32 flags = q_u->delete_flags;
2061 WERROR status_win2k = WERR_ACCESS_DENIED;
2062 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2064 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2065 and not a printer admin, then fail */
2067 if ( (p->pipe_user.ut.uid != 0)
2068 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2069 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2070 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2072 return WERR_ACCESS_DENIED;
2075 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2076 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2078 /* check that we have a valid driver name first */
2079 if ((version=get_version_id(arch)) == -1) {
2080 /* this is what NT returns */
2081 return WERR_INVALID_ENVIRONMENT;
2084 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2085 version = q_u->version;
2088 ZERO_STRUCT(info_win2k);
2090 status = get_a_printer_driver(&info, 3, driver, arch, version);
2092 if ( !W_ERROR_IS_OK(status) )
2095 * if the client asked for a specific version,
2096 * or this is something other than Windows NT x86,
2100 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2103 /* try for Win2k driver if "Windows NT x86" */
2106 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2107 status = WERR_UNKNOWN_PRINTER_DRIVER;
2112 if ( printer_driver_in_use(info.info_3) ) {
2113 status = WERR_PRINTER_DRIVER_IN_USE;
2118 * we have a couple of cases to consider.
2119 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2120 * then the delete should fail if **any** files overlap with
2122 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2123 * non-overlapping files
2124 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2125 * is set, the do not delete any files
2126 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2129 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2131 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2133 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2134 /* no idea of the correct error here */
2135 status = WERR_ACCESS_DENIED;
2140 /* also check for W32X86/3 if necessary; maybe we already have? */
2142 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2143 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2146 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2147 /* no idea of the correct error here */
2148 free_a_printer_driver( info_win2k, 3 );
2149 status = WERR_ACCESS_DENIED;
2153 /* if we get to here, we now have 2 driver info structures to remove */
2154 /* remove the Win2k driver first*/
2156 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2157 free_a_printer_driver( info_win2k, 3 );
2159 /* this should not have failed---if it did, report to client */
2161 if ( !W_ERROR_IS_OK(status_win2k) )
2166 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2168 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2171 free_a_printer_driver( info, 3 );
2177 /****************************************************************************
2178 Internal routine for retreiving printerdata
2179 ***************************************************************************/
2181 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2182 const char *key, const char *value, uint32 *type, uint8 **data,
2183 uint32 *needed, uint32 in_size )
2185 REGISTRY_VALUE *val;
2189 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2190 return WERR_BADFILE;
2192 *type = regval_type( val );
2194 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2196 size = regval_size( val );
2198 /* copy the min(in_size, len) */
2201 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2203 /* special case for 0 length values */
2205 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2209 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2218 DEBUG(5,("get_printer_dataex: copy done\n"));
2223 /****************************************************************************
2224 Internal routine for removing printerdata
2225 ***************************************************************************/
2227 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2229 return delete_printer_data( printer->info_2, key, value );
2232 /****************************************************************************
2233 Internal routine for storing printerdata
2234 ***************************************************************************/
2236 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2237 uint32 type, uint8 *data, int real_len )
2239 /* the registry objects enforce uniqueness based on value name */
2241 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2244 /********************************************************************
2245 GetPrinterData on a printer server Handle.
2246 ********************************************************************/
2248 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2252 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2254 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2256 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2262 if (!StrCaseCmp(value, "BeepEnabled")) {
2264 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2266 SIVAL(*data, 0, 0x00);
2271 if (!StrCaseCmp(value, "EventLog")) {
2273 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2275 /* formally was 0x1b */
2276 SIVAL(*data, 0, 0x0);
2281 if (!StrCaseCmp(value, "NetPopup")) {
2283 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2285 SIVAL(*data, 0, 0x00);
2290 if (!StrCaseCmp(value, "MajorVersion")) {
2292 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2295 /* Windows NT 4.0 seems to not allow uploading of drivers
2296 to a server that reports 0x3 as the MajorVersion.
2297 need to investigate more how Win2k gets around this .
2300 if ( RA_WINNT == get_remote_arch() )
2309 if (!StrCaseCmp(value, "MinorVersion")) {
2311 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2319 * uint32 size = 0x114
2321 * uint32 minor = [0|1]
2322 * uint32 build = [2195|2600]
2323 * extra unicode string = e.g. "Service Pack 3"
2325 if (!StrCaseCmp(value, "OSVersion")) {
2329 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2332 SIVAL(*data, 0, *needed); /* size */
2333 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2335 SIVAL(*data, 12, 2195); /* build */
2337 /* leave extra string empty */
2343 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2344 const char *string="C:\\PRINTERS";
2346 *needed = 2*(strlen(string)+1);
2347 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2349 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2351 /* it's done by hand ready to go on the wire */
2352 for (i=0; i<strlen(string); i++) {
2353 (*data)[2*i]=string[i];
2354 (*data)[2*i+1]='\0';
2359 if (!StrCaseCmp(value, "Architecture")) {
2360 const char *string="Windows NT x86";
2362 *needed = 2*(strlen(string)+1);
2363 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2365 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2366 for (i=0; i<strlen(string); i++) {
2367 (*data)[2*i]=string[i];
2368 (*data)[2*i+1]='\0';
2373 if (!StrCaseCmp(value, "DsPresent")) {
2375 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2378 /* only show the publish check box if we are a
2379 memeber of a AD domain */
2381 if ( lp_security() == SEC_ADS )
2382 SIVAL(*data, 0, 0x01);
2384 SIVAL(*data, 0, 0x00);
2390 if (!StrCaseCmp(value, "DNSMachineName")) {
2393 if (!get_mydnsfullname(hostname))
2394 return WERR_BADFILE;
2396 *needed = 2*(strlen(hostname)+1);
2397 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2399 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2400 for (i=0; i<strlen(hostname); i++) {
2401 (*data)[2*i]=hostname[i];
2402 (*data)[2*i+1]='\0';
2408 return WERR_BADFILE;
2411 /********************************************************************
2412 * spoolss_getprinterdata
2413 ********************************************************************/
2415 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2417 POLICY_HND *handle = &q_u->handle;
2418 UNISTR2 *valuename = &q_u->valuename;
2419 uint32 in_size = q_u->size;
2420 uint32 *type = &r_u->type;
2421 uint32 *out_size = &r_u->size;
2422 uint8 **data = &r_u->data;
2423 uint32 *needed = &r_u->needed;
2426 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2427 NT_PRINTER_INFO_LEVEL *printer = NULL;
2431 * Reminder: when it's a string, the length is in BYTES
2432 * even if UNICODE is negociated.
2437 *out_size = in_size;
2439 /* in case of problem, return some default values */
2444 DEBUG(4,("_spoolss_getprinterdata\n"));
2447 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2448 status = WERR_BADFID;
2452 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2454 if ( Printer->printer_type == SPLHND_SERVER )
2455 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2458 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2459 status = WERR_BADFID;
2463 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2464 if ( !W_ERROR_IS_OK(status) )
2467 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2469 if ( strequal(value, "ChangeId") ) {
2471 *needed = sizeof(uint32);
2472 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2473 status = WERR_NOMEM;
2476 SIVAL( *data, 0, printer->info_2->changeid );
2480 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2483 if (*needed > *out_size)
2484 status = WERR_MORE_DATA;
2487 if ( !W_ERROR_IS_OK(status) )
2489 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2491 /* reply this param doesn't exist */
2494 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2496 free_a_printer( &printer, 2 );
2505 /* cleanup & exit */
2508 free_a_printer( &printer, 2 );
2513 /*********************************************************
2514 Connect to the client machine.
2515 **********************************************************/
2517 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2518 struct in_addr *client_ip, const char *remote_machine)
2521 struct cli_state *the_cli;
2522 struct in_addr rm_addr;
2524 if ( is_zero_ip(*client_ip) ) {
2525 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2526 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2530 if ( ismyip( rm_addr )) {
2531 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2535 rm_addr.s_addr = client_ip->s_addr;
2536 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2537 inet_ntoa(*client_ip) ));
2540 /* setup the connection */
2542 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2543 &rm_addr, 0, "IPC$", "IPC",
2547 0, lp_client_signing(), NULL );
2549 if ( !NT_STATUS_IS_OK( ret ) ) {
2550 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2555 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2556 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2557 cli_shutdown(the_cli);
2562 * Ok - we have an anonymous connection to the IPC$ share.
2563 * Now start the NT Domain stuff :-).
2566 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2567 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2568 remote_machine, nt_errstr(ret)));
2569 cli_shutdown(the_cli);
2573 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2575 (*pp_pipe)->cli = the_cli;
2580 /***************************************************************************
2581 Connect to the client.
2582 ****************************************************************************/
2584 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2585 uint32 localprinter, uint32 type,
2586 POLICY_HND *handle, struct in_addr *client_ip)
2591 * If it's the first connection, contact the client
2592 * and connect to the IPC$ share anonymously
2594 if (smb_connections==0) {
2595 fstring unix_printer;
2597 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2599 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2602 message_register(MSG_PRINTER_NOTIFY2,
2603 receive_notify2_message_list, NULL);
2604 /* Tell the connections db we're now interested in printer
2605 * notify messages. */
2606 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2610 * Tell the specific printing tdb we want messages for this printer
2611 * by registering our PID.
2614 if (!print_notify_register_pid(snum))
2615 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2619 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2622 if (!W_ERROR_IS_OK(result))
2623 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2624 dos_errstr(result)));
2626 return (W_ERROR_IS_OK(result));
2629 /********************************************************************
2631 * ReplyFindFirstPrinterChangeNotifyEx
2633 * before replying OK: status=0 a rpc call is made to the workstation
2634 * asking ReplyOpenPrinter
2636 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2637 * called from api_spoolss_rffpcnex
2638 ********************************************************************/
2640 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2642 POLICY_HND *handle = &q_u->handle;
2643 uint32 flags = q_u->flags;
2644 uint32 options = q_u->options;
2645 UNISTR2 *localmachine = &q_u->localmachine;
2646 uint32 printerlocal = q_u->printerlocal;
2648 SPOOL_NOTIFY_OPTION *option = q_u->option;
2649 struct in_addr client_ip;
2651 /* store the notify value in the printer struct */
2653 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2656 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2660 Printer->notify.flags=flags;
2661 Printer->notify.options=options;
2662 Printer->notify.printerlocal=printerlocal;
2664 if (Printer->notify.option)
2665 free_spool_notify_option(&Printer->notify.option);
2667 Printer->notify.option=dup_spool_notify_option(option);
2669 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2670 sizeof(Printer->notify.localmachine)-1);
2672 /* Connect to the client machine and send a ReplyOpenPrinter */
2674 if ( Printer->printer_type == SPLHND_SERVER)
2676 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2677 !get_printer_snum(p, handle, &snum, NULL) )
2680 client_ip.s_addr = inet_addr(p->conn->client_address);
2682 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2683 Printer->notify.printerlocal, 1,
2684 &Printer->notify.client_hnd, &client_ip))
2685 return WERR_SERVER_UNAVAILABLE;
2687 Printer->notify.client_connected=True;
2692 /*******************************************************************
2693 * fill a notify_info_data with the servername
2694 ********************************************************************/
2696 void spoolss_notify_server_name(int snum,
2697 SPOOL_NOTIFY_INFO_DATA *data,
2698 print_queue_struct *queue,
2699 NT_PRINTER_INFO_LEVEL *printer,
2700 TALLOC_CTX *mem_ctx)
2705 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2707 data->notify_data.data.length = len;
2708 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2710 if (!data->notify_data.data.string) {
2711 data->notify_data.data.length = 0;
2715 memcpy(data->notify_data.data.string, temp, len);
2718 /*******************************************************************
2719 * fill a notify_info_data with the printername (not including the servername).
2720 ********************************************************************/
2722 void spoolss_notify_printer_name(int snum,
2723 SPOOL_NOTIFY_INFO_DATA *data,
2724 print_queue_struct *queue,
2725 NT_PRINTER_INFO_LEVEL *printer,
2726 TALLOC_CTX *mem_ctx)
2731 /* the notify name should not contain the \\server\ part */
2732 char *p = strrchr(printer->info_2->printername, '\\');
2735 p = printer->info_2->printername;
2740 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2742 data->notify_data.data.length = len;
2743 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2745 if (!data->notify_data.data.string) {
2746 data->notify_data.data.length = 0;
2750 memcpy(data->notify_data.data.string, temp, len);
2753 /*******************************************************************
2754 * fill a notify_info_data with the servicename
2755 ********************************************************************/
2757 void spoolss_notify_share_name(int snum,
2758 SPOOL_NOTIFY_INFO_DATA *data,
2759 print_queue_struct *queue,
2760 NT_PRINTER_INFO_LEVEL *printer,
2761 TALLOC_CTX *mem_ctx)
2766 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2768 data->notify_data.data.length = len;
2769 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2771 if (!data->notify_data.data.string) {
2772 data->notify_data.data.length = 0;
2776 memcpy(data->notify_data.data.string, temp, len);
2779 /*******************************************************************
2780 * fill a notify_info_data with the port name
2781 ********************************************************************/
2783 void spoolss_notify_port_name(int snum,
2784 SPOOL_NOTIFY_INFO_DATA *data,
2785 print_queue_struct *queue,
2786 NT_PRINTER_INFO_LEVEL *printer,
2787 TALLOC_CTX *mem_ctx)
2792 /* even if it's strange, that's consistant in all the code */
2794 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2796 data->notify_data.data.length = len;
2797 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2799 if (!data->notify_data.data.string) {
2800 data->notify_data.data.length = 0;
2804 memcpy(data->notify_data.data.string, temp, len);
2807 /*******************************************************************
2808 * fill a notify_info_data with the printername
2809 * but it doesn't exist, have to see what to do
2810 ********************************************************************/
2812 void spoolss_notify_driver_name(int snum,
2813 SPOOL_NOTIFY_INFO_DATA *data,
2814 print_queue_struct *queue,
2815 NT_PRINTER_INFO_LEVEL *printer,
2816 TALLOC_CTX *mem_ctx)
2821 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2823 data->notify_data.data.length = len;
2824 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2826 if (!data->notify_data.data.string) {
2827 data->notify_data.data.length = 0;
2831 memcpy(data->notify_data.data.string, temp, len);
2834 /*******************************************************************
2835 * fill a notify_info_data with the comment
2836 ********************************************************************/
2838 void spoolss_notify_comment(int snum,
2839 SPOOL_NOTIFY_INFO_DATA *data,
2840 print_queue_struct *queue,
2841 NT_PRINTER_INFO_LEVEL *printer,
2842 TALLOC_CTX *mem_ctx)
2847 if (*printer->info_2->comment == '\0')
2848 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2850 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2852 data->notify_data.data.length = len;
2853 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2855 if (!data->notify_data.data.string) {
2856 data->notify_data.data.length = 0;
2860 memcpy(data->notify_data.data.string, temp, len);
2863 /*******************************************************************
2864 * fill a notify_info_data with the comment
2865 * location = "Room 1, floor 2, building 3"
2866 ********************************************************************/
2868 void spoolss_notify_location(int snum,
2869 SPOOL_NOTIFY_INFO_DATA *data,
2870 print_queue_struct *queue,
2871 NT_PRINTER_INFO_LEVEL *printer,
2872 TALLOC_CTX *mem_ctx)
2877 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2879 data->notify_data.data.length = len;
2880 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2882 if (!data->notify_data.data.string) {
2883 data->notify_data.data.length = 0;
2887 memcpy(data->notify_data.data.string, temp, len);
2890 /*******************************************************************
2891 * fill a notify_info_data with the device mode
2892 * jfm:xxxx don't to it for know but that's a real problem !!!
2893 ********************************************************************/
2895 static void spoolss_notify_devmode(int snum,
2896 SPOOL_NOTIFY_INFO_DATA *data,
2897 print_queue_struct *queue,
2898 NT_PRINTER_INFO_LEVEL *printer,
2899 TALLOC_CTX *mem_ctx)
2901 /* for a dummy implementation we have to zero the fields */
2902 data->notify_data.data.length = 0;
2903 data->notify_data.data.string = NULL;
2906 /*******************************************************************
2907 * fill a notify_info_data with the separator file name
2908 ********************************************************************/
2910 void spoolss_notify_sepfile(int snum,
2911 SPOOL_NOTIFY_INFO_DATA *data,
2912 print_queue_struct *queue,
2913 NT_PRINTER_INFO_LEVEL *printer,
2914 TALLOC_CTX *mem_ctx)
2919 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2921 data->notify_data.data.length = len;
2922 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2924 if (!data->notify_data.data.string) {
2925 data->notify_data.data.length = 0;
2929 memcpy(data->notify_data.data.string, temp, len);
2932 /*******************************************************************
2933 * fill a notify_info_data with the print processor
2934 * jfm:xxxx return always winprint to indicate we don't do anything to it
2935 ********************************************************************/
2937 void spoolss_notify_print_processor(int snum,
2938 SPOOL_NOTIFY_INFO_DATA *data,
2939 print_queue_struct *queue,
2940 NT_PRINTER_INFO_LEVEL *printer,
2941 TALLOC_CTX *mem_ctx)
2946 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2948 data->notify_data.data.length = len;
2949 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2951 if (!data->notify_data.data.string) {
2952 data->notify_data.data.length = 0;
2956 memcpy(data->notify_data.data.string, temp, len);
2959 /*******************************************************************
2960 * fill a notify_info_data with the print processor options
2961 * jfm:xxxx send an empty string
2962 ********************************************************************/
2964 void spoolss_notify_parameters(int snum,
2965 SPOOL_NOTIFY_INFO_DATA *data,
2966 print_queue_struct *queue,
2967 NT_PRINTER_INFO_LEVEL *printer,
2968 TALLOC_CTX *mem_ctx)
2973 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2975 data->notify_data.data.length = len;
2976 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2978 if (!data->notify_data.data.string) {
2979 data->notify_data.data.length = 0;
2983 memcpy(data->notify_data.data.string, temp, len);
2986 /*******************************************************************
2987 * fill a notify_info_data with the data type
2988 * jfm:xxxx always send RAW as data type
2989 ********************************************************************/
2991 void spoolss_notify_datatype(int snum,
2992 SPOOL_NOTIFY_INFO_DATA *data,
2993 print_queue_struct *queue,
2994 NT_PRINTER_INFO_LEVEL *printer,
2995 TALLOC_CTX *mem_ctx)
3000 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3002 data->notify_data.data.length = len;
3003 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3005 if (!data->notify_data.data.string) {
3006 data->notify_data.data.length = 0;
3010 memcpy(data->notify_data.data.string, temp, len);
3013 /*******************************************************************
3014 * fill a notify_info_data with the security descriptor
3015 * jfm:xxxx send an null pointer to say no security desc
3016 * have to implement security before !
3017 ********************************************************************/
3019 static void spoolss_notify_security_desc(int snum,
3020 SPOOL_NOTIFY_INFO_DATA *data,
3021 print_queue_struct *queue,
3022 NT_PRINTER_INFO_LEVEL *printer,
3023 TALLOC_CTX *mem_ctx)
3025 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3026 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3029 /*******************************************************************
3030 * fill a notify_info_data with the attributes
3031 * jfm:xxxx a samba printer is always shared
3032 ********************************************************************/
3034 void spoolss_notify_attributes(int snum,
3035 SPOOL_NOTIFY_INFO_DATA *data,
3036 print_queue_struct *queue,
3037 NT_PRINTER_INFO_LEVEL *printer,
3038 TALLOC_CTX *mem_ctx)
3040 data->notify_data.value[0] = printer->info_2->attributes;
3041 data->notify_data.value[1] = 0;
3044 /*******************************************************************
3045 * fill a notify_info_data with the priority
3046 ********************************************************************/
3048 static void spoolss_notify_priority(int snum,
3049 SPOOL_NOTIFY_INFO_DATA *data,
3050 print_queue_struct *queue,
3051 NT_PRINTER_INFO_LEVEL *printer,
3052 TALLOC_CTX *mem_ctx)
3054 data->notify_data.value[0] = printer->info_2->priority;
3055 data->notify_data.value[1] = 0;
3058 /*******************************************************************
3059 * fill a notify_info_data with the default priority
3060 ********************************************************************/
3062 static void spoolss_notify_default_priority(int snum,
3063 SPOOL_NOTIFY_INFO_DATA *data,
3064 print_queue_struct *queue,
3065 NT_PRINTER_INFO_LEVEL *printer,
3066 TALLOC_CTX *mem_ctx)
3068 data->notify_data.value[0] = printer->info_2->default_priority;
3069 data->notify_data.value[1] = 0;
3072 /*******************************************************************
3073 * fill a notify_info_data with the start time
3074 ********************************************************************/
3076 static void spoolss_notify_start_time(int snum,
3077 SPOOL_NOTIFY_INFO_DATA *data,
3078 print_queue_struct *queue,
3079 NT_PRINTER_INFO_LEVEL *printer,
3080 TALLOC_CTX *mem_ctx)
3082 data->notify_data.value[0] = printer->info_2->starttime;
3083 data->notify_data.value[1] = 0;
3086 /*******************************************************************
3087 * fill a notify_info_data with the until time
3088 ********************************************************************/
3090 static void spoolss_notify_until_time(int snum,
3091 SPOOL_NOTIFY_INFO_DATA *data,
3092 print_queue_struct *queue,
3093 NT_PRINTER_INFO_LEVEL *printer,
3094 TALLOC_CTX *mem_ctx)
3096 data->notify_data.value[0] = printer->info_2->untiltime;
3097 data->notify_data.value[1] = 0;
3100 /*******************************************************************
3101 * fill a notify_info_data with the status
3102 ********************************************************************/
3104 static void spoolss_notify_status(int snum,
3105 SPOOL_NOTIFY_INFO_DATA *data,
3106 print_queue_struct *queue,
3107 NT_PRINTER_INFO_LEVEL *printer,
3108 TALLOC_CTX *mem_ctx)
3110 print_status_struct status;
3112 print_queue_length(snum, &status);
3113 data->notify_data.value[0]=(uint32) status.status;
3114 data->notify_data.value[1] = 0;
3117 /*******************************************************************
3118 * fill a notify_info_data with the number of jobs queued
3119 ********************************************************************/
3121 void spoolss_notify_cjobs(int snum,
3122 SPOOL_NOTIFY_INFO_DATA *data,
3123 print_queue_struct *queue,
3124 NT_PRINTER_INFO_LEVEL *printer,
3125 TALLOC_CTX *mem_ctx)
3127 data->notify_data.value[0] = print_queue_length(snum, NULL);
3128 data->notify_data.value[1] = 0;
3131 /*******************************************************************
3132 * fill a notify_info_data with the average ppm
3133 ********************************************************************/
3135 static void spoolss_notify_average_ppm(int snum,
3136 SPOOL_NOTIFY_INFO_DATA *data,
3137 print_queue_struct *queue,
3138 NT_PRINTER_INFO_LEVEL *printer,
3139 TALLOC_CTX *mem_ctx)
3141 /* always respond 8 pages per minutes */
3142 /* a little hard ! */
3143 data->notify_data.value[0] = printer->info_2->averageppm;
3144 data->notify_data.value[1] = 0;
3147 /*******************************************************************
3148 * fill a notify_info_data with username
3149 ********************************************************************/
3151 static void spoolss_notify_username(int snum,
3152 SPOOL_NOTIFY_INFO_DATA *data,
3153 print_queue_struct *queue,
3154 NT_PRINTER_INFO_LEVEL *printer,
3155 TALLOC_CTX *mem_ctx)
3160 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3162 data->notify_data.data.length = len;
3163 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3165 if (!data->notify_data.data.string) {
3166 data->notify_data.data.length = 0;
3170 memcpy(data->notify_data.data.string, temp, len);
3173 /*******************************************************************
3174 * fill a notify_info_data with job status
3175 ********************************************************************/
3177 static void spoolss_notify_job_status(int snum,
3178 SPOOL_NOTIFY_INFO_DATA *data,
3179 print_queue_struct *queue,
3180 NT_PRINTER_INFO_LEVEL *printer,
3181 TALLOC_CTX *mem_ctx)
3183 data->notify_data.value[0]=nt_printj_status(queue->status);
3184 data->notify_data.value[1] = 0;
3187 /*******************************************************************
3188 * fill a notify_info_data with job name
3189 ********************************************************************/
3191 static void spoolss_notify_job_name(int snum,
3192 SPOOL_NOTIFY_INFO_DATA *data,
3193 print_queue_struct *queue,
3194 NT_PRINTER_INFO_LEVEL *printer,
3195 TALLOC_CTX *mem_ctx)
3200 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3202 data->notify_data.data.length = len;
3203 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3205 if (!data->notify_data.data.string) {
3206 data->notify_data.data.length = 0;
3210 memcpy(data->notify_data.data.string, temp, len);
3213 /*******************************************************************
3214 * fill a notify_info_data with job status
3215 ********************************************************************/
3217 static void spoolss_notify_job_status_string(int snum,
3218 SPOOL_NOTIFY_INFO_DATA *data,
3219 print_queue_struct *queue,
3220 NT_PRINTER_INFO_LEVEL *printer,
3221 TALLOC_CTX *mem_ctx)
3224 * Now we're returning job status codes we just return a "" here. JRA.
3231 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3234 switch (queue->status) {
3239 p = ""; /* NT provides the paused string */
3248 #endif /* NO LONGER NEEDED. */
3250 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3252 data->notify_data.data.length = len;
3253 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3255 if (!data->notify_data.data.string) {
3256 data->notify_data.data.length = 0;
3260 memcpy(data->notify_data.data.string, temp, len);
3263 /*******************************************************************
3264 * fill a notify_info_data with job time
3265 ********************************************************************/
3267 static void spoolss_notify_job_time(int snum,
3268 SPOOL_NOTIFY_INFO_DATA *data,
3269 print_queue_struct *queue,
3270 NT_PRINTER_INFO_LEVEL *printer,
3271 TALLOC_CTX *mem_ctx)
3273 data->notify_data.value[0]=0x0;
3274 data->notify_data.value[1]=0;
3277 /*******************************************************************
3278 * fill a notify_info_data with job size
3279 ********************************************************************/
3281 static void spoolss_notify_job_size(int snum,
3282 SPOOL_NOTIFY_INFO_DATA *data,
3283 print_queue_struct *queue,
3284 NT_PRINTER_INFO_LEVEL *printer,
3285 TALLOC_CTX *mem_ctx)
3287 data->notify_data.value[0]=queue->size;
3288 data->notify_data.value[1]=0;
3291 /*******************************************************************
3292 * fill a notify_info_data with page info
3293 ********************************************************************/
3294 static void spoolss_notify_total_pages(int snum,
3295 SPOOL_NOTIFY_INFO_DATA *data,
3296 print_queue_struct *queue,
3297 NT_PRINTER_INFO_LEVEL *printer,
3298 TALLOC_CTX *mem_ctx)
3300 data->notify_data.value[0]=queue->page_count;
3301 data->notify_data.value[1]=0;
3304 /*******************************************************************
3305 * fill a notify_info_data with pages printed info.
3306 ********************************************************************/
3307 static void spoolss_notify_pages_printed(int snum,
3308 SPOOL_NOTIFY_INFO_DATA *data,
3309 print_queue_struct *queue,
3310 NT_PRINTER_INFO_LEVEL *printer,
3311 TALLOC_CTX *mem_ctx)
3313 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3314 data->notify_data.value[1]=0;
3317 /*******************************************************************
3318 Fill a notify_info_data with job position.
3319 ********************************************************************/
3321 static void spoolss_notify_job_position(int snum,
3322 SPOOL_NOTIFY_INFO_DATA *data,
3323 print_queue_struct *queue,
3324 NT_PRINTER_INFO_LEVEL *printer,
3325 TALLOC_CTX *mem_ctx)
3327 data->notify_data.value[0]=queue->job;
3328 data->notify_data.value[1]=0;
3331 /*******************************************************************
3332 Fill a notify_info_data with submitted time.
3333 ********************************************************************/
3335 static void spoolss_notify_submitted_time(int snum,
3336 SPOOL_NOTIFY_INFO_DATA *data,
3337 print_queue_struct *queue,
3338 NT_PRINTER_INFO_LEVEL *printer,
3339 TALLOC_CTX *mem_ctx)
3346 t=gmtime(&queue->time);
3348 len = sizeof(SYSTEMTIME);
3350 data->notify_data.data.length = len;
3351 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3353 if (!data->notify_data.data.string) {
3354 data->notify_data.data.length = 0;
3358 make_systemtime(&st, t);
3361 * Systemtime must be linearized as a set of UINT16's.
3362 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3365 p = (char *)data->notify_data.data.string;
3366 SSVAL(p, 0, st.year);
3367 SSVAL(p, 2, st.month);
3368 SSVAL(p, 4, st.dayofweek);
3369 SSVAL(p, 6, st.day);
3370 SSVAL(p, 8, st.hour);
3371 SSVAL(p, 10, st.minute);
3372 SSVAL(p, 12, st.second);
3373 SSVAL(p, 14, st.milliseconds);
3376 struct s_notify_info_data_table
3382 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3383 print_queue_struct *queue,
3384 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3387 /* A table describing the various print notification constants and
3388 whether the notification data is a pointer to a variable sized
3389 buffer, a one value uint32 or a two value uint32. */
3391 static const struct s_notify_info_data_table notify_info_data_table[] =
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3440 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3442 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3445 /*******************************************************************
3446 Return the size of info_data structure.
3447 ********************************************************************/
3449 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3453 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3454 if ( (notify_info_data_table[i].type == type)
3455 && (notify_info_data_table[i].field == field) ) {
3456 switch(notify_info_data_table[i].size) {
3457 case NOTIFY_ONE_VALUE:
3458 case NOTIFY_TWO_VALUE:
3463 /* The only pointer notify data I have seen on
3464 the wire is the submitted time and this has
3465 the notify size set to 4. -tpot */
3467 case NOTIFY_POINTER:
3470 case NOTIFY_SECDESC:
3476 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3481 /*******************************************************************
3482 Return the type of notify_info_data.
3483 ********************************************************************/
3485 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3489 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3490 if (notify_info_data_table[i].type == type &&
3491 notify_info_data_table[i].field == field)
3492 return notify_info_data_table[i].size;
3498 /****************************************************************************
3499 ****************************************************************************/
3501 static BOOL search_notify(uint16 type, uint16 field, int *value)
3505 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3506 if (notify_info_data_table[i].type == type &&
3507 notify_info_data_table[i].field == field &&
3508 notify_info_data_table[i].fn != NULL) {
3517 /****************************************************************************
3518 ****************************************************************************/
3520 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3522 info_data->type = type;
3523 info_data->field = field;
3524 info_data->reserved = 0;
3526 info_data->size = size_of_notify_info_data(type, field);
3527 info_data->enc_type = type_of_notify_info_data(type, field);
3532 /*******************************************************************
3534 * fill a notify_info struct with info asked
3536 ********************************************************************/
3538 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3539 snum, SPOOL_NOTIFY_OPTION_TYPE
3540 *option_type, uint32 id,
3541 TALLOC_CTX *mem_ctx)
3547 SPOOL_NOTIFY_INFO_DATA *current_data;
3548 NT_PRINTER_INFO_LEVEL *printer = NULL;
3549 print_queue_struct *queue=NULL;
3551 type=option_type->type;
3553 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3554 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3555 option_type->count, lp_servicename(snum)));
3557 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3560 for(field_num=0; field_num<option_type->count; field_num++) {
3561 field = option_type->fields[field_num];
3563 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3565 if (!search_notify(type, field, &j) )
3568 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3569 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3570 free_a_printer(&printer, 2);
3574 current_data = &info->data[info->count];
3576 construct_info_data(current_data, type, field, id);
3578 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3579 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3581 notify_info_data_table[j].fn(snum, current_data, queue,
3587 free_a_printer(&printer, 2);
3591 /*******************************************************************
3593 * fill a notify_info struct with info asked
3595 ********************************************************************/
3597 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3598 SPOOL_NOTIFY_INFO *info,
3599 NT_PRINTER_INFO_LEVEL *printer,
3600 int snum, SPOOL_NOTIFY_OPTION_TYPE
3601 *option_type, uint32 id,
3602 TALLOC_CTX *mem_ctx)
3608 SPOOL_NOTIFY_INFO_DATA *current_data;
3610 DEBUG(4,("construct_notify_jobs_info\n"));
3612 type = option_type->type;
3614 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3615 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3616 option_type->count));
3618 for(field_num=0; field_num<option_type->count; field_num++) {
3619 field = option_type->fields[field_num];
3621 if (!search_notify(type, field, &j) )
3624 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3625 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3629 current_data=&(info->data[info->count]);
3631 construct_info_data(current_data, type, field, id);
3632 notify_info_data_table[j].fn(snum, current_data, queue,
3641 * JFM: The enumeration is not that simple, it's even non obvious.
3643 * let's take an example: I want to monitor the PRINTER SERVER for
3644 * the printer's name and the number of jobs currently queued.
3645 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3646 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3648 * I have 3 printers on the back of my server.
3650 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3653 * 1 printer 1 name 1
3654 * 2 printer 1 cjob 1
3655 * 3 printer 2 name 2
3656 * 4 printer 2 cjob 2
3657 * 5 printer 3 name 3
3658 * 6 printer 3 name 3
3660 * that's the print server case, the printer case is even worse.
3663 /*******************************************************************
3665 * enumerate all printers on the printserver
3666 * fill a notify_info struct with info asked
3668 ********************************************************************/
3670 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3671 SPOOL_NOTIFY_INFO *info,
3672 TALLOC_CTX *mem_ctx)
3675 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3676 int n_services=lp_numservices();
3678 SPOOL_NOTIFY_OPTION *option;
3679 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3681 DEBUG(4,("printserver_notify_info\n"));
3686 option=Printer->notify.option;
3691 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3692 sending a ffpcn() request first */
3697 for (i=0; i<option->count; i++) {
3698 option_type=&(option->ctr.type[i]);
3700 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3703 for (snum=0; snum<n_services; snum++)
3705 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3706 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3712 * Debugging information, don't delete.
3715 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3716 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3717 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3719 for (i=0; i<info->count; i++) {
3720 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3721 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3722 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3729 /*******************************************************************
3731 * fill a notify_info struct with info asked
3733 ********************************************************************/
3735 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3736 TALLOC_CTX *mem_ctx)
3739 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3742 SPOOL_NOTIFY_OPTION *option;
3743 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3745 print_queue_struct *queue=NULL;
3746 print_status_struct status;
3748 DEBUG(4,("printer_notify_info\n"));
3753 option=Printer->notify.option;
3759 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3760 sending a ffpcn() request first */
3765 get_printer_snum(p, hnd, &snum, NULL);
3767 for (i=0; i<option->count; i++) {
3768 option_type=&option->ctr.type[i];
3770 switch ( option_type->type ) {
3771 case PRINTER_NOTIFY_TYPE:
3772 if(construct_notify_printer_info(Printer, info, snum,
3778 case JOB_NOTIFY_TYPE: {
3779 NT_PRINTER_INFO_LEVEL *printer = NULL;
3781 count = print_queue_status(snum, &queue, &status);
3783 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3786 for (j=0; j<count; j++) {
3787 construct_notify_jobs_info(&queue[j], info,
3794 free_a_printer(&printer, 2);
3804 * Debugging information, don't delete.
3807 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3808 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3809 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3811 for (i=0; i<info->count; i++) {
3812 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3813 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3814 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3820 /********************************************************************
3822 ********************************************************************/
3824 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3826 POLICY_HND *handle = &q_u->handle;
3827 SPOOL_NOTIFY_INFO *info = &r_u->info;
3829 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3830 WERROR result = WERR_BADFID;
3832 /* we always have a NOTIFY_INFO struct */
3836 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3837 OUR_HANDLE(handle)));
3841 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3844 * We are now using the change value, and
3845 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3846 * I don't have a global notification system, I'm sending back all the
3847 * informations even when _NOTHING_ has changed.
3850 /* We need to keep track of the change value to send back in
3851 RRPCN replies otherwise our updates are ignored. */
3853 Printer->notify.fnpcn = True;
3855 if (Printer->notify.client_connected) {
3856 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3857 Printer->notify.change = q_u->change;
3860 /* just ignore the SPOOL_NOTIFY_OPTION */
3862 switch (Printer->printer_type) {
3864 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3867 case SPLHND_PRINTER:
3868 result = printer_notify_info(p, handle, info, p->mem_ctx);
3872 Printer->notify.fnpcn = False;
3878 /********************************************************************
3879 * construct_printer_info_0
3880 * fill a printer_info_0 struct
3881 ********************************************************************/
3883 static BOOL construct_printer_info_0(Printer_entry *print_hnd,
3884 PRINTER_INFO_0 *printer,
3885 const struct share_params *params)
3889 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3890 counter_printer_0 *session_counter;
3891 uint32 global_counter;
3894 print_status_struct status;
3896 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
3897 lp_const_servicename(params->service))))
3900 count = print_queue_length(params->service, &status);
3902 /* check if we already have a counter for this printer */
3903 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3904 if (session_counter->snum == params->service)
3908 /* it's the first time, add it to the list */
3909 if (session_counter==NULL) {
3910 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3911 free_a_printer(&ntprinter, 2);
3914 ZERO_STRUCTP(session_counter);
3915 session_counter->snum=params->service;
3916 session_counter->counter=0;
3917 DLIST_ADD(counter_list, session_counter);
3921 session_counter->counter++;
3924 * the global_counter should be stored in a TDB as it's common to all the clients
3925 * and should be zeroed on samba startup
3927 global_counter=session_counter->counter;
3929 pstrcpy(chaine,ntprinter->info_2->printername);
3931 init_unistr(&printer->printername, chaine);
3933 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3934 init_unistr(&printer->servername, chaine);
3936 printer->cjobs = count;
3937 printer->total_jobs = 0;
3938 printer->total_bytes = 0;
3940 setuptime = (time_t)ntprinter->info_2->setuptime;
3941 t=gmtime(&setuptime);
3943 printer->year = t->tm_year+1900;
3944 printer->month = t->tm_mon+1;
3945 printer->dayofweek = t->tm_wday;
3946 printer->day = t->tm_mday;
3947 printer->hour = t->tm_hour;
3948 printer->minute = t->tm_min;
3949 printer->second = t->tm_sec;
3950 printer->milliseconds = 0;
3952 printer->global_counter = global_counter;
3953 printer->total_pages = 0;
3955 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3956 printer->major_version = 0x0005; /* NT 5 */
3957 printer->build_version = 0x0893; /* build 2195 */
3959 printer->unknown7 = 0x1;
3960 printer->unknown8 = 0x0;
3961 printer->unknown9 = 0x0;
3962 printer->session_counter = session_counter->counter;
3963 printer->unknown11 = 0x0;
3964 printer->printer_errors = 0x0; /* number of print failure */
3965 printer->unknown13 = 0x0;
3966 printer->unknown14 = 0x1;
3967 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3968 printer->unknown16 = 0x0;
3969 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3970 printer->unknown18 = 0x0;
3971 printer->status = nt_printq_status(status.status);
3972 printer->unknown20 = 0x0;
3973 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3974 printer->unknown22 = 0x0;
3975 printer->unknown23 = 0x6; /* 6 ???*/
3976 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3977 printer->unknown25 = 0;
3978 printer->unknown26 = 0;
3979 printer->unknown27 = 0;
3980 printer->unknown28 = 0;
3981 printer->unknown29 = 0;
3983 free_a_printer(&ntprinter,2);
3987 /********************************************************************
3988 * construct_printer_info_1
3989 * fill a printer_info_1 struct
3990 ********************************************************************/
3991 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags,
3992 PRINTER_INFO_1 *printer,
3993 const struct share_params *params)
3997 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3999 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4000 lp_const_servicename(params->service))))
4003 printer->flags=flags;
4005 if (*ntprinter->info_2->comment == '\0') {
4006 init_unistr(&printer->comment, lp_comment(params->service));
4007 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4008 ntprinter->info_2->drivername,
4009 lp_comment(params->service));
4012 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4013 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4014 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4017 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4019 init_unistr(&printer->description, chaine);
4020 init_unistr(&printer->name, chaine2);
4022 free_a_printer(&ntprinter,2);
4027 /****************************************************************************
4028 Free a DEVMODE struct.
4029 ****************************************************************************/
4031 static void free_dev_mode(DEVICEMODE *dev)
4036 SAFE_FREE(dev->dev_private);
4041 /****************************************************************************
4042 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4043 should be valid upon entry
4044 ****************************************************************************/
4046 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4048 if ( !devmode || !ntdevmode )
4051 init_unistr(&devmode->devicename, ntdevmode->devicename);
4053 init_unistr(&devmode->formname, ntdevmode->formname);
4055 devmode->specversion = ntdevmode->specversion;
4056 devmode->driverversion = ntdevmode->driverversion;
4057 devmode->size = ntdevmode->size;
4058 devmode->driverextra = ntdevmode->driverextra;
4059 devmode->fields = ntdevmode->fields;
4061 devmode->orientation = ntdevmode->orientation;
4062 devmode->papersize = ntdevmode->papersize;
4063 devmode->paperlength = ntdevmode->paperlength;
4064 devmode->paperwidth = ntdevmode->paperwidth;
4065 devmode->scale = ntdevmode->scale;
4066 devmode->copies = ntdevmode->copies;
4067 devmode->defaultsource = ntdevmode->defaultsource;
4068 devmode->printquality = ntdevmode->printquality;
4069 devmode->color = ntdevmode->color;
4070 devmode->duplex = ntdevmode->duplex;
4071 devmode->yresolution = ntdevmode->yresolution;
4072 devmode->ttoption = ntdevmode->ttoption;
4073 devmode->collate = ntdevmode->collate;
4074 devmode->icmmethod = ntdevmode->icmmethod;
4075 devmode->icmintent = ntdevmode->icmintent;
4076 devmode->mediatype = ntdevmode->mediatype;
4077 devmode->dithertype = ntdevmode->dithertype;
4079 if (ntdevmode->nt_dev_private != NULL) {
4080 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4087 /****************************************************************************
4088 Create a DEVMODE struct. Returns malloced memory.
4089 ****************************************************************************/
4091 DEVICEMODE *construct_dev_mode(const char *servicename)
4093 NT_PRINTER_INFO_LEVEL *printer = NULL;
4094 DEVICEMODE *devmode = NULL;
4096 DEBUG(7,("construct_dev_mode\n"));
4098 DEBUGADD(8,("getting printer characteristics\n"));
4100 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4103 if ( !printer->info_2->devmode ) {
4104 DEBUG(5, ("BONG! There was no device mode!\n"));
4108 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4109 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4113 ZERO_STRUCTP(devmode);
4115 DEBUGADD(8,("loading DEVICEMODE\n"));
4117 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4118 free_dev_mode( devmode );
4123 free_a_printer(&printer,2);
4128 /********************************************************************
4129 * construct_printer_info_2
4130 * fill a printer_info_2 struct
4131 ********************************************************************/
4133 static BOOL construct_printer_info_2(Printer_entry *print_hnd,
4134 PRINTER_INFO_2 *printer,
4135 const struct share_params *params)
4138 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4140 print_status_struct status;
4142 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4143 lp_const_servicename(params->service))))
4146 count = print_queue_length(params->service, &status);
4148 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4149 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4150 init_unistr(&printer->sharename, lp_servicename(params->service)); /* sharename */
4151 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4152 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4154 if (*ntprinter->info_2->comment == '\0')
4155 init_unistr(&printer->comment, lp_comment(params->service)); /* comment */
4157 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4159 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4160 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4161 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4162 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4163 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4165 printer->attributes = ntprinter->info_2->attributes;
4167 printer->priority = ntprinter->info_2->priority; /* priority */
4168 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4169 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4170 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4171 printer->status = nt_printq_status(status.status); /* status */
4172 printer->cjobs = count; /* jobs */
4173 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4175 if ( !(printer->devmode = construct_dev_mode(
4176 lp_const_servicename(params->service))) )
4177 DEBUG(8, ("Returning NULL Devicemode!\n"));
4179 printer->secdesc = NULL;
4181 if ( ntprinter->info_2->secdesc_buf
4182 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4184 /* don't use talloc_steal() here unless you do a deep steal of all
4185 the SEC_DESC members */
4187 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4188 ntprinter->info_2->secdesc_buf->sd );
4191 free_a_printer(&ntprinter, 2);
4196 /********************************************************************
4197 * construct_printer_info_3
4198 * fill a printer_info_3 struct
4199 ********************************************************************/
4201 static BOOL construct_printer_info_3(Printer_entry *print_hnd,
4202 PRINTER_INFO_3 **pp_printer,
4203 const struct share_params *params)
4205 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4206 PRINTER_INFO_3 *printer = NULL;
4208 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4209 lp_const_servicename(params->service))))
4213 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4214 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4215 free_a_printer(&ntprinter, 2);
4219 ZERO_STRUCTP(printer);
4221 /* These are the components of the SD we are returning. */
4223 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4224 /* don't use talloc_steal() here unless you do a deep steal of all
4225 the SEC_DESC members */
4227 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4228 ntprinter->info_2->secdesc_buf->sd );
4231 free_a_printer(&ntprinter, 2);
4233 *pp_printer = printer;
4237 /********************************************************************
4238 * construct_printer_info_4
4239 * fill a printer_info_4 struct
4240 ********************************************************************/
4242 static BOOL construct_printer_info_4(Printer_entry *print_hnd,
4243 PRINTER_INFO_4 *printer,
4244 const struct share_params *params)
4246 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4248 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4249 lp_const_servicename(params->service))))
4252 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4253 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4254 printer->attributes = ntprinter->info_2->attributes;
4256 free_a_printer(&ntprinter, 2);
4260 /********************************************************************
4261 * construct_printer_info_5
4262 * fill a printer_info_5 struct
4263 ********************************************************************/
4265 static BOOL construct_printer_info_5(Printer_entry *print_hnd,
4266 PRINTER_INFO_5 *printer,
4267 const struct share_params *params)
4269 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4271 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4272 lp_const_servicename(params->service))))
4275 init_unistr(&printer->printername, ntprinter->info_2->printername);
4276 init_unistr(&printer->portname, ntprinter->info_2->portname);
4277 printer->attributes = ntprinter->info_2->attributes;
4279 /* these two are not used by NT+ according to MSDN */
4281 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4282 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4284 free_a_printer(&ntprinter, 2);
4289 /********************************************************************
4290 * construct_printer_info_6
4291 * fill a printer_info_6 struct
4292 ********************************************************************/
4294 static BOOL construct_printer_info_6(Printer_entry *print_hnd,
4295 PRINTER_INFO_6 *printer,
4296 const struct share_params *params)
4298 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4300 print_status_struct status;
4302 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4303 lp_const_servicename(params->service))))
4306 count = print_queue_length(params->service, &status);
4308 printer->status = nt_printq_status(status.status);
4310 free_a_printer(&ntprinter, 2);
4315 /********************************************************************
4316 * construct_printer_info_7
4317 * fill a printer_info_7 struct
4318 ********************************************************************/
4320 static BOOL construct_printer_info_7(Printer_entry *print_hnd,
4321 PRINTER_INFO_7 *printer,
4322 const struct share_params *params)
4324 char *guid_str = NULL;
4327 if (is_printer_published(print_hnd, params->service, &guid)) {
4328 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4329 strupper_m(guid_str);
4330 init_unistr(&printer->guid, guid_str);
4331 printer->action = SPOOL_DS_PUBLISH;
4333 init_unistr(&printer->guid, "");
4334 printer->action = SPOOL_DS_UNPUBLISH;
4340 /********************************************************************
4341 Spoolss_enumprinters.
4342 ********************************************************************/
4344 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4347 struct share_iterator *shares;
4348 struct share_params *printer;
4349 PRINTER_INFO_1 *printers=NULL;
4350 WERROR result = WERR_OK;
4352 DEBUG(4,("enum_all_printers_info_1\n"));
4354 if (!(shares = share_list_all(NULL))) {
4355 DEBUG(5, ("Could not list printers\n"));
4356 return WERR_ACCESS_DENIED;
4359 while ((printer = next_printer(shares)) != NULL) {
4360 PRINTER_INFO_1 current_prt;
4362 DEBUG(4,("Found a printer in smb.conf: %s\n",
4363 lp_servicename(printer->service)));
4365 if (!construct_printer_info_1(NULL, flags, ¤t_prt,
4370 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1,
4371 *returned +1)) == NULL) {
4372 DEBUG(2,("enum_all_printers_info_1: failed to enlarge "
4373 "printers buffer!\n"));
4375 TALLOC_FREE(shares);
4378 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n",
4381 memcpy(&printers[*returned], ¤t_prt,
4382 sizeof(PRINTER_INFO_1));
4384 TALLOC_FREE(printer);
4387 /* check the required size. */
4388 for (i=0; i<*returned; i++)
4389 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4391 if (*needed > offered) {
4392 result = WERR_INSUFFICIENT_BUFFER;
4396 if (!rpcbuf_alloc_size(buffer, *needed)) {
4397 result = WERR_NOMEM;
4401 /* fill the buffer with the structures */
4402 for (i=0; i<*returned; i++)
4403 smb_io_printer_info_1("", buffer, &printers[i], 0);
4408 SAFE_FREE(printers);
4409 TALLOC_FREE(shares);
4411 if ( !W_ERROR_IS_OK(result) )
4417 /********************************************************************
4418 enum_all_printers_info_1_local.
4419 *********************************************************************/
4421 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4423 DEBUG(4,("enum_all_printers_info_1_local\n"));
4425 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4428 /********************************************************************
4429 enum_all_printers_info_1_name.
4430 *********************************************************************/
4432 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4436 DEBUG(4,("enum_all_printers_info_1_name\n"));
4438 if ((name[0] == '\\') && (name[1] == '\\'))
4441 if (is_myname_or_ipaddr(s)) {
4442 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4445 return WERR_INVALID_NAME;
4448 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4449 /********************************************************************
4450 enum_all_printers_info_1_remote.
4451 *********************************************************************/
4453 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4455 PRINTER_INFO_1 *printer;
4456 fstring printername;
4459 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4460 WERROR result = WERR_OK;
4462 /* JFM: currently it's more a place holder than anything else.
4463 * In the spooler world there is a notion of server registration.
4464 * the print servers are registered on the PDC (in the same domain)
4466 * We should have a TDB here. The registration is done thru an
4467 * undocumented RPC call.
4470 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4475 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4476 slprintf(desc, sizeof(desc)-1,"%s", name);
4477 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4479 init_unistr(&printer->description, desc);
4480 init_unistr(&printer->name, printername);
4481 init_unistr(&printer->comment, comment);
4482 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4484 /* check the required size. */
4485 *needed += spoolss_size_printer_info_1(printer);
4487 if (*needed > offered) {
4488 result = WERR_INSUFFICIENT_BUFFER;
4492 if (!rpcbuf_alloc_size(buffer, *needed)) {
4493 result = WERR_NOMEM;
4497 /* fill the buffer with the structures */
4498 smb_io_printer_info_1("", buffer, printer, 0);
4504 if ( !W_ERROR_IS_OK(result) )
4512 /********************************************************************
4513 enum_all_printers_info_1_network.
4514 *********************************************************************/
4516 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4520 DEBUG(4,("enum_all_printers_info_1_network\n"));
4522 /* If we respond to a enum_printers level 1 on our name with flags
4523 set to PRINTER_ENUM_REMOTE with a list of printers then these
4524 printers incorrectly appear in the APW browse list.
4525 Specifically the printers for the server appear at the workgroup
4526 level where all the other servers in the domain are
4527 listed. Windows responds to this call with a
4528 WERR_CAN_NOT_COMPLETE so we should do the same. */
4530 if (name[0] == '\\' && name[1] == '\\')
4533 if (is_myname_or_ipaddr(s))
4534 return WERR_CAN_NOT_COMPLETE;
4536 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4539 /********************************************************************
4540 * api_spoolss_enumprinters
4542 * called from api_spoolss_enumprinters (see this to understand)
4543 ********************************************************************/
4545 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4548 struct share_iterator *shares;
4549 struct share_params *printer;
4550 PRINTER_INFO_2 *printers=NULL;
4551 WERROR result = WERR_OK;
4555 if (!(shares = share_list_all(NULL))) {
4556 DEBUG(5, ("Could not list printers\n"));
4557 return WERR_ACCESS_DENIED;
4560 while ((printer = next_printer(shares)) != NULL) {
4561 PRINTER_INFO_2 current_prt;
4563 DEBUG(4,("Found a printer in smb.conf: %s\n",
4564 lp_servicename(printer->service)));
4566 if (!construct_printer_info_2(NULL, ¤t_prt,
4570 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2,
4572 DEBUG(2,("enum_all_printers_info_2: failed to enlarge "
4573 "printers buffer!\n"));
4575 TALLOC_FREE(shares);
4579 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n",
4582 memcpy(&printers[*returned], ¤t_prt,
4583 sizeof(PRINTER_INFO_2));
4585 TALLOC_FREE(printer);
4588 /* check the required size. */
4589 for (i=0; i<*returned; i++)
4590 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4592 if (*needed > offered) {
4593 result = WERR_INSUFFICIENT_BUFFER;
4597 if (!rpcbuf_alloc_size(buffer, *needed)) {
4598 result = WERR_NOMEM;
4602 /* fill the buffer with the structures */
4603 for (i=0; i<*returned; i++)
4604 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4609 for (i=0; i<*returned; i++)
4610 free_devmode(printers[i].devmode);
4612 SAFE_FREE(printers);
4613 TALLOC_FREE(shares);
4615 if ( !W_ERROR_IS_OK(result) )
4621 /********************************************************************
4622 * handle enumeration of printers at level 1
4623 ********************************************************************/
4625 static WERROR enumprinters_level1( uint32 flags, fstring name,
4626 RPC_BUFFER *buffer, uint32 offered,
4627 uint32 *needed, uint32 *returned)
4629 /* Not all the flags are equals */
4631 if (flags & PRINTER_ENUM_LOCAL)
4632 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4634 if (flags & PRINTER_ENUM_NAME)
4635 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4637 #if 0 /* JERRY - disabled for now */
4638 if (flags & PRINTER_ENUM_REMOTE)
4639 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4642 if (flags & PRINTER_ENUM_NETWORK)
4643 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4645 return WERR_OK; /* NT4sp5 does that */
4648 /********************************************************************
4649 * handle enumeration of printers at level 2
4650 ********************************************************************/
4652 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4653 RPC_BUFFER *buffer, uint32 offered,
4654 uint32 *needed, uint32 *returned)
4656 char *s = servername;
4658 if (flags & PRINTER_ENUM_LOCAL) {
4659 return enum_all_printers_info_2(buffer, offered, needed, returned);
4662 if (flags & PRINTER_ENUM_NAME) {
4663 if ((servername[0] == '\\') && (servername[1] == '\\'))
4665 if (is_myname_or_ipaddr(s))
4666 return enum_all_printers_info_2(buffer, offered, needed, returned);
4668 return WERR_INVALID_NAME;
4671 if (flags & PRINTER_ENUM_REMOTE)
4672 return WERR_UNKNOWN_LEVEL;
4677 /********************************************************************
4678 * handle enumeration of printers at level 5
4679 ********************************************************************/
4681 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4682 RPC_BUFFER *buffer, uint32 offered,
4683 uint32 *needed, uint32 *returned)
4685 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4689 /********************************************************************
4690 * api_spoolss_enumprinters
4692 * called from api_spoolss_enumprinters (see this to understand)
4693 ********************************************************************/
4695 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4697 uint32 flags = q_u->flags;
4698 UNISTR2 *servername = &q_u->servername;
4699 uint32 level = q_u->level;
4700 RPC_BUFFER *buffer = NULL;
4701 uint32 offered = q_u->offered;
4702 uint32 *needed = &r_u->needed;
4703 uint32 *returned = &r_u->returned;
4707 /* that's an [in out] buffer */
4709 if (!q_u->buffer && (offered!=0)) {
4710 return WERR_INVALID_PARAM;
4713 rpcbuf_move(q_u->buffer, &r_u->buffer);
4714 buffer = r_u->buffer;
4716 DEBUG(4,("_spoolss_enumprinters\n"));
4723 * flags==PRINTER_ENUM_NAME
4724 * if name=="" then enumerates all printers
4725 * if name!="" then enumerate the printer
4726 * flags==PRINTER_ENUM_REMOTE
4727 * name is NULL, enumerate printers
4728 * Level 2: name!="" enumerates printers, name can't be NULL
4729 * Level 3: doesn't exist
4730 * Level 4: does a local registry lookup
4731 * Level 5: same as Level 2
4734 unistr2_to_ascii(name, servername, sizeof(name)-1);
4739 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4741 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4743 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4748 return WERR_UNKNOWN_LEVEL;
4751 /****************************************************************************
4752 ****************************************************************************/
4754 static WERROR getprinter_level_0(Printer_entry *print_hnd,
4755 const struct share_params *params,
4756 RPC_BUFFER *buffer, uint32 offered,
4759 PRINTER_INFO_0 *printer=NULL;
4760 WERROR result = WERR_OK;
4762 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4765 construct_printer_info_0(print_hnd, printer, params);
4767 /* check the required size. */
4768 *needed += spoolss_size_printer_info_0(printer);
4770 if (*needed > offered) {
4771 result = WERR_INSUFFICIENT_BUFFER;
4775 if (!rpcbuf_alloc_size(buffer, *needed)) {
4776 result = WERR_NOMEM;
4780 /* fill the buffer with the structures */
4781 smb_io_printer_info_0("", buffer, printer, 0);
4791 /****************************************************************************
4792 ****************************************************************************/
4794 static WERROR getprinter_level_1(Printer_entry *print_hnd,
4795 const struct share_params *params,
4796 RPC_BUFFER *buffer, uint32 offered,
4799 PRINTER_INFO_1 *printer=NULL;
4800 WERROR result = WERR_OK;
4802 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4805 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer,
4808 /* check the required size. */
4809 *needed += spoolss_size_printer_info_1(printer);
4811 if (*needed > offered) {
4812 result = WERR_INSUFFICIENT_BUFFER;
4816 if (!rpcbuf_alloc_size(buffer, *needed)) {
4817 result = WERR_NOMEM;
4821 /* fill the buffer with the structures */
4822 smb_io_printer_info_1("", buffer, printer, 0);
4831 /****************************************************************************
4832 ****************************************************************************/
4834 static WERROR getprinter_level_2(Printer_entry *print_hnd,
4835 const struct share_params *params,
4836 RPC_BUFFER *buffer, uint32 offered,
4839 PRINTER_INFO_2 *printer=NULL;
4840 WERROR result = WERR_OK;
4842 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4845 construct_printer_info_2(print_hnd, printer, params);
4847 /* check the required size. */
4848 *needed += spoolss_size_printer_info_2(printer);
4850 if (*needed > offered) {
4851 result = WERR_INSUFFICIENT_BUFFER;
4855 if (!rpcbuf_alloc_size(buffer, *needed)) {
4856 result = WERR_NOMEM;
4860 /* fill the buffer with the structures */
4861 if (!smb_io_printer_info_2("", buffer, printer, 0))
4862 result = WERR_NOMEM;
4866 free_printer_info_2(printer);
4871 /****************************************************************************
4872 ****************************************************************************/
4874 static WERROR getprinter_level_3(Printer_entry *print_hnd,
4875 const struct share_params *params,
4876 RPC_BUFFER *buffer, uint32 offered,
4879 PRINTER_INFO_3 *printer=NULL;
4880 WERROR result = WERR_OK;
4882 if (!construct_printer_info_3(print_hnd, &printer, params))
4885 /* check the required size. */
4886 *needed += spoolss_size_printer_info_3(printer);
4888 if (*needed > offered) {
4889 result = WERR_INSUFFICIENT_BUFFER;
4893 if (!rpcbuf_alloc_size(buffer, *needed)) {
4894 result = WERR_NOMEM;
4898 /* fill the buffer with the structures */
4899 smb_io_printer_info_3("", buffer, printer, 0);
4903 free_printer_info_3(printer);
4908 /****************************************************************************
4909 ****************************************************************************/
4911 static WERROR getprinter_level_4(Printer_entry *print_hnd,
4912 const struct share_params *params,
4913 RPC_BUFFER *buffer, uint32 offered,
4916 PRINTER_INFO_4 *printer=NULL;
4917 WERROR result = WERR_OK;
4919 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4922 if (!construct_printer_info_4(print_hnd, printer, params)) {
4927 /* check the required size. */
4928 *needed += spoolss_size_printer_info_4(printer);
4930 if (*needed > offered) {
4931 result = WERR_INSUFFICIENT_BUFFER;
4935 if (!rpcbuf_alloc_size(buffer, *needed)) {
4936 result = WERR_NOMEM;
4940 /* fill the buffer with the structures */
4941 smb_io_printer_info_4("", buffer, printer, 0);
4945 free_printer_info_4(printer);
4950 /****************************************************************************
4951 ****************************************************************************/
4953 static WERROR getprinter_level_5(Printer_entry *print_hnd,
4954 const struct share_params *params,
4955 RPC_BUFFER *buffer, uint32 offered,
4958 PRINTER_INFO_5 *printer=NULL;
4959 WERROR result = WERR_OK;
4961 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4964 if (!construct_printer_info_5(print_hnd, printer, params)) {
4965 free_printer_info_5(printer);
4969 /* check the required size. */
4970 *needed += spoolss_size_printer_info_5(printer);
4972 if (*needed > offered) {
4973 result = WERR_INSUFFICIENT_BUFFER;
4977 if (!rpcbuf_alloc_size(buffer, *needed)) {
4978 result = WERR_NOMEM;
4982 /* fill the buffer with the structures */
4983 smb_io_printer_info_5("", buffer, printer, 0);
4987 free_printer_info_5(printer);
4992 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4993 const struct share_params *params,
4994 RPC_BUFFER *buffer, uint32 offered,
4997 PRINTER_INFO_6 *printer;
4998 WERROR result = WERR_OK;
5000 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5004 if (!construct_printer_info_6(print_hnd, printer, params)) {
5005 free_printer_info_6(printer);
5009 /* check the required size. */
5010 *needed += spoolss_size_printer_info_6(printer);
5012 if (*needed > offered) {
5013 result = WERR_INSUFFICIENT_BUFFER;
5017 if (!rpcbuf_alloc_size(buffer, *needed)) {
5018 result = WERR_NOMEM;
5022 /* fill the buffer with the structures */
5023 smb_io_printer_info_6("", buffer, printer, 0);
5027 free_printer_info_6(printer);
5032 static WERROR getprinter_level_7(Printer_entry *print_hnd,
5033 const struct share_params *params,
5034 RPC_BUFFER *buffer, uint32 offered,
5037 PRINTER_INFO_7 *printer=NULL;
5038 WERROR result = WERR_OK;
5040 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5043 if (!construct_printer_info_7(print_hnd, printer, params))
5046 /* check the required size. */
5047 *needed += spoolss_size_printer_info_7(printer);
5049 if (*needed > offered) {
5050 result = WERR_INSUFFICIENT_BUFFER;
5054 if (!rpcbuf_alloc_size(buffer, *needed)) {
5055 result = WERR_NOMEM;
5060 /* fill the buffer with the structures */
5061 smb_io_printer_info_7("", buffer, printer, 0);
5065 free_printer_info_7(printer);
5070 /****************************************************************************
5071 ****************************************************************************/
5073 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5075 POLICY_HND *handle = &q_u->handle;
5076 uint32 level = q_u->level;
5077 RPC_BUFFER *buffer = NULL;
5078 uint32 offered = q_u->offered;
5079 uint32 *needed = &r_u->needed;
5080 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5081 struct share_params *params;
5085 /* that's an [in out] buffer */
5087 if (!q_u->buffer && (offered!=0)) {
5088 return WERR_INVALID_PARAM;
5091 rpcbuf_move(q_u->buffer, &r_u->buffer);
5092 buffer = r_u->buffer;
5096 if (!get_printer_snum(p, handle, &snum, ¶ms))
5101 return getprinter_level_0(Printer, params, buffer, offered,
5104 return getprinter_level_1(Printer, params, buffer, offered,
5107 return getprinter_level_2(Printer, params, buffer, offered,
5110 return getprinter_level_3(Printer, params, buffer, offered,
5113 return getprinter_level_4(Printer, params, buffer, offered,
5116 return getprinter_level_5(Printer, params, buffer, offered,
5119 return getprinter_level_6(Printer, params, buffer, offered,
5122 return getprinter_level_7(Printer, params, buffer, offered,
5125 return WERR_UNKNOWN_LEVEL;
5128 /********************************************************************
5129 * fill a DRIVER_INFO_1 struct
5130 ********************************************************************/
5132 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5134 init_unistr( &info->name, driver.info_3->name);
5137 /********************************************************************
5138 * construct_printer_driver_info_1
5139 ********************************************************************/
5141 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5143 NT_PRINTER_INFO_LEVEL *printer = NULL;
5144 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5146 ZERO_STRUCT(driver);
5148 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5149 return WERR_INVALID_PRINTER_NAME;
5151 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5152 free_a_printer(&printer, 2);
5153 return WERR_UNKNOWN_PRINTER_DRIVER;
5156 fill_printer_driver_info_1(info, driver, servername, architecture);
5158 free_a_printer(&printer,2);
5163 /********************************************************************
5164 * construct_printer_driver_info_2
5165 * fill a printer_info_2 struct
5166 ********************************************************************/
5168 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5172 info->version=driver.info_3->cversion;
5174 init_unistr( &info->name, driver.info_3->name );
5175 init_unistr( &info->architecture, driver.info_3->environment );
5178 if (strlen(driver.info_3->driverpath)) {
5179 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5180 init_unistr( &info->driverpath, temp );
5182 init_unistr( &info->driverpath, "" );
5184 if (strlen(driver.info_3->datafile)) {
5185 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5186 init_unistr( &info->datafile, temp );
5188 init_unistr( &info->datafile, "" );
5190 if (strlen(driver.info_3->configfile)) {
5191 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5192 init_unistr( &info->configfile, temp );
5194 init_unistr( &info->configfile, "" );
5197 /********************************************************************
5198 * construct_printer_driver_info_2
5199 * fill a printer_info_2 struct
5200 ********************************************************************/
5202 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5204 NT_PRINTER_INFO_LEVEL *printer = NULL;
5205 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5207 ZERO_STRUCT(printer);
5208 ZERO_STRUCT(driver);
5210 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5211 return WERR_INVALID_PRINTER_NAME;
5213 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5214 free_a_printer(&printer, 2);
5215 return WERR_UNKNOWN_PRINTER_DRIVER;
5218 fill_printer_driver_info_2(info, driver, servername);
5220 free_a_printer(&printer,2);
5225 /********************************************************************
5226 * copy a strings array and convert to UNICODE
5228 * convert an array of ascii string to a UNICODE string
5229 ********************************************************************/
5231 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5238 DEBUG(6,("init_unistr_array\n"));
5249 v = ""; /* hack to handle null lists */
5252 /* hack to allow this to be used in places other than when generating
5253 the list of dependent files */
5256 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5260 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5262 /* add one extra unit16 for the second terminating NULL */
5264 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5265 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5272 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5277 /* special case for ""; we need to add both NULL's here */
5279 (*uni_array)[j++]=0x0000;
5280 (*uni_array)[j]=0x0000;
5283 DEBUGADD(6,("last one:done\n"));
5285 /* return size of array in uint16's */
5290 /********************************************************************
5291 * construct_printer_info_3
5292 * fill a printer_info_3 struct
5293 ********************************************************************/
5295 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5301 info->version=driver.info_3->cversion;
5303 init_unistr( &info->name, driver.info_3->name );
5304 init_unistr( &info->architecture, driver.info_3->environment );
5306 if (strlen(driver.info_3->driverpath)) {
5307 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5308 init_unistr( &info->driverpath, temp );
5310 init_unistr( &info->driverpath, "" );
5312 if (strlen(driver.info_3->datafile)) {
5313 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5314 init_unistr( &info->datafile, temp );
5316 init_unistr( &info->datafile, "" );
5318 if (strlen(driver.info_3->configfile)) {
5319 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5320 init_unistr( &info->configfile, temp );
5322 init_unistr( &info->configfile, "" );
5324 if (strlen(driver.info_3->helpfile)) {
5325 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5326 init_unistr( &info->helpfile, temp );
5328 init_unistr( &info->helpfile, "" );
5330 init_unistr( &info->monitorname, driver.info_3->monitorname );
5331 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5333 info->dependentfiles=NULL;
5334 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5337 /********************************************************************
5338 * construct_printer_info_3
5339 * fill a printer_info_3 struct
5340 ********************************************************************/
5342 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5344 NT_PRINTER_INFO_LEVEL *printer = NULL;
5345 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5347 ZERO_STRUCT(driver);
5349 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5350 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5351 if (!W_ERROR_IS_OK(status))
5352 return WERR_INVALID_PRINTER_NAME;
5354 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5355 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5360 * I put this code in during testing. Helpful when commenting out the
5361 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5362 * as win2k always queries the driver using an infor level of 6.
5363 * I've left it in (but ifdef'd out) because I'll probably
5364 * use it in experimentation again in the future. --jerry 22/01/2002
5367 if (!W_ERROR_IS_OK(status)) {
5369 * Is this a W2k client ?
5372 /* Yes - try again with a WinNT driver. */
5374 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5375 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5379 if (!W_ERROR_IS_OK(status)) {
5380 free_a_printer(&printer,2);
5381 return WERR_UNKNOWN_PRINTER_DRIVER;
5389 fill_printer_driver_info_3(info, driver, servername);
5391 free_a_printer(&printer,2);
5396 /********************************************************************
5397 * construct_printer_info_6
5398 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5399 ********************************************************************/
5401 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5407 memset(&nullstr, '\0', sizeof(fstring));
5409 info->version=driver.info_3->cversion;
5411 init_unistr( &info->name, driver.info_3->name );
5412 init_unistr( &info->architecture, driver.info_3->environment );
5414 if (strlen(driver.info_3->driverpath)) {
5415 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5416 init_unistr( &info->driverpath, temp );
5418 init_unistr( &info->driverpath, "" );
5420 if (strlen(driver.info_3->datafile)) {
5421 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5422 init_unistr( &info->datafile, temp );
5424 init_unistr( &info->datafile, "" );
5426 if (strlen(driver.info_3->configfile)) {
5427 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5428 init_unistr( &info->configfile, temp );
5430 init_unistr( &info->configfile, "" );
5432 if (strlen(driver.info_3->helpfile)) {
5433 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5434 init_unistr( &info->helpfile, temp );
5436 init_unistr( &info->helpfile, "" );
5438 init_unistr( &info->monitorname, driver.info_3->monitorname );
5439 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5441 info->dependentfiles = NULL;
5442 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5444 info->previousdrivernames=NULL;
5445 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5447 info->driver_date=0;
5450 info->driver_version_low=0;
5451 info->driver_version_high=0;
5453 init_unistr( &info->mfgname, "");
5454 init_unistr( &info->oem_url, "");
5455 init_unistr( &info->hardware_id, "");
5456 init_unistr( &info->provider, "");
5459 /********************************************************************
5460 * construct_printer_info_6
5461 * fill a printer_info_6 struct
5462 ********************************************************************/
5464 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5465 fstring servername, fstring architecture, uint32 version)
5467 NT_PRINTER_INFO_LEVEL *printer = NULL;
5468 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5471 ZERO_STRUCT(driver);
5473 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5475 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5477 if (!W_ERROR_IS_OK(status))
5478 return WERR_INVALID_PRINTER_NAME;
5480 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5482 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5484 if (!W_ERROR_IS_OK(status))
5487 * Is this a W2k client ?
5491 free_a_printer(&printer,2);
5492 return WERR_UNKNOWN_PRINTER_DRIVER;
5495 /* Yes - try again with a WinNT driver. */
5497 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5498 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5499 if (!W_ERROR_IS_OK(status)) {
5500 free_a_printer(&printer,2);
5501 return WERR_UNKNOWN_PRINTER_DRIVER;
5505 fill_printer_driver_info_6(info, driver, servername);
5507 free_a_printer(&printer,2);
5508 free_a_printer_driver(driver, 3);
5513 /****************************************************************************
5514 ****************************************************************************/
5516 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5518 SAFE_FREE(info->dependentfiles);
5521 /****************************************************************************
5522 ****************************************************************************/
5524 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5526 SAFE_FREE(info->dependentfiles);
5529 /****************************************************************************
5530 ****************************************************************************/
5532 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5534 DRIVER_INFO_1 *info=NULL;
5537 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5540 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5541 if (!W_ERROR_IS_OK(result))
5544 /* check the required size. */
5545 *needed += spoolss_size_printer_driver_info_1(info);
5547 if (*needed > offered) {
5548 result = WERR_INSUFFICIENT_BUFFER;
5552 if (!rpcbuf_alloc_size(buffer, *needed)) {
5553 result = WERR_NOMEM;
5557 /* fill the buffer with the structures */
5558 smb_io_printer_driver_info_1("", buffer, info, 0);
5567 /****************************************************************************
5568 ****************************************************************************/
5570 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5572 DRIVER_INFO_2 *info=NULL;
5575 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5578 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5579 if (!W_ERROR_IS_OK(result))
5582 /* check the required size. */
5583 *needed += spoolss_size_printer_driver_info_2(info);
5585 if (*needed > offered) {
5586 result = WERR_INSUFFICIENT_BUFFER;
5590 if (!rpcbuf_alloc_size(buffer, *needed)) {
5591 result = WERR_NOMEM;
5595 /* fill the buffer with the structures */
5596 smb_io_printer_driver_info_2("", buffer, info, 0);
5605 /****************************************************************************
5606 ****************************************************************************/
5608 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5615 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5616 if (!W_ERROR_IS_OK(result))
5619 /* check the required size. */
5620 *needed += spoolss_size_printer_driver_info_3(&info);
5622 if (*needed > offered) {
5623 result = WERR_INSUFFICIENT_BUFFER;
5627 if (!rpcbuf_alloc_size(buffer, *needed)) {
5628 result = WERR_NOMEM;
5632 /* fill the buffer with the structures */
5633 smb_io_printer_driver_info_3("", buffer, &info, 0);
5636 free_printer_driver_info_3(&info);
5641 /****************************************************************************
5642 ****************************************************************************/
5644 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5651 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5652 if (!W_ERROR_IS_OK(result))
5655 /* check the required size. */
5656 *needed += spoolss_size_printer_driver_info_6(&info);
5658 if (*needed > offered) {
5659 result = WERR_INSUFFICIENT_BUFFER;
5663 if (!rpcbuf_alloc_size(buffer, *needed)) {
5664 result = WERR_NOMEM;
5668 /* fill the buffer with the structures */
5669 smb_io_printer_driver_info_6("", buffer, &info, 0);
5672 free_printer_driver_info_6(&info);
5677 /****************************************************************************
5678 ****************************************************************************/
5680 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5682 POLICY_HND *handle = &q_u->handle;
5683 UNISTR2 *uni_arch = &q_u->architecture;
5684 uint32 level = q_u->level;
5685 uint32 clientmajorversion = q_u->clientmajorversion;
5686 RPC_BUFFER *buffer = NULL;
5687 uint32 offered = q_u->offered;
5688 uint32 *needed = &r_u->needed;
5689 uint32 *servermajorversion = &r_u->servermajorversion;
5690 uint32 *serverminorversion = &r_u->serverminorversion;
5691 Printer_entry *printer;
5694 fstring architecture;
5697 /* that's an [in out] buffer */
5699 if (!q_u->buffer && (offered!=0)) {
5700 return WERR_INVALID_PARAM;
5703 rpcbuf_move(q_u->buffer, &r_u->buffer);
5704 buffer = r_u->buffer;
5706 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5708 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5709 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5710 return WERR_INVALID_PRINTER_NAME;
5714 *servermajorversion = 0;
5715 *serverminorversion = 0;
5717 fstrcpy(servername, get_server_name( printer ));
5718 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5720 if (!get_printer_snum(p, handle, &snum, NULL))
5725 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5727 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5729 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5731 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5734 /* apparently this call is the equivalent of
5735 EnumPrinterDataEx() for the DsDriver key */
5740 return WERR_UNKNOWN_LEVEL;
5743 /****************************************************************************
5744 ****************************************************************************/
5746 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5748 POLICY_HND *handle = &q_u->handle;
5750 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5753 DEBUG(3,("Error in startpageprinter printer handle\n"));
5757 Printer->page_started=True;
5761 /****************************************************************************
5762 ****************************************************************************/
5764 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5766 POLICY_HND *handle = &q_u->handle;
5769 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5772 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5776 if (!get_printer_snum(p, handle, &snum, NULL))
5779 Printer->page_started=False;
5780 print_job_endpage(snum, Printer->jobid);
5785 /********************************************************************
5786 * api_spoolss_getprinter
5787 * called from the spoolss dispatcher
5789 ********************************************************************/
5791 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5793 POLICY_HND *handle = &q_u->handle;
5794 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5795 uint32 *jobid = &r_u->jobid;
5797 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5801 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5804 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5809 * a nice thing with NT is it doesn't listen to what you tell it.
5810 * when asked to send _only_ RAW datas, it tries to send datas
5813 * So I add checks like in NT Server ...
5816 if (info_1->p_datatype != 0) {
5817 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5818 if (strcmp(datatype, "RAW") != 0) {
5820 return WERR_INVALID_DATATYPE;
5824 /* get the share number of the printer */
5825 if (!get_printer_snum(p, handle, &snum, NULL)) {
5829 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5831 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5833 /* An error occured in print_job_start() so return an appropriate
5836 if (Printer->jobid == -1) {
5837 return map_werror_from_unix(errno);
5840 Printer->document_started=True;
5841 (*jobid) = Printer->jobid;
5846 /********************************************************************
5847 * api_spoolss_getprinter
5848 * called from the spoolss dispatcher
5850 ********************************************************************/
5852 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5854 POLICY_HND *handle = &q_u->handle;
5856 return _spoolss_enddocprinter_internal(p, handle);
5859 /****************************************************************************
5860 ****************************************************************************/
5862 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5864 POLICY_HND *handle = &q_u->handle;
5865 uint32 buffer_size = q_u->buffer_size;
5866 uint8 *buffer = q_u->buffer;
5867 uint32 *buffer_written = &q_u->buffer_size2;
5869 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5872 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5873 r_u->buffer_written = q_u->buffer_size2;
5877 if (!get_printer_snum(p, handle, &snum, NULL))
5880 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5881 (SMB_OFF_T)-1, (size_t)buffer_size);
5882 if (*buffer_written == (uint32)-1) {
5883 r_u->buffer_written = 0;
5884 if (errno == ENOSPC)
5885 return WERR_NO_SPOOL_SPACE;
5887 return WERR_ACCESS_DENIED;
5890 r_u->buffer_written = q_u->buffer_size2;
5895 /********************************************************************
5896 * api_spoolss_getprinter
5897 * called from the spoolss dispatcher
5899 ********************************************************************/
5901 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5905 WERROR errcode = WERR_BADFUNC;
5906 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5909 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5913 if (!get_printer_snum(p, handle, &snum, NULL))
5917 case PRINTER_CONTROL_PAUSE:
5918 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5922 case PRINTER_CONTROL_RESUME:
5923 case PRINTER_CONTROL_UNPAUSE:
5924 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5928 case PRINTER_CONTROL_PURGE:
5929 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5934 return WERR_UNKNOWN_LEVEL;
5940 /********************************************************************
5941 * api_spoolss_abortprinter
5942 * From MSDN: "Deletes printer's spool file if printer is configured
5944 ********************************************************************/
5946 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5948 POLICY_HND *handle = &q_u->handle;
5949 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5951 WERROR errcode = WERR_OK;
5954 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5958 if (!get_printer_snum(p, handle, &snum, NULL))
5961 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5966 /********************************************************************
5967 * called by spoolss_api_setprinter
5968 * when updating a printer description
5969 ********************************************************************/
5971 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5972 const SPOOL_PRINTER_INFO_LEVEL *info,
5973 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5975 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5979 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5981 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5982 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5983 OUR_HANDLE(handle)));
5985 result = WERR_BADFID;
5990 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5991 result = WERR_INVALID_PARAM;
5995 /* Check the user has permissions to change the security
5996 descriptor. By experimentation with two NT machines, the user
5997 requires Full Access to the printer to change security
6000 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6001 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6002 result = WERR_ACCESS_DENIED;
6006 /* NT seems to like setting the security descriptor even though
6007 nothing may have actually changed. */
6009 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
6011 if (DEBUGLEVEL >= 10) {
6015 the_acl = old_secdesc_ctr->sd->dacl;
6016 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6017 PRINTERNAME(snum), the_acl->num_aces));
6019 for (i = 0; i < the_acl->num_aces; i++) {
6022 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6024 DEBUG(10, ("%s 0x%08x\n", sid_str,
6025 the_acl->aces[i].access_mask));
6028 the_acl = secdesc_ctr->sd->dacl;
6031 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6032 PRINTERNAME(snum), the_acl->num_aces));
6034 for (i = 0; i < the_acl->num_aces; i++) {
6037 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6039 DEBUG(10, ("%s 0x%08x\n", sid_str,
6040 the_acl->aces[i].access_mask));
6043 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6047 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6048 if (!new_secdesc_ctr) {
6049 result = WERR_NOMEM;
6053 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6058 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6065 /********************************************************************
6066 Canonicalize printer info from a client
6068 ATTN: It does not matter what we set the servername to hear
6069 since we do the necessary work in get_a_printer() to set it to
6070 the correct value based on what the client sent in the
6071 _spoolss_open_printer_ex().
6072 ********************************************************************/
6074 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6076 fstring printername;
6079 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6080 "portname=%s drivername=%s comment=%s location=%s\n",
6081 info->servername, info->printername, info->sharename,
6082 info->portname, info->drivername, info->comment, info->location));
6084 /* we force some elements to "correct" values */
6085 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6086 fstrcpy(info->sharename, lp_servicename(snum));
6088 /* check to see if we allow printername != sharename */
6090 if ( lp_force_printername(snum) ) {
6091 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6092 global_myname(), info->sharename );
6095 /* make sure printername is in \\server\printername format */
6097 fstrcpy( printername, info->printername );
6099 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6100 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6104 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6105 global_myname(), p );
6108 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6109 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6116 /****************************************************************************
6117 ****************************************************************************/
6119 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
6121 char *cmd = lp_addport_cmd();
6125 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6126 BOOL is_print_op = False;
6129 return WERR_ACCESS_DENIED;
6132 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
6135 is_print_op = user_has_privileges( token, &se_printop );
6137 DEBUG(10,("Running [%s]\n", command));
6139 /********* BEGIN SePrintOperatorPrivilege **********/
6144 ret = smbrun(command, &fd);
6149 /********* END SePrintOperatorPrivilege **********/
6151 DEBUGADD(10,("returned [%d]\n", ret));
6156 return WERR_ACCESS_DENIED;
6162 /****************************************************************************
6163 ****************************************************************************/
6165 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6167 char *cmd = lp_addprinter_cmd();
6173 fstring remote_machine = "%m";
6174 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6175 BOOL is_print_op = False;
6177 standard_sub_basic(current_user_info.smb_name,
6178 current_user_info.domain,
6179 remote_machine,sizeof(remote_machine));
6181 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6182 cmd, printer->info_2->printername, printer->info_2->sharename,
6183 printer->info_2->portname, printer->info_2->drivername,
6184 printer->info_2->location, printer->info_2->comment, remote_machine);
6187 is_print_op = user_has_privileges( token, &se_printop );
6189 DEBUG(10,("Running [%s]\n", command));
6191 /********* BEGIN SePrintOperatorPrivilege **********/
6196 if ( (ret = smbrun(command, &fd)) == 0 ) {
6197 /* Tell everyone we updated smb.conf. */
6198 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6204 /********* END SePrintOperatorPrivilege **********/
6206 DEBUGADD(10,("returned [%d]\n", ret));
6214 /* reload our services immediately */
6215 reload_services( False );
6218 /* Get lines and convert them back to dos-codepage */
6219 qlines = fd_lines_load(fd, &numlines, 0);
6220 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6223 /* Set the portname to what the script says the portname should be. */
6224 /* but don't require anything to be return from the script exit a good error code */
6227 /* Set the portname to what the script says the portname should be. */
6228 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6229 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6232 file_lines_free(qlines);
6237 /********************************************************************
6238 * Called by spoolss_api_setprinter
6239 * when updating a printer description.
6240 ********************************************************************/
6242 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6243 const SPOOL_PRINTER_INFO_LEVEL *info,
6244 DEVICEMODE *devmode)
6247 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6248 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6253 DEBUG(8,("update_printer\n"));
6258 result = WERR_BADFID;
6262 if (!get_printer_snum(p, handle, &snum, NULL)) {
6263 result = WERR_BADFID;
6267 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6268 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6269 result = WERR_BADFID;
6273 DEBUGADD(8,("Converting info_2 struct\n"));
6276 * convert_printer_info converts the incoming
6277 * info from the client and overwrites the info
6278 * just read from the tdb in the pointer 'printer'.
6281 if (!convert_printer_info(info, printer, level)) {
6282 result = WERR_NOMEM;
6287 /* we have a valid devmode
6288 convert it and link it*/
6290 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6291 if (!convert_devicemode(printer->info_2->printername, devmode,
6292 &printer->info_2->devmode)) {
6293 result = WERR_NOMEM;
6298 /* Do sanity check on the requested changes for Samba */
6300 if (!check_printer_ok(printer->info_2, snum)) {
6301 result = WERR_INVALID_PARAM;
6305 /* FIXME!!! If the driver has changed we really should verify that
6306 it is installed before doing much else --jerry */
6308 /* Check calling user has permission to update printer description */
6310 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6311 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6312 result = WERR_ACCESS_DENIED;
6316 /* Call addprinter hook */
6317 /* Check changes to see if this is really needed */
6319 if ( *lp_addprinter_cmd()
6320 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6321 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6322 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6323 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6325 /* add_printer_hook() will call reload_services() */
6327 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6328 result = WERR_ACCESS_DENIED;
6334 * When a *new* driver is bound to a printer, the drivername is used to
6335 * lookup previously saved driver initialization info, which is then
6336 * bound to the printer, simulating what happens in the Windows arch.
6338 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6340 if (!set_driver_init(printer, 2))
6342 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6343 printer->info_2->drivername));
6346 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6347 printer->info_2->drivername));
6349 notify_printer_driver(snum, printer->info_2->drivername);
6353 * flag which changes actually occured. This is a small subset of
6354 * all the possible changes. We also have to update things in the
6358 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6359 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6360 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6361 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6363 notify_printer_comment(snum, printer->info_2->comment);
6366 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6367 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6368 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6369 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6371 notify_printer_sharename(snum, printer->info_2->sharename);
6374 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6377 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6380 pname = printer->info_2->printername;
6383 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6384 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6385 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6387 notify_printer_printername( snum, pname );
6390 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6391 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6392 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6393 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6395 notify_printer_port(snum, printer->info_2->portname);
6398 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6399 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6400 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6401 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6403 notify_printer_location(snum, printer->info_2->location);
6406 /* here we need to update some more DsSpooler keys */
6407 /* uNCName, serverName, shortServerName */
6409 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6410 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6411 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6412 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6413 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6415 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6416 global_myname(), printer->info_2->sharename );
6417 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6418 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6419 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6421 /* Update printer info */
6422 result = mod_a_printer(printer, 2);
6425 free_a_printer(&printer, 2);
6426 free_a_printer(&old_printer, 2);
6432 /****************************************************************************
6433 ****************************************************************************/
6434 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6435 const SPOOL_PRINTER_INFO_LEVEL *info)
6438 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6440 Printer_entry *Printer;
6442 if ( lp_security() != SEC_ADS ) {
6443 return WERR_UNKNOWN_LEVEL;
6446 Printer = find_printer_index_by_hnd(p, handle);
6448 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6453 if (!get_printer_snum(p, handle, &snum, NULL))
6456 nt_printer_publish(Printer, snum, info7->action);
6460 return WERR_UNKNOWN_LEVEL;
6463 /****************************************************************************
6464 ****************************************************************************/
6466 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6468 POLICY_HND *handle = &q_u->handle;
6469 uint32 level = q_u->level;
6470 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6471 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6472 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6473 uint32 command = q_u->command;
6476 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6479 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6483 /* check the level */
6486 return control_printer(handle, command, p);
6488 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6489 if (!W_ERROR_IS_OK(result))
6492 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6495 return update_printer_sec(handle, level, info, p,
6498 return publish_or_unpublish_printer(p, handle, info);
6500 return WERR_UNKNOWN_LEVEL;
6504 /****************************************************************************
6505 ****************************************************************************/
6507 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6509 POLICY_HND *handle = &q_u->handle;
6510 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6513 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6517 if (Printer->notify.client_connected==True) {
6520 if ( Printer->printer_type == SPLHND_SERVER)
6522 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6523 !get_printer_snum(p, handle, &snum, NULL) )
6526 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6529 Printer->notify.flags=0;
6530 Printer->notify.options=0;
6531 Printer->notify.localmachine[0]='\0';
6532 Printer->notify.printerlocal=0;
6533 if (Printer->notify.option)
6534 free_spool_notify_option(&Printer->notify.option);
6535 Printer->notify.client_connected=False;
6540 /****************************************************************************
6541 ****************************************************************************/
6543 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6545 /* that's an [in out] buffer */
6547 if (!q_u->buffer && (q_u->offered!=0)) {
6548 return WERR_INVALID_PARAM;
6551 rpcbuf_move(q_u->buffer, &r_u->buffer);
6554 return WERR_INVALID_PARAM; /* this is what a NT server
6555 returns for AddJob. AddJob
6556 must fail on non-local
6560 /****************************************************************************
6561 ****************************************************************************/
6563 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6564 int position, int snum,
6565 const NT_PRINTER_INFO_LEVEL *ntprinter)
6569 t=gmtime(&queue->time);
6571 job_info->jobid=queue->job;
6572 init_unistr(&job_info->printername, lp_servicename(snum));
6573 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6574 init_unistr(&job_info->username, queue->fs_user);
6575 init_unistr(&job_info->document, queue->fs_file);
6576 init_unistr(&job_info->datatype, "RAW");
6577 init_unistr(&job_info->text_status, "");
6578 job_info->status=nt_printj_status(queue->status);
6579 job_info->priority=queue->priority;
6580 job_info->position=position;
6581 job_info->totalpages=queue->page_count;
6582 job_info->pagesprinted=0;
6584 make_systemtime(&job_info->submitted, t);
6587 /****************************************************************************
6588 ****************************************************************************/
6590 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6591 int position, int snum,
6592 const NT_PRINTER_INFO_LEVEL *ntprinter,
6593 DEVICEMODE *devmode)
6597 t=gmtime(&queue->time);
6599 job_info->jobid=queue->job;
6601 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6603 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6604 init_unistr(&job_info->username, queue->fs_user);
6605 init_unistr(&job_info->document, queue->fs_file);
6606 init_unistr(&job_info->notifyname, queue->fs_user);
6607 init_unistr(&job_info->datatype, "RAW");
6608 init_unistr(&job_info->printprocessor, "winprint");
6609 init_unistr(&job_info->parameters, "");
6610 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6611 init_unistr(&job_info->text_status, "");
6613 /* and here the security descriptor */
6615 job_info->status=nt_printj_status(queue->status);
6616 job_info->priority=queue->priority;
6617 job_info->position=position;
6618 job_info->starttime=0;
6619 job_info->untiltime=0;
6620 job_info->totalpages=queue->page_count;
6621 job_info->size=queue->size;
6622 make_systemtime(&(job_info->submitted), t);
6623 job_info->timeelapsed=0;
6624 job_info->pagesprinted=0;
6626 job_info->devmode = devmode;
6631 /****************************************************************************
6632 Enumjobs at level 1.
6633 ****************************************************************************/
6635 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6636 const NT_PRINTER_INFO_LEVEL *ntprinter,
6637 RPC_BUFFER *buffer, uint32 offered,
6638 uint32 *needed, uint32 *returned)
6642 WERROR result = WERR_OK;
6644 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6650 for (i=0; i<*returned; i++)
6651 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6653 /* check the required size. */
6654 for (i=0; i<*returned; i++)
6655 (*needed) += spoolss_size_job_info_1(&info[i]);
6657 if (*needed > offered) {
6658 result = WERR_INSUFFICIENT_BUFFER;
6662 if (!rpcbuf_alloc_size(buffer, *needed)) {
6663 result = WERR_NOMEM;
6667 /* fill the buffer with the structures */
6668 for (i=0; i<*returned; i++)
6669 smb_io_job_info_1("", buffer, &info[i], 0);
6675 if ( !W_ERROR_IS_OK(result) )
6681 /****************************************************************************
6682 Enumjobs at level 2.
6683 ****************************************************************************/
6685 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6686 const NT_PRINTER_INFO_LEVEL *ntprinter,
6687 RPC_BUFFER *buffer, uint32 offered,
6688 uint32 *needed, uint32 *returned)
6690 JOB_INFO_2 *info = NULL;
6692 WERROR result = WERR_OK;
6693 DEVICEMODE *devmode = NULL;
6695 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6700 /* this should not be a failure condition if the devmode is NULL */
6702 devmode = construct_dev_mode(lp_const_servicename(snum));
6704 for (i=0; i<*returned; i++)
6705 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6707 /* check the required size. */
6708 for (i=0; i<*returned; i++)
6709 (*needed) += spoolss_size_job_info_2(&info[i]);
6711 if (*needed > offered) {
6712 result = WERR_INSUFFICIENT_BUFFER;
6716 if (!rpcbuf_alloc_size(buffer, *needed)) {
6717 result = WERR_NOMEM;
6721 /* fill the buffer with the structures */
6722 for (i=0; i<*returned; i++)
6723 smb_io_job_info_2("", buffer, &info[i], 0);
6726 free_devmode(devmode);
6729 if ( !W_ERROR_IS_OK(result) )
6736 /****************************************************************************
6738 ****************************************************************************/
6740 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6742 POLICY_HND *handle = &q_u->handle;
6743 uint32 level = q_u->level;
6744 RPC_BUFFER *buffer = NULL;
6745 uint32 offered = q_u->offered;
6746 uint32 *needed = &r_u->needed;
6747 uint32 *returned = &r_u->returned;
6749 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6751 print_status_struct prt_status;
6752 print_queue_struct *queue=NULL;
6754 /* that's an [in out] buffer */
6756 if (!q_u->buffer && (offered!=0)) {
6757 return WERR_INVALID_PARAM;
6760 rpcbuf_move(q_u->buffer, &r_u->buffer);
6761 buffer = r_u->buffer;
6763 DEBUG(4,("_spoolss_enumjobs\n"));
6768 /* lookup the printer snum and tdb entry */
6770 if (!get_printer_snum(p, handle, &snum, NULL))
6773 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6774 if ( !W_ERROR_IS_OK(wret) )
6777 *returned = print_queue_status(snum, &queue, &prt_status);
6778 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6780 if (*returned == 0) {
6782 free_a_printer(&ntprinter, 2);
6788 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6791 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6795 wret = WERR_UNKNOWN_LEVEL;
6800 free_a_printer( &ntprinter, 2 );
6804 /****************************************************************************
6805 ****************************************************************************/
6807 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6812 /****************************************************************************
6813 ****************************************************************************/
6815 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6817 POLICY_HND *handle = &q_u->handle;
6818 uint32 jobid = q_u->jobid;
6819 uint32 command = q_u->command;
6822 WERROR errcode = WERR_BADFUNC;
6824 if (!get_printer_snum(p, handle, &snum, NULL)) {
6828 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6829 return WERR_INVALID_PRINTER_NAME;
6833 case JOB_CONTROL_CANCEL:
6834 case JOB_CONTROL_DELETE:
6835 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6839 case JOB_CONTROL_PAUSE:
6840 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6844 case JOB_CONTROL_RESTART:
6845 case JOB_CONTROL_RESUME:
6846 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6851 return WERR_UNKNOWN_LEVEL;
6857 /****************************************************************************
6858 Enumerates all printer drivers at level 1.
6859 ****************************************************************************/
6861 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6866 fstring *list = NULL;
6867 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6868 DRIVER_INFO_1 *driver_info_1=NULL;
6869 WERROR result = WERR_OK;
6873 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6875 ndrivers=get_ntdrivers(&list, architecture, version);
6876 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6878 if(ndrivers == -1) {
6879 SAFE_FREE(driver_info_1);
6884 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6885 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6891 for (i=0; i<ndrivers; i++) {
6893 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6894 ZERO_STRUCT(driver);
6895 status = get_a_printer_driver(&driver, 3, list[i],
6896 architecture, version);
6897 if (!W_ERROR_IS_OK(status)) {
6899 SAFE_FREE(driver_info_1);
6902 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6903 free_a_printer_driver(driver, 3);
6906 *returned+=ndrivers;
6910 /* check the required size. */
6911 for (i=0; i<*returned; i++) {
6912 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6913 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6916 if (*needed > offered) {
6917 result = WERR_INSUFFICIENT_BUFFER;
6921 if (!rpcbuf_alloc_size(buffer, *needed)) {
6922 result = WERR_NOMEM;
6926 /* fill the buffer with the driver structures */
6927 for (i=0; i<*returned; i++) {
6928 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6929 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6933 SAFE_FREE(driver_info_1);
6935 if ( !W_ERROR_IS_OK(result) )
6941 /****************************************************************************
6942 Enumerates all printer drivers at level 2.
6943 ****************************************************************************/
6945 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6950 fstring *list = NULL;
6951 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6952 DRIVER_INFO_2 *driver_info_2=NULL;
6953 WERROR result = WERR_OK;
6957 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6959 ndrivers=get_ntdrivers(&list, architecture, version);
6960 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6962 if(ndrivers == -1) {
6963 SAFE_FREE(driver_info_2);
6968 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6969 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6975 for (i=0; i<ndrivers; i++) {
6978 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6979 ZERO_STRUCT(driver);
6980 status = get_a_printer_driver(&driver, 3, list[i],
6981 architecture, version);
6982 if (!W_ERROR_IS_OK(status)) {
6984 SAFE_FREE(driver_info_2);
6987 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6988 free_a_printer_driver(driver, 3);
6991 *returned+=ndrivers;
6995 /* check the required size. */
6996 for (i=0; i<*returned; i++) {
6997 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6998 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7001 if (*needed > offered) {
7002 result = WERR_INSUFFICIENT_BUFFER;
7006 if (!rpcbuf_alloc_size(buffer, *needed)) {
7007 result = WERR_NOMEM;
7011 /* fill the buffer with the form structures */
7012 for (i=0; i<*returned; i++) {
7013 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7014 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7018 SAFE_FREE(driver_info_2);
7020 if ( !W_ERROR_IS_OK(result) )
7026 /****************************************************************************
7027 Enumerates all printer drivers at level 3.
7028 ****************************************************************************/
7030 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7035 fstring *list = NULL;
7036 DRIVER_INFO_3 *driver_info_3=NULL;
7037 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7038 WERROR result = WERR_OK;
7042 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7044 ndrivers=get_ntdrivers(&list, architecture, version);
7045 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7047 if(ndrivers == -1) {
7048 SAFE_FREE(driver_info_3);
7053 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7054 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7060 for (i=0; i<ndrivers; i++) {
7063 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7064 ZERO_STRUCT(driver);
7065 status = get_a_printer_driver(&driver, 3, list[i],
7066 architecture, version);
7067 if (!W_ERROR_IS_OK(status)) {
7069 SAFE_FREE(driver_info_3);
7072 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7073 free_a_printer_driver(driver, 3);
7076 *returned+=ndrivers;
7080 /* check the required size. */
7081 for (i=0; i<*returned; i++) {
7082 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7083 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7086 if (*needed > offered) {
7087 result = WERR_INSUFFICIENT_BUFFER;
7091 if (!rpcbuf_alloc_size(buffer, *needed)) {
7092 result = WERR_NOMEM;
7096 /* fill the buffer with the driver structures */
7097 for (i=0; i<*returned; i++) {
7098 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7099 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7103 for (i=0; i<*returned; i++) {
7104 SAFE_FREE(driver_info_3[i].dependentfiles);
7107 SAFE_FREE(driver_info_3);
7109 if ( !W_ERROR_IS_OK(result) )
7115 /****************************************************************************
7116 Enumerates all printer drivers.
7117 ****************************************************************************/
7119 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7121 uint32 level = q_u->level;
7122 RPC_BUFFER *buffer = NULL;
7123 uint32 offered = q_u->offered;
7124 uint32 *needed = &r_u->needed;
7125 uint32 *returned = &r_u->returned;
7128 fstring architecture;
7130 /* that's an [in out] buffer */
7132 if (!q_u->buffer && (offered!=0)) {
7133 return WERR_INVALID_PARAM;
7136 rpcbuf_move(q_u->buffer, &r_u->buffer);
7137 buffer = r_u->buffer;
7139 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7144 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7145 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7147 if ( !is_myname_or_ipaddr( servername ) )
7148 return WERR_UNKNOWN_PRINTER_DRIVER;
7152 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7154 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7156 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7158 return WERR_UNKNOWN_LEVEL;
7162 /****************************************************************************
7163 ****************************************************************************/
7165 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7167 form->flag=list->flag;
7168 init_unistr(&form->name, list->name);
7169 form->width=list->width;
7170 form->length=list->length;
7171 form->left=list->left;
7172 form->top=list->top;
7173 form->right=list->right;
7174 form->bottom=list->bottom;
7177 /****************************************************************************
7178 ****************************************************************************/
7180 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7182 uint32 level = q_u->level;
7183 RPC_BUFFER *buffer = NULL;
7184 uint32 offered = q_u->offered;
7185 uint32 *needed = &r_u->needed;
7186 uint32 *numofforms = &r_u->numofforms;
7187 uint32 numbuiltinforms;
7189 nt_forms_struct *list=NULL;
7190 nt_forms_struct *builtinlist=NULL;
7195 /* that's an [in out] buffer */
7197 if (!q_u->buffer && (offered!=0) ) {
7198 return WERR_INVALID_PARAM;
7201 rpcbuf_move(q_u->buffer, &r_u->buffer);
7202 buffer = r_u->buffer;
7204 DEBUG(4,("_spoolss_enumforms\n"));
7205 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7206 DEBUGADD(5,("Info level [%d]\n", level));
7208 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7209 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7210 *numofforms = get_ntforms(&list);
7211 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7212 *numofforms += numbuiltinforms;
7214 if (*numofforms == 0) {
7215 SAFE_FREE(builtinlist);
7217 return WERR_NO_MORE_ITEMS;
7222 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7223 SAFE_FREE(builtinlist);
7229 /* construct the list of form structures */
7230 for (i=0; i<numbuiltinforms; i++) {
7231 DEBUGADD(6,("Filling form number [%d]\n",i));
7232 fill_form_1(&forms_1[i], &builtinlist[i]);
7235 SAFE_FREE(builtinlist);
7237 for (; i<*numofforms; i++) {
7238 DEBUGADD(6,("Filling form number [%d]\n",i));
7239 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7244 /* check the required size. */
7245 for (i=0; i<numbuiltinforms; i++) {
7246 DEBUGADD(6,("adding form [%d]'s size\n",i));
7247 buffer_size += spoolss_size_form_1(&forms_1[i]);
7249 for (; i<*numofforms; i++) {
7250 DEBUGADD(6,("adding form [%d]'s size\n",i));
7251 buffer_size += spoolss_size_form_1(&forms_1[i]);
7254 *needed=buffer_size;
7256 if (*needed > offered) {
7259 return WERR_INSUFFICIENT_BUFFER;
7262 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7268 /* fill the buffer with the form structures */
7269 for (i=0; i<numbuiltinforms; i++) {
7270 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7271 smb_io_form_1("", buffer, &forms_1[i], 0);
7273 for (; i<*numofforms; i++) {
7274 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7275 smb_io_form_1("", buffer, &forms_1[i], 0);
7284 SAFE_FREE(builtinlist);
7285 return WERR_UNKNOWN_LEVEL;
7289 /****************************************************************************
7290 ****************************************************************************/
7292 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7294 uint32 level = q_u->level;
7295 UNISTR2 *uni_formname = &q_u->formname;
7296 RPC_BUFFER *buffer = NULL;
7297 uint32 offered = q_u->offered;
7298 uint32 *needed = &r_u->needed;
7300 nt_forms_struct *list=NULL;
7301 nt_forms_struct builtin_form;
7306 int numofforms=0, i=0;
7308 /* that's an [in out] buffer */
7310 if (!q_u->buffer && (offered!=0)) {
7311 return WERR_INVALID_PARAM;
7314 rpcbuf_move(q_u->buffer, &r_u->buffer);
7315 buffer = r_u->buffer;
7317 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7319 DEBUG(4,("_spoolss_getform\n"));
7320 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7321 DEBUGADD(5,("Info level [%d]\n", level));
7323 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7324 if (!foundBuiltin) {
7325 numofforms = get_ntforms(&list);
7326 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7328 if (numofforms == 0)
7335 fill_form_1(&form_1, &builtin_form);
7338 /* Check if the requested name is in the list of form structures */
7339 for (i=0; i<numofforms; i++) {
7341 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7343 if (strequal(form_name, list[i].name)) {
7344 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7345 fill_form_1(&form_1, &list[i]);
7351 if (i == numofforms) {
7355 /* check the required size. */
7357 *needed=spoolss_size_form_1(&form_1);
7359 if (*needed > offered)
7360 return WERR_INSUFFICIENT_BUFFER;
7362 if (!rpcbuf_alloc_size(buffer, buffer_size))
7365 /* fill the buffer with the form structures */
7366 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7367 smb_io_form_1("", buffer, &form_1, 0);
7373 return WERR_UNKNOWN_LEVEL;
7377 /****************************************************************************
7378 ****************************************************************************/
7380 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7382 init_unistr(&port->port_name, name);
7385 /****************************************************************************
7386 TODO: This probably needs distinguish between TCP/IP and Local ports
7388 ****************************************************************************/
7390 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7392 init_unistr(&port->port_name, name);
7393 init_unistr(&port->monitor_name, "Local Monitor");
7394 init_unistr(&port->description, SPL_LOCAL_PORT );
7395 port->port_type=PORT_TYPE_WRITE;
7400 /****************************************************************************
7401 wrapper around the enumer ports command
7402 ****************************************************************************/
7404 WERROR enumports_hook( int *count, char ***lines )
7406 char *cmd = lp_enumports_cmd();
7416 /* if no hook then just fill in the default port */
7419 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7420 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7425 /* we have a valid enumport command */
7427 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7429 DEBUG(10,("Running [%s]\n", command));
7430 ret = smbrun(command, &fd);
7431 DEBUG(10,("Returned [%d]\n", ret));
7436 return WERR_ACCESS_DENIED;
7440 qlines = fd_lines_load(fd, &numlines, 0);
7441 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7451 /****************************************************************************
7453 ****************************************************************************/
7455 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7457 PORT_INFO_1 *ports=NULL;
7459 WERROR result = WERR_OK;
7460 char **qlines = NULL;
7463 result = enumports_hook( &numlines, &qlines );
7464 if (!W_ERROR_IS_OK(result)) {
7465 file_lines_free(qlines);
7470 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7471 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7472 dos_errstr(WERR_NOMEM)));
7473 file_lines_free(qlines);
7477 for (i=0; i<numlines; i++) {
7478 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7479 fill_port_1(&ports[i], qlines[i]);
7482 file_lines_free(qlines);
7484 *returned = numlines;
7486 /* check the required size. */
7487 for (i=0; i<*returned; i++) {
7488 DEBUGADD(6,("adding port [%d]'s size\n", i));
7489 *needed += spoolss_size_port_info_1(&ports[i]);
7492 if (*needed > offered) {
7493 result = WERR_INSUFFICIENT_BUFFER;
7497 if (!rpcbuf_alloc_size(buffer, *needed)) {
7498 result = WERR_NOMEM;
7502 /* fill the buffer with the ports structures */
7503 for (i=0; i<*returned; i++) {
7504 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7505 smb_io_port_1("", buffer, &ports[i], 0);
7511 if ( !W_ERROR_IS_OK(result) )
7517 /****************************************************************************
7519 ****************************************************************************/
7521 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7523 PORT_INFO_2 *ports=NULL;
7525 WERROR result = WERR_OK;
7526 char **qlines = NULL;
7529 result = enumports_hook( &numlines, &qlines );
7530 if ( !W_ERROR_IS_OK(result)) {
7531 file_lines_free(qlines);
7536 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7537 file_lines_free(qlines);
7541 for (i=0; i<numlines; i++) {
7542 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7543 fill_port_2(&(ports[i]), qlines[i]);
7547 file_lines_free(qlines);
7549 *returned = numlines;
7551 /* check the required size. */
7552 for (i=0; i<*returned; i++) {
7553 DEBUGADD(6,("adding port [%d]'s size\n", i));
7554 *needed += spoolss_size_port_info_2(&ports[i]);
7557 if (*needed > offered) {
7558 result = WERR_INSUFFICIENT_BUFFER;
7562 if (!rpcbuf_alloc_size(buffer, *needed)) {
7563 result = WERR_NOMEM;
7567 /* fill the buffer with the ports structures */
7568 for (i=0; i<*returned; i++) {
7569 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7570 smb_io_port_2("", buffer, &ports[i], 0);
7576 if ( !W_ERROR_IS_OK(result) )
7582 /****************************************************************************
7584 ****************************************************************************/
7586 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7588 uint32 level = q_u->level;
7589 RPC_BUFFER *buffer = NULL;
7590 uint32 offered = q_u->offered;
7591 uint32 *needed = &r_u->needed;
7592 uint32 *returned = &r_u->returned;
7594 /* that's an [in out] buffer */
7596 if (!q_u->buffer && (offered!=0)) {
7597 return WERR_INVALID_PARAM;
7600 rpcbuf_move(q_u->buffer, &r_u->buffer);
7601 buffer = r_u->buffer;
7603 DEBUG(4,("_spoolss_enumports\n"));
7610 return enumports_level_1(buffer, offered, needed, returned);
7612 return enumports_level_2(buffer, offered, needed, returned);
7614 return WERR_UNKNOWN_LEVEL;
7618 /****************************************************************************
7619 ****************************************************************************/
7621 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7622 const SPOOL_PRINTER_INFO_LEVEL *info,
7623 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7624 uint32 user_switch, const SPOOL_USER_CTR *user,
7627 NT_PRINTER_INFO_LEVEL *printer = NULL;
7630 WERROR err = WERR_OK;
7632 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7633 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7637 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7638 if (!convert_printer_info(info, printer, 2)) {
7639 free_a_printer(&printer, 2);
7643 /* check to see if the printer already exists */
7645 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7646 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7647 printer->info_2->sharename));
7648 free_a_printer(&printer, 2);
7649 return WERR_PRINTER_ALREADY_EXISTS;
7652 /* FIXME!!! smbd should check to see if the driver is installed before
7653 trying to add a printer like this --jerry */
7655 if (*lp_addprinter_cmd() ) {
7656 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7657 free_a_printer(&printer,2);
7658 return WERR_ACCESS_DENIED;
7661 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7662 "smb.conf parameter \"addprinter command\" is defined. This"
7663 "parameter must exist for this call to succeed\n",
7664 printer->info_2->sharename ));
7667 /* use our primary netbios name since get_a_printer() will convert
7668 it to what the client expects on a case by case basis */
7670 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7671 printer->info_2->sharename);
7674 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7675 free_a_printer(&printer,2);
7676 return WERR_ACCESS_DENIED;
7679 /* you must be a printer admin to add a new printer */
7680 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7681 free_a_printer(&printer,2);
7682 return WERR_ACCESS_DENIED;
7686 * Do sanity check on the requested changes for Samba.
7689 if (!check_printer_ok(printer->info_2, snum)) {
7690 free_a_printer(&printer,2);
7691 return WERR_INVALID_PARAM;
7695 * When a printer is created, the drivername bound to the printer is used
7696 * to lookup previously saved driver initialization info, which is then
7697 * bound to the new printer, simulating what happens in the Windows arch.
7702 set_driver_init(printer, 2);
7706 /* A valid devmode was included, convert and link it
7708 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7710 if (!convert_devicemode(printer->info_2->printername, devmode,
7711 &printer->info_2->devmode))
7715 /* write the ASCII on disk */
7716 err = mod_a_printer(printer, 2);
7717 if (!W_ERROR_IS_OK(err)) {
7718 free_a_printer(&printer,2);
7722 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7723 /* Handle open failed - remove addition. */
7724 del_a_printer(printer->info_2->sharename);
7725 free_a_printer(&printer,2);
7726 return WERR_ACCESS_DENIED;
7729 update_c_setprinter(False);
7730 free_a_printer(&printer,2);
7735 /****************************************************************************
7736 ****************************************************************************/
7738 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7740 UNISTR2 *uni_srv_name = q_u->server_name;
7741 uint32 level = q_u->level;
7742 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7743 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7744 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7745 uint32 user_switch = q_u->user_switch;
7746 SPOOL_USER_CTR *user = &q_u->user_ctr;
7747 POLICY_HND *handle = &r_u->handle;
7751 /* we don't handle yet */
7752 /* but I know what to do ... */
7753 return WERR_UNKNOWN_LEVEL;
7755 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7757 user_switch, user, handle);
7759 return WERR_UNKNOWN_LEVEL;
7763 /****************************************************************************
7764 ****************************************************************************/
7766 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7768 uint32 level = q_u->level;
7769 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7770 WERROR err = WERR_OK;
7771 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7772 fstring driver_name;
7775 ZERO_STRUCT(driver);
7777 if (!convert_printer_driver_info(info, &driver, level)) {
7782 DEBUG(5,("Cleaning driver's information\n"));
7783 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7784 if (!W_ERROR_IS_OK(err))
7787 DEBUG(5,("Moving driver to final destination\n"));
7788 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7792 if (add_a_printer_driver(driver, level)!=0) {
7793 err = WERR_ACCESS_DENIED;
7798 * I think this is where he DrvUpgradePrinter() hook would be
7799 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7800 * server. Right now, we just need to send ourselves a message
7801 * to update each printer bound to this driver. --jerry
7804 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7805 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7810 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7811 * decide if the driver init data should be deleted. The rules are:
7812 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7813 * 2) delete init data only if there is no 2k/Xp driver
7814 * 3) always delete init data
7815 * The generalized rule is always use init data from the highest order driver.
7816 * It is necessary to follow the driver install by an initialization step to
7817 * finish off this process.
7820 version = driver.info_3->cversion;
7821 else if (level == 6)
7822 version = driver.info_6->version;
7827 * 9x printer driver - never delete init data
7830 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7835 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7836 * there is no 2k/Xp driver init data for this driver name.
7840 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7842 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7844 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7846 if (!del_driver_init(driver_name))
7847 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7850 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7852 free_a_printer_driver(driver1,3);
7853 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7860 * 2k or Xp printer driver - always delete init data
7863 if (!del_driver_init(driver_name))
7864 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7868 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7874 free_a_printer_driver(driver, level);
7878 /********************************************************************
7879 * spoolss_addprinterdriverex
7880 ********************************************************************/
7882 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7884 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7885 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7888 * we only support the semantics of AddPrinterDriver()
7889 * i.e. only copy files that are newer than existing ones
7892 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7893 return WERR_ACCESS_DENIED;
7895 ZERO_STRUCT(q_u_local);
7896 ZERO_STRUCT(r_u_local);
7898 /* just pass the information off to _spoolss_addprinterdriver() */
7899 q_u_local.server_name_ptr = q_u->server_name_ptr;
7900 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7901 q_u_local.level = q_u->level;
7902 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7904 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7907 /****************************************************************************
7908 ****************************************************************************/
7910 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7912 init_unistr(&info->name, name);
7915 /****************************************************************************
7916 ****************************************************************************/
7918 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7924 const char *short_archi;
7925 DRIVER_DIRECTORY_1 *info=NULL;
7926 WERROR result = WERR_OK;
7928 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7929 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7931 /* check for beginning double '\'s and that the server
7934 pservername = servername;
7935 if ( *pservername == '\\' && strlen(servername)>2 ) {
7939 if ( !is_myname_or_ipaddr( pservername ) )
7940 return WERR_INVALID_PARAM;
7942 if (!(short_archi = get_short_archi(long_archi)))
7943 return WERR_INVALID_ENVIRONMENT;
7945 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7948 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7950 DEBUG(4,("printer driver directory: [%s]\n", path));
7952 fill_driverdir_1(info, path);
7954 *needed += spoolss_size_driverdir_info_1(info);
7956 if (*needed > offered) {
7957 result = WERR_INSUFFICIENT_BUFFER;
7961 if (!rpcbuf_alloc_size(buffer, *needed)) {
7962 result = WERR_NOMEM;
7966 smb_io_driverdir_1("", buffer, info, 0);
7974 /****************************************************************************
7975 ****************************************************************************/
7977 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7979 UNISTR2 *name = &q_u->name;
7980 UNISTR2 *uni_environment = &q_u->environment;
7981 uint32 level = q_u->level;
7982 RPC_BUFFER *buffer = NULL;
7983 uint32 offered = q_u->offered;
7984 uint32 *needed = &r_u->needed;
7986 /* that's an [in out] buffer */
7988 if (!q_u->buffer && (offered!=0)) {
7989 return WERR_INVALID_PARAM;
7992 rpcbuf_move(q_u->buffer, &r_u->buffer);
7993 buffer = r_u->buffer;
7995 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8001 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8003 return WERR_UNKNOWN_LEVEL;
8007 /****************************************************************************
8008 ****************************************************************************/
8010 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8012 POLICY_HND *handle = &q_u->handle;
8013 uint32 idx = q_u->index;
8014 uint32 in_value_len = q_u->valuesize;
8015 uint32 in_data_len = q_u->datasize;
8016 uint32 *out_max_value_len = &r_u->valuesize;
8017 uint16 **out_value = &r_u->value;
8018 uint32 *out_value_len = &r_u->realvaluesize;
8019 uint32 *out_type = &r_u->type;
8020 uint32 *out_max_data_len = &r_u->datasize;
8021 uint8 **data_out = &r_u->data;
8022 uint32 *out_data_len = &r_u->realdatasize;
8024 NT_PRINTER_INFO_LEVEL *printer = NULL;
8026 uint32 biggest_valuesize;
8027 uint32 biggest_datasize;
8029 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8032 REGISTRY_VALUE *val = NULL;
8033 NT_PRINTER_DATA *p_data;
8034 int i, key_index, num_values;
8039 *out_max_data_len = 0;
8043 DEBUG(5,("spoolss_enumprinterdata\n"));
8046 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8050 if (!get_printer_snum(p,handle, &snum, NULL))
8053 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8054 if (!W_ERROR_IS_OK(result))
8057 p_data = printer->info_2->data;
8058 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8063 * The NT machine wants to know the biggest size of value and data
8065 * cf: MSDN EnumPrinterData remark section
8068 if ( !in_value_len && !in_data_len && (key_index != -1) )
8070 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8072 biggest_valuesize = 0;
8073 biggest_datasize = 0;
8075 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8077 for ( i=0; i<num_values; i++ )
8079 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8081 name_length = strlen(val->valuename);
8082 if ( strlen(val->valuename) > biggest_valuesize )
8083 biggest_valuesize = name_length;
8085 if ( val->size > biggest_datasize )
8086 biggest_datasize = val->size;
8088 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8092 /* the value is an UNICODE string but real_value_size is the length
8093 in bytes including the trailing 0 */
8095 *out_value_len = 2 * (1+biggest_valuesize);
8096 *out_data_len = biggest_datasize;
8098 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8104 * the value len is wrong in NT sp3
8105 * that's the number of bytes not the number of unicode chars
8108 if ( key_index != -1 )
8109 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8114 /* out_value should default to "" or else NT4 has
8115 problems unmarshalling the response */
8117 *out_max_value_len=(in_value_len/sizeof(uint16));
8119 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8121 result = WERR_NOMEM;
8125 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8127 /* the data is counted in bytes */
8129 *out_max_data_len = in_data_len;
8130 *out_data_len = in_data_len;
8132 /* only allocate when given a non-zero data_len */
8134 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8136 result = WERR_NOMEM;
8140 result = WERR_NO_MORE_ITEMS;
8146 * - counted in bytes in the request
8147 * - counted in UNICODE chars in the max reply
8148 * - counted in bytes in the real size
8150 * take a pause *before* coding not *during* coding
8154 *out_max_value_len=(in_value_len/sizeof(uint16));
8155 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8157 result = WERR_NOMEM;
8161 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8165 *out_type = regval_type( val );
8167 /* data - counted in bytes */
8169 *out_max_data_len = in_data_len;
8170 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8172 result = WERR_NOMEM;
8175 data_len = regval_size(val);
8177 memcpy( *data_out, regval_data_p(val), data_len );
8178 *out_data_len = data_len;
8182 free_a_printer(&printer, 2);
8186 /****************************************************************************
8187 ****************************************************************************/
8189 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8191 POLICY_HND *handle = &q_u->handle;
8192 UNISTR2 *value = &q_u->value;
8193 uint32 type = q_u->type;
8194 uint8 *data = q_u->data;
8195 uint32 real_len = q_u->real_len;
8197 NT_PRINTER_INFO_LEVEL *printer = NULL;
8199 WERROR status = WERR_OK;
8200 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8203 DEBUG(5,("spoolss_setprinterdata\n"));
8206 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8210 if ( Printer->printer_type == SPLHND_SERVER ) {
8211 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8212 return WERR_INVALID_PARAM;
8215 if (!get_printer_snum(p,handle, &snum, NULL))
8219 * Access check : NT returns "access denied" if you make a
8220 * SetPrinterData call without the necessary privildge.
8221 * we were originally returning OK if nothing changed
8222 * which made Win2k issue **a lot** of SetPrinterData
8223 * when connecting to a printer --jerry
8226 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8228 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8229 status = WERR_ACCESS_DENIED;
8233 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8234 if (!W_ERROR_IS_OK(status))
8237 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8240 * When client side code sets a magic printer data key, detect it and save
8241 * the current printer data and the magic key's data (its the DEVMODE) for
8242 * future printer/driver initializations.
8244 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8246 /* Set devmode and printer initialization info */
8247 status = save_driver_init( printer, 2, data, real_len );
8249 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8253 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8254 type, data, real_len );
8255 if ( W_ERROR_IS_OK(status) )
8256 status = mod_a_printer(printer, 2);
8260 free_a_printer(&printer, 2);
8265 /****************************************************************************
8266 ****************************************************************************/
8268 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8270 POLICY_HND *handle = &q_u->handle;
8271 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8274 DEBUG(5,("_spoolss_resetprinter\n"));
8277 * All we do is to check to see if the handle and queue is valid.
8278 * This call really doesn't mean anything to us because we only
8279 * support RAW printing. --jerry
8283 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8287 if (!get_printer_snum(p,handle, &snum, NULL))
8291 /* blindly return success */
8296 /****************************************************************************
8297 ****************************************************************************/
8299 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8301 POLICY_HND *handle = &q_u->handle;
8302 UNISTR2 *value = &q_u->valuename;
8304 NT_PRINTER_INFO_LEVEL *printer = NULL;
8306 WERROR status = WERR_OK;
8307 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8310 DEBUG(5,("spoolss_deleteprinterdata\n"));
8313 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8317 if (!get_printer_snum(p, handle, &snum, NULL))
8320 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8321 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8322 return WERR_ACCESS_DENIED;
8325 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8326 if (!W_ERROR_IS_OK(status))
8329 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8331 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8333 if ( W_ERROR_IS_OK(status) )
8334 mod_a_printer( printer, 2 );
8336 free_a_printer(&printer, 2);
8341 /****************************************************************************
8342 ****************************************************************************/
8344 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8346 POLICY_HND *handle = &q_u->handle;
8347 FORM *form = &q_u->form;
8348 nt_forms_struct tmpForm;
8350 WERROR status = WERR_OK;
8351 NT_PRINTER_INFO_LEVEL *printer = NULL;
8354 nt_forms_struct *list=NULL;
8355 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8357 DEBUG(5,("spoolss_addform\n"));
8360 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8365 /* forms can be added on printer of on the print server handle */
8367 if ( Printer->printer_type == SPLHND_PRINTER )
8369 if (!get_printer_snum(p,handle, &snum, NULL))
8372 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8373 if (!W_ERROR_IS_OK(status))
8377 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8378 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8379 status = WERR_ACCESS_DENIED;
8383 /* can't add if builtin */
8385 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8386 status = WERR_ALREADY_EXISTS;
8390 count = get_ntforms(&list);
8392 if(!add_a_form(&list, form, &count)) {
8393 status = WERR_NOMEM;
8397 write_ntforms(&list, count);
8400 * ChangeID must always be set if this is a printer
8403 if ( Printer->printer_type == SPLHND_PRINTER )
8404 status = mod_a_printer(printer, 2);
8408 free_a_printer(&printer, 2);
8414 /****************************************************************************
8415 ****************************************************************************/
8417 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8419 POLICY_HND *handle = &q_u->handle;
8420 UNISTR2 *form_name = &q_u->name;
8421 nt_forms_struct tmpForm;
8423 nt_forms_struct *list=NULL;
8424 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8426 WERROR status = WERR_OK;
8427 NT_PRINTER_INFO_LEVEL *printer = NULL;
8429 DEBUG(5,("spoolss_deleteform\n"));
8432 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8436 /* forms can be deleted on printer of on the print server handle */
8438 if ( Printer->printer_type == SPLHND_PRINTER )
8440 if (!get_printer_snum(p,handle, &snum, NULL))
8443 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8444 if (!W_ERROR_IS_OK(status))
8448 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8449 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8450 status = WERR_ACCESS_DENIED;
8454 /* can't delete if builtin */
8456 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8457 status = WERR_INVALID_PARAM;
8461 count = get_ntforms(&list);
8463 if ( !delete_a_form(&list, form_name, &count, &status ))
8467 * ChangeID must always be set if this is a printer
8470 if ( Printer->printer_type == SPLHND_PRINTER )
8471 status = mod_a_printer(printer, 2);
8475 free_a_printer(&printer, 2);
8481 /****************************************************************************
8482 ****************************************************************************/
8484 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8486 POLICY_HND *handle = &q_u->handle;
8487 FORM *form = &q_u->form;
8488 nt_forms_struct tmpForm;
8490 WERROR status = WERR_OK;
8491 NT_PRINTER_INFO_LEVEL *printer = NULL;
8494 nt_forms_struct *list=NULL;
8495 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8497 DEBUG(5,("spoolss_setform\n"));
8500 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8504 /* forms can be modified on printer of on the print server handle */
8506 if ( Printer->printer_type == SPLHND_PRINTER )
8508 if (!get_printer_snum(p,handle, &snum, NULL))
8511 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8512 if (!W_ERROR_IS_OK(status))
8516 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8517 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8518 status = WERR_ACCESS_DENIED;
8522 /* can't set if builtin */
8523 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8524 status = WERR_INVALID_PARAM;
8528 count = get_ntforms(&list);
8529 update_a_form(&list, form, count);
8530 write_ntforms(&list, count);
8533 * ChangeID must always be set if this is a printer
8536 if ( Printer->printer_type == SPLHND_PRINTER )
8537 status = mod_a_printer(printer, 2);
8542 free_a_printer(&printer, 2);
8548 /****************************************************************************
8549 enumprintprocessors level 1.
8550 ****************************************************************************/
8552 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8554 PRINTPROCESSOR_1 *info_1=NULL;
8555 WERROR result = WERR_OK;
8557 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8562 init_unistr(&info_1->name, "winprint");
8564 *needed += spoolss_size_printprocessor_info_1(info_1);
8566 if (*needed > offered) {
8567 result = WERR_INSUFFICIENT_BUFFER;
8571 if (!rpcbuf_alloc_size(buffer, *needed)) {
8572 result = WERR_NOMEM;
8576 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8581 if ( !W_ERROR_IS_OK(result) )
8587 /****************************************************************************
8588 ****************************************************************************/
8590 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8592 uint32 level = q_u->level;
8593 RPC_BUFFER *buffer = NULL;
8594 uint32 offered = q_u->offered;
8595 uint32 *needed = &r_u->needed;
8596 uint32 *returned = &r_u->returned;
8598 /* that's an [in out] buffer */
8600 if (!q_u->buffer && (offered!=0)) {
8601 return WERR_INVALID_PARAM;
8604 rpcbuf_move(q_u->buffer, &r_u->buffer);
8605 buffer = r_u->buffer;
8607 DEBUG(5,("spoolss_enumprintprocessors\n"));
8610 * Enumerate the print processors ...
8612 * Just reply with "winprint", to keep NT happy
8613 * and I can use my nice printer checker.
8621 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8623 return WERR_UNKNOWN_LEVEL;
8627 /****************************************************************************
8628 enumprintprocdatatypes level 1.
8629 ****************************************************************************/
8631 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8633 PRINTPROCDATATYPE_1 *info_1=NULL;
8634 WERROR result = WERR_OK;
8636 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8641 init_unistr(&info_1->name, "RAW");
8643 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8645 if (*needed > offered) {
8646 result = WERR_INSUFFICIENT_BUFFER;
8650 if (!rpcbuf_alloc_size(buffer, *needed)) {
8651 result = WERR_NOMEM;
8655 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8660 if ( !W_ERROR_IS_OK(result) )
8666 /****************************************************************************
8667 ****************************************************************************/
8669 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8671 uint32 level = q_u->level;
8672 RPC_BUFFER *buffer = NULL;
8673 uint32 offered = q_u->offered;
8674 uint32 *needed = &r_u->needed;
8675 uint32 *returned = &r_u->returned;
8677 /* that's an [in out] buffer */
8679 if (!q_u->buffer && (offered!=0)) {
8680 return WERR_INVALID_PARAM;
8683 rpcbuf_move(q_u->buffer, &r_u->buffer);
8684 buffer = r_u->buffer;
8686 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8693 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8695 return WERR_UNKNOWN_LEVEL;
8699 /****************************************************************************
8700 enumprintmonitors level 1.
8701 ****************************************************************************/
8703 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8705 PRINTMONITOR_1 *info_1;
8706 WERROR result = WERR_OK;
8709 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8714 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8715 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8717 for ( i=0; i<*returned; i++ ) {
8718 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8721 if (*needed > offered) {
8722 result = WERR_INSUFFICIENT_BUFFER;
8726 if (!rpcbuf_alloc_size(buffer, *needed)) {
8727 result = WERR_NOMEM;
8731 for ( i=0; i<*returned; i++ ) {
8732 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8738 if ( !W_ERROR_IS_OK(result) )
8744 /****************************************************************************
8745 enumprintmonitors level 2.
8746 ****************************************************************************/
8748 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8750 PRINTMONITOR_2 *info_2;
8751 WERROR result = WERR_OK;
8754 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8759 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8760 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8761 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8763 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8764 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8765 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8767 for ( i=0; i<*returned; i++ ) {
8768 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8771 if (*needed > offered) {
8772 result = WERR_INSUFFICIENT_BUFFER;
8776 if (!rpcbuf_alloc_size(buffer, *needed)) {
8777 result = WERR_NOMEM;
8781 for ( i=0; i<*returned; i++ ) {
8782 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8788 if ( !W_ERROR_IS_OK(result) )
8794 /****************************************************************************
8795 ****************************************************************************/
8797 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8799 uint32 level = q_u->level;
8800 RPC_BUFFER *buffer = NULL;
8801 uint32 offered = q_u->offered;
8802 uint32 *needed = &r_u->needed;
8803 uint32 *returned = &r_u->returned;
8805 /* that's an [in out] buffer */
8807 if (!q_u->buffer && (offered!=0)) {
8808 return WERR_INVALID_PARAM;
8811 rpcbuf_move(q_u->buffer, &r_u->buffer);
8812 buffer = r_u->buffer;
8814 DEBUG(5,("spoolss_enumprintmonitors\n"));
8817 * Enumerate the print monitors ...
8819 * Just reply with "Local Port", to keep NT happy
8820 * and I can use my nice printer checker.
8828 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8830 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8832 return WERR_UNKNOWN_LEVEL;
8836 /****************************************************************************
8837 ****************************************************************************/
8839 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8840 NT_PRINTER_INFO_LEVEL *ntprinter,
8841 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8846 JOB_INFO_1 *info_1=NULL;
8847 WERROR result = WERR_OK;
8849 info_1=SMB_MALLOC_P(JOB_INFO_1);
8851 if (info_1 == NULL) {
8855 for (i=0; i<count && found==False; i++) {
8856 if ((*queue)[i].job==(int)jobid)
8862 /* NT treats not found as bad param... yet another bad choice */
8863 return WERR_INVALID_PARAM;
8866 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8868 *needed += spoolss_size_job_info_1(info_1);
8870 if (*needed > offered) {
8871 result = WERR_INSUFFICIENT_BUFFER;
8875 if (!rpcbuf_alloc_size(buffer, *needed)) {
8876 result = WERR_NOMEM;
8880 smb_io_job_info_1("", buffer, info_1, 0);
8888 /****************************************************************************
8889 ****************************************************************************/
8891 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8892 NT_PRINTER_INFO_LEVEL *ntprinter,
8893 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8900 DEVICEMODE *devmode = NULL;
8901 NT_DEVICEMODE *nt_devmode = NULL;
8903 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8906 ZERO_STRUCTP(info_2);
8908 for ( i=0; i<count && found==False; i++ )
8910 if ((*queue)[i].job == (int)jobid)
8915 /* NT treats not found as bad param... yet another bad
8917 result = WERR_INVALID_PARAM;
8922 * if the print job does not have a DEVMODE associated with it,
8923 * just use the one for the printer. A NULL devicemode is not
8924 * a failure condition
8927 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8928 devmode = construct_dev_mode(lp_const_servicename(snum));
8930 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8931 ZERO_STRUCTP( devmode );
8932 convert_nt_devicemode( devmode, nt_devmode );
8936 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8938 *needed += spoolss_size_job_info_2(info_2);
8940 if (*needed > offered) {
8941 result = WERR_INSUFFICIENT_BUFFER;
8945 if (!rpcbuf_alloc_size(buffer, *needed)) {
8946 result = WERR_NOMEM;
8950 smb_io_job_info_2("", buffer, info_2, 0);
8955 /* Cleanup allocated memory */
8957 free_job_info_2(info_2); /* Also frees devmode */
8963 /****************************************************************************
8964 ****************************************************************************/
8966 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8968 POLICY_HND *handle = &q_u->handle;
8969 uint32 jobid = q_u->jobid;
8970 uint32 level = q_u->level;
8971 RPC_BUFFER *buffer = NULL;
8972 uint32 offered = q_u->offered;
8973 uint32 *needed = &r_u->needed;
8974 WERROR wstatus = WERR_OK;
8975 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8978 print_queue_struct *queue = NULL;
8979 print_status_struct prt_status;
8981 /* that's an [in out] buffer */
8983 if (!q_u->buffer && (offered!=0)) {
8984 return WERR_INVALID_PARAM;
8987 rpcbuf_move(q_u->buffer, &r_u->buffer);
8988 buffer = r_u->buffer;
8990 DEBUG(5,("spoolss_getjob\n"));
8994 if (!get_printer_snum(p, handle, &snum, NULL))
8997 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8998 if ( !W_ERROR_IS_OK(wstatus) )
9001 count = print_queue_status(snum, &queue, &prt_status);
9003 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9004 count, prt_status.status, prt_status.message));
9008 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9009 buffer, offered, needed);
9012 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9013 buffer, offered, needed);
9016 wstatus = WERR_UNKNOWN_LEVEL;
9021 free_a_printer( &ntprinter, 2 );
9026 /********************************************************************
9027 spoolss_getprinterdataex
9029 From MSDN documentation of GetPrinterDataEx: pass request
9030 to GetPrinterData if key is "PrinterDriverData".
9031 ********************************************************************/
9033 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9035 POLICY_HND *handle = &q_u->handle;
9036 uint32 in_size = q_u->size;
9037 uint32 *type = &r_u->type;
9038 uint32 *out_size = &r_u->size;
9039 uint8 **data = &r_u->data;
9040 uint32 *needed = &r_u->needed;
9041 fstring keyname, valuename;
9043 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9045 NT_PRINTER_INFO_LEVEL *printer = NULL;
9047 WERROR status = WERR_OK;
9049 DEBUG(4,("_spoolss_getprinterdataex\n"));
9051 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
9052 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
9054 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9055 keyname, valuename));
9057 /* in case of problem, return some default values */
9061 *out_size = in_size;
9064 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9065 status = WERR_BADFID;
9069 /* Is the handle to a printer or to the server? */
9071 if (Printer->printer_type == SPLHND_SERVER) {
9072 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9073 status = WERR_INVALID_PARAM;
9077 if ( !get_printer_snum(p,handle, &snum, NULL) )
9080 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9081 if ( !W_ERROR_IS_OK(status) )
9084 /* check to see if the keyname is valid */
9085 if ( !strlen(keyname) ) {
9086 status = WERR_INVALID_PARAM;
9090 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9091 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9092 free_a_printer( &printer, 2 );
9093 status = WERR_BADFILE;
9097 /* When given a new keyname, we should just create it */
9099 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9101 if (*needed > *out_size)
9102 status = WERR_MORE_DATA;
9105 if ( !W_ERROR_IS_OK(status) )
9107 DEBUG(5, ("error: allocating %d\n", *out_size));
9109 /* reply this param doesn't exist */
9113 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9114 status = WERR_NOMEM;
9124 free_a_printer( &printer, 2 );
9129 /********************************************************************
9130 * spoolss_setprinterdataex
9131 ********************************************************************/
9133 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9135 POLICY_HND *handle = &q_u->handle;
9136 uint32 type = q_u->type;
9137 uint8 *data = q_u->data;
9138 uint32 real_len = q_u->real_len;
9140 NT_PRINTER_INFO_LEVEL *printer = NULL;
9142 WERROR status = WERR_OK;
9143 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9148 DEBUG(4,("_spoolss_setprinterdataex\n"));
9150 /* From MSDN documentation of SetPrinterDataEx: pass request to
9151 SetPrinterData if key is "PrinterDriverData" */
9154 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9158 if ( Printer->printer_type == SPLHND_SERVER ) {
9159 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9160 return WERR_INVALID_PARAM;
9163 if ( !get_printer_snum(p,handle, &snum, NULL) )
9167 * Access check : NT returns "access denied" if you make a
9168 * SetPrinterData call without the necessary privildge.
9169 * we were originally returning OK if nothing changed
9170 * which made Win2k issue **a lot** of SetPrinterData
9171 * when connecting to a printer --jerry
9174 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9176 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9177 return WERR_ACCESS_DENIED;
9180 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9181 if (!W_ERROR_IS_OK(status))
9184 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9185 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9187 /* check for OID in valuename */
9189 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9195 /* save the registry data */
9197 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9199 if ( W_ERROR_IS_OK(status) )
9201 /* save the OID if one was specified */
9203 fstrcat( keyname, "\\" );
9204 fstrcat( keyname, SPOOL_OID_KEY );
9207 * I'm not checking the status here on purpose. Don't know
9208 * if this is right, but I'm returning the status from the
9209 * previous set_printer_dataex() call. I have no idea if
9210 * this is right. --jerry
9213 set_printer_dataex( printer, keyname, valuename,
9214 REG_SZ, (uint8 *)oid_string,
9215 strlen(oid_string)+1 );
9218 status = mod_a_printer(printer, 2);
9221 free_a_printer(&printer, 2);
9227 /********************************************************************
9228 * spoolss_deleteprinterdataex
9229 ********************************************************************/
9231 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9233 POLICY_HND *handle = &q_u->handle;
9234 UNISTR2 *value = &q_u->valuename;
9235 UNISTR2 *key = &q_u->keyname;
9237 NT_PRINTER_INFO_LEVEL *printer = NULL;
9239 WERROR status = WERR_OK;
9240 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9241 pstring valuename, keyname;
9243 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9246 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9250 if (!get_printer_snum(p, handle, &snum, NULL))
9253 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9254 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9255 return WERR_ACCESS_DENIED;
9258 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9259 if (!W_ERROR_IS_OK(status))
9262 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9263 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9265 status = delete_printer_dataex( printer, keyname, valuename );
9267 if ( W_ERROR_IS_OK(status) )
9268 mod_a_printer( printer, 2 );
9270 free_a_printer(&printer, 2);
9275 /********************************************************************
9276 * spoolss_enumprinterkey
9277 ********************************************************************/
9280 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9283 fstring *keynames = NULL;
9284 uint16 *enumkeys = NULL;
9287 POLICY_HND *handle = &q_u->handle;
9288 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9289 NT_PRINTER_DATA *data;
9290 NT_PRINTER_INFO_LEVEL *printer = NULL;
9292 WERROR status = WERR_BADFILE;
9295 DEBUG(4,("_spoolss_enumprinterkey\n"));
9298 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9302 if ( !get_printer_snum(p,handle, &snum, NULL) )
9305 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9306 if (!W_ERROR_IS_OK(status))
9309 /* get the list of subkey names */
9311 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9312 data = printer->info_2->data;
9314 num_keys = get_printer_subkeys( data, key, &keynames );
9316 if ( num_keys == -1 ) {
9317 status = WERR_BADFILE;
9321 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9323 r_u->needed = printerkey_len*2;
9325 if ( q_u->size < r_u->needed ) {
9326 status = WERR_MORE_DATA;
9330 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9331 status = WERR_NOMEM;
9337 if ( q_u->size < r_u->needed )
9338 status = WERR_MORE_DATA;
9341 free_a_printer( &printer, 2 );
9342 SAFE_FREE( keynames );
9347 /********************************************************************
9348 * spoolss_deleteprinterkey
9349 ********************************************************************/
9351 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9353 POLICY_HND *handle = &q_u->handle;
9354 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9356 NT_PRINTER_INFO_LEVEL *printer = NULL;
9360 DEBUG(5,("spoolss_deleteprinterkey\n"));
9363 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9367 /* if keyname == NULL, return error */
9369 if ( !q_u->keyname.buffer )
9370 return WERR_INVALID_PARAM;
9372 if (!get_printer_snum(p, handle, &snum, NULL))
9375 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9376 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9377 return WERR_ACCESS_DENIED;
9380 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9381 if (!W_ERROR_IS_OK(status))
9384 /* delete the key and all subneys */
9386 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9388 status = delete_all_printer_data( printer->info_2, key );
9390 if ( W_ERROR_IS_OK(status) )
9391 status = mod_a_printer(printer, 2);
9393 free_a_printer( &printer, 2 );
9399 /********************************************************************
9400 * spoolss_enumprinterdataex
9401 ********************************************************************/
9403 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9405 POLICY_HND *handle = &q_u->handle;
9406 uint32 in_size = q_u->size;
9409 NT_PRINTER_INFO_LEVEL *printer = NULL;
9410 PRINTER_ENUM_VALUES *enum_values = NULL;
9411 NT_PRINTER_DATA *p_data;
9413 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9418 REGISTRY_VALUE *val;
9423 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9426 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9431 * first check for a keyname of NULL or "". Win2k seems to send
9432 * this a lot and we should send back WERR_INVALID_PARAM
9433 * no need to spend time looking up the printer in this case.
9437 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9438 if ( !strlen(key) ) {
9439 result = WERR_INVALID_PARAM;
9443 /* get the printer off of disk */
9445 if (!get_printer_snum(p,handle, &snum, NULL))
9448 ZERO_STRUCT(printer);
9449 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9450 if (!W_ERROR_IS_OK(result))
9453 /* now look for a match on the key name */
9455 p_data = printer->info_2->data;
9457 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9458 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9460 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9461 result = WERR_INVALID_PARAM;
9468 /* allocate the memory for the array of pointers -- if necessary */
9470 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9473 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9475 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9476 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9477 result = WERR_NOMEM;
9481 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9485 * loop through all params and build the array to pass
9486 * back to the client
9489 for ( i=0; i<num_entries; i++ )
9491 /* lookup the registry value */
9493 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9494 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9498 value_name = regval_name( val );
9499 init_unistr( &enum_values[i].valuename, value_name );
9500 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9501 enum_values[i].type = regval_type( val );
9503 data_len = regval_size( val );
9505 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9507 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9509 result = WERR_NOMEM;
9513 enum_values[i].data_len = data_len;
9515 /* keep track of the size of the array in bytes */
9517 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9520 /* housekeeping information in the reply */
9522 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9523 * the hand marshalled container size is a multiple
9524 * of 4 bytes for RPC alignment.
9528 needed += 4-(needed % 4);
9531 r_u->needed = needed;
9532 r_u->returned = num_entries;
9534 if (needed > in_size) {
9535 result = WERR_MORE_DATA;
9539 /* copy data into the reply */
9541 r_u->ctr.size = r_u->needed;
9543 r_u->ctr.size_of_array = r_u->returned;
9544 r_u->ctr.values = enum_values;
9550 free_a_printer(&printer, 2);
9555 /****************************************************************************
9556 ****************************************************************************/
9558 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9560 init_unistr(&info->name, name);
9563 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9564 UNISTR2 *environment,
9571 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9572 WERROR result = WERR_OK;
9574 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9576 if (!get_short_archi(long_archi))
9577 return WERR_INVALID_ENVIRONMENT;
9579 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9582 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9584 fill_printprocessordirectory_1(info, path);
9586 *needed += spoolss_size_printprocessordirectory_info_1(info);
9588 if (*needed > offered) {
9589 result = WERR_INSUFFICIENT_BUFFER;
9593 if (!rpcbuf_alloc_size(buffer, *needed)) {
9594 result = WERR_INSUFFICIENT_BUFFER;
9598 smb_io_printprocessordirectory_1("", buffer, info, 0);
9606 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9608 uint32 level = q_u->level;
9609 RPC_BUFFER *buffer = NULL;
9610 uint32 offered = q_u->offered;
9611 uint32 *needed = &r_u->needed;
9614 /* that's an [in out] buffer */
9616 if (!q_u->buffer && (offered!=0)) {
9617 return WERR_INVALID_PARAM;
9620 rpcbuf_move(q_u->buffer, &r_u->buffer);
9621 buffer = r_u->buffer;
9623 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9629 result = getprintprocessordirectory_level_1
9630 (&q_u->name, &q_u->environment, buffer, offered, needed);
9633 result = WERR_UNKNOWN_LEVEL;
9639 /*******************************************************************
9640 Streams the monitor UI DLL name in UNICODE
9641 *******************************************************************/
9643 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9644 RPC_BUFFER *out, uint32 *needed )
9646 const char *dllname = "tcpmonui.dll";
9648 *needed = (strlen(dllname)+1) * 2;
9650 if ( rpcbuf_get_size(out) < *needed ) {
9651 return WERR_INSUFFICIENT_BUFFER;
9654 if ( !make_monitorui_buf( out, dllname ) ) {
9661 /*******************************************************************
9662 Create a new TCP/IP port
9663 *******************************************************************/
9665 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9666 RPC_BUFFER *out, uint32 *needed )
9668 NT_PORT_DATA_1 port1;
9671 ZERO_STRUCT( port1 );
9673 /* convert to our internal port data structure */
9675 if ( !convert_port_data_1( &port1, in ) ) {
9679 /* create the device URI and call the add_port_hook() */
9681 switch ( port1.protocol ) {
9682 case PORT_PROTOCOL_DIRECT:
9683 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9686 case PORT_PROTOCOL_LPR:
9687 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9691 return WERR_UNKNOWN_PORT;
9694 return add_port_hook( token, port1.name, device_uri );
9697 /*******************************************************************
9698 *******************************************************************/
9700 struct xcv_api_table xcvtcp_cmds[] = {
9701 { "MonitorUI", xcvtcp_monitorui },
9702 { "AddPort", xcvtcp_addport},
9706 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9707 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9712 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9714 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9715 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9716 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9719 return WERR_BADFUNC;
9722 /*******************************************************************
9723 *******************************************************************/
9724 #if 0 /* don't support management using the "Local Port" monitor */
9726 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9727 RPC_BUFFER *out, uint32 *needed )
9729 const char *dllname = "localui.dll";
9731 *needed = (strlen(dllname)+1) * 2;
9733 if ( rpcbuf_get_size(out) < *needed ) {
9734 return WERR_INSUFFICIENT_BUFFER;
9737 if ( !make_monitorui_buf( out, dllname )) {
9744 /*******************************************************************
9745 *******************************************************************/
9747 struct xcv_api_table xcvlocal_cmds[] = {
9748 { "MonitorUI", xcvlocal_monitorui },
9752 struct xcv_api_table xcvlocal_cmds[] = {
9759 /*******************************************************************
9760 *******************************************************************/
9762 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9763 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9768 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9770 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9771 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9772 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9774 return WERR_BADFUNC;
9777 /*******************************************************************
9778 *******************************************************************/
9780 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9782 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9786 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9790 /* Has to be a handle to the TCP/IP port monitor */
9792 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9793 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9797 /* requires administrative access to the server */
9799 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9800 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9801 return WERR_ACCESS_DENIED;
9804 /* Get the command name. There's numerous commands supported by the
9805 TCPMON interface. */
9807 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9808 q_u->dataname.uni_str_len*2, 0);
9810 /* Allocate the outgoing buffer */
9812 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9814 switch ( Printer->printer_type ) {
9815 case SPLHND_PORTMON_TCP:
9816 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9817 &q_u->indata, &r_u->outdata, &r_u->needed );
9818 case SPLHND_PORTMON_LOCAL:
9819 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9820 &q_u->indata, &r_u->outdata, &r_u->needed );
9823 return WERR_INVALID_PRINT_MONITOR;