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 if (prs_offset(&ps)) {
727 data->notify_data.data.string = (uint16 *)
728 TALLOC(mem_ctx, prs_offset(&ps));
729 if (!data->notify_data.data.string) {
733 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
735 data->notify_data.data.string = NULL;
741 struct notify2_message_table {
743 void (*fn)(struct spoolss_notify_msg *msg,
744 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
747 static struct notify2_message_table printer_notify_table[] = {
748 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
749 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
750 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
751 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
752 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
753 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
754 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
755 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
756 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
757 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
758 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
759 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
760 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
761 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
762 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
763 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
764 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
765 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
766 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
769 static struct notify2_message_table job_notify_table[] = {
770 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
771 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
772 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
773 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
774 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
775 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
776 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
777 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
778 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
779 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
780 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
781 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
782 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
783 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
784 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
785 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
786 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
787 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
788 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
789 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
790 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
791 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
792 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
793 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
797 /***********************************************************************
798 Allocate talloc context for container object
799 **********************************************************************/
801 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
806 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
811 /***********************************************************************
812 release all allocated memory and zero out structure
813 **********************************************************************/
815 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
821 talloc_destroy(ctr->ctx);
828 /***********************************************************************
829 **********************************************************************/
831 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
839 /***********************************************************************
840 **********************************************************************/
842 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
844 if ( !ctr || !ctr->msg_groups )
847 if ( idx >= ctr->num_groups )
850 return &ctr->msg_groups[idx];
854 /***********************************************************************
855 How many groups of change messages do we have ?
856 **********************************************************************/
858 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
863 return ctr->num_groups;
866 /***********************************************************************
867 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
868 **********************************************************************/
870 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
872 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
873 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
874 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
880 /* loop over all groups looking for a matching printer name */
882 for ( i=0; i<ctr->num_groups; i++ ) {
883 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
887 /* add a new group? */
889 if ( i == ctr->num_groups ) {
892 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
893 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
896 ctr->msg_groups = groups;
898 /* clear the new entry and set the printer name */
900 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
901 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
904 /* add the change messages; 'i' is the correct index now regardless */
906 msg_grp = &ctr->msg_groups[i];
910 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
911 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
914 msg_grp->msgs = msg_list;
916 new_slot = msg_grp->num_msgs-1;
917 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
919 /* need to allocate own copy of data */
922 msg_grp->msgs[new_slot].notify.data = (char *)
923 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
925 return ctr->num_groups;
928 /***********************************************************************
929 Send a change notication message on all handles which have a call
931 **********************************************************************/
933 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
936 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
937 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
938 SPOOLSS_NOTIFY_MSG *messages;
939 int sending_msg_count;
942 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
946 messages = msg_group->msgs;
949 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
953 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
955 /* loop over all printers */
957 for (p = printers_list; p; p = p->next) {
958 SPOOL_NOTIFY_INFO_DATA *data;
963 /* Is there notification on this handle? */
965 if ( !p->notify.client_connected )
968 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
970 /* For this printer? Print servers always receive
973 if ( ( p->printer_type == SPLHND_PRINTER ) &&
974 ( !strequal(msg_group->printername, p->sharename) ) )
977 DEBUG(10,("Our printer\n"));
979 /* allocate the max entries possible */
981 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
988 /* build the array of change notifications */
990 sending_msg_count = 0;
992 for ( i=0; i<msg_group->num_msgs; i++ ) {
993 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
995 /* Are we monitoring this event? */
997 if (!is_monitoring_event(p, msg->type, msg->field))
1000 sending_msg_count++;
1003 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1004 msg->type, msg->field, p->sharename));
1007 * if the is a printer notification handle and not a job notification
1008 * type, then set the id to 0. Other wise just use what was specified
1011 * When registering change notification on a print server handle
1012 * we always need to send back the id (snum) matching the printer
1013 * for which the change took place. For change notify registered
1014 * on a printer handle, this does not matter and the id should be 0.
1019 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1025 /* Convert unix jobid to smb jobid */
1027 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1028 id = sysjob_to_jobid(msg->id);
1031 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1036 construct_info_data( &data[data_len], msg->type, msg->field, id );
1039 case PRINTER_NOTIFY_TYPE:
1040 if ( printer_notify_table[msg->field].fn )
1041 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1044 case JOB_NOTIFY_TYPE:
1045 if ( job_notify_table[msg->field].fn )
1046 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1050 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1057 if ( sending_msg_count ) {
1058 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1059 data_len, data, p->notify.change, 0 );
1064 DEBUG(8,("send_notify2_changes: Exit...\n"));
1068 /***********************************************************************
1069 **********************************************************************/
1071 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1074 uint32 tv_sec, tv_usec;
1077 /* Unpack message */
1079 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1082 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1084 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1087 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1088 &msg->notify.value[0], &msg->notify.value[1]);
1090 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1091 &msg->len, &msg->notify.data);
1093 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1094 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1096 tv->tv_sec = tv_sec;
1097 tv->tv_usec = tv_usec;
1100 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1101 msg->notify.value[1]));
1103 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1108 /********************************************************************
1109 Receive a notify2 message list
1110 ********************************************************************/
1112 static void receive_notify2_message_list(int msg_type, struct server_id src,
1113 void *msg, size_t len,
1116 size_t msg_count, i;
1117 char *buf = (char *)msg;
1120 SPOOLSS_NOTIFY_MSG notify;
1121 SPOOLSS_NOTIFY_MSG_CTR messages;
1125 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1129 msg_count = IVAL(buf, 0);
1132 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1134 if (msg_count == 0) {
1135 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1139 /* initialize the container */
1141 ZERO_STRUCT( messages );
1142 notify_msg_ctr_init( &messages );
1145 * build message groups for each printer identified
1146 * in a change_notify msg. Remember that a PCN message
1147 * includes the handle returned for the srv_spoolss_replyopenprinter()
1148 * call. Therefore messages are grouped according to printer handle.
1151 for ( i=0; i<msg_count; i++ ) {
1152 struct timeval msg_tv;
1154 if (msg_ptr + 4 - buf > len) {
1155 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1159 msg_len = IVAL(msg_ptr,0);
1162 if (msg_ptr + msg_len - buf > len) {
1163 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1167 /* unpack messages */
1169 ZERO_STRUCT( notify );
1170 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1173 /* add to correct list in container */
1175 notify_msg_ctr_addmsg( &messages, ¬ify );
1177 /* free memory that might have been allocated by notify2_unpack_msg() */
1179 if ( notify.len != 0 )
1180 SAFE_FREE( notify.notify.data );
1183 /* process each group of messages */
1185 num_groups = notify_msg_ctr_numgroups( &messages );
1186 for ( i=0; i<num_groups; i++ )
1187 send_notify2_changes( &messages, i );
1192 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1194 notify_msg_ctr_destroy( &messages );
1199 /********************************************************************
1200 Send a message to ourself about new driver being installed
1201 so we can upgrade the information for each printer bound to this
1203 ********************************************************************/
1205 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1207 int len = strlen(drivername);
1212 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1215 message_send_pid(pid_to_procid(sys_getpid()),
1216 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1221 /**********************************************************************
1222 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1223 over all printers, upgrading ones as necessary
1224 **********************************************************************/
1226 void do_drv_upgrade_printer(int msg_type, struct server_id src,
1227 void *buf, size_t len, void *private_data)
1231 int n_services = lp_numservices();
1233 len = MIN(len,sizeof(drivername)-1);
1234 strncpy(drivername, (const char *)buf, len);
1236 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1238 /* Iterate the printer list */
1240 for (snum=0; snum<n_services; snum++)
1242 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1245 NT_PRINTER_INFO_LEVEL *printer = NULL;
1247 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1248 if (!W_ERROR_IS_OK(result))
1251 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1253 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1255 /* all we care about currently is the change_id */
1257 result = mod_a_printer(printer, 2);
1258 if (!W_ERROR_IS_OK(result)) {
1259 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1260 dos_errstr(result)));
1264 free_a_printer(&printer, 2);
1271 /********************************************************************
1272 Update the cache for all printq's with a registered client
1274 ********************************************************************/
1276 void update_monitored_printq_cache( void )
1278 Printer_entry *printer = printers_list;
1281 /* loop through all printers and update the cache where
1282 client_connected == True */
1285 if ( (printer->printer_type == SPLHND_PRINTER)
1286 && printer->notify.client_connected )
1288 snum = print_queue_snum(printer->sharename);
1289 print_queue_status( snum, NULL, NULL );
1292 printer = printer->next;
1297 /********************************************************************
1298 Send a message to ourself about new driver being installed
1299 so we can upgrade the information for each printer bound to this
1301 ********************************************************************/
1303 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1305 int len = strlen(drivername);
1310 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1313 message_send_pid(pid_to_procid(sys_getpid()),
1314 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1319 /**********************************************************************
1320 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1321 over all printers, resetting printer data as neessary
1322 **********************************************************************/
1324 void reset_all_printerdata(int msg_type, struct server_id src,
1325 void *buf, size_t len, void *private_data)
1329 int n_services = lp_numservices();
1331 len = MIN( len, sizeof(drivername)-1 );
1332 strncpy( drivername, (const char *)buf, len );
1334 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1336 /* Iterate the printer list */
1338 for ( snum=0; snum<n_services; snum++ )
1340 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1343 NT_PRINTER_INFO_LEVEL *printer = NULL;
1345 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1346 if ( !W_ERROR_IS_OK(result) )
1350 * if the printer is bound to the driver,
1351 * then reset to the new driver initdata
1354 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1356 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1358 if ( !set_driver_init(printer, 2) ) {
1359 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1360 printer->info_2->printername, printer->info_2->drivername));
1363 result = mod_a_printer( printer, 2 );
1364 if ( !W_ERROR_IS_OK(result) ) {
1365 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1366 get_dos_error_msg(result)));
1370 free_a_printer( &printer, 2 );
1379 /********************************************************************
1380 Copy routines used by convert_to_openprinterex()
1381 *******************************************************************/
1383 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1391 DEBUG (8,("dup_devmode\n"));
1393 /* bulk copy first */
1395 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1399 /* dup the pointer members separately */
1401 len = unistrlen(devmode->devicename.buffer);
1403 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1404 if (!d->devicename.buffer) {
1407 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1412 len = unistrlen(devmode->formname.buffer);
1414 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1415 if (!d->devicename.buffer) {
1418 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1422 if (devmode->driverextra) {
1423 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1424 devmode->driverextra);
1425 if (!d->dev_private) {
1429 d->dev_private = NULL;
1434 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1436 if (!new_ctr || !ctr)
1439 DEBUG(8,("copy_devmode_ctr\n"));
1441 new_ctr->size = ctr->size;
1442 new_ctr->devmode_ptr = ctr->devmode_ptr;
1444 if(ctr->devmode_ptr)
1445 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1448 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1450 if (!new_def || !def)
1453 DEBUG(8,("copy_printer_defaults\n"));
1455 new_def->datatype_ptr = def->datatype_ptr;
1457 if (def->datatype_ptr)
1458 copy_unistr2(&new_def->datatype, &def->datatype);
1460 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1462 new_def->access_required = def->access_required;
1465 /********************************************************************
1466 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1467 * SPOOL_Q_OPEN_PRINTER_EX structure
1468 ********************************************************************/
1470 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1472 if (!q_u_ex || !q_u)
1475 DEBUG(8,("convert_to_openprinterex\n"));
1477 if ( q_u->printername ) {
1478 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1479 if (q_u_ex->printername == NULL)
1481 copy_unistr2(q_u_ex->printername, q_u->printername);
1484 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1489 /********************************************************************
1490 * spoolss_open_printer
1492 * called from the spoolss dispatcher
1493 ********************************************************************/
1495 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1497 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1498 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1503 ZERO_STRUCT(q_u_ex);
1504 ZERO_STRUCT(r_u_ex);
1506 /* convert the OpenPrinter() call to OpenPrinterEx() */
1508 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1509 if (!W_ERROR_IS_OK(r_u_ex.status))
1510 return r_u_ex.status;
1512 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1514 /* convert back to OpenPrinter() */
1516 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1521 /********************************************************************
1522 ********************************************************************/
1524 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1526 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1527 POLICY_HND *handle = &r_u->handle;
1531 Printer_entry *Printer=NULL;
1533 if ( !q_u->printername )
1534 return WERR_INVALID_PRINTER_NAME;
1536 /* some sanity check because you can open a printer or a print server */
1537 /* aka: \\server\printer or \\server */
1539 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1541 DEBUGADD(3,("checking name: %s\n",name));
1543 if (!open_printer_hnd(p, handle, name, 0))
1544 return WERR_INVALID_PRINTER_NAME;
1546 Printer=find_printer_index_by_hnd(p, handle);
1548 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1549 "handle we created for printer %s\n", name ));
1550 close_printer_handle(p,handle);
1551 return WERR_INVALID_PRINTER_NAME;
1555 * First case: the user is opening the print server:
1557 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1558 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1560 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1561 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1562 * or if the user is listed in the smb.conf printer admin parameter.
1564 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1565 * client view printer folder, but does not show the MSAPW.
1567 * Note: this test needs code to check access rights here too. Jeremy
1568 * could you look at this?
1570 * Second case: the user is opening a printer:
1571 * NT doesn't let us connect to a printer if the connecting user
1572 * doesn't have print permission.
1574 * Third case: user is opening a Port Monitor
1575 * access checks same as opening a handle to the print server.
1578 switch (Printer->printer_type )
1581 case SPLHND_PORTMON_TCP:
1582 case SPLHND_PORTMON_LOCAL:
1583 /* Printserver handles use global struct... */
1587 /* Map standard access rights to object specific access rights */
1589 se_map_standard(&printer_default->access_required,
1590 &printserver_std_mapping);
1592 /* Deny any object specific bits that don't apply to print
1593 servers (i.e printer and job specific bits) */
1595 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1597 if (printer_default->access_required &
1598 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1599 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1600 close_printer_handle(p, handle);
1601 return WERR_ACCESS_DENIED;
1604 /* Allow admin access */
1606 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1608 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1610 if (!lp_ms_add_printer_wizard()) {
1611 close_printer_handle(p, handle);
1612 return WERR_ACCESS_DENIED;
1615 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1616 and not a printer admin, then fail */
1618 if ((p->pipe_user.ut.uid != 0) &&
1619 !user_has_privileges(p->pipe_user.nt_user_token,
1621 !token_contains_name_in_list(
1622 uidtoname(p->pipe_user.ut.uid), NULL,
1623 p->pipe_user.nt_user_token,
1624 lp_printer_admin(snum))) {
1625 close_printer_handle(p, handle);
1626 return WERR_ACCESS_DENIED;
1629 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1633 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1636 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1637 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1639 /* We fall through to return WERR_OK */
1642 case SPLHND_PRINTER:
1643 /* NT doesn't let us connect to a printer if the connecting user
1644 doesn't have print permission. */
1646 if (!get_printer_snum(p, handle, &snum, NULL)) {
1647 close_printer_handle(p, handle);
1651 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1653 /* map an empty access mask to the minimum access mask */
1654 if (printer_default->access_required == 0x0)
1655 printer_default->access_required = PRINTER_ACCESS_USE;
1658 * If we are not serving the printer driver for this printer,
1659 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1660 * will keep NT clients happy --jerry
1663 if (lp_use_client_driver(snum)
1664 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1666 printer_default->access_required = PRINTER_ACCESS_USE;
1669 /* check smb.conf parameters and the the sec_desc */
1671 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1672 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1673 return WERR_ACCESS_DENIED;
1676 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1677 p->pipe_user.nt_user_token, snum) ||
1678 !print_access_check(&p->pipe_user, snum,
1679 printer_default->access_required)) {
1680 DEBUG(3, ("access DENIED for printer open\n"));
1681 close_printer_handle(p, handle);
1682 return WERR_ACCESS_DENIED;
1685 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1686 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1687 close_printer_handle(p, handle);
1688 return WERR_ACCESS_DENIED;
1691 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1692 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1694 printer_default->access_required = PRINTER_ACCESS_USE;
1696 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1697 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1702 /* sanity check to prevent programmer error */
1706 Printer->access_granted = printer_default->access_required;
1709 * If the client sent a devmode in the OpenPrinter() call, then
1710 * save it here in case we get a job submission on this handle
1713 if ( (Printer->printer_type != SPLHND_SERVER)
1714 && q_u->printer_default.devmode_cont.devmode_ptr )
1716 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1717 &Printer->nt_devmode );
1720 #if 0 /* JERRY -- I'm doubtful this is really effective */
1721 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1722 optimization in Windows 2000 clients --jerry */
1724 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1725 && (RA_WIN2K == get_remote_arch()) )
1727 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1728 sys_usleep( 500000 );
1735 /****************************************************************************
1736 ****************************************************************************/
1738 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1739 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1745 /* allocate memory if needed. Messy because
1746 convert_printer_info is used to update an existing
1747 printer or build a new one */
1749 if ( !printer->info_2 ) {
1750 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1751 if ( !printer->info_2 ) {
1752 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1757 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1758 printer->info_2->setuptime = time(NULL);
1766 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1767 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1773 printer->info_3=NULL;
1774 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1778 printer->info_6=NULL;
1779 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1789 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1790 NT_DEVICEMODE **pp_nt_devmode)
1792 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1795 * Ensure nt_devmode is a valid pointer
1796 * as we will be overwriting it.
1799 if (nt_devmode == NULL) {
1800 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1801 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1805 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1806 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1808 nt_devmode->specversion=devmode->specversion;
1809 nt_devmode->driverversion=devmode->driverversion;
1810 nt_devmode->size=devmode->size;
1811 nt_devmode->fields=devmode->fields;
1812 nt_devmode->orientation=devmode->orientation;
1813 nt_devmode->papersize=devmode->papersize;
1814 nt_devmode->paperlength=devmode->paperlength;
1815 nt_devmode->paperwidth=devmode->paperwidth;
1816 nt_devmode->scale=devmode->scale;
1817 nt_devmode->copies=devmode->copies;
1818 nt_devmode->defaultsource=devmode->defaultsource;
1819 nt_devmode->printquality=devmode->printquality;
1820 nt_devmode->color=devmode->color;
1821 nt_devmode->duplex=devmode->duplex;
1822 nt_devmode->yresolution=devmode->yresolution;
1823 nt_devmode->ttoption=devmode->ttoption;
1824 nt_devmode->collate=devmode->collate;
1826 nt_devmode->logpixels=devmode->logpixels;
1827 nt_devmode->bitsperpel=devmode->bitsperpel;
1828 nt_devmode->pelswidth=devmode->pelswidth;
1829 nt_devmode->pelsheight=devmode->pelsheight;
1830 nt_devmode->displayflags=devmode->displayflags;
1831 nt_devmode->displayfrequency=devmode->displayfrequency;
1832 nt_devmode->icmmethod=devmode->icmmethod;
1833 nt_devmode->icmintent=devmode->icmintent;
1834 nt_devmode->mediatype=devmode->mediatype;
1835 nt_devmode->dithertype=devmode->dithertype;
1836 nt_devmode->reserved1=devmode->reserved1;
1837 nt_devmode->reserved2=devmode->reserved2;
1838 nt_devmode->panningwidth=devmode->panningwidth;
1839 nt_devmode->panningheight=devmode->panningheight;
1842 * Only change private and driverextra if the incoming devmode
1843 * has a new one. JRA.
1846 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1847 SAFE_FREE(nt_devmode->nt_dev_private);
1848 nt_devmode->driverextra=devmode->driverextra;
1849 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1851 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1854 *pp_nt_devmode = nt_devmode;
1859 /********************************************************************
1860 * _spoolss_enddocprinter_internal.
1861 ********************************************************************/
1863 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1865 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1869 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1873 if (!get_printer_snum(p, handle, &snum, NULL))
1876 Printer->document_started=False;
1877 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1878 /* error codes unhandled so far ... */
1883 /********************************************************************
1884 * api_spoolss_closeprinter
1885 ********************************************************************/
1887 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1889 POLICY_HND *handle = &q_u->handle;
1891 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1893 if (Printer && Printer->document_started)
1894 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1896 if (!close_printer_handle(p, handle))
1899 /* clear the returned printer handle. Observed behavior
1900 from Win2k server. Don't think this really matters.
1901 Previous code just copied the value of the closed
1904 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1909 /********************************************************************
1910 * api_spoolss_deleteprinter
1912 ********************************************************************/
1914 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1916 POLICY_HND *handle = &q_u->handle;
1917 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1920 if (Printer && Printer->document_started)
1921 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1923 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1925 result = delete_printer_handle(p, handle);
1927 update_c_setprinter(False);
1932 /*******************************************************************
1933 * static function to lookup the version id corresponding to an
1934 * long architecture string
1935 ******************************************************************/
1937 static int get_version_id (char * arch)
1940 struct table_node archi_table[]= {
1942 {"Windows 4.0", "WIN40", 0 },
1943 {"Windows NT x86", "W32X86", 2 },
1944 {"Windows NT R4000", "W32MIPS", 2 },
1945 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1946 {"Windows NT PowerPC", "W32PPC", 2 },
1947 {"Windows IA64", "IA64", 3 },
1948 {"Windows x64", "x64", 3 },
1952 for (i=0; archi_table[i].long_archi != NULL; i++)
1954 if (strcmp(arch, archi_table[i].long_archi) == 0)
1955 return (archi_table[i].version);
1961 /********************************************************************
1962 * _spoolss_deleteprinterdriver
1963 ********************************************************************/
1965 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1969 NT_PRINTER_DRIVER_INFO_LEVEL info;
1970 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1973 WERROR status_win2k = WERR_ACCESS_DENIED;
1974 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1976 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1977 and not a printer admin, then fail */
1979 if ( (p->pipe_user.ut.uid != 0)
1980 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
1981 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
1982 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
1984 return WERR_ACCESS_DENIED;
1987 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1988 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1990 /* check that we have a valid driver name first */
1992 if ((version=get_version_id(arch)) == -1)
1993 return WERR_INVALID_ENVIRONMENT;
1996 ZERO_STRUCT(info_win2k);
1998 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2000 /* try for Win2k driver if "Windows NT x86" */
2002 if ( version == 2 ) {
2004 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2005 status = WERR_UNKNOWN_PRINTER_DRIVER;
2009 /* otherwise it was a failure */
2011 status = WERR_UNKNOWN_PRINTER_DRIVER;
2017 if (printer_driver_in_use(info.info_3)) {
2018 status = WERR_PRINTER_DRIVER_IN_USE;
2024 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2026 /* if we get to here, we now have 2 driver info structures to remove */
2027 /* remove the Win2k driver first*/
2029 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2030 free_a_printer_driver( info_win2k, 3 );
2032 /* this should not have failed---if it did, report to client */
2033 if ( !W_ERROR_IS_OK(status_win2k) )
2035 status = status_win2k;
2041 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2043 /* if at least one of the deletes succeeded return OK */
2045 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2049 free_a_printer_driver( info, 3 );
2054 /********************************************************************
2055 * spoolss_deleteprinterdriverex
2056 ********************************************************************/
2058 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2062 NT_PRINTER_DRIVER_INFO_LEVEL info;
2063 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2065 uint32 flags = q_u->delete_flags;
2068 WERROR status_win2k = WERR_ACCESS_DENIED;
2069 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2071 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2072 and not a printer admin, then fail */
2074 if ( (p->pipe_user.ut.uid != 0)
2075 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2076 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2077 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2079 return WERR_ACCESS_DENIED;
2082 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2083 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2085 /* check that we have a valid driver name first */
2086 if ((version=get_version_id(arch)) == -1) {
2087 /* this is what NT returns */
2088 return WERR_INVALID_ENVIRONMENT;
2091 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2092 version = q_u->version;
2095 ZERO_STRUCT(info_win2k);
2097 status = get_a_printer_driver(&info, 3, driver, arch, version);
2099 if ( !W_ERROR_IS_OK(status) )
2102 * if the client asked for a specific version,
2103 * or this is something other than Windows NT x86,
2107 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2110 /* try for Win2k driver if "Windows NT x86" */
2113 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2114 status = WERR_UNKNOWN_PRINTER_DRIVER;
2119 if ( printer_driver_in_use(info.info_3) ) {
2120 status = WERR_PRINTER_DRIVER_IN_USE;
2125 * we have a couple of cases to consider.
2126 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2127 * then the delete should fail if **any** files overlap with
2129 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2130 * non-overlapping files
2131 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2132 * is set, the do not delete any files
2133 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2136 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2138 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2140 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2141 /* no idea of the correct error here */
2142 status = WERR_ACCESS_DENIED;
2147 /* also check for W32X86/3 if necessary; maybe we already have? */
2149 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2150 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2153 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2154 /* no idea of the correct error here */
2155 free_a_printer_driver( info_win2k, 3 );
2156 status = WERR_ACCESS_DENIED;
2160 /* if we get to here, we now have 2 driver info structures to remove */
2161 /* remove the Win2k driver first*/
2163 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2164 free_a_printer_driver( info_win2k, 3 );
2166 /* this should not have failed---if it did, report to client */
2168 if ( !W_ERROR_IS_OK(status_win2k) )
2173 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2175 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2178 free_a_printer_driver( info, 3 );
2184 /****************************************************************************
2185 Internal routine for retreiving printerdata
2186 ***************************************************************************/
2188 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2189 const char *key, const char *value, uint32 *type, uint8 **data,
2190 uint32 *needed, uint32 in_size )
2192 REGISTRY_VALUE *val;
2196 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2197 return WERR_BADFILE;
2199 *type = regval_type( val );
2201 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2203 size = regval_size( val );
2205 /* copy the min(in_size, len) */
2208 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2210 /* special case for 0 length values */
2212 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2216 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2225 DEBUG(5,("get_printer_dataex: copy done\n"));
2230 /****************************************************************************
2231 Internal routine for removing printerdata
2232 ***************************************************************************/
2234 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2236 return delete_printer_data( printer->info_2, key, value );
2239 /****************************************************************************
2240 Internal routine for storing printerdata
2241 ***************************************************************************/
2243 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2244 uint32 type, uint8 *data, int real_len )
2246 /* the registry objects enforce uniqueness based on value name */
2248 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2251 /********************************************************************
2252 GetPrinterData on a printer server Handle.
2253 ********************************************************************/
2255 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2259 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2261 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2263 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2269 if (!StrCaseCmp(value, "BeepEnabled")) {
2271 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2273 SIVAL(*data, 0, 0x00);
2278 if (!StrCaseCmp(value, "EventLog")) {
2280 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2282 /* formally was 0x1b */
2283 SIVAL(*data, 0, 0x0);
2288 if (!StrCaseCmp(value, "NetPopup")) {
2290 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2292 SIVAL(*data, 0, 0x00);
2297 if (!StrCaseCmp(value, "MajorVersion")) {
2299 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2302 /* Windows NT 4.0 seems to not allow uploading of drivers
2303 to a server that reports 0x3 as the MajorVersion.
2304 need to investigate more how Win2k gets around this .
2307 if ( RA_WINNT == get_remote_arch() )
2316 if (!StrCaseCmp(value, "MinorVersion")) {
2318 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2326 * uint32 size = 0x114
2328 * uint32 minor = [0|1]
2329 * uint32 build = [2195|2600]
2330 * extra unicode string = e.g. "Service Pack 3"
2332 if (!StrCaseCmp(value, "OSVersion")) {
2336 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2339 SIVAL(*data, 0, *needed); /* size */
2340 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2342 SIVAL(*data, 12, 2195); /* build */
2344 /* leave extra string empty */
2350 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2351 const char *string="C:\\PRINTERS";
2353 *needed = 2*(strlen(string)+1);
2354 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2356 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2358 /* it's done by hand ready to go on the wire */
2359 for (i=0; i<strlen(string); i++) {
2360 (*data)[2*i]=string[i];
2361 (*data)[2*i+1]='\0';
2366 if (!StrCaseCmp(value, "Architecture")) {
2367 const char *string="Windows NT x86";
2369 *needed = 2*(strlen(string)+1);
2370 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2372 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2373 for (i=0; i<strlen(string); i++) {
2374 (*data)[2*i]=string[i];
2375 (*data)[2*i+1]='\0';
2380 if (!StrCaseCmp(value, "DsPresent")) {
2382 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2385 /* only show the publish check box if we are a
2386 memeber of a AD domain */
2388 if ( lp_security() == SEC_ADS )
2389 SIVAL(*data, 0, 0x01);
2391 SIVAL(*data, 0, 0x00);
2397 if (!StrCaseCmp(value, "DNSMachineName")) {
2400 if (!get_mydnsfullname(hostname))
2401 return WERR_BADFILE;
2403 *needed = 2*(strlen(hostname)+1);
2404 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2406 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2407 for (i=0; i<strlen(hostname); i++) {
2408 (*data)[2*i]=hostname[i];
2409 (*data)[2*i+1]='\0';
2415 return WERR_BADFILE;
2418 /********************************************************************
2419 * spoolss_getprinterdata
2420 ********************************************************************/
2422 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2424 POLICY_HND *handle = &q_u->handle;
2425 UNISTR2 *valuename = &q_u->valuename;
2426 uint32 in_size = q_u->size;
2427 uint32 *type = &r_u->type;
2428 uint32 *out_size = &r_u->size;
2429 uint8 **data = &r_u->data;
2430 uint32 *needed = &r_u->needed;
2433 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2434 NT_PRINTER_INFO_LEVEL *printer = NULL;
2438 * Reminder: when it's a string, the length is in BYTES
2439 * even if UNICODE is negociated.
2444 *out_size = in_size;
2446 /* in case of problem, return some default values */
2451 DEBUG(4,("_spoolss_getprinterdata\n"));
2454 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2455 status = WERR_BADFID;
2459 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2461 if ( Printer->printer_type == SPLHND_SERVER )
2462 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2465 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2466 status = WERR_BADFID;
2470 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2471 if ( !W_ERROR_IS_OK(status) )
2474 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2476 if ( strequal(value, "ChangeId") ) {
2478 *needed = sizeof(uint32);
2479 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2480 status = WERR_NOMEM;
2483 SIVAL( *data, 0, printer->info_2->changeid );
2487 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2490 if (*needed > *out_size)
2491 status = WERR_MORE_DATA;
2494 if ( !W_ERROR_IS_OK(status) )
2496 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2498 /* reply this param doesn't exist */
2501 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2503 free_a_printer( &printer, 2 );
2511 /* cleanup & exit */
2514 free_a_printer( &printer, 2 );
2519 /*********************************************************
2520 Connect to the client machine.
2521 **********************************************************/
2523 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2524 struct in_addr *client_ip, const char *remote_machine)
2527 struct cli_state *the_cli;
2528 struct in_addr rm_addr;
2530 if ( is_zero_ip(*client_ip) ) {
2531 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2532 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2536 if ( ismyip( rm_addr )) {
2537 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2541 rm_addr.s_addr = client_ip->s_addr;
2542 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2543 inet_ntoa(*client_ip) ));
2546 /* setup the connection */
2548 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2549 &rm_addr, 0, "IPC$", "IPC",
2553 0, lp_client_signing(), NULL );
2555 if ( !NT_STATUS_IS_OK( ret ) ) {
2556 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2561 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2562 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2563 cli_shutdown(the_cli);
2568 * Ok - we have an anonymous connection to the IPC$ share.
2569 * Now start the NT Domain stuff :-).
2572 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2573 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2574 remote_machine, nt_errstr(ret)));
2575 cli_shutdown(the_cli);
2579 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2581 (*pp_pipe)->cli = the_cli;
2586 /***************************************************************************
2587 Connect to the client.
2588 ****************************************************************************/
2590 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2591 uint32 localprinter, uint32 type,
2592 POLICY_HND *handle, struct in_addr *client_ip)
2597 * If it's the first connection, contact the client
2598 * and connect to the IPC$ share anonymously
2600 if (smb_connections==0) {
2601 fstring unix_printer;
2603 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2605 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2608 message_register(MSG_PRINTER_NOTIFY2,
2609 receive_notify2_message_list, NULL);
2610 /* Tell the connections db we're now interested in printer
2611 * notify messages. */
2612 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2616 * Tell the specific printing tdb we want messages for this printer
2617 * by registering our PID.
2620 if (!print_notify_register_pid(snum))
2621 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2625 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2628 if (!W_ERROR_IS_OK(result))
2629 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2630 dos_errstr(result)));
2632 return (W_ERROR_IS_OK(result));
2635 /********************************************************************
2637 * ReplyFindFirstPrinterChangeNotifyEx
2639 * before replying OK: status=0 a rpc call is made to the workstation
2640 * asking ReplyOpenPrinter
2642 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2643 * called from api_spoolss_rffpcnex
2644 ********************************************************************/
2646 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2648 POLICY_HND *handle = &q_u->handle;
2649 uint32 flags = q_u->flags;
2650 uint32 options = q_u->options;
2651 UNISTR2 *localmachine = &q_u->localmachine;
2652 uint32 printerlocal = q_u->printerlocal;
2654 SPOOL_NOTIFY_OPTION *option = q_u->option;
2655 struct in_addr client_ip;
2657 /* store the notify value in the printer struct */
2659 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2662 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2666 Printer->notify.flags=flags;
2667 Printer->notify.options=options;
2668 Printer->notify.printerlocal=printerlocal;
2670 if (Printer->notify.option)
2671 free_spool_notify_option(&Printer->notify.option);
2673 Printer->notify.option=dup_spool_notify_option(option);
2675 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2676 sizeof(Printer->notify.localmachine)-1);
2678 /* Connect to the client machine and send a ReplyOpenPrinter */
2680 if ( Printer->printer_type == SPLHND_SERVER)
2682 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2683 !get_printer_snum(p, handle, &snum, NULL) )
2686 client_ip.s_addr = inet_addr(p->conn->client_address);
2688 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2689 Printer->notify.printerlocal, 1,
2690 &Printer->notify.client_hnd, &client_ip))
2691 return WERR_SERVER_UNAVAILABLE;
2693 Printer->notify.client_connected=True;
2698 /*******************************************************************
2699 * fill a notify_info_data with the servername
2700 ********************************************************************/
2702 void spoolss_notify_server_name(int snum,
2703 SPOOL_NOTIFY_INFO_DATA *data,
2704 print_queue_struct *queue,
2705 NT_PRINTER_INFO_LEVEL *printer,
2706 TALLOC_CTX *mem_ctx)
2711 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2713 data->notify_data.data.length = len;
2715 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2716 if (!data->notify_data.data.string) {
2717 data->notify_data.data.length = 0;
2721 memcpy(data->notify_data.data.string, temp, len);
2723 data->notify_data.data.string = NULL;
2727 /*******************************************************************
2728 * fill a notify_info_data with the printername (not including the servername).
2729 ********************************************************************/
2731 void spoolss_notify_printer_name(int snum,
2732 SPOOL_NOTIFY_INFO_DATA *data,
2733 print_queue_struct *queue,
2734 NT_PRINTER_INFO_LEVEL *printer,
2735 TALLOC_CTX *mem_ctx)
2740 /* the notify name should not contain the \\server\ part */
2741 char *p = strrchr(printer->info_2->printername, '\\');
2744 p = printer->info_2->printername;
2749 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2751 data->notify_data.data.length = len;
2753 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2754 if (!data->notify_data.data.string) {
2755 data->notify_data.data.length = 0;
2758 memcpy(data->notify_data.data.string, temp, len);
2760 data->notify_data.data.string = NULL;
2764 /*******************************************************************
2765 * fill a notify_info_data with the servicename
2766 ********************************************************************/
2768 void spoolss_notify_share_name(int snum,
2769 SPOOL_NOTIFY_INFO_DATA *data,
2770 print_queue_struct *queue,
2771 NT_PRINTER_INFO_LEVEL *printer,
2772 TALLOC_CTX *mem_ctx)
2777 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2779 data->notify_data.data.length = len;
2781 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2782 if (!data->notify_data.data.string) {
2783 data->notify_data.data.length = 0;
2786 memcpy(data->notify_data.data.string, temp, len);
2788 data->notify_data.data.string = NULL;
2793 /*******************************************************************
2794 * fill a notify_info_data with the port name
2795 ********************************************************************/
2797 void spoolss_notify_port_name(int snum,
2798 SPOOL_NOTIFY_INFO_DATA *data,
2799 print_queue_struct *queue,
2800 NT_PRINTER_INFO_LEVEL *printer,
2801 TALLOC_CTX *mem_ctx)
2806 /* even if it's strange, that's consistant in all the code */
2808 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2810 data->notify_data.data.length = len;
2812 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2814 if (!data->notify_data.data.string) {
2815 data->notify_data.data.length = 0;
2819 memcpy(data->notify_data.data.string, temp, len);
2821 data->notify_data.data.string = NULL;
2825 /*******************************************************************
2826 * fill a notify_info_data with the printername
2827 * but it doesn't exist, have to see what to do
2828 ********************************************************************/
2830 void spoolss_notify_driver_name(int snum,
2831 SPOOL_NOTIFY_INFO_DATA *data,
2832 print_queue_struct *queue,
2833 NT_PRINTER_INFO_LEVEL *printer,
2834 TALLOC_CTX *mem_ctx)
2839 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2841 data->notify_data.data.length = len;
2843 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2845 if (!data->notify_data.data.string) {
2846 data->notify_data.data.length = 0;
2850 memcpy(data->notify_data.data.string, temp, len);
2852 data->notify_data.data.string = NULL;
2856 /*******************************************************************
2857 * fill a notify_info_data with the comment
2858 ********************************************************************/
2860 void spoolss_notify_comment(int snum,
2861 SPOOL_NOTIFY_INFO_DATA *data,
2862 print_queue_struct *queue,
2863 NT_PRINTER_INFO_LEVEL *printer,
2864 TALLOC_CTX *mem_ctx)
2869 if (*printer->info_2->comment == '\0')
2870 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2872 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2874 data->notify_data.data.length = len;
2876 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2878 if (!data->notify_data.data.string) {
2879 data->notify_data.data.length = 0;
2883 memcpy(data->notify_data.data.string, temp, len);
2885 data->notify_data.data.string = NULL;
2889 /*******************************************************************
2890 * fill a notify_info_data with the comment
2891 * location = "Room 1, floor 2, building 3"
2892 ********************************************************************/
2894 void spoolss_notify_location(int snum,
2895 SPOOL_NOTIFY_INFO_DATA *data,
2896 print_queue_struct *queue,
2897 NT_PRINTER_INFO_LEVEL *printer,
2898 TALLOC_CTX *mem_ctx)
2903 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2905 data->notify_data.data.length = len;
2907 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2909 if (!data->notify_data.data.string) {
2910 data->notify_data.data.length = 0;
2914 memcpy(data->notify_data.data.string, temp, len);
2916 data->notify_data.data.string = NULL;
2920 /*******************************************************************
2921 * fill a notify_info_data with the device mode
2922 * jfm:xxxx don't to it for know but that's a real problem !!!
2923 ********************************************************************/
2925 static void spoolss_notify_devmode(int snum,
2926 SPOOL_NOTIFY_INFO_DATA *data,
2927 print_queue_struct *queue,
2928 NT_PRINTER_INFO_LEVEL *printer,
2929 TALLOC_CTX *mem_ctx)
2931 /* for a dummy implementation we have to zero the fields */
2932 data->notify_data.data.length = 0;
2933 data->notify_data.data.string = NULL;
2936 /*******************************************************************
2937 * fill a notify_info_data with the separator file name
2938 ********************************************************************/
2940 void spoolss_notify_sepfile(int snum,
2941 SPOOL_NOTIFY_INFO_DATA *data,
2942 print_queue_struct *queue,
2943 NT_PRINTER_INFO_LEVEL *printer,
2944 TALLOC_CTX *mem_ctx)
2949 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2951 data->notify_data.data.length = len;
2953 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2955 if (!data->notify_data.data.string) {
2956 data->notify_data.data.length = 0;
2960 memcpy(data->notify_data.data.string, temp, len);
2962 data->notify_data.data.string = NULL;
2966 /*******************************************************************
2967 * fill a notify_info_data with the print processor
2968 * jfm:xxxx return always winprint to indicate we don't do anything to it
2969 ********************************************************************/
2971 void spoolss_notify_print_processor(int snum,
2972 SPOOL_NOTIFY_INFO_DATA *data,
2973 print_queue_struct *queue,
2974 NT_PRINTER_INFO_LEVEL *printer,
2975 TALLOC_CTX *mem_ctx)
2980 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2982 data->notify_data.data.length = len;
2984 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2986 if (!data->notify_data.data.string) {
2987 data->notify_data.data.length = 0;
2991 memcpy(data->notify_data.data.string, temp, len);
2993 data->notify_data.data.string = NULL;
2997 /*******************************************************************
2998 * fill a notify_info_data with the print processor options
2999 * jfm:xxxx send an empty string
3000 ********************************************************************/
3002 void spoolss_notify_parameters(int snum,
3003 SPOOL_NOTIFY_INFO_DATA *data,
3004 print_queue_struct *queue,
3005 NT_PRINTER_INFO_LEVEL *printer,
3006 TALLOC_CTX *mem_ctx)
3011 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3013 data->notify_data.data.length = len;
3015 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3017 if (!data->notify_data.data.string) {
3018 data->notify_data.data.length = 0;
3022 memcpy(data->notify_data.data.string, temp, len);
3024 data->notify_data.data.string = NULL;
3028 /*******************************************************************
3029 * fill a notify_info_data with the data type
3030 * jfm:xxxx always send RAW as data type
3031 ********************************************************************/
3033 void spoolss_notify_datatype(int snum,
3034 SPOOL_NOTIFY_INFO_DATA *data,
3035 print_queue_struct *queue,
3036 NT_PRINTER_INFO_LEVEL *printer,
3037 TALLOC_CTX *mem_ctx)
3042 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3044 data->notify_data.data.length = len;
3046 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3048 if (!data->notify_data.data.string) {
3049 data->notify_data.data.length = 0;
3053 memcpy(data->notify_data.data.string, temp, len);
3055 data->notify_data.data.string = NULL;
3059 /*******************************************************************
3060 * fill a notify_info_data with the security descriptor
3061 * jfm:xxxx send an null pointer to say no security desc
3062 * have to implement security before !
3063 ********************************************************************/
3065 static void spoolss_notify_security_desc(int snum,
3066 SPOOL_NOTIFY_INFO_DATA *data,
3067 print_queue_struct *queue,
3068 NT_PRINTER_INFO_LEVEL *printer,
3069 TALLOC_CTX *mem_ctx)
3071 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3072 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3075 /*******************************************************************
3076 * fill a notify_info_data with the attributes
3077 * jfm:xxxx a samba printer is always shared
3078 ********************************************************************/
3080 void spoolss_notify_attributes(int snum,
3081 SPOOL_NOTIFY_INFO_DATA *data,
3082 print_queue_struct *queue,
3083 NT_PRINTER_INFO_LEVEL *printer,
3084 TALLOC_CTX *mem_ctx)
3086 data->notify_data.value[0] = printer->info_2->attributes;
3087 data->notify_data.value[1] = 0;
3090 /*******************************************************************
3091 * fill a notify_info_data with the priority
3092 ********************************************************************/
3094 static void spoolss_notify_priority(int snum,
3095 SPOOL_NOTIFY_INFO_DATA *data,
3096 print_queue_struct *queue,
3097 NT_PRINTER_INFO_LEVEL *printer,
3098 TALLOC_CTX *mem_ctx)
3100 data->notify_data.value[0] = printer->info_2->priority;
3101 data->notify_data.value[1] = 0;
3104 /*******************************************************************
3105 * fill a notify_info_data with the default priority
3106 ********************************************************************/
3108 static void spoolss_notify_default_priority(int snum,
3109 SPOOL_NOTIFY_INFO_DATA *data,
3110 print_queue_struct *queue,
3111 NT_PRINTER_INFO_LEVEL *printer,
3112 TALLOC_CTX *mem_ctx)
3114 data->notify_data.value[0] = printer->info_2->default_priority;
3115 data->notify_data.value[1] = 0;
3118 /*******************************************************************
3119 * fill a notify_info_data with the start time
3120 ********************************************************************/
3122 static void spoolss_notify_start_time(int snum,
3123 SPOOL_NOTIFY_INFO_DATA *data,
3124 print_queue_struct *queue,
3125 NT_PRINTER_INFO_LEVEL *printer,
3126 TALLOC_CTX *mem_ctx)
3128 data->notify_data.value[0] = printer->info_2->starttime;
3129 data->notify_data.value[1] = 0;
3132 /*******************************************************************
3133 * fill a notify_info_data with the until time
3134 ********************************************************************/
3136 static void spoolss_notify_until_time(int snum,
3137 SPOOL_NOTIFY_INFO_DATA *data,
3138 print_queue_struct *queue,
3139 NT_PRINTER_INFO_LEVEL *printer,
3140 TALLOC_CTX *mem_ctx)
3142 data->notify_data.value[0] = printer->info_2->untiltime;
3143 data->notify_data.value[1] = 0;
3146 /*******************************************************************
3147 * fill a notify_info_data with the status
3148 ********************************************************************/
3150 static void spoolss_notify_status(int snum,
3151 SPOOL_NOTIFY_INFO_DATA *data,
3152 print_queue_struct *queue,
3153 NT_PRINTER_INFO_LEVEL *printer,
3154 TALLOC_CTX *mem_ctx)
3156 print_status_struct status;
3158 print_queue_length(snum, &status);
3159 data->notify_data.value[0]=(uint32) status.status;
3160 data->notify_data.value[1] = 0;
3163 /*******************************************************************
3164 * fill a notify_info_data with the number of jobs queued
3165 ********************************************************************/
3167 void spoolss_notify_cjobs(int snum,
3168 SPOOL_NOTIFY_INFO_DATA *data,
3169 print_queue_struct *queue,
3170 NT_PRINTER_INFO_LEVEL *printer,
3171 TALLOC_CTX *mem_ctx)
3173 data->notify_data.value[0] = print_queue_length(snum, NULL);
3174 data->notify_data.value[1] = 0;
3177 /*******************************************************************
3178 * fill a notify_info_data with the average ppm
3179 ********************************************************************/
3181 static void spoolss_notify_average_ppm(int snum,
3182 SPOOL_NOTIFY_INFO_DATA *data,
3183 print_queue_struct *queue,
3184 NT_PRINTER_INFO_LEVEL *printer,
3185 TALLOC_CTX *mem_ctx)
3187 /* always respond 8 pages per minutes */
3188 /* a little hard ! */
3189 data->notify_data.value[0] = printer->info_2->averageppm;
3190 data->notify_data.value[1] = 0;
3193 /*******************************************************************
3194 * fill a notify_info_data with username
3195 ********************************************************************/
3197 static void spoolss_notify_username(int snum,
3198 SPOOL_NOTIFY_INFO_DATA *data,
3199 print_queue_struct *queue,
3200 NT_PRINTER_INFO_LEVEL *printer,
3201 TALLOC_CTX *mem_ctx)
3206 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3208 data->notify_data.data.length = len;
3210 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3212 if (!data->notify_data.data.string) {
3213 data->notify_data.data.length = 0;
3217 memcpy(data->notify_data.data.string, temp, len);
3219 data->notify_data.data.string = NULL;
3223 /*******************************************************************
3224 * fill a notify_info_data with job status
3225 ********************************************************************/
3227 static void spoolss_notify_job_status(int snum,
3228 SPOOL_NOTIFY_INFO_DATA *data,
3229 print_queue_struct *queue,
3230 NT_PRINTER_INFO_LEVEL *printer,
3231 TALLOC_CTX *mem_ctx)
3233 data->notify_data.value[0]=nt_printj_status(queue->status);
3234 data->notify_data.value[1] = 0;
3237 /*******************************************************************
3238 * fill a notify_info_data with job name
3239 ********************************************************************/
3241 static void spoolss_notify_job_name(int snum,
3242 SPOOL_NOTIFY_INFO_DATA *data,
3243 print_queue_struct *queue,
3244 NT_PRINTER_INFO_LEVEL *printer,
3245 TALLOC_CTX *mem_ctx)
3250 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3252 data->notify_data.data.length = len;
3254 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3256 if (!data->notify_data.data.string) {
3257 data->notify_data.data.length = 0;
3261 memcpy(data->notify_data.data.string, temp, len);
3263 data->notify_data.data.string = NULL;
3267 /*******************************************************************
3268 * fill a notify_info_data with job status
3269 ********************************************************************/
3271 static void spoolss_notify_job_status_string(int snum,
3272 SPOOL_NOTIFY_INFO_DATA *data,
3273 print_queue_struct *queue,
3274 NT_PRINTER_INFO_LEVEL *printer,
3275 TALLOC_CTX *mem_ctx)
3278 * Now we're returning job status codes we just return a "" here. JRA.
3285 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3288 switch (queue->status) {
3293 p = ""; /* NT provides the paused string */
3302 #endif /* NO LONGER NEEDED. */
3304 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3306 data->notify_data.data.length = len;
3308 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3310 if (!data->notify_data.data.string) {
3311 data->notify_data.data.length = 0;
3315 memcpy(data->notify_data.data.string, temp, len);
3317 data->notify_data.data.string = NULL;
3321 /*******************************************************************
3322 * fill a notify_info_data with job time
3323 ********************************************************************/
3325 static void spoolss_notify_job_time(int snum,
3326 SPOOL_NOTIFY_INFO_DATA *data,
3327 print_queue_struct *queue,
3328 NT_PRINTER_INFO_LEVEL *printer,
3329 TALLOC_CTX *mem_ctx)
3331 data->notify_data.value[0]=0x0;
3332 data->notify_data.value[1]=0;
3335 /*******************************************************************
3336 * fill a notify_info_data with job size
3337 ********************************************************************/
3339 static void spoolss_notify_job_size(int snum,
3340 SPOOL_NOTIFY_INFO_DATA *data,
3341 print_queue_struct *queue,
3342 NT_PRINTER_INFO_LEVEL *printer,
3343 TALLOC_CTX *mem_ctx)
3345 data->notify_data.value[0]=queue->size;
3346 data->notify_data.value[1]=0;
3349 /*******************************************************************
3350 * fill a notify_info_data with page info
3351 ********************************************************************/
3352 static void spoolss_notify_total_pages(int snum,
3353 SPOOL_NOTIFY_INFO_DATA *data,
3354 print_queue_struct *queue,
3355 NT_PRINTER_INFO_LEVEL *printer,
3356 TALLOC_CTX *mem_ctx)
3358 data->notify_data.value[0]=queue->page_count;
3359 data->notify_data.value[1]=0;
3362 /*******************************************************************
3363 * fill a notify_info_data with pages printed info.
3364 ********************************************************************/
3365 static void spoolss_notify_pages_printed(int snum,
3366 SPOOL_NOTIFY_INFO_DATA *data,
3367 print_queue_struct *queue,
3368 NT_PRINTER_INFO_LEVEL *printer,
3369 TALLOC_CTX *mem_ctx)
3371 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3372 data->notify_data.value[1]=0;
3375 /*******************************************************************
3376 Fill a notify_info_data with job position.
3377 ********************************************************************/
3379 static void spoolss_notify_job_position(int snum,
3380 SPOOL_NOTIFY_INFO_DATA *data,
3381 print_queue_struct *queue,
3382 NT_PRINTER_INFO_LEVEL *printer,
3383 TALLOC_CTX *mem_ctx)
3385 data->notify_data.value[0]=queue->job;
3386 data->notify_data.value[1]=0;
3389 /*******************************************************************
3390 Fill a notify_info_data with submitted time.
3391 ********************************************************************/
3393 static void spoolss_notify_submitted_time(int snum,
3394 SPOOL_NOTIFY_INFO_DATA *data,
3395 print_queue_struct *queue,
3396 NT_PRINTER_INFO_LEVEL *printer,
3397 TALLOC_CTX *mem_ctx)
3404 t=gmtime(&queue->time);
3406 len = sizeof(SYSTEMTIME);
3408 data->notify_data.data.length = len;
3409 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3411 if (!data->notify_data.data.string) {
3412 data->notify_data.data.length = 0;
3416 make_systemtime(&st, t);
3419 * Systemtime must be linearized as a set of UINT16's.
3420 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3423 p = (char *)data->notify_data.data.string;
3424 SSVAL(p, 0, st.year);
3425 SSVAL(p, 2, st.month);
3426 SSVAL(p, 4, st.dayofweek);
3427 SSVAL(p, 6, st.day);
3428 SSVAL(p, 8, st.hour);
3429 SSVAL(p, 10, st.minute);
3430 SSVAL(p, 12, st.second);
3431 SSVAL(p, 14, st.milliseconds);
3434 struct s_notify_info_data_table
3440 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3441 print_queue_struct *queue,
3442 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3445 /* A table describing the various print notification constants and
3446 whether the notification data is a pointer to a variable sized
3447 buffer, a one value uint32 or a two value uint32. */
3449 static const struct s_notify_info_data_table notify_info_data_table[] =
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3500 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3503 /*******************************************************************
3504 Return the size of info_data structure.
3505 ********************************************************************/
3507 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3511 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3512 if ( (notify_info_data_table[i].type == type)
3513 && (notify_info_data_table[i].field == field) ) {
3514 switch(notify_info_data_table[i].size) {
3515 case NOTIFY_ONE_VALUE:
3516 case NOTIFY_TWO_VALUE:
3521 /* The only pointer notify data I have seen on
3522 the wire is the submitted time and this has
3523 the notify size set to 4. -tpot */
3525 case NOTIFY_POINTER:
3528 case NOTIFY_SECDESC:
3534 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3539 /*******************************************************************
3540 Return the type of notify_info_data.
3541 ********************************************************************/
3543 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3547 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3548 if (notify_info_data_table[i].type == type &&
3549 notify_info_data_table[i].field == field)
3550 return notify_info_data_table[i].size;
3556 /****************************************************************************
3557 ****************************************************************************/
3559 static BOOL search_notify(uint16 type, uint16 field, int *value)
3563 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3564 if (notify_info_data_table[i].type == type &&
3565 notify_info_data_table[i].field == field &&
3566 notify_info_data_table[i].fn != NULL) {
3575 /****************************************************************************
3576 ****************************************************************************/
3578 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3580 info_data->type = type;
3581 info_data->field = field;
3582 info_data->reserved = 0;
3584 info_data->size = size_of_notify_info_data(type, field);
3585 info_data->enc_type = type_of_notify_info_data(type, field);
3590 /*******************************************************************
3592 * fill a notify_info struct with info asked
3594 ********************************************************************/
3596 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3597 snum, SPOOL_NOTIFY_OPTION_TYPE
3598 *option_type, uint32 id,
3599 TALLOC_CTX *mem_ctx)
3605 SPOOL_NOTIFY_INFO_DATA *current_data;
3606 NT_PRINTER_INFO_LEVEL *printer = NULL;
3607 print_queue_struct *queue=NULL;
3609 type=option_type->type;
3611 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3612 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3613 option_type->count, lp_servicename(snum)));
3615 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3618 for(field_num=0; field_num<option_type->count; field_num++) {
3619 field = option_type->fields[field_num];
3621 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3623 if (!search_notify(type, field, &j) )
3626 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3627 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3628 free_a_printer(&printer, 2);
3632 current_data = &info->data[info->count];
3634 construct_info_data(current_data, type, field, id);
3636 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3637 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3639 notify_info_data_table[j].fn(snum, current_data, queue,
3645 free_a_printer(&printer, 2);
3649 /*******************************************************************
3651 * fill a notify_info struct with info asked
3653 ********************************************************************/
3655 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3656 SPOOL_NOTIFY_INFO *info,
3657 NT_PRINTER_INFO_LEVEL *printer,
3658 int snum, SPOOL_NOTIFY_OPTION_TYPE
3659 *option_type, uint32 id,
3660 TALLOC_CTX *mem_ctx)
3666 SPOOL_NOTIFY_INFO_DATA *current_data;
3668 DEBUG(4,("construct_notify_jobs_info\n"));
3670 type = option_type->type;
3672 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3673 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3674 option_type->count));
3676 for(field_num=0; field_num<option_type->count; field_num++) {
3677 field = option_type->fields[field_num];
3679 if (!search_notify(type, field, &j) )
3682 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3683 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3687 current_data=&(info->data[info->count]);
3689 construct_info_data(current_data, type, field, id);
3690 notify_info_data_table[j].fn(snum, current_data, queue,
3699 * JFM: The enumeration is not that simple, it's even non obvious.
3701 * let's take an example: I want to monitor the PRINTER SERVER for
3702 * the printer's name and the number of jobs currently queued.
3703 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3704 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3706 * I have 3 printers on the back of my server.
3708 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3711 * 1 printer 1 name 1
3712 * 2 printer 1 cjob 1
3713 * 3 printer 2 name 2
3714 * 4 printer 2 cjob 2
3715 * 5 printer 3 name 3
3716 * 6 printer 3 name 3
3718 * that's the print server case, the printer case is even worse.
3721 /*******************************************************************
3723 * enumerate all printers on the printserver
3724 * fill a notify_info struct with info asked
3726 ********************************************************************/
3728 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3729 SPOOL_NOTIFY_INFO *info,
3730 TALLOC_CTX *mem_ctx)
3733 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3734 int n_services=lp_numservices();
3736 SPOOL_NOTIFY_OPTION *option;
3737 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3739 DEBUG(4,("printserver_notify_info\n"));
3744 option=Printer->notify.option;
3749 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3750 sending a ffpcn() request first */
3755 for (i=0; i<option->count; i++) {
3756 option_type=&(option->ctr.type[i]);
3758 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3761 for (snum=0; snum<n_services; snum++)
3763 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3764 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3770 * Debugging information, don't delete.
3773 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3774 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3775 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3777 for (i=0; i<info->count; i++) {
3778 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3779 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3780 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3787 /*******************************************************************
3789 * fill a notify_info struct with info asked
3791 ********************************************************************/
3793 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3794 TALLOC_CTX *mem_ctx)
3797 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3800 SPOOL_NOTIFY_OPTION *option;
3801 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3803 print_queue_struct *queue=NULL;
3804 print_status_struct status;
3806 DEBUG(4,("printer_notify_info\n"));
3811 option=Printer->notify.option;
3817 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3818 sending a ffpcn() request first */
3823 get_printer_snum(p, hnd, &snum, NULL);
3825 for (i=0; i<option->count; i++) {
3826 option_type=&option->ctr.type[i];
3828 switch ( option_type->type ) {
3829 case PRINTER_NOTIFY_TYPE:
3830 if(construct_notify_printer_info(Printer, info, snum,
3836 case JOB_NOTIFY_TYPE: {
3837 NT_PRINTER_INFO_LEVEL *printer = NULL;
3839 count = print_queue_status(snum, &queue, &status);
3841 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3844 for (j=0; j<count; j++) {
3845 construct_notify_jobs_info(&queue[j], info,
3852 free_a_printer(&printer, 2);
3862 * Debugging information, don't delete.
3865 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3866 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3867 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3869 for (i=0; i<info->count; i++) {
3870 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3871 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3872 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3878 /********************************************************************
3880 ********************************************************************/
3882 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3884 POLICY_HND *handle = &q_u->handle;
3885 SPOOL_NOTIFY_INFO *info = &r_u->info;
3887 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3888 WERROR result = WERR_BADFID;
3890 /* we always have a NOTIFY_INFO struct */
3894 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3895 OUR_HANDLE(handle)));
3899 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3902 * We are now using the change value, and
3903 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3904 * I don't have a global notification system, I'm sending back all the
3905 * informations even when _NOTHING_ has changed.
3908 /* We need to keep track of the change value to send back in
3909 RRPCN replies otherwise our updates are ignored. */
3911 Printer->notify.fnpcn = True;
3913 if (Printer->notify.client_connected) {
3914 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3915 Printer->notify.change = q_u->change;
3918 /* just ignore the SPOOL_NOTIFY_OPTION */
3920 switch (Printer->printer_type) {
3922 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3925 case SPLHND_PRINTER:
3926 result = printer_notify_info(p, handle, info, p->mem_ctx);
3930 Printer->notify.fnpcn = False;
3936 /********************************************************************
3937 * construct_printer_info_0
3938 * fill a printer_info_0 struct
3939 ********************************************************************/
3941 static BOOL construct_printer_info_0(Printer_entry *print_hnd,
3942 PRINTER_INFO_0 *printer,
3943 const struct share_params *params)
3947 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3948 counter_printer_0 *session_counter;
3949 uint32 global_counter;
3952 print_status_struct status;
3954 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
3955 lp_const_servicename(params->service))))
3958 count = print_queue_length(params->service, &status);
3960 /* check if we already have a counter for this printer */
3961 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3962 if (session_counter->snum == params->service)
3966 /* it's the first time, add it to the list */
3967 if (session_counter==NULL) {
3968 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3969 free_a_printer(&ntprinter, 2);
3972 ZERO_STRUCTP(session_counter);
3973 session_counter->snum=params->service;
3974 session_counter->counter=0;
3975 DLIST_ADD(counter_list, session_counter);
3979 session_counter->counter++;
3982 * the global_counter should be stored in a TDB as it's common to all the clients
3983 * and should be zeroed on samba startup
3985 global_counter=session_counter->counter;
3987 pstrcpy(chaine,ntprinter->info_2->printername);
3989 init_unistr(&printer->printername, chaine);
3991 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3992 init_unistr(&printer->servername, chaine);
3994 printer->cjobs = count;
3995 printer->total_jobs = 0;
3996 printer->total_bytes = 0;
3998 setuptime = (time_t)ntprinter->info_2->setuptime;
3999 t=gmtime(&setuptime);
4001 printer->year = t->tm_year+1900;
4002 printer->month = t->tm_mon+1;
4003 printer->dayofweek = t->tm_wday;
4004 printer->day = t->tm_mday;
4005 printer->hour = t->tm_hour;
4006 printer->minute = t->tm_min;
4007 printer->second = t->tm_sec;
4008 printer->milliseconds = 0;
4010 printer->global_counter = global_counter;
4011 printer->total_pages = 0;
4013 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4014 printer->major_version = 0x0005; /* NT 5 */
4015 printer->build_version = 0x0893; /* build 2195 */
4017 printer->unknown7 = 0x1;
4018 printer->unknown8 = 0x0;
4019 printer->unknown9 = 0x0;
4020 printer->session_counter = session_counter->counter;
4021 printer->unknown11 = 0x0;
4022 printer->printer_errors = 0x0; /* number of print failure */
4023 printer->unknown13 = 0x0;
4024 printer->unknown14 = 0x1;
4025 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4026 printer->unknown16 = 0x0;
4027 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4028 printer->unknown18 = 0x0;
4029 printer->status = nt_printq_status(status.status);
4030 printer->unknown20 = 0x0;
4031 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4032 printer->unknown22 = 0x0;
4033 printer->unknown23 = 0x6; /* 6 ???*/
4034 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4035 printer->unknown25 = 0;
4036 printer->unknown26 = 0;
4037 printer->unknown27 = 0;
4038 printer->unknown28 = 0;
4039 printer->unknown29 = 0;
4041 free_a_printer(&ntprinter,2);
4045 /********************************************************************
4046 * construct_printer_info_1
4047 * fill a printer_info_1 struct
4048 ********************************************************************/
4049 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags,
4050 PRINTER_INFO_1 *printer,
4051 const struct share_params *params)
4055 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4057 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4058 lp_const_servicename(params->service))))
4061 printer->flags=flags;
4063 if (*ntprinter->info_2->comment == '\0') {
4064 init_unistr(&printer->comment, lp_comment(params->service));
4065 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4066 ntprinter->info_2->drivername,
4067 lp_comment(params->service));
4070 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4071 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4072 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4075 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4077 init_unistr(&printer->description, chaine);
4078 init_unistr(&printer->name, chaine2);
4080 free_a_printer(&ntprinter,2);
4085 /****************************************************************************
4086 Free a DEVMODE struct.
4087 ****************************************************************************/
4089 static void free_dev_mode(DEVICEMODE *dev)
4094 SAFE_FREE(dev->dev_private);
4099 /****************************************************************************
4100 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4101 should be valid upon entry
4102 ****************************************************************************/
4104 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4106 if ( !devmode || !ntdevmode )
4109 init_unistr(&devmode->devicename, ntdevmode->devicename);
4111 init_unistr(&devmode->formname, ntdevmode->formname);
4113 devmode->specversion = ntdevmode->specversion;
4114 devmode->driverversion = ntdevmode->driverversion;
4115 devmode->size = ntdevmode->size;
4116 devmode->driverextra = ntdevmode->driverextra;
4117 devmode->fields = ntdevmode->fields;
4119 devmode->orientation = ntdevmode->orientation;
4120 devmode->papersize = ntdevmode->papersize;
4121 devmode->paperlength = ntdevmode->paperlength;
4122 devmode->paperwidth = ntdevmode->paperwidth;
4123 devmode->scale = ntdevmode->scale;
4124 devmode->copies = ntdevmode->copies;
4125 devmode->defaultsource = ntdevmode->defaultsource;
4126 devmode->printquality = ntdevmode->printquality;
4127 devmode->color = ntdevmode->color;
4128 devmode->duplex = ntdevmode->duplex;
4129 devmode->yresolution = ntdevmode->yresolution;
4130 devmode->ttoption = ntdevmode->ttoption;
4131 devmode->collate = ntdevmode->collate;
4132 devmode->icmmethod = ntdevmode->icmmethod;
4133 devmode->icmintent = ntdevmode->icmintent;
4134 devmode->mediatype = ntdevmode->mediatype;
4135 devmode->dithertype = ntdevmode->dithertype;
4137 if (ntdevmode->nt_dev_private != NULL) {
4138 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4145 /****************************************************************************
4146 Create a DEVMODE struct. Returns malloced memory.
4147 ****************************************************************************/
4149 DEVICEMODE *construct_dev_mode(const char *servicename)
4151 NT_PRINTER_INFO_LEVEL *printer = NULL;
4152 DEVICEMODE *devmode = NULL;
4154 DEBUG(7,("construct_dev_mode\n"));
4156 DEBUGADD(8,("getting printer characteristics\n"));
4158 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4161 if ( !printer->info_2->devmode ) {
4162 DEBUG(5, ("BONG! There was no device mode!\n"));
4166 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4167 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4171 ZERO_STRUCTP(devmode);
4173 DEBUGADD(8,("loading DEVICEMODE\n"));
4175 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4176 free_dev_mode( devmode );
4181 free_a_printer(&printer,2);
4186 /********************************************************************
4187 * construct_printer_info_2
4188 * fill a printer_info_2 struct
4189 ********************************************************************/
4191 static BOOL construct_printer_info_2(Printer_entry *print_hnd,
4192 PRINTER_INFO_2 *printer,
4193 const struct share_params *params)
4196 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4198 print_status_struct status;
4200 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4201 lp_const_servicename(params->service))))
4204 count = print_queue_length(params->service, &status);
4206 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4207 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4208 init_unistr(&printer->sharename, lp_servicename(params->service)); /* sharename */
4209 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4210 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4212 if (*ntprinter->info_2->comment == '\0')
4213 init_unistr(&printer->comment, lp_comment(params->service)); /* comment */
4215 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4217 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4218 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4219 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4220 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4221 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4223 printer->attributes = ntprinter->info_2->attributes;
4225 printer->priority = ntprinter->info_2->priority; /* priority */
4226 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4227 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4228 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4229 printer->status = nt_printq_status(status.status); /* status */
4230 printer->cjobs = count; /* jobs */
4231 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4233 if ( !(printer->devmode = construct_dev_mode(
4234 lp_const_servicename(params->service))) )
4235 DEBUG(8, ("Returning NULL Devicemode!\n"));
4237 printer->secdesc = NULL;
4239 if ( ntprinter->info_2->secdesc_buf
4240 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4242 /* don't use talloc_steal() here unless you do a deep steal of all
4243 the SEC_DESC members */
4245 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4246 ntprinter->info_2->secdesc_buf->sd );
4249 free_a_printer(&ntprinter, 2);
4254 /********************************************************************
4255 * construct_printer_info_3
4256 * fill a printer_info_3 struct
4257 ********************************************************************/
4259 static BOOL construct_printer_info_3(Printer_entry *print_hnd,
4260 PRINTER_INFO_3 **pp_printer,
4261 const struct share_params *params)
4263 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4264 PRINTER_INFO_3 *printer = NULL;
4266 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4267 lp_const_servicename(params->service))))
4271 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4272 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4273 free_a_printer(&ntprinter, 2);
4277 ZERO_STRUCTP(printer);
4279 /* These are the components of the SD we are returning. */
4281 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4282 /* don't use talloc_steal() here unless you do a deep steal of all
4283 the SEC_DESC members */
4285 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4286 ntprinter->info_2->secdesc_buf->sd );
4289 free_a_printer(&ntprinter, 2);
4291 *pp_printer = printer;
4295 /********************************************************************
4296 * construct_printer_info_4
4297 * fill a printer_info_4 struct
4298 ********************************************************************/
4300 static BOOL construct_printer_info_4(Printer_entry *print_hnd,
4301 PRINTER_INFO_4 *printer,
4302 const struct share_params *params)
4304 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4306 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4307 lp_const_servicename(params->service))))
4310 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4311 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4312 printer->attributes = ntprinter->info_2->attributes;
4314 free_a_printer(&ntprinter, 2);
4318 /********************************************************************
4319 * construct_printer_info_5
4320 * fill a printer_info_5 struct
4321 ********************************************************************/
4323 static BOOL construct_printer_info_5(Printer_entry *print_hnd,
4324 PRINTER_INFO_5 *printer,
4325 const struct share_params *params)
4327 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4329 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4330 lp_const_servicename(params->service))))
4333 init_unistr(&printer->printername, ntprinter->info_2->printername);
4334 init_unistr(&printer->portname, ntprinter->info_2->portname);
4335 printer->attributes = ntprinter->info_2->attributes;
4337 /* these two are not used by NT+ according to MSDN */
4339 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4340 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4342 free_a_printer(&ntprinter, 2);
4347 /********************************************************************
4348 * construct_printer_info_6
4349 * fill a printer_info_6 struct
4350 ********************************************************************/
4352 static BOOL construct_printer_info_6(Printer_entry *print_hnd,
4353 PRINTER_INFO_6 *printer,
4354 const struct share_params *params)
4356 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4358 print_status_struct status;
4360 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4361 lp_const_servicename(params->service))))
4364 count = print_queue_length(params->service, &status);
4366 printer->status = nt_printq_status(status.status);
4368 free_a_printer(&ntprinter, 2);
4373 /********************************************************************
4374 * construct_printer_info_7
4375 * fill a printer_info_7 struct
4376 ********************************************************************/
4378 static BOOL construct_printer_info_7(Printer_entry *print_hnd,
4379 PRINTER_INFO_7 *printer,
4380 const struct share_params *params)
4382 char *guid_str = NULL;
4385 if (is_printer_published(print_hnd, params->service, &guid)) {
4386 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4387 strupper_m(guid_str);
4388 init_unistr(&printer->guid, guid_str);
4389 printer->action = SPOOL_DS_PUBLISH;
4391 init_unistr(&printer->guid, "");
4392 printer->action = SPOOL_DS_UNPUBLISH;
4398 /********************************************************************
4399 Spoolss_enumprinters.
4400 ********************************************************************/
4402 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4405 struct share_iterator *shares;
4406 struct share_params *printer;
4407 PRINTER_INFO_1 *printers=NULL;
4408 WERROR result = WERR_OK;
4410 DEBUG(4,("enum_all_printers_info_1\n"));
4412 if (!(shares = share_list_all(NULL))) {
4413 DEBUG(5, ("Could not list printers\n"));
4414 return WERR_ACCESS_DENIED;
4417 while ((printer = next_printer(shares)) != NULL) {
4418 PRINTER_INFO_1 current_prt;
4420 DEBUG(4,("Found a printer in smb.conf: %s\n",
4421 lp_servicename(printer->service)));
4423 if (!construct_printer_info_1(NULL, flags, ¤t_prt,
4428 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1,
4429 *returned +1)) == NULL) {
4430 DEBUG(2,("enum_all_printers_info_1: failed to enlarge "
4431 "printers buffer!\n"));
4433 TALLOC_FREE(shares);
4436 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n",
4439 memcpy(&printers[*returned], ¤t_prt,
4440 sizeof(PRINTER_INFO_1));
4442 TALLOC_FREE(printer);
4445 /* check the required size. */
4446 for (i=0; i<*returned; i++)
4447 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4449 if (*needed > offered) {
4450 result = WERR_INSUFFICIENT_BUFFER;
4454 if (!rpcbuf_alloc_size(buffer, *needed)) {
4455 result = WERR_NOMEM;
4459 /* fill the buffer with the structures */
4460 for (i=0; i<*returned; i++)
4461 smb_io_printer_info_1("", buffer, &printers[i], 0);
4466 SAFE_FREE(printers);
4467 TALLOC_FREE(shares);
4469 if ( !W_ERROR_IS_OK(result) )
4475 /********************************************************************
4476 enum_all_printers_info_1_local.
4477 *********************************************************************/
4479 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4481 DEBUG(4,("enum_all_printers_info_1_local\n"));
4483 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4486 /********************************************************************
4487 enum_all_printers_info_1_name.
4488 *********************************************************************/
4490 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4494 DEBUG(4,("enum_all_printers_info_1_name\n"));
4496 if ((name[0] == '\\') && (name[1] == '\\'))
4499 if (is_myname_or_ipaddr(s)) {
4500 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4503 return WERR_INVALID_NAME;
4506 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4507 /********************************************************************
4508 enum_all_printers_info_1_remote.
4509 *********************************************************************/
4511 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4513 PRINTER_INFO_1 *printer;
4514 fstring printername;
4517 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4518 WERROR result = WERR_OK;
4520 /* JFM: currently it's more a place holder than anything else.
4521 * In the spooler world there is a notion of server registration.
4522 * the print servers are registered on the PDC (in the same domain)
4524 * We should have a TDB here. The registration is done thru an
4525 * undocumented RPC call.
4528 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4533 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4534 slprintf(desc, sizeof(desc)-1,"%s", name);
4535 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4537 init_unistr(&printer->description, desc);
4538 init_unistr(&printer->name, printername);
4539 init_unistr(&printer->comment, comment);
4540 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4542 /* check the required size. */
4543 *needed += spoolss_size_printer_info_1(printer);
4545 if (*needed > offered) {
4546 result = WERR_INSUFFICIENT_BUFFER;
4550 if (!rpcbuf_alloc_size(buffer, *needed)) {
4551 result = WERR_NOMEM;
4555 /* fill the buffer with the structures */
4556 smb_io_printer_info_1("", buffer, printer, 0);
4562 if ( !W_ERROR_IS_OK(result) )
4570 /********************************************************************
4571 enum_all_printers_info_1_network.
4572 *********************************************************************/
4574 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4578 DEBUG(4,("enum_all_printers_info_1_network\n"));
4580 /* If we respond to a enum_printers level 1 on our name with flags
4581 set to PRINTER_ENUM_REMOTE with a list of printers then these
4582 printers incorrectly appear in the APW browse list.
4583 Specifically the printers for the server appear at the workgroup
4584 level where all the other servers in the domain are
4585 listed. Windows responds to this call with a
4586 WERR_CAN_NOT_COMPLETE so we should do the same. */
4588 if (name[0] == '\\' && name[1] == '\\')
4591 if (is_myname_or_ipaddr(s))
4592 return WERR_CAN_NOT_COMPLETE;
4594 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4597 /********************************************************************
4598 * api_spoolss_enumprinters
4600 * called from api_spoolss_enumprinters (see this to understand)
4601 ********************************************************************/
4603 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4606 struct share_iterator *shares;
4607 struct share_params *printer;
4608 PRINTER_INFO_2 *printers=NULL;
4609 WERROR result = WERR_OK;
4613 if (!(shares = share_list_all(NULL))) {
4614 DEBUG(5, ("Could not list printers\n"));
4615 return WERR_ACCESS_DENIED;
4618 while ((printer = next_printer(shares)) != NULL) {
4619 PRINTER_INFO_2 current_prt;
4621 DEBUG(4,("Found a printer in smb.conf: %s\n",
4622 lp_servicename(printer->service)));
4624 if (!construct_printer_info_2(NULL, ¤t_prt,
4628 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2,
4630 DEBUG(2,("enum_all_printers_info_2: failed to enlarge "
4631 "printers buffer!\n"));
4633 TALLOC_FREE(shares);
4637 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n",
4640 memcpy(&printers[*returned], ¤t_prt,
4641 sizeof(PRINTER_INFO_2));
4643 TALLOC_FREE(printer);
4646 /* check the required size. */
4647 for (i=0; i<*returned; i++)
4648 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4650 if (*needed > offered) {
4651 result = WERR_INSUFFICIENT_BUFFER;
4655 if (!rpcbuf_alloc_size(buffer, *needed)) {
4656 result = WERR_NOMEM;
4660 /* fill the buffer with the structures */
4661 for (i=0; i<*returned; i++)
4662 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4667 for (i=0; i<*returned; i++)
4668 free_devmode(printers[i].devmode);
4670 SAFE_FREE(printers);
4671 TALLOC_FREE(shares);
4673 if ( !W_ERROR_IS_OK(result) )
4679 /********************************************************************
4680 * handle enumeration of printers at level 1
4681 ********************************************************************/
4683 static WERROR enumprinters_level1( uint32 flags, fstring name,
4684 RPC_BUFFER *buffer, uint32 offered,
4685 uint32 *needed, uint32 *returned)
4687 /* Not all the flags are equals */
4689 if (flags & PRINTER_ENUM_LOCAL)
4690 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4692 if (flags & PRINTER_ENUM_NAME)
4693 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4695 #if 0 /* JERRY - disabled for now */
4696 if (flags & PRINTER_ENUM_REMOTE)
4697 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4700 if (flags & PRINTER_ENUM_NETWORK)
4701 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4703 return WERR_OK; /* NT4sp5 does that */
4706 /********************************************************************
4707 * handle enumeration of printers at level 2
4708 ********************************************************************/
4710 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4711 RPC_BUFFER *buffer, uint32 offered,
4712 uint32 *needed, uint32 *returned)
4714 char *s = servername;
4716 if (flags & PRINTER_ENUM_LOCAL) {
4717 return enum_all_printers_info_2(buffer, offered, needed, returned);
4720 if (flags & PRINTER_ENUM_NAME) {
4721 if ((servername[0] == '\\') && (servername[1] == '\\'))
4723 if (is_myname_or_ipaddr(s))
4724 return enum_all_printers_info_2(buffer, offered, needed, returned);
4726 return WERR_INVALID_NAME;
4729 if (flags & PRINTER_ENUM_REMOTE)
4730 return WERR_UNKNOWN_LEVEL;
4735 /********************************************************************
4736 * handle enumeration of printers at level 5
4737 ********************************************************************/
4739 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4740 RPC_BUFFER *buffer, uint32 offered,
4741 uint32 *needed, uint32 *returned)
4743 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4747 /********************************************************************
4748 * api_spoolss_enumprinters
4750 * called from api_spoolss_enumprinters (see this to understand)
4751 ********************************************************************/
4753 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4755 uint32 flags = q_u->flags;
4756 UNISTR2 *servername = &q_u->servername;
4757 uint32 level = q_u->level;
4758 RPC_BUFFER *buffer = NULL;
4759 uint32 offered = q_u->offered;
4760 uint32 *needed = &r_u->needed;
4761 uint32 *returned = &r_u->returned;
4765 /* that's an [in out] buffer */
4767 if (!q_u->buffer && (offered!=0)) {
4768 return WERR_INVALID_PARAM;
4771 rpcbuf_move(q_u->buffer, &r_u->buffer);
4772 buffer = r_u->buffer;
4774 DEBUG(4,("_spoolss_enumprinters\n"));
4781 * flags==PRINTER_ENUM_NAME
4782 * if name=="" then enumerates all printers
4783 * if name!="" then enumerate the printer
4784 * flags==PRINTER_ENUM_REMOTE
4785 * name is NULL, enumerate printers
4786 * Level 2: name!="" enumerates printers, name can't be NULL
4787 * Level 3: doesn't exist
4788 * Level 4: does a local registry lookup
4789 * Level 5: same as Level 2
4792 unistr2_to_ascii(name, servername, sizeof(name)-1);
4797 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4799 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4801 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4806 return WERR_UNKNOWN_LEVEL;
4809 /****************************************************************************
4810 ****************************************************************************/
4812 static WERROR getprinter_level_0(Printer_entry *print_hnd,
4813 const struct share_params *params,
4814 RPC_BUFFER *buffer, uint32 offered,
4817 PRINTER_INFO_0 *printer=NULL;
4818 WERROR result = WERR_OK;
4820 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4823 construct_printer_info_0(print_hnd, printer, params);
4825 /* check the required size. */
4826 *needed += spoolss_size_printer_info_0(printer);
4828 if (*needed > offered) {
4829 result = WERR_INSUFFICIENT_BUFFER;
4833 if (!rpcbuf_alloc_size(buffer, *needed)) {
4834 result = WERR_NOMEM;
4838 /* fill the buffer with the structures */
4839 smb_io_printer_info_0("", buffer, printer, 0);
4849 /****************************************************************************
4850 ****************************************************************************/
4852 static WERROR getprinter_level_1(Printer_entry *print_hnd,
4853 const struct share_params *params,
4854 RPC_BUFFER *buffer, uint32 offered,
4857 PRINTER_INFO_1 *printer=NULL;
4858 WERROR result = WERR_OK;
4860 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4863 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer,
4866 /* check the required size. */
4867 *needed += spoolss_size_printer_info_1(printer);
4869 if (*needed > offered) {
4870 result = WERR_INSUFFICIENT_BUFFER;
4874 if (!rpcbuf_alloc_size(buffer, *needed)) {
4875 result = WERR_NOMEM;
4879 /* fill the buffer with the structures */
4880 smb_io_printer_info_1("", buffer, printer, 0);
4889 /****************************************************************************
4890 ****************************************************************************/
4892 static WERROR getprinter_level_2(Printer_entry *print_hnd,
4893 const struct share_params *params,
4894 RPC_BUFFER *buffer, uint32 offered,
4897 PRINTER_INFO_2 *printer=NULL;
4898 WERROR result = WERR_OK;
4900 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4903 construct_printer_info_2(print_hnd, printer, params);
4905 /* check the required size. */
4906 *needed += spoolss_size_printer_info_2(printer);
4908 if (*needed > offered) {
4909 result = WERR_INSUFFICIENT_BUFFER;
4913 if (!rpcbuf_alloc_size(buffer, *needed)) {
4914 result = WERR_NOMEM;
4918 /* fill the buffer with the structures */
4919 if (!smb_io_printer_info_2("", buffer, printer, 0))
4920 result = WERR_NOMEM;
4924 free_printer_info_2(printer);
4929 /****************************************************************************
4930 ****************************************************************************/
4932 static WERROR getprinter_level_3(Printer_entry *print_hnd,
4933 const struct share_params *params,
4934 RPC_BUFFER *buffer, uint32 offered,
4937 PRINTER_INFO_3 *printer=NULL;
4938 WERROR result = WERR_OK;
4940 if (!construct_printer_info_3(print_hnd, &printer, params))
4943 /* check the required size. */
4944 *needed += spoolss_size_printer_info_3(printer);
4946 if (*needed > offered) {
4947 result = WERR_INSUFFICIENT_BUFFER;
4951 if (!rpcbuf_alloc_size(buffer, *needed)) {
4952 result = WERR_NOMEM;
4956 /* fill the buffer with the structures */
4957 smb_io_printer_info_3("", buffer, printer, 0);
4961 free_printer_info_3(printer);
4966 /****************************************************************************
4967 ****************************************************************************/
4969 static WERROR getprinter_level_4(Printer_entry *print_hnd,
4970 const struct share_params *params,
4971 RPC_BUFFER *buffer, uint32 offered,
4974 PRINTER_INFO_4 *printer=NULL;
4975 WERROR result = WERR_OK;
4977 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4980 if (!construct_printer_info_4(print_hnd, printer, params)) {
4985 /* check the required size. */
4986 *needed += spoolss_size_printer_info_4(printer);
4988 if (*needed > offered) {
4989 result = WERR_INSUFFICIENT_BUFFER;
4993 if (!rpcbuf_alloc_size(buffer, *needed)) {
4994 result = WERR_NOMEM;
4998 /* fill the buffer with the structures */
4999 smb_io_printer_info_4("", buffer, printer, 0);
5003 free_printer_info_4(printer);
5008 /****************************************************************************
5009 ****************************************************************************/
5011 static WERROR getprinter_level_5(Printer_entry *print_hnd,
5012 const struct share_params *params,
5013 RPC_BUFFER *buffer, uint32 offered,
5016 PRINTER_INFO_5 *printer=NULL;
5017 WERROR result = WERR_OK;
5019 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
5022 if (!construct_printer_info_5(print_hnd, printer, params)) {
5023 free_printer_info_5(printer);
5027 /* check the required size. */
5028 *needed += spoolss_size_printer_info_5(printer);
5030 if (*needed > offered) {
5031 result = WERR_INSUFFICIENT_BUFFER;
5035 if (!rpcbuf_alloc_size(buffer, *needed)) {
5036 result = WERR_NOMEM;
5040 /* fill the buffer with the structures */
5041 smb_io_printer_info_5("", buffer, printer, 0);
5045 free_printer_info_5(printer);
5050 static WERROR getprinter_level_6(Printer_entry *print_hnd,
5051 const struct share_params *params,
5052 RPC_BUFFER *buffer, uint32 offered,
5055 PRINTER_INFO_6 *printer;
5056 WERROR result = WERR_OK;
5058 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5062 if (!construct_printer_info_6(print_hnd, printer, params)) {
5063 free_printer_info_6(printer);
5067 /* check the required size. */
5068 *needed += spoolss_size_printer_info_6(printer);
5070 if (*needed > offered) {
5071 result = WERR_INSUFFICIENT_BUFFER;
5075 if (!rpcbuf_alloc_size(buffer, *needed)) {
5076 result = WERR_NOMEM;
5080 /* fill the buffer with the structures */
5081 smb_io_printer_info_6("", buffer, printer, 0);
5085 free_printer_info_6(printer);
5090 static WERROR getprinter_level_7(Printer_entry *print_hnd,
5091 const struct share_params *params,
5092 RPC_BUFFER *buffer, uint32 offered,
5095 PRINTER_INFO_7 *printer=NULL;
5096 WERROR result = WERR_OK;
5098 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5101 if (!construct_printer_info_7(print_hnd, printer, params))
5104 /* check the required size. */
5105 *needed += spoolss_size_printer_info_7(printer);
5107 if (*needed > offered) {
5108 result = WERR_INSUFFICIENT_BUFFER;
5112 if (!rpcbuf_alloc_size(buffer, *needed)) {
5113 result = WERR_NOMEM;
5118 /* fill the buffer with the structures */
5119 smb_io_printer_info_7("", buffer, printer, 0);
5123 free_printer_info_7(printer);
5128 /****************************************************************************
5129 ****************************************************************************/
5131 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5133 POLICY_HND *handle = &q_u->handle;
5134 uint32 level = q_u->level;
5135 RPC_BUFFER *buffer = NULL;
5136 uint32 offered = q_u->offered;
5137 uint32 *needed = &r_u->needed;
5138 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5139 struct share_params *params;
5143 /* that's an [in out] buffer */
5145 if (!q_u->buffer && (offered!=0)) {
5146 return WERR_INVALID_PARAM;
5149 rpcbuf_move(q_u->buffer, &r_u->buffer);
5150 buffer = r_u->buffer;
5154 if (!get_printer_snum(p, handle, &snum, ¶ms))
5159 return getprinter_level_0(Printer, params, buffer, offered,
5162 return getprinter_level_1(Printer, params, buffer, offered,
5165 return getprinter_level_2(Printer, params, buffer, offered,
5168 return getprinter_level_3(Printer, params, buffer, offered,
5171 return getprinter_level_4(Printer, params, buffer, offered,
5174 return getprinter_level_5(Printer, params, buffer, offered,
5177 return getprinter_level_6(Printer, params, buffer, offered,
5180 return getprinter_level_7(Printer, params, buffer, offered,
5183 return WERR_UNKNOWN_LEVEL;
5186 /********************************************************************
5187 * fill a DRIVER_INFO_1 struct
5188 ********************************************************************/
5190 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5192 init_unistr( &info->name, driver.info_3->name);
5195 /********************************************************************
5196 * construct_printer_driver_info_1
5197 ********************************************************************/
5199 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5201 NT_PRINTER_INFO_LEVEL *printer = NULL;
5202 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5204 ZERO_STRUCT(driver);
5206 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5207 return WERR_INVALID_PRINTER_NAME;
5209 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5210 free_a_printer(&printer, 2);
5211 return WERR_UNKNOWN_PRINTER_DRIVER;
5214 fill_printer_driver_info_1(info, driver, servername, architecture);
5216 free_a_printer(&printer,2);
5221 /********************************************************************
5222 * construct_printer_driver_info_2
5223 * fill a printer_info_2 struct
5224 ********************************************************************/
5226 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5230 info->version=driver.info_3->cversion;
5232 init_unistr( &info->name, driver.info_3->name );
5233 init_unistr( &info->architecture, driver.info_3->environment );
5236 if (strlen(driver.info_3->driverpath)) {
5237 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5238 init_unistr( &info->driverpath, temp );
5240 init_unistr( &info->driverpath, "" );
5242 if (strlen(driver.info_3->datafile)) {
5243 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5244 init_unistr( &info->datafile, temp );
5246 init_unistr( &info->datafile, "" );
5248 if (strlen(driver.info_3->configfile)) {
5249 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5250 init_unistr( &info->configfile, temp );
5252 init_unistr( &info->configfile, "" );
5255 /********************************************************************
5256 * construct_printer_driver_info_2
5257 * fill a printer_info_2 struct
5258 ********************************************************************/
5260 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5262 NT_PRINTER_INFO_LEVEL *printer = NULL;
5263 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5265 ZERO_STRUCT(printer);
5266 ZERO_STRUCT(driver);
5268 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5269 return WERR_INVALID_PRINTER_NAME;
5271 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5272 free_a_printer(&printer, 2);
5273 return WERR_UNKNOWN_PRINTER_DRIVER;
5276 fill_printer_driver_info_2(info, driver, servername);
5278 free_a_printer(&printer,2);
5283 /********************************************************************
5284 * copy a strings array and convert to UNICODE
5286 * convert an array of ascii string to a UNICODE string
5287 ********************************************************************/
5289 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5296 DEBUG(6,("init_unistr_array\n"));
5307 v = ""; /* hack to handle null lists */
5310 /* hack to allow this to be used in places other than when generating
5311 the list of dependent files */
5314 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5318 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5320 /* add one extra unit16 for the second terminating NULL */
5322 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5323 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5330 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5335 /* special case for ""; we need to add both NULL's here */
5337 (*uni_array)[j++]=0x0000;
5338 (*uni_array)[j]=0x0000;
5341 DEBUGADD(6,("last one:done\n"));
5343 /* return size of array in uint16's */
5348 /********************************************************************
5349 * construct_printer_info_3
5350 * fill a printer_info_3 struct
5351 ********************************************************************/
5353 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5359 info->version=driver.info_3->cversion;
5361 init_unistr( &info->name, driver.info_3->name );
5362 init_unistr( &info->architecture, driver.info_3->environment );
5364 if (strlen(driver.info_3->driverpath)) {
5365 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5366 init_unistr( &info->driverpath, temp );
5368 init_unistr( &info->driverpath, "" );
5370 if (strlen(driver.info_3->datafile)) {
5371 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5372 init_unistr( &info->datafile, temp );
5374 init_unistr( &info->datafile, "" );
5376 if (strlen(driver.info_3->configfile)) {
5377 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5378 init_unistr( &info->configfile, temp );
5380 init_unistr( &info->configfile, "" );
5382 if (strlen(driver.info_3->helpfile)) {
5383 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5384 init_unistr( &info->helpfile, temp );
5386 init_unistr( &info->helpfile, "" );
5388 init_unistr( &info->monitorname, driver.info_3->monitorname );
5389 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5391 info->dependentfiles=NULL;
5392 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5395 /********************************************************************
5396 * construct_printer_info_3
5397 * fill a printer_info_3 struct
5398 ********************************************************************/
5400 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5402 NT_PRINTER_INFO_LEVEL *printer = NULL;
5403 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5405 ZERO_STRUCT(driver);
5407 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5408 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5409 if (!W_ERROR_IS_OK(status))
5410 return WERR_INVALID_PRINTER_NAME;
5412 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5413 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5418 * I put this code in during testing. Helpful when commenting out the
5419 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5420 * as win2k always queries the driver using an infor level of 6.
5421 * I've left it in (but ifdef'd out) because I'll probably
5422 * use it in experimentation again in the future. --jerry 22/01/2002
5425 if (!W_ERROR_IS_OK(status)) {
5427 * Is this a W2k client ?
5430 /* Yes - try again with a WinNT driver. */
5432 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5433 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5437 if (!W_ERROR_IS_OK(status)) {
5438 free_a_printer(&printer,2);
5439 return WERR_UNKNOWN_PRINTER_DRIVER;
5447 fill_printer_driver_info_3(info, driver, servername);
5449 free_a_printer(&printer,2);
5454 /********************************************************************
5455 * construct_printer_info_6
5456 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5457 ********************************************************************/
5459 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5465 memset(&nullstr, '\0', sizeof(fstring));
5467 info->version=driver.info_3->cversion;
5469 init_unistr( &info->name, driver.info_3->name );
5470 init_unistr( &info->architecture, driver.info_3->environment );
5472 if (strlen(driver.info_3->driverpath)) {
5473 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5474 init_unistr( &info->driverpath, temp );
5476 init_unistr( &info->driverpath, "" );
5478 if (strlen(driver.info_3->datafile)) {
5479 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5480 init_unistr( &info->datafile, temp );
5482 init_unistr( &info->datafile, "" );
5484 if (strlen(driver.info_3->configfile)) {
5485 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5486 init_unistr( &info->configfile, temp );
5488 init_unistr( &info->configfile, "" );
5490 if (strlen(driver.info_3->helpfile)) {
5491 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5492 init_unistr( &info->helpfile, temp );
5494 init_unistr( &info->helpfile, "" );
5496 init_unistr( &info->monitorname, driver.info_3->monitorname );
5497 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5499 info->dependentfiles = NULL;
5500 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5502 info->previousdrivernames=NULL;
5503 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5505 info->driver_date=0;
5508 info->driver_version_low=0;
5509 info->driver_version_high=0;
5511 init_unistr( &info->mfgname, "");
5512 init_unistr( &info->oem_url, "");
5513 init_unistr( &info->hardware_id, "");
5514 init_unistr( &info->provider, "");
5517 /********************************************************************
5518 * construct_printer_info_6
5519 * fill a printer_info_6 struct
5520 ********************************************************************/
5522 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5523 fstring servername, fstring architecture, uint32 version)
5525 NT_PRINTER_INFO_LEVEL *printer = NULL;
5526 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5529 ZERO_STRUCT(driver);
5531 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5533 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5535 if (!W_ERROR_IS_OK(status))
5536 return WERR_INVALID_PRINTER_NAME;
5538 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5540 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5542 if (!W_ERROR_IS_OK(status))
5545 * Is this a W2k client ?
5549 free_a_printer(&printer,2);
5550 return WERR_UNKNOWN_PRINTER_DRIVER;
5553 /* Yes - try again with a WinNT driver. */
5555 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5556 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5557 if (!W_ERROR_IS_OK(status)) {
5558 free_a_printer(&printer,2);
5559 return WERR_UNKNOWN_PRINTER_DRIVER;
5563 fill_printer_driver_info_6(info, driver, servername);
5565 free_a_printer(&printer,2);
5566 free_a_printer_driver(driver, 3);
5571 /****************************************************************************
5572 ****************************************************************************/
5574 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5576 SAFE_FREE(info->dependentfiles);
5579 /****************************************************************************
5580 ****************************************************************************/
5582 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5584 SAFE_FREE(info->dependentfiles);
5587 /****************************************************************************
5588 ****************************************************************************/
5590 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5592 DRIVER_INFO_1 *info=NULL;
5595 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5598 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5599 if (!W_ERROR_IS_OK(result))
5602 /* check the required size. */
5603 *needed += spoolss_size_printer_driver_info_1(info);
5605 if (*needed > offered) {
5606 result = WERR_INSUFFICIENT_BUFFER;
5610 if (!rpcbuf_alloc_size(buffer, *needed)) {
5611 result = WERR_NOMEM;
5615 /* fill the buffer with the structures */
5616 smb_io_printer_driver_info_1("", buffer, info, 0);
5625 /****************************************************************************
5626 ****************************************************************************/
5628 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5630 DRIVER_INFO_2 *info=NULL;
5633 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5636 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5637 if (!W_ERROR_IS_OK(result))
5640 /* check the required size. */
5641 *needed += spoolss_size_printer_driver_info_2(info);
5643 if (*needed > offered) {
5644 result = WERR_INSUFFICIENT_BUFFER;
5648 if (!rpcbuf_alloc_size(buffer, *needed)) {
5649 result = WERR_NOMEM;
5653 /* fill the buffer with the structures */
5654 smb_io_printer_driver_info_2("", buffer, info, 0);
5663 /****************************************************************************
5664 ****************************************************************************/
5666 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5673 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5674 if (!W_ERROR_IS_OK(result))
5677 /* check the required size. */
5678 *needed += spoolss_size_printer_driver_info_3(&info);
5680 if (*needed > offered) {
5681 result = WERR_INSUFFICIENT_BUFFER;
5685 if (!rpcbuf_alloc_size(buffer, *needed)) {
5686 result = WERR_NOMEM;
5690 /* fill the buffer with the structures */
5691 smb_io_printer_driver_info_3("", buffer, &info, 0);
5694 free_printer_driver_info_3(&info);
5699 /****************************************************************************
5700 ****************************************************************************/
5702 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5709 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5710 if (!W_ERROR_IS_OK(result))
5713 /* check the required size. */
5714 *needed += spoolss_size_printer_driver_info_6(&info);
5716 if (*needed > offered) {
5717 result = WERR_INSUFFICIENT_BUFFER;
5721 if (!rpcbuf_alloc_size(buffer, *needed)) {
5722 result = WERR_NOMEM;
5726 /* fill the buffer with the structures */
5727 smb_io_printer_driver_info_6("", buffer, &info, 0);
5730 free_printer_driver_info_6(&info);
5735 /****************************************************************************
5736 ****************************************************************************/
5738 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5740 POLICY_HND *handle = &q_u->handle;
5741 UNISTR2 *uni_arch = &q_u->architecture;
5742 uint32 level = q_u->level;
5743 uint32 clientmajorversion = q_u->clientmajorversion;
5744 RPC_BUFFER *buffer = NULL;
5745 uint32 offered = q_u->offered;
5746 uint32 *needed = &r_u->needed;
5747 uint32 *servermajorversion = &r_u->servermajorversion;
5748 uint32 *serverminorversion = &r_u->serverminorversion;
5749 Printer_entry *printer;
5752 fstring architecture;
5755 /* that's an [in out] buffer */
5757 if (!q_u->buffer && (offered!=0)) {
5758 return WERR_INVALID_PARAM;
5761 rpcbuf_move(q_u->buffer, &r_u->buffer);
5762 buffer = r_u->buffer;
5764 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5766 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5767 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5768 return WERR_INVALID_PRINTER_NAME;
5772 *servermajorversion = 0;
5773 *serverminorversion = 0;
5775 fstrcpy(servername, get_server_name( printer ));
5776 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5778 if (!get_printer_snum(p, handle, &snum, NULL))
5783 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5785 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5787 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5789 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5792 /* apparently this call is the equivalent of
5793 EnumPrinterDataEx() for the DsDriver key */
5798 return WERR_UNKNOWN_LEVEL;
5801 /****************************************************************************
5802 ****************************************************************************/
5804 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5806 POLICY_HND *handle = &q_u->handle;
5808 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5811 DEBUG(3,("Error in startpageprinter printer handle\n"));
5815 Printer->page_started=True;
5819 /****************************************************************************
5820 ****************************************************************************/
5822 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5824 POLICY_HND *handle = &q_u->handle;
5827 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5830 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5834 if (!get_printer_snum(p, handle, &snum, NULL))
5837 Printer->page_started=False;
5838 print_job_endpage(snum, Printer->jobid);
5843 /********************************************************************
5844 * api_spoolss_getprinter
5845 * called from the spoolss dispatcher
5847 ********************************************************************/
5849 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5851 POLICY_HND *handle = &q_u->handle;
5852 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5853 uint32 *jobid = &r_u->jobid;
5855 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5859 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5862 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5867 * a nice thing with NT is it doesn't listen to what you tell it.
5868 * when asked to send _only_ RAW datas, it tries to send datas
5871 * So I add checks like in NT Server ...
5874 if (info_1->p_datatype != 0) {
5875 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5876 if (strcmp(datatype, "RAW") != 0) {
5878 return WERR_INVALID_DATATYPE;
5882 /* get the share number of the printer */
5883 if (!get_printer_snum(p, handle, &snum, NULL)) {
5887 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5889 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5891 /* An error occured in print_job_start() so return an appropriate
5894 if (Printer->jobid == -1) {
5895 return map_werror_from_unix(errno);
5898 Printer->document_started=True;
5899 (*jobid) = Printer->jobid;
5904 /********************************************************************
5905 * api_spoolss_getprinter
5906 * called from the spoolss dispatcher
5908 ********************************************************************/
5910 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5912 POLICY_HND *handle = &q_u->handle;
5914 return _spoolss_enddocprinter_internal(p, handle);
5917 /****************************************************************************
5918 ****************************************************************************/
5920 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5922 POLICY_HND *handle = &q_u->handle;
5923 uint32 buffer_size = q_u->buffer_size;
5924 uint8 *buffer = q_u->buffer;
5925 uint32 *buffer_written = &q_u->buffer_size2;
5927 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5930 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5931 r_u->buffer_written = q_u->buffer_size2;
5935 if (!get_printer_snum(p, handle, &snum, NULL))
5938 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5939 (SMB_OFF_T)-1, (size_t)buffer_size);
5940 if (*buffer_written == (uint32)-1) {
5941 r_u->buffer_written = 0;
5942 if (errno == ENOSPC)
5943 return WERR_NO_SPOOL_SPACE;
5945 return WERR_ACCESS_DENIED;
5948 r_u->buffer_written = q_u->buffer_size2;
5953 /********************************************************************
5954 * api_spoolss_getprinter
5955 * called from the spoolss dispatcher
5957 ********************************************************************/
5959 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5963 WERROR errcode = WERR_BADFUNC;
5964 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5967 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5971 if (!get_printer_snum(p, handle, &snum, NULL))
5975 case PRINTER_CONTROL_PAUSE:
5976 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5980 case PRINTER_CONTROL_RESUME:
5981 case PRINTER_CONTROL_UNPAUSE:
5982 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5986 case PRINTER_CONTROL_PURGE:
5987 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5992 return WERR_UNKNOWN_LEVEL;
5998 /********************************************************************
5999 * api_spoolss_abortprinter
6000 * From MSDN: "Deletes printer's spool file if printer is configured
6002 ********************************************************************/
6004 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
6006 POLICY_HND *handle = &q_u->handle;
6007 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6009 WERROR errcode = WERR_OK;
6012 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
6016 if (!get_printer_snum(p, handle, &snum, NULL))
6019 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
6024 /********************************************************************
6025 * called by spoolss_api_setprinter
6026 * when updating a printer description
6027 ********************************************************************/
6029 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
6030 const SPOOL_PRINTER_INFO_LEVEL *info,
6031 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6033 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6037 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6039 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6040 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6041 OUR_HANDLE(handle)));
6043 result = WERR_BADFID;
6048 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6049 result = WERR_INVALID_PARAM;
6053 /* Check the user has permissions to change the security
6054 descriptor. By experimentation with two NT machines, the user
6055 requires Full Access to the printer to change security
6058 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6059 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6060 result = WERR_ACCESS_DENIED;
6064 /* NT seems to like setting the security descriptor even though
6065 nothing may have actually changed. */
6067 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
6069 if (DEBUGLEVEL >= 10) {
6073 the_acl = old_secdesc_ctr->sd->dacl;
6074 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6075 PRINTERNAME(snum), the_acl->num_aces));
6077 for (i = 0; i < the_acl->num_aces; i++) {
6080 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6082 DEBUG(10, ("%s 0x%08x\n", sid_str,
6083 the_acl->aces[i].access_mask));
6086 the_acl = secdesc_ctr->sd->dacl;
6089 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6090 PRINTERNAME(snum), the_acl->num_aces));
6092 for (i = 0; i < the_acl->num_aces; i++) {
6095 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6097 DEBUG(10, ("%s 0x%08x\n", sid_str,
6098 the_acl->aces[i].access_mask));
6101 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6105 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6106 if (!new_secdesc_ctr) {
6107 result = WERR_NOMEM;
6111 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6116 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6123 /********************************************************************
6124 Canonicalize printer info from a client
6126 ATTN: It does not matter what we set the servername to hear
6127 since we do the necessary work in get_a_printer() to set it to
6128 the correct value based on what the client sent in the
6129 _spoolss_open_printer_ex().
6130 ********************************************************************/
6132 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6134 fstring printername;
6137 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6138 "portname=%s drivername=%s comment=%s location=%s\n",
6139 info->servername, info->printername, info->sharename,
6140 info->portname, info->drivername, info->comment, info->location));
6142 /* we force some elements to "correct" values */
6143 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6144 fstrcpy(info->sharename, lp_servicename(snum));
6146 /* check to see if we allow printername != sharename */
6148 if ( lp_force_printername(snum) ) {
6149 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6150 global_myname(), info->sharename );
6153 /* make sure printername is in \\server\printername format */
6155 fstrcpy( printername, info->printername );
6157 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6158 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6162 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6163 global_myname(), p );
6166 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6167 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6174 /****************************************************************************
6175 ****************************************************************************/
6177 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
6179 char *cmd = lp_addport_cmd();
6183 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6184 BOOL is_print_op = False;
6187 return WERR_ACCESS_DENIED;
6190 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
6193 is_print_op = user_has_privileges( token, &se_printop );
6195 DEBUG(10,("Running [%s]\n", command));
6197 /********* BEGIN SePrintOperatorPrivilege **********/
6202 ret = smbrun(command, &fd);
6207 /********* END SePrintOperatorPrivilege **********/
6209 DEBUGADD(10,("returned [%d]\n", ret));
6214 return WERR_ACCESS_DENIED;
6220 /****************************************************************************
6221 ****************************************************************************/
6223 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6225 char *cmd = lp_addprinter_cmd();
6231 fstring remote_machine = "%m";
6232 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6233 BOOL is_print_op = False;
6235 standard_sub_basic(current_user_info.smb_name,
6236 current_user_info.domain,
6237 remote_machine,sizeof(remote_machine));
6239 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6240 cmd, printer->info_2->printername, printer->info_2->sharename,
6241 printer->info_2->portname, printer->info_2->drivername,
6242 printer->info_2->location, printer->info_2->comment, remote_machine);
6245 is_print_op = user_has_privileges( token, &se_printop );
6247 DEBUG(10,("Running [%s]\n", command));
6249 /********* BEGIN SePrintOperatorPrivilege **********/
6254 if ( (ret = smbrun(command, &fd)) == 0 ) {
6255 /* Tell everyone we updated smb.conf. */
6256 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6262 /********* END SePrintOperatorPrivilege **********/
6264 DEBUGADD(10,("returned [%d]\n", ret));
6272 /* reload our services immediately */
6273 reload_services( False );
6276 /* Get lines and convert them back to dos-codepage */
6277 qlines = fd_lines_load(fd, &numlines, 0);
6278 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6281 /* Set the portname to what the script says the portname should be. */
6282 /* but don't require anything to be return from the script exit a good error code */
6285 /* Set the portname to what the script says the portname should be. */
6286 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6287 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6290 file_lines_free(qlines);
6295 /********************************************************************
6296 * Called by spoolss_api_setprinter
6297 * when updating a printer description.
6298 ********************************************************************/
6300 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6301 const SPOOL_PRINTER_INFO_LEVEL *info,
6302 DEVICEMODE *devmode)
6305 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6306 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6311 DEBUG(8,("update_printer\n"));
6316 result = WERR_BADFID;
6320 if (!get_printer_snum(p, handle, &snum, NULL)) {
6321 result = WERR_BADFID;
6325 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6326 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6327 result = WERR_BADFID;
6331 DEBUGADD(8,("Converting info_2 struct\n"));
6334 * convert_printer_info converts the incoming
6335 * info from the client and overwrites the info
6336 * just read from the tdb in the pointer 'printer'.
6339 if (!convert_printer_info(info, printer, level)) {
6340 result = WERR_NOMEM;
6345 /* we have a valid devmode
6346 convert it and link it*/
6348 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6349 if (!convert_devicemode(printer->info_2->printername, devmode,
6350 &printer->info_2->devmode)) {
6351 result = WERR_NOMEM;
6356 /* Do sanity check on the requested changes for Samba */
6358 if (!check_printer_ok(printer->info_2, snum)) {
6359 result = WERR_INVALID_PARAM;
6363 /* FIXME!!! If the driver has changed we really should verify that
6364 it is installed before doing much else --jerry */
6366 /* Check calling user has permission to update printer description */
6368 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6369 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6370 result = WERR_ACCESS_DENIED;
6374 /* Call addprinter hook */
6375 /* Check changes to see if this is really needed */
6377 if ( *lp_addprinter_cmd()
6378 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6379 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6380 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6381 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6383 /* add_printer_hook() will call reload_services() */
6385 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6386 result = WERR_ACCESS_DENIED;
6392 * When a *new* driver is bound to a printer, the drivername is used to
6393 * lookup previously saved driver initialization info, which is then
6394 * bound to the printer, simulating what happens in the Windows arch.
6396 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6398 if (!set_driver_init(printer, 2))
6400 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6401 printer->info_2->drivername));
6404 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6405 printer->info_2->drivername));
6407 notify_printer_driver(snum, printer->info_2->drivername);
6411 * flag which changes actually occured. This is a small subset of
6412 * all the possible changes. We also have to update things in the
6416 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6417 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6418 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6419 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6421 notify_printer_comment(snum, printer->info_2->comment);
6424 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6425 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6426 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6427 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6429 notify_printer_sharename(snum, printer->info_2->sharename);
6432 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6435 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6438 pname = printer->info_2->printername;
6441 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6442 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6443 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6445 notify_printer_printername( snum, pname );
6448 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6449 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6450 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6451 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6453 notify_printer_port(snum, printer->info_2->portname);
6456 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6457 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6458 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6459 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6461 notify_printer_location(snum, printer->info_2->location);
6464 /* here we need to update some more DsSpooler keys */
6465 /* uNCName, serverName, shortServerName */
6467 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6468 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6469 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6470 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6471 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6473 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6474 global_myname(), printer->info_2->sharename );
6475 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6476 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6477 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6479 /* Update printer info */
6480 result = mod_a_printer(printer, 2);
6483 free_a_printer(&printer, 2);
6484 free_a_printer(&old_printer, 2);
6490 /****************************************************************************
6491 ****************************************************************************/
6492 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6493 const SPOOL_PRINTER_INFO_LEVEL *info)
6496 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6498 Printer_entry *Printer;
6500 if ( lp_security() != SEC_ADS ) {
6501 return WERR_UNKNOWN_LEVEL;
6504 Printer = find_printer_index_by_hnd(p, handle);
6506 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6511 if (!get_printer_snum(p, handle, &snum, NULL))
6514 nt_printer_publish(Printer, snum, info7->action);
6518 return WERR_UNKNOWN_LEVEL;
6521 /****************************************************************************
6522 ****************************************************************************/
6524 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6526 POLICY_HND *handle = &q_u->handle;
6527 uint32 level = q_u->level;
6528 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6529 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6530 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6531 uint32 command = q_u->command;
6534 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6537 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6541 /* check the level */
6544 return control_printer(handle, command, p);
6546 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6547 if (!W_ERROR_IS_OK(result))
6550 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6553 return update_printer_sec(handle, level, info, p,
6556 return publish_or_unpublish_printer(p, handle, info);
6558 return WERR_UNKNOWN_LEVEL;
6562 /****************************************************************************
6563 ****************************************************************************/
6565 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6567 POLICY_HND *handle = &q_u->handle;
6568 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6571 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6575 if (Printer->notify.client_connected==True) {
6578 if ( Printer->printer_type == SPLHND_SERVER)
6580 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6581 !get_printer_snum(p, handle, &snum, NULL) )
6584 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6587 Printer->notify.flags=0;
6588 Printer->notify.options=0;
6589 Printer->notify.localmachine[0]='\0';
6590 Printer->notify.printerlocal=0;
6591 if (Printer->notify.option)
6592 free_spool_notify_option(&Printer->notify.option);
6593 Printer->notify.client_connected=False;
6598 /****************************************************************************
6599 ****************************************************************************/
6601 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6603 /* that's an [in out] buffer */
6605 if (!q_u->buffer && (q_u->offered!=0)) {
6606 return WERR_INVALID_PARAM;
6609 rpcbuf_move(q_u->buffer, &r_u->buffer);
6612 return WERR_INVALID_PARAM; /* this is what a NT server
6613 returns for AddJob. AddJob
6614 must fail on non-local
6618 /****************************************************************************
6619 ****************************************************************************/
6621 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6622 int position, int snum,
6623 const NT_PRINTER_INFO_LEVEL *ntprinter)
6627 t=gmtime(&queue->time);
6629 job_info->jobid=queue->job;
6630 init_unistr(&job_info->printername, lp_servicename(snum));
6631 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6632 init_unistr(&job_info->username, queue->fs_user);
6633 init_unistr(&job_info->document, queue->fs_file);
6634 init_unistr(&job_info->datatype, "RAW");
6635 init_unistr(&job_info->text_status, "");
6636 job_info->status=nt_printj_status(queue->status);
6637 job_info->priority=queue->priority;
6638 job_info->position=position;
6639 job_info->totalpages=queue->page_count;
6640 job_info->pagesprinted=0;
6642 make_systemtime(&job_info->submitted, t);
6645 /****************************************************************************
6646 ****************************************************************************/
6648 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6649 int position, int snum,
6650 const NT_PRINTER_INFO_LEVEL *ntprinter,
6651 DEVICEMODE *devmode)
6655 t=gmtime(&queue->time);
6657 job_info->jobid=queue->job;
6659 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6661 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6662 init_unistr(&job_info->username, queue->fs_user);
6663 init_unistr(&job_info->document, queue->fs_file);
6664 init_unistr(&job_info->notifyname, queue->fs_user);
6665 init_unistr(&job_info->datatype, "RAW");
6666 init_unistr(&job_info->printprocessor, "winprint");
6667 init_unistr(&job_info->parameters, "");
6668 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6669 init_unistr(&job_info->text_status, "");
6671 /* and here the security descriptor */
6673 job_info->status=nt_printj_status(queue->status);
6674 job_info->priority=queue->priority;
6675 job_info->position=position;
6676 job_info->starttime=0;
6677 job_info->untiltime=0;
6678 job_info->totalpages=queue->page_count;
6679 job_info->size=queue->size;
6680 make_systemtime(&(job_info->submitted), t);
6681 job_info->timeelapsed=0;
6682 job_info->pagesprinted=0;
6684 job_info->devmode = devmode;
6689 /****************************************************************************
6690 Enumjobs at level 1.
6691 ****************************************************************************/
6693 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6694 const NT_PRINTER_INFO_LEVEL *ntprinter,
6695 RPC_BUFFER *buffer, uint32 offered,
6696 uint32 *needed, uint32 *returned)
6700 WERROR result = WERR_OK;
6702 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6708 for (i=0; i<*returned; i++)
6709 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6711 /* check the required size. */
6712 for (i=0; i<*returned; i++)
6713 (*needed) += spoolss_size_job_info_1(&info[i]);
6715 if (*needed > offered) {
6716 result = WERR_INSUFFICIENT_BUFFER;
6720 if (!rpcbuf_alloc_size(buffer, *needed)) {
6721 result = WERR_NOMEM;
6725 /* fill the buffer with the structures */
6726 for (i=0; i<*returned; i++)
6727 smb_io_job_info_1("", buffer, &info[i], 0);
6733 if ( !W_ERROR_IS_OK(result) )
6739 /****************************************************************************
6740 Enumjobs at level 2.
6741 ****************************************************************************/
6743 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6744 const NT_PRINTER_INFO_LEVEL *ntprinter,
6745 RPC_BUFFER *buffer, uint32 offered,
6746 uint32 *needed, uint32 *returned)
6748 JOB_INFO_2 *info = NULL;
6750 WERROR result = WERR_OK;
6751 DEVICEMODE *devmode = NULL;
6753 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6758 /* this should not be a failure condition if the devmode is NULL */
6760 devmode = construct_dev_mode(lp_const_servicename(snum));
6762 for (i=0; i<*returned; i++)
6763 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6765 /* check the required size. */
6766 for (i=0; i<*returned; i++)
6767 (*needed) += spoolss_size_job_info_2(&info[i]);
6769 if (*needed > offered) {
6770 result = WERR_INSUFFICIENT_BUFFER;
6774 if (!rpcbuf_alloc_size(buffer, *needed)) {
6775 result = WERR_NOMEM;
6779 /* fill the buffer with the structures */
6780 for (i=0; i<*returned; i++)
6781 smb_io_job_info_2("", buffer, &info[i], 0);
6784 free_devmode(devmode);
6787 if ( !W_ERROR_IS_OK(result) )
6794 /****************************************************************************
6796 ****************************************************************************/
6798 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6800 POLICY_HND *handle = &q_u->handle;
6801 uint32 level = q_u->level;
6802 RPC_BUFFER *buffer = NULL;
6803 uint32 offered = q_u->offered;
6804 uint32 *needed = &r_u->needed;
6805 uint32 *returned = &r_u->returned;
6807 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6809 print_status_struct prt_status;
6810 print_queue_struct *queue=NULL;
6812 /* that's an [in out] buffer */
6814 if (!q_u->buffer && (offered!=0)) {
6815 return WERR_INVALID_PARAM;
6818 rpcbuf_move(q_u->buffer, &r_u->buffer);
6819 buffer = r_u->buffer;
6821 DEBUG(4,("_spoolss_enumjobs\n"));
6826 /* lookup the printer snum and tdb entry */
6828 if (!get_printer_snum(p, handle, &snum, NULL))
6831 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6832 if ( !W_ERROR_IS_OK(wret) )
6835 *returned = print_queue_status(snum, &queue, &prt_status);
6836 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6838 if (*returned == 0) {
6840 free_a_printer(&ntprinter, 2);
6846 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6849 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6853 wret = WERR_UNKNOWN_LEVEL;
6858 free_a_printer( &ntprinter, 2 );
6862 /****************************************************************************
6863 ****************************************************************************/
6865 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6870 /****************************************************************************
6871 ****************************************************************************/
6873 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6875 POLICY_HND *handle = &q_u->handle;
6876 uint32 jobid = q_u->jobid;
6877 uint32 command = q_u->command;
6880 WERROR errcode = WERR_BADFUNC;
6882 if (!get_printer_snum(p, handle, &snum, NULL)) {
6886 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6887 return WERR_INVALID_PRINTER_NAME;
6891 case JOB_CONTROL_CANCEL:
6892 case JOB_CONTROL_DELETE:
6893 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6897 case JOB_CONTROL_PAUSE:
6898 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6902 case JOB_CONTROL_RESTART:
6903 case JOB_CONTROL_RESUME:
6904 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6909 return WERR_UNKNOWN_LEVEL;
6915 /****************************************************************************
6916 Enumerates all printer drivers at level 1.
6917 ****************************************************************************/
6919 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6924 fstring *list = NULL;
6925 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6926 DRIVER_INFO_1 *driver_info_1=NULL;
6927 WERROR result = WERR_OK;
6931 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6933 ndrivers=get_ntdrivers(&list, architecture, version);
6934 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6936 if(ndrivers == -1) {
6937 SAFE_FREE(driver_info_1);
6942 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6943 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6949 for (i=0; i<ndrivers; i++) {
6951 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6952 ZERO_STRUCT(driver);
6953 status = get_a_printer_driver(&driver, 3, list[i],
6954 architecture, version);
6955 if (!W_ERROR_IS_OK(status)) {
6957 SAFE_FREE(driver_info_1);
6960 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6961 free_a_printer_driver(driver, 3);
6964 *returned+=ndrivers;
6968 /* check the required size. */
6969 for (i=0; i<*returned; i++) {
6970 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6971 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6974 if (*needed > offered) {
6975 result = WERR_INSUFFICIENT_BUFFER;
6979 if (!rpcbuf_alloc_size(buffer, *needed)) {
6980 result = WERR_NOMEM;
6984 /* fill the buffer with the driver structures */
6985 for (i=0; i<*returned; i++) {
6986 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6987 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6991 SAFE_FREE(driver_info_1);
6993 if ( !W_ERROR_IS_OK(result) )
6999 /****************************************************************************
7000 Enumerates all printer drivers at level 2.
7001 ****************************************************************************/
7003 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7008 fstring *list = NULL;
7009 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7010 DRIVER_INFO_2 *driver_info_2=NULL;
7011 WERROR result = WERR_OK;
7015 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7017 ndrivers=get_ntdrivers(&list, architecture, version);
7018 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7020 if(ndrivers == -1) {
7021 SAFE_FREE(driver_info_2);
7026 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7027 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7033 for (i=0; i<ndrivers; i++) {
7036 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7037 ZERO_STRUCT(driver);
7038 status = get_a_printer_driver(&driver, 3, list[i],
7039 architecture, version);
7040 if (!W_ERROR_IS_OK(status)) {
7042 SAFE_FREE(driver_info_2);
7045 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7046 free_a_printer_driver(driver, 3);
7049 *returned+=ndrivers;
7053 /* check the required size. */
7054 for (i=0; i<*returned; i++) {
7055 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7056 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7059 if (*needed > offered) {
7060 result = WERR_INSUFFICIENT_BUFFER;
7064 if (!rpcbuf_alloc_size(buffer, *needed)) {
7065 result = WERR_NOMEM;
7069 /* fill the buffer with the form structures */
7070 for (i=0; i<*returned; i++) {
7071 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7072 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7076 SAFE_FREE(driver_info_2);
7078 if ( !W_ERROR_IS_OK(result) )
7084 /****************************************************************************
7085 Enumerates all printer drivers at level 3.
7086 ****************************************************************************/
7088 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7093 fstring *list = NULL;
7094 DRIVER_INFO_3 *driver_info_3=NULL;
7095 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7096 WERROR result = WERR_OK;
7100 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7102 ndrivers=get_ntdrivers(&list, architecture, version);
7103 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7105 if(ndrivers == -1) {
7106 SAFE_FREE(driver_info_3);
7111 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7112 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7118 for (i=0; i<ndrivers; i++) {
7121 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7122 ZERO_STRUCT(driver);
7123 status = get_a_printer_driver(&driver, 3, list[i],
7124 architecture, version);
7125 if (!W_ERROR_IS_OK(status)) {
7127 SAFE_FREE(driver_info_3);
7130 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7131 free_a_printer_driver(driver, 3);
7134 *returned+=ndrivers;
7138 /* check the required size. */
7139 for (i=0; i<*returned; i++) {
7140 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7141 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7144 if (*needed > offered) {
7145 result = WERR_INSUFFICIENT_BUFFER;
7149 if (!rpcbuf_alloc_size(buffer, *needed)) {
7150 result = WERR_NOMEM;
7154 /* fill the buffer with the driver structures */
7155 for (i=0; i<*returned; i++) {
7156 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7157 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7161 for (i=0; i<*returned; i++) {
7162 SAFE_FREE(driver_info_3[i].dependentfiles);
7165 SAFE_FREE(driver_info_3);
7167 if ( !W_ERROR_IS_OK(result) )
7173 /****************************************************************************
7174 Enumerates all printer drivers.
7175 ****************************************************************************/
7177 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7179 uint32 level = q_u->level;
7180 RPC_BUFFER *buffer = NULL;
7181 uint32 offered = q_u->offered;
7182 uint32 *needed = &r_u->needed;
7183 uint32 *returned = &r_u->returned;
7186 fstring architecture;
7188 /* that's an [in out] buffer */
7190 if (!q_u->buffer && (offered!=0)) {
7191 return WERR_INVALID_PARAM;
7194 rpcbuf_move(q_u->buffer, &r_u->buffer);
7195 buffer = r_u->buffer;
7197 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7202 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7203 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7205 if ( !is_myname_or_ipaddr( servername ) )
7206 return WERR_UNKNOWN_PRINTER_DRIVER;
7210 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7212 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7214 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7216 return WERR_UNKNOWN_LEVEL;
7220 /****************************************************************************
7221 ****************************************************************************/
7223 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7225 form->flag=list->flag;
7226 init_unistr(&form->name, list->name);
7227 form->width=list->width;
7228 form->length=list->length;
7229 form->left=list->left;
7230 form->top=list->top;
7231 form->right=list->right;
7232 form->bottom=list->bottom;
7235 /****************************************************************************
7236 ****************************************************************************/
7238 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7240 uint32 level = q_u->level;
7241 RPC_BUFFER *buffer = NULL;
7242 uint32 offered = q_u->offered;
7243 uint32 *needed = &r_u->needed;
7244 uint32 *numofforms = &r_u->numofforms;
7245 uint32 numbuiltinforms;
7247 nt_forms_struct *list=NULL;
7248 nt_forms_struct *builtinlist=NULL;
7253 /* that's an [in out] buffer */
7255 if (!q_u->buffer && (offered!=0) ) {
7256 return WERR_INVALID_PARAM;
7259 rpcbuf_move(q_u->buffer, &r_u->buffer);
7260 buffer = r_u->buffer;
7262 DEBUG(4,("_spoolss_enumforms\n"));
7263 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7264 DEBUGADD(5,("Info level [%d]\n", level));
7266 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7267 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7268 *numofforms = get_ntforms(&list);
7269 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7270 *numofforms += numbuiltinforms;
7272 if (*numofforms == 0) {
7273 SAFE_FREE(builtinlist);
7275 return WERR_NO_MORE_ITEMS;
7280 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7281 SAFE_FREE(builtinlist);
7287 /* construct the list of form structures */
7288 for (i=0; i<numbuiltinforms; i++) {
7289 DEBUGADD(6,("Filling form number [%d]\n",i));
7290 fill_form_1(&forms_1[i], &builtinlist[i]);
7293 SAFE_FREE(builtinlist);
7295 for (; i<*numofforms; i++) {
7296 DEBUGADD(6,("Filling form number [%d]\n",i));
7297 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7302 /* check the required size. */
7303 for (i=0; i<numbuiltinforms; i++) {
7304 DEBUGADD(6,("adding form [%d]'s size\n",i));
7305 buffer_size += spoolss_size_form_1(&forms_1[i]);
7307 for (; i<*numofforms; i++) {
7308 DEBUGADD(6,("adding form [%d]'s size\n",i));
7309 buffer_size += spoolss_size_form_1(&forms_1[i]);
7312 *needed=buffer_size;
7314 if (*needed > offered) {
7317 return WERR_INSUFFICIENT_BUFFER;
7320 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7326 /* fill the buffer with the form structures */
7327 for (i=0; i<numbuiltinforms; i++) {
7328 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7329 smb_io_form_1("", buffer, &forms_1[i], 0);
7331 for (; i<*numofforms; i++) {
7332 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7333 smb_io_form_1("", buffer, &forms_1[i], 0);
7342 SAFE_FREE(builtinlist);
7343 return WERR_UNKNOWN_LEVEL;
7347 /****************************************************************************
7348 ****************************************************************************/
7350 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7352 uint32 level = q_u->level;
7353 UNISTR2 *uni_formname = &q_u->formname;
7354 RPC_BUFFER *buffer = NULL;
7355 uint32 offered = q_u->offered;
7356 uint32 *needed = &r_u->needed;
7358 nt_forms_struct *list=NULL;
7359 nt_forms_struct builtin_form;
7364 int numofforms=0, i=0;
7366 /* that's an [in out] buffer */
7368 if (!q_u->buffer && (offered!=0)) {
7369 return WERR_INVALID_PARAM;
7372 rpcbuf_move(q_u->buffer, &r_u->buffer);
7373 buffer = r_u->buffer;
7375 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7377 DEBUG(4,("_spoolss_getform\n"));
7378 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7379 DEBUGADD(5,("Info level [%d]\n", level));
7381 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7382 if (!foundBuiltin) {
7383 numofforms = get_ntforms(&list);
7384 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7386 if (numofforms == 0)
7393 fill_form_1(&form_1, &builtin_form);
7396 /* Check if the requested name is in the list of form structures */
7397 for (i=0; i<numofforms; i++) {
7399 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7401 if (strequal(form_name, list[i].name)) {
7402 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7403 fill_form_1(&form_1, &list[i]);
7409 if (i == numofforms) {
7413 /* check the required size. */
7415 *needed=spoolss_size_form_1(&form_1);
7417 if (*needed > offered)
7418 return WERR_INSUFFICIENT_BUFFER;
7420 if (!rpcbuf_alloc_size(buffer, buffer_size))
7423 /* fill the buffer with the form structures */
7424 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7425 smb_io_form_1("", buffer, &form_1, 0);
7431 return WERR_UNKNOWN_LEVEL;
7435 /****************************************************************************
7436 ****************************************************************************/
7438 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7440 init_unistr(&port->port_name, name);
7443 /****************************************************************************
7444 TODO: This probably needs distinguish between TCP/IP and Local ports
7446 ****************************************************************************/
7448 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7450 init_unistr(&port->port_name, name);
7451 init_unistr(&port->monitor_name, "Local Monitor");
7452 init_unistr(&port->description, SPL_LOCAL_PORT );
7453 port->port_type=PORT_TYPE_WRITE;
7458 /****************************************************************************
7459 wrapper around the enumer ports command
7460 ****************************************************************************/
7462 WERROR enumports_hook( int *count, char ***lines )
7464 char *cmd = lp_enumports_cmd();
7474 /* if no hook then just fill in the default port */
7477 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7478 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7483 /* we have a valid enumport command */
7485 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7487 DEBUG(10,("Running [%s]\n", command));
7488 ret = smbrun(command, &fd);
7489 DEBUG(10,("Returned [%d]\n", ret));
7494 return WERR_ACCESS_DENIED;
7498 qlines = fd_lines_load(fd, &numlines, 0);
7499 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7509 /****************************************************************************
7511 ****************************************************************************/
7513 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7515 PORT_INFO_1 *ports=NULL;
7517 WERROR result = WERR_OK;
7518 char **qlines = NULL;
7521 result = enumports_hook( &numlines, &qlines );
7522 if (!W_ERROR_IS_OK(result)) {
7523 file_lines_free(qlines);
7528 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7529 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7530 dos_errstr(WERR_NOMEM)));
7531 file_lines_free(qlines);
7535 for (i=0; i<numlines; i++) {
7536 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7537 fill_port_1(&ports[i], qlines[i]);
7540 file_lines_free(qlines);
7542 *returned = numlines;
7544 /* check the required size. */
7545 for (i=0; i<*returned; i++) {
7546 DEBUGADD(6,("adding port [%d]'s size\n", i));
7547 *needed += spoolss_size_port_info_1(&ports[i]);
7550 if (*needed > offered) {
7551 result = WERR_INSUFFICIENT_BUFFER;
7555 if (!rpcbuf_alloc_size(buffer, *needed)) {
7556 result = WERR_NOMEM;
7560 /* fill the buffer with the ports structures */
7561 for (i=0; i<*returned; i++) {
7562 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7563 smb_io_port_1("", buffer, &ports[i], 0);
7569 if ( !W_ERROR_IS_OK(result) )
7575 /****************************************************************************
7577 ****************************************************************************/
7579 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7581 PORT_INFO_2 *ports=NULL;
7583 WERROR result = WERR_OK;
7584 char **qlines = NULL;
7587 result = enumports_hook( &numlines, &qlines );
7588 if ( !W_ERROR_IS_OK(result)) {
7589 file_lines_free(qlines);
7594 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7595 file_lines_free(qlines);
7599 for (i=0; i<numlines; i++) {
7600 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7601 fill_port_2(&(ports[i]), qlines[i]);
7605 file_lines_free(qlines);
7607 *returned = numlines;
7609 /* check the required size. */
7610 for (i=0; i<*returned; i++) {
7611 DEBUGADD(6,("adding port [%d]'s size\n", i));
7612 *needed += spoolss_size_port_info_2(&ports[i]);
7615 if (*needed > offered) {
7616 result = WERR_INSUFFICIENT_BUFFER;
7620 if (!rpcbuf_alloc_size(buffer, *needed)) {
7621 result = WERR_NOMEM;
7625 /* fill the buffer with the ports structures */
7626 for (i=0; i<*returned; i++) {
7627 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7628 smb_io_port_2("", buffer, &ports[i], 0);
7634 if ( !W_ERROR_IS_OK(result) )
7640 /****************************************************************************
7642 ****************************************************************************/
7644 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7646 uint32 level = q_u->level;
7647 RPC_BUFFER *buffer = NULL;
7648 uint32 offered = q_u->offered;
7649 uint32 *needed = &r_u->needed;
7650 uint32 *returned = &r_u->returned;
7652 /* that's an [in out] buffer */
7654 if (!q_u->buffer && (offered!=0)) {
7655 return WERR_INVALID_PARAM;
7658 rpcbuf_move(q_u->buffer, &r_u->buffer);
7659 buffer = r_u->buffer;
7661 DEBUG(4,("_spoolss_enumports\n"));
7668 return enumports_level_1(buffer, offered, needed, returned);
7670 return enumports_level_2(buffer, offered, needed, returned);
7672 return WERR_UNKNOWN_LEVEL;
7676 /****************************************************************************
7677 ****************************************************************************/
7679 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7680 const SPOOL_PRINTER_INFO_LEVEL *info,
7681 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7682 uint32 user_switch, const SPOOL_USER_CTR *user,
7685 NT_PRINTER_INFO_LEVEL *printer = NULL;
7688 WERROR err = WERR_OK;
7690 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7691 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7695 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7696 if (!convert_printer_info(info, printer, 2)) {
7697 free_a_printer(&printer, 2);
7701 /* check to see if the printer already exists */
7703 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7704 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7705 printer->info_2->sharename));
7706 free_a_printer(&printer, 2);
7707 return WERR_PRINTER_ALREADY_EXISTS;
7710 /* FIXME!!! smbd should check to see if the driver is installed before
7711 trying to add a printer like this --jerry */
7713 if (*lp_addprinter_cmd() ) {
7714 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7715 free_a_printer(&printer,2);
7716 return WERR_ACCESS_DENIED;
7719 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7720 "smb.conf parameter \"addprinter command\" is defined. This"
7721 "parameter must exist for this call to succeed\n",
7722 printer->info_2->sharename ));
7725 /* use our primary netbios name since get_a_printer() will convert
7726 it to what the client expects on a case by case basis */
7728 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7729 printer->info_2->sharename);
7732 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7733 free_a_printer(&printer,2);
7734 return WERR_ACCESS_DENIED;
7737 /* you must be a printer admin to add a new printer */
7738 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7739 free_a_printer(&printer,2);
7740 return WERR_ACCESS_DENIED;
7744 * Do sanity check on the requested changes for Samba.
7747 if (!check_printer_ok(printer->info_2, snum)) {
7748 free_a_printer(&printer,2);
7749 return WERR_INVALID_PARAM;
7753 * When a printer is created, the drivername bound to the printer is used
7754 * to lookup previously saved driver initialization info, which is then
7755 * bound to the new printer, simulating what happens in the Windows arch.
7760 set_driver_init(printer, 2);
7764 /* A valid devmode was included, convert and link it
7766 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7768 if (!convert_devicemode(printer->info_2->printername, devmode,
7769 &printer->info_2->devmode))
7773 /* write the ASCII on disk */
7774 err = mod_a_printer(printer, 2);
7775 if (!W_ERROR_IS_OK(err)) {
7776 free_a_printer(&printer,2);
7780 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7781 /* Handle open failed - remove addition. */
7782 del_a_printer(printer->info_2->sharename);
7783 free_a_printer(&printer,2);
7784 return WERR_ACCESS_DENIED;
7787 update_c_setprinter(False);
7788 free_a_printer(&printer,2);
7793 /****************************************************************************
7794 ****************************************************************************/
7796 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7798 UNISTR2 *uni_srv_name = q_u->server_name;
7799 uint32 level = q_u->level;
7800 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7801 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7802 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7803 uint32 user_switch = q_u->user_switch;
7804 SPOOL_USER_CTR *user = &q_u->user_ctr;
7805 POLICY_HND *handle = &r_u->handle;
7809 /* we don't handle yet */
7810 /* but I know what to do ... */
7811 return WERR_UNKNOWN_LEVEL;
7813 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7815 user_switch, user, handle);
7817 return WERR_UNKNOWN_LEVEL;
7821 /****************************************************************************
7822 ****************************************************************************/
7824 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7826 uint32 level = q_u->level;
7827 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7828 WERROR err = WERR_OK;
7829 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7830 fstring driver_name;
7833 ZERO_STRUCT(driver);
7835 if (!convert_printer_driver_info(info, &driver, level)) {
7840 DEBUG(5,("Cleaning driver's information\n"));
7841 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7842 if (!W_ERROR_IS_OK(err))
7845 DEBUG(5,("Moving driver to final destination\n"));
7846 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7850 if (add_a_printer_driver(driver, level)!=0) {
7851 err = WERR_ACCESS_DENIED;
7856 * I think this is where he DrvUpgradePrinter() hook would be
7857 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7858 * server. Right now, we just need to send ourselves a message
7859 * to update each printer bound to this driver. --jerry
7862 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7863 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7868 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7869 * decide if the driver init data should be deleted. The rules are:
7870 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7871 * 2) delete init data only if there is no 2k/Xp driver
7872 * 3) always delete init data
7873 * The generalized rule is always use init data from the highest order driver.
7874 * It is necessary to follow the driver install by an initialization step to
7875 * finish off this process.
7878 version = driver.info_3->cversion;
7879 else if (level == 6)
7880 version = driver.info_6->version;
7885 * 9x printer driver - never delete init data
7888 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7893 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7894 * there is no 2k/Xp driver init data for this driver name.
7898 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7900 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7902 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7904 if (!del_driver_init(driver_name))
7905 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7908 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7910 free_a_printer_driver(driver1,3);
7911 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7918 * 2k or Xp printer driver - always delete init data
7921 if (!del_driver_init(driver_name))
7922 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7926 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7932 free_a_printer_driver(driver, level);
7936 /********************************************************************
7937 * spoolss_addprinterdriverex
7938 ********************************************************************/
7940 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7942 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7943 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7946 * we only support the semantics of AddPrinterDriver()
7947 * i.e. only copy files that are newer than existing ones
7950 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7951 return WERR_ACCESS_DENIED;
7953 ZERO_STRUCT(q_u_local);
7954 ZERO_STRUCT(r_u_local);
7956 /* just pass the information off to _spoolss_addprinterdriver() */
7957 q_u_local.server_name_ptr = q_u->server_name_ptr;
7958 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7959 q_u_local.level = q_u->level;
7960 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7962 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7965 /****************************************************************************
7966 ****************************************************************************/
7968 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7970 init_unistr(&info->name, name);
7973 /****************************************************************************
7974 ****************************************************************************/
7976 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7982 const char *short_archi;
7983 DRIVER_DIRECTORY_1 *info=NULL;
7984 WERROR result = WERR_OK;
7986 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7987 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7989 /* check for beginning double '\'s and that the server
7992 pservername = servername;
7993 if ( *pservername == '\\' && strlen(servername)>2 ) {
7997 if ( !is_myname_or_ipaddr( pservername ) )
7998 return WERR_INVALID_PARAM;
8000 if (!(short_archi = get_short_archi(long_archi)))
8001 return WERR_INVALID_ENVIRONMENT;
8003 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8006 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
8008 DEBUG(4,("printer driver directory: [%s]\n", path));
8010 fill_driverdir_1(info, path);
8012 *needed += spoolss_size_driverdir_info_1(info);
8014 if (*needed > offered) {
8015 result = WERR_INSUFFICIENT_BUFFER;
8019 if (!rpcbuf_alloc_size(buffer, *needed)) {
8020 result = WERR_NOMEM;
8024 smb_io_driverdir_1("", buffer, info, 0);
8032 /****************************************************************************
8033 ****************************************************************************/
8035 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8037 UNISTR2 *name = &q_u->name;
8038 UNISTR2 *uni_environment = &q_u->environment;
8039 uint32 level = q_u->level;
8040 RPC_BUFFER *buffer = NULL;
8041 uint32 offered = q_u->offered;
8042 uint32 *needed = &r_u->needed;
8044 /* that's an [in out] buffer */
8046 if (!q_u->buffer && (offered!=0)) {
8047 return WERR_INVALID_PARAM;
8050 rpcbuf_move(q_u->buffer, &r_u->buffer);
8051 buffer = r_u->buffer;
8053 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8059 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8061 return WERR_UNKNOWN_LEVEL;
8065 /****************************************************************************
8066 ****************************************************************************/
8068 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8070 POLICY_HND *handle = &q_u->handle;
8071 uint32 idx = q_u->index;
8072 uint32 in_value_len = q_u->valuesize;
8073 uint32 in_data_len = q_u->datasize;
8074 uint32 *out_max_value_len = &r_u->valuesize;
8075 uint16 **out_value = &r_u->value;
8076 uint32 *out_value_len = &r_u->realvaluesize;
8077 uint32 *out_type = &r_u->type;
8078 uint32 *out_max_data_len = &r_u->datasize;
8079 uint8 **data_out = &r_u->data;
8080 uint32 *out_data_len = &r_u->realdatasize;
8082 NT_PRINTER_INFO_LEVEL *printer = NULL;
8084 uint32 biggest_valuesize;
8085 uint32 biggest_datasize;
8087 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8090 REGISTRY_VALUE *val = NULL;
8091 NT_PRINTER_DATA *p_data;
8092 int i, key_index, num_values;
8097 *out_max_data_len = 0;
8101 DEBUG(5,("spoolss_enumprinterdata\n"));
8104 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8108 if (!get_printer_snum(p,handle, &snum, NULL))
8111 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8112 if (!W_ERROR_IS_OK(result))
8115 p_data = printer->info_2->data;
8116 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8121 * The NT machine wants to know the biggest size of value and data
8123 * cf: MSDN EnumPrinterData remark section
8126 if ( !in_value_len && !in_data_len && (key_index != -1) )
8128 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8130 biggest_valuesize = 0;
8131 biggest_datasize = 0;
8133 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8135 for ( i=0; i<num_values; i++ )
8137 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8139 name_length = strlen(val->valuename);
8140 if ( strlen(val->valuename) > biggest_valuesize )
8141 biggest_valuesize = name_length;
8143 if ( val->size > biggest_datasize )
8144 biggest_datasize = val->size;
8146 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8150 /* the value is an UNICODE string but real_value_size is the length
8151 in bytes including the trailing 0 */
8153 *out_value_len = 2 * (1+biggest_valuesize);
8154 *out_data_len = biggest_datasize;
8156 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8162 * the value len is wrong in NT sp3
8163 * that's the number of bytes not the number of unicode chars
8166 if ( key_index != -1 )
8167 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8172 /* out_value should default to "" or else NT4 has
8173 problems unmarshalling the response */
8175 *out_max_value_len=(in_value_len/sizeof(uint16));
8178 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8180 result = WERR_NOMEM;
8183 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8189 /* the data is counted in bytes */
8191 *out_max_data_len = in_data_len;
8192 *out_data_len = in_data_len;
8194 /* only allocate when given a non-zero data_len */
8196 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8198 result = WERR_NOMEM;
8202 result = WERR_NO_MORE_ITEMS;
8208 * - counted in bytes in the request
8209 * - counted in UNICODE chars in the max reply
8210 * - counted in bytes in the real size
8212 * take a pause *before* coding not *during* coding
8216 *out_max_value_len=(in_value_len/sizeof(uint16));
8218 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8220 result = WERR_NOMEM;
8224 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8232 *out_type = regval_type( val );
8234 /* data - counted in bytes */
8236 *out_max_data_len = in_data_len;
8237 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8239 result = WERR_NOMEM;
8242 data_len = regval_size(val);
8243 if ( *data_out && data_len )
8244 memcpy( *data_out, regval_data_p(val), data_len );
8245 *out_data_len = data_len;
8249 free_a_printer(&printer, 2);
8253 /****************************************************************************
8254 ****************************************************************************/
8256 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8258 POLICY_HND *handle = &q_u->handle;
8259 UNISTR2 *value = &q_u->value;
8260 uint32 type = q_u->type;
8261 uint8 *data = q_u->data;
8262 uint32 real_len = q_u->real_len;
8264 NT_PRINTER_INFO_LEVEL *printer = NULL;
8266 WERROR status = WERR_OK;
8267 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8270 DEBUG(5,("spoolss_setprinterdata\n"));
8273 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8277 if ( Printer->printer_type == SPLHND_SERVER ) {
8278 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8279 return WERR_INVALID_PARAM;
8282 if (!get_printer_snum(p,handle, &snum, NULL))
8286 * Access check : NT returns "access denied" if you make a
8287 * SetPrinterData call without the necessary privildge.
8288 * we were originally returning OK if nothing changed
8289 * which made Win2k issue **a lot** of SetPrinterData
8290 * when connecting to a printer --jerry
8293 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8295 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8296 status = WERR_ACCESS_DENIED;
8300 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8301 if (!W_ERROR_IS_OK(status))
8304 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8307 * When client side code sets a magic printer data key, detect it and save
8308 * the current printer data and the magic key's data (its the DEVMODE) for
8309 * future printer/driver initializations.
8311 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8313 /* Set devmode and printer initialization info */
8314 status = save_driver_init( printer, 2, data, real_len );
8316 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8320 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8321 type, data, real_len );
8322 if ( W_ERROR_IS_OK(status) )
8323 status = mod_a_printer(printer, 2);
8327 free_a_printer(&printer, 2);
8332 /****************************************************************************
8333 ****************************************************************************/
8335 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8337 POLICY_HND *handle = &q_u->handle;
8338 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8341 DEBUG(5,("_spoolss_resetprinter\n"));
8344 * All we do is to check to see if the handle and queue is valid.
8345 * This call really doesn't mean anything to us because we only
8346 * support RAW printing. --jerry
8350 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8354 if (!get_printer_snum(p,handle, &snum, NULL))
8358 /* blindly return success */
8363 /****************************************************************************
8364 ****************************************************************************/
8366 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8368 POLICY_HND *handle = &q_u->handle;
8369 UNISTR2 *value = &q_u->valuename;
8371 NT_PRINTER_INFO_LEVEL *printer = NULL;
8373 WERROR status = WERR_OK;
8374 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8377 DEBUG(5,("spoolss_deleteprinterdata\n"));
8380 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8384 if (!get_printer_snum(p, handle, &snum, NULL))
8387 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8388 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8389 return WERR_ACCESS_DENIED;
8392 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8393 if (!W_ERROR_IS_OK(status))
8396 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8398 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8400 if ( W_ERROR_IS_OK(status) )
8401 mod_a_printer( printer, 2 );
8403 free_a_printer(&printer, 2);
8408 /****************************************************************************
8409 ****************************************************************************/
8411 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8413 POLICY_HND *handle = &q_u->handle;
8414 FORM *form = &q_u->form;
8415 nt_forms_struct tmpForm;
8417 WERROR status = WERR_OK;
8418 NT_PRINTER_INFO_LEVEL *printer = NULL;
8421 nt_forms_struct *list=NULL;
8422 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8424 DEBUG(5,("spoolss_addform\n"));
8427 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8432 /* forms can be added on printer of on the print server handle */
8434 if ( Printer->printer_type == SPLHND_PRINTER )
8436 if (!get_printer_snum(p,handle, &snum, NULL))
8439 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8440 if (!W_ERROR_IS_OK(status))
8444 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8445 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8446 status = WERR_ACCESS_DENIED;
8450 /* can't add if builtin */
8452 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8453 status = WERR_ALREADY_EXISTS;
8457 count = get_ntforms(&list);
8459 if(!add_a_form(&list, form, &count)) {
8460 status = WERR_NOMEM;
8464 write_ntforms(&list, count);
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_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8486 POLICY_HND *handle = &q_u->handle;
8487 UNISTR2 *form_name = &q_u->name;
8488 nt_forms_struct tmpForm;
8490 nt_forms_struct *list=NULL;
8491 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8493 WERROR status = WERR_OK;
8494 NT_PRINTER_INFO_LEVEL *printer = NULL;
8496 DEBUG(5,("spoolss_deleteform\n"));
8499 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8503 /* forms can be deleted on printer of on the print server handle */
8505 if ( Printer->printer_type == SPLHND_PRINTER )
8507 if (!get_printer_snum(p,handle, &snum, NULL))
8510 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8511 if (!W_ERROR_IS_OK(status))
8515 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8516 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8517 status = WERR_ACCESS_DENIED;
8521 /* can't delete if builtin */
8523 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8524 status = WERR_INVALID_PARAM;
8528 count = get_ntforms(&list);
8530 if ( !delete_a_form(&list, form_name, &count, &status ))
8534 * ChangeID must always be set if this is a printer
8537 if ( Printer->printer_type == SPLHND_PRINTER )
8538 status = mod_a_printer(printer, 2);
8542 free_a_printer(&printer, 2);
8548 /****************************************************************************
8549 ****************************************************************************/
8551 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8553 POLICY_HND *handle = &q_u->handle;
8554 FORM *form = &q_u->form;
8555 nt_forms_struct tmpForm;
8557 WERROR status = WERR_OK;
8558 NT_PRINTER_INFO_LEVEL *printer = NULL;
8561 nt_forms_struct *list=NULL;
8562 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8564 DEBUG(5,("spoolss_setform\n"));
8567 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8571 /* forms can be modified on printer of on the print server handle */
8573 if ( Printer->printer_type == SPLHND_PRINTER )
8575 if (!get_printer_snum(p,handle, &snum, NULL))
8578 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8579 if (!W_ERROR_IS_OK(status))
8583 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8584 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8585 status = WERR_ACCESS_DENIED;
8589 /* can't set if builtin */
8590 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8591 status = WERR_INVALID_PARAM;
8595 count = get_ntforms(&list);
8596 update_a_form(&list, form, count);
8597 write_ntforms(&list, count);
8600 * ChangeID must always be set if this is a printer
8603 if ( Printer->printer_type == SPLHND_PRINTER )
8604 status = mod_a_printer(printer, 2);
8609 free_a_printer(&printer, 2);
8615 /****************************************************************************
8616 enumprintprocessors level 1.
8617 ****************************************************************************/
8619 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8621 PRINTPROCESSOR_1 *info_1=NULL;
8622 WERROR result = WERR_OK;
8624 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8629 init_unistr(&info_1->name, "winprint");
8631 *needed += spoolss_size_printprocessor_info_1(info_1);
8633 if (*needed > offered) {
8634 result = WERR_INSUFFICIENT_BUFFER;
8638 if (!rpcbuf_alloc_size(buffer, *needed)) {
8639 result = WERR_NOMEM;
8643 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8648 if ( !W_ERROR_IS_OK(result) )
8654 /****************************************************************************
8655 ****************************************************************************/
8657 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8659 uint32 level = q_u->level;
8660 RPC_BUFFER *buffer = NULL;
8661 uint32 offered = q_u->offered;
8662 uint32 *needed = &r_u->needed;
8663 uint32 *returned = &r_u->returned;
8665 /* that's an [in out] buffer */
8667 if (!q_u->buffer && (offered!=0)) {
8668 return WERR_INVALID_PARAM;
8671 rpcbuf_move(q_u->buffer, &r_u->buffer);
8672 buffer = r_u->buffer;
8674 DEBUG(5,("spoolss_enumprintprocessors\n"));
8677 * Enumerate the print processors ...
8679 * Just reply with "winprint", to keep NT happy
8680 * and I can use my nice printer checker.
8688 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8690 return WERR_UNKNOWN_LEVEL;
8694 /****************************************************************************
8695 enumprintprocdatatypes level 1.
8696 ****************************************************************************/
8698 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8700 PRINTPROCDATATYPE_1 *info_1=NULL;
8701 WERROR result = WERR_OK;
8703 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8708 init_unistr(&info_1->name, "RAW");
8710 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8712 if (*needed > offered) {
8713 result = WERR_INSUFFICIENT_BUFFER;
8717 if (!rpcbuf_alloc_size(buffer, *needed)) {
8718 result = WERR_NOMEM;
8722 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8727 if ( !W_ERROR_IS_OK(result) )
8733 /****************************************************************************
8734 ****************************************************************************/
8736 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8738 uint32 level = q_u->level;
8739 RPC_BUFFER *buffer = NULL;
8740 uint32 offered = q_u->offered;
8741 uint32 *needed = &r_u->needed;
8742 uint32 *returned = &r_u->returned;
8744 /* that's an [in out] buffer */
8746 if (!q_u->buffer && (offered!=0)) {
8747 return WERR_INVALID_PARAM;
8750 rpcbuf_move(q_u->buffer, &r_u->buffer);
8751 buffer = r_u->buffer;
8753 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8760 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8762 return WERR_UNKNOWN_LEVEL;
8766 /****************************************************************************
8767 enumprintmonitors level 1.
8768 ****************************************************************************/
8770 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8772 PRINTMONITOR_1 *info_1;
8773 WERROR result = WERR_OK;
8776 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8781 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8782 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8784 for ( i=0; i<*returned; i++ ) {
8785 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8788 if (*needed > offered) {
8789 result = WERR_INSUFFICIENT_BUFFER;
8793 if (!rpcbuf_alloc_size(buffer, *needed)) {
8794 result = WERR_NOMEM;
8798 for ( i=0; i<*returned; i++ ) {
8799 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8805 if ( !W_ERROR_IS_OK(result) )
8811 /****************************************************************************
8812 enumprintmonitors level 2.
8813 ****************************************************************************/
8815 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8817 PRINTMONITOR_2 *info_2;
8818 WERROR result = WERR_OK;
8821 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8826 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8827 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8828 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8830 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8831 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8832 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8834 for ( i=0; i<*returned; i++ ) {
8835 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8838 if (*needed > offered) {
8839 result = WERR_INSUFFICIENT_BUFFER;
8843 if (!rpcbuf_alloc_size(buffer, *needed)) {
8844 result = WERR_NOMEM;
8848 for ( i=0; i<*returned; i++ ) {
8849 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8855 if ( !W_ERROR_IS_OK(result) )
8861 /****************************************************************************
8862 ****************************************************************************/
8864 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8866 uint32 level = q_u->level;
8867 RPC_BUFFER *buffer = NULL;
8868 uint32 offered = q_u->offered;
8869 uint32 *needed = &r_u->needed;
8870 uint32 *returned = &r_u->returned;
8872 /* that's an [in out] buffer */
8874 if (!q_u->buffer && (offered!=0)) {
8875 return WERR_INVALID_PARAM;
8878 rpcbuf_move(q_u->buffer, &r_u->buffer);
8879 buffer = r_u->buffer;
8881 DEBUG(5,("spoolss_enumprintmonitors\n"));
8884 * Enumerate the print monitors ...
8886 * Just reply with "Local Port", to keep NT happy
8887 * and I can use my nice printer checker.
8895 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8897 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8899 return WERR_UNKNOWN_LEVEL;
8903 /****************************************************************************
8904 ****************************************************************************/
8906 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8907 NT_PRINTER_INFO_LEVEL *ntprinter,
8908 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8913 JOB_INFO_1 *info_1=NULL;
8914 WERROR result = WERR_OK;
8916 info_1=SMB_MALLOC_P(JOB_INFO_1);
8918 if (info_1 == NULL) {
8922 for (i=0; i<count && found==False; i++) {
8923 if ((*queue)[i].job==(int)jobid)
8929 /* NT treats not found as bad param... yet another bad choice */
8930 return WERR_INVALID_PARAM;
8933 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8935 *needed += spoolss_size_job_info_1(info_1);
8937 if (*needed > offered) {
8938 result = WERR_INSUFFICIENT_BUFFER;
8942 if (!rpcbuf_alloc_size(buffer, *needed)) {
8943 result = WERR_NOMEM;
8947 smb_io_job_info_1("", buffer, info_1, 0);
8955 /****************************************************************************
8956 ****************************************************************************/
8958 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8959 NT_PRINTER_INFO_LEVEL *ntprinter,
8960 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8967 DEVICEMODE *devmode = NULL;
8968 NT_DEVICEMODE *nt_devmode = NULL;
8970 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8973 ZERO_STRUCTP(info_2);
8975 for ( i=0; i<count && found==False; i++ )
8977 if ((*queue)[i].job == (int)jobid)
8982 /* NT treats not found as bad param... yet another bad
8984 result = WERR_INVALID_PARAM;
8989 * if the print job does not have a DEVMODE associated with it,
8990 * just use the one for the printer. A NULL devicemode is not
8991 * a failure condition
8994 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8995 devmode = construct_dev_mode(lp_const_servicename(snum));
8997 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8998 ZERO_STRUCTP( devmode );
8999 convert_nt_devicemode( devmode, nt_devmode );
9003 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9005 *needed += spoolss_size_job_info_2(info_2);
9007 if (*needed > offered) {
9008 result = WERR_INSUFFICIENT_BUFFER;
9012 if (!rpcbuf_alloc_size(buffer, *needed)) {
9013 result = WERR_NOMEM;
9017 smb_io_job_info_2("", buffer, info_2, 0);
9022 /* Cleanup allocated memory */
9024 free_job_info_2(info_2); /* Also frees devmode */
9030 /****************************************************************************
9031 ****************************************************************************/
9033 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9035 POLICY_HND *handle = &q_u->handle;
9036 uint32 jobid = q_u->jobid;
9037 uint32 level = q_u->level;
9038 RPC_BUFFER *buffer = NULL;
9039 uint32 offered = q_u->offered;
9040 uint32 *needed = &r_u->needed;
9041 WERROR wstatus = WERR_OK;
9042 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9045 print_queue_struct *queue = NULL;
9046 print_status_struct prt_status;
9048 /* that's an [in out] buffer */
9050 if (!q_u->buffer && (offered!=0)) {
9051 return WERR_INVALID_PARAM;
9054 rpcbuf_move(q_u->buffer, &r_u->buffer);
9055 buffer = r_u->buffer;
9057 DEBUG(5,("spoolss_getjob\n"));
9061 if (!get_printer_snum(p, handle, &snum, NULL))
9064 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9065 if ( !W_ERROR_IS_OK(wstatus) )
9068 count = print_queue_status(snum, &queue, &prt_status);
9070 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9071 count, prt_status.status, prt_status.message));
9075 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9076 buffer, offered, needed);
9079 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9080 buffer, offered, needed);
9083 wstatus = WERR_UNKNOWN_LEVEL;
9088 free_a_printer( &ntprinter, 2 );
9093 /********************************************************************
9094 spoolss_getprinterdataex
9096 From MSDN documentation of GetPrinterDataEx: pass request
9097 to GetPrinterData if key is "PrinterDriverData".
9098 ********************************************************************/
9100 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9102 POLICY_HND *handle = &q_u->handle;
9103 uint32 in_size = q_u->size;
9104 uint32 *type = &r_u->type;
9105 uint32 *out_size = &r_u->size;
9106 uint8 **data = &r_u->data;
9107 uint32 *needed = &r_u->needed;
9108 fstring keyname, valuename;
9110 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9112 NT_PRINTER_INFO_LEVEL *printer = NULL;
9114 WERROR status = WERR_OK;
9116 DEBUG(4,("_spoolss_getprinterdataex\n"));
9118 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
9119 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
9121 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9122 keyname, valuename));
9124 /* in case of problem, return some default values */
9128 *out_size = in_size;
9131 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9132 status = WERR_BADFID;
9136 /* Is the handle to a printer or to the server? */
9138 if (Printer->printer_type == SPLHND_SERVER) {
9139 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9140 status = WERR_INVALID_PARAM;
9144 if ( !get_printer_snum(p,handle, &snum, NULL) )
9147 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9148 if ( !W_ERROR_IS_OK(status) )
9151 /* check to see if the keyname is valid */
9152 if ( !strlen(keyname) ) {
9153 status = WERR_INVALID_PARAM;
9157 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9158 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9159 free_a_printer( &printer, 2 );
9160 status = WERR_BADFILE;
9164 /* When given a new keyname, we should just create it */
9166 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9168 if (*needed > *out_size)
9169 status = WERR_MORE_DATA;
9172 if ( !W_ERROR_IS_OK(status) )
9174 DEBUG(5, ("error: allocating %d\n", *out_size));
9176 /* reply this param doesn't exist */
9180 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9181 status = WERR_NOMEM;
9190 free_a_printer( &printer, 2 );
9195 /********************************************************************
9196 * spoolss_setprinterdataex
9197 ********************************************************************/
9199 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9201 POLICY_HND *handle = &q_u->handle;
9202 uint32 type = q_u->type;
9203 uint8 *data = q_u->data;
9204 uint32 real_len = q_u->real_len;
9206 NT_PRINTER_INFO_LEVEL *printer = NULL;
9208 WERROR status = WERR_OK;
9209 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9214 DEBUG(4,("_spoolss_setprinterdataex\n"));
9216 /* From MSDN documentation of SetPrinterDataEx: pass request to
9217 SetPrinterData if key is "PrinterDriverData" */
9220 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9224 if ( Printer->printer_type == SPLHND_SERVER ) {
9225 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9226 return WERR_INVALID_PARAM;
9229 if ( !get_printer_snum(p,handle, &snum, NULL) )
9233 * Access check : NT returns "access denied" if you make a
9234 * SetPrinterData call without the necessary privildge.
9235 * we were originally returning OK if nothing changed
9236 * which made Win2k issue **a lot** of SetPrinterData
9237 * when connecting to a printer --jerry
9240 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9242 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9243 return WERR_ACCESS_DENIED;
9246 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9247 if (!W_ERROR_IS_OK(status))
9250 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9251 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9253 /* check for OID in valuename */
9255 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9261 /* save the registry data */
9263 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9265 if ( W_ERROR_IS_OK(status) )
9267 /* save the OID if one was specified */
9269 fstrcat( keyname, "\\" );
9270 fstrcat( keyname, SPOOL_OID_KEY );
9273 * I'm not checking the status here on purpose. Don't know
9274 * if this is right, but I'm returning the status from the
9275 * previous set_printer_dataex() call. I have no idea if
9276 * this is right. --jerry
9279 set_printer_dataex( printer, keyname, valuename,
9280 REG_SZ, (uint8 *)oid_string,
9281 strlen(oid_string)+1 );
9284 status = mod_a_printer(printer, 2);
9287 free_a_printer(&printer, 2);
9293 /********************************************************************
9294 * spoolss_deleteprinterdataex
9295 ********************************************************************/
9297 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9299 POLICY_HND *handle = &q_u->handle;
9300 UNISTR2 *value = &q_u->valuename;
9301 UNISTR2 *key = &q_u->keyname;
9303 NT_PRINTER_INFO_LEVEL *printer = NULL;
9305 WERROR status = WERR_OK;
9306 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9307 pstring valuename, keyname;
9309 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9312 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9316 if (!get_printer_snum(p, handle, &snum, NULL))
9319 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9320 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9321 return WERR_ACCESS_DENIED;
9324 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9325 if (!W_ERROR_IS_OK(status))
9328 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9329 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9331 status = delete_printer_dataex( printer, keyname, valuename );
9333 if ( W_ERROR_IS_OK(status) )
9334 mod_a_printer( printer, 2 );
9336 free_a_printer(&printer, 2);
9341 /********************************************************************
9342 * spoolss_enumprinterkey
9343 ********************************************************************/
9346 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9349 fstring *keynames = NULL;
9350 uint16 *enumkeys = NULL;
9353 POLICY_HND *handle = &q_u->handle;
9354 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9355 NT_PRINTER_DATA *data;
9356 NT_PRINTER_INFO_LEVEL *printer = NULL;
9358 WERROR status = WERR_BADFILE;
9361 DEBUG(4,("_spoolss_enumprinterkey\n"));
9364 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9368 if ( !get_printer_snum(p,handle, &snum, NULL) )
9371 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9372 if (!W_ERROR_IS_OK(status))
9375 /* get the list of subkey names */
9377 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9378 data = printer->info_2->data;
9380 num_keys = get_printer_subkeys( data, key, &keynames );
9382 if ( num_keys == -1 ) {
9383 status = WERR_BADFILE;
9387 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9389 r_u->needed = printerkey_len*2;
9391 if ( q_u->size < r_u->needed ) {
9392 status = WERR_MORE_DATA;
9396 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9397 status = WERR_NOMEM;
9403 if ( q_u->size < r_u->needed )
9404 status = WERR_MORE_DATA;
9407 free_a_printer( &printer, 2 );
9408 SAFE_FREE( keynames );
9413 /********************************************************************
9414 * spoolss_deleteprinterkey
9415 ********************************************************************/
9417 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9419 POLICY_HND *handle = &q_u->handle;
9420 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9422 NT_PRINTER_INFO_LEVEL *printer = NULL;
9426 DEBUG(5,("spoolss_deleteprinterkey\n"));
9429 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9433 /* if keyname == NULL, return error */
9435 if ( !q_u->keyname.buffer )
9436 return WERR_INVALID_PARAM;
9438 if (!get_printer_snum(p, handle, &snum, NULL))
9441 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9442 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9443 return WERR_ACCESS_DENIED;
9446 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9447 if (!W_ERROR_IS_OK(status))
9450 /* delete the key and all subneys */
9452 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9454 status = delete_all_printer_data( printer->info_2, key );
9456 if ( W_ERROR_IS_OK(status) )
9457 status = mod_a_printer(printer, 2);
9459 free_a_printer( &printer, 2 );
9465 /********************************************************************
9466 * spoolss_enumprinterdataex
9467 ********************************************************************/
9469 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9471 POLICY_HND *handle = &q_u->handle;
9472 uint32 in_size = q_u->size;
9475 NT_PRINTER_INFO_LEVEL *printer = NULL;
9476 PRINTER_ENUM_VALUES *enum_values = NULL;
9477 NT_PRINTER_DATA *p_data;
9479 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9484 REGISTRY_VALUE *val;
9489 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9492 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9497 * first check for a keyname of NULL or "". Win2k seems to send
9498 * this a lot and we should send back WERR_INVALID_PARAM
9499 * no need to spend time looking up the printer in this case.
9503 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9504 if ( !strlen(key) ) {
9505 result = WERR_INVALID_PARAM;
9509 /* get the printer off of disk */
9511 if (!get_printer_snum(p,handle, &snum, NULL))
9514 ZERO_STRUCT(printer);
9515 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9516 if (!W_ERROR_IS_OK(result))
9519 /* now look for a match on the key name */
9521 p_data = printer->info_2->data;
9523 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9524 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9526 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9527 result = WERR_INVALID_PARAM;
9534 /* allocate the memory for the array of pointers -- if necessary */
9536 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9539 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9541 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9542 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9543 result = WERR_NOMEM;
9547 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9551 * loop through all params and build the array to pass
9552 * back to the client
9555 for ( i=0; i<num_entries; i++ )
9557 /* lookup the registry value */
9559 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9560 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9564 value_name = regval_name( val );
9565 init_unistr( &enum_values[i].valuename, value_name );
9566 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9567 enum_values[i].type = regval_type( val );
9569 data_len = regval_size( val );
9571 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9573 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9575 result = WERR_NOMEM;
9579 enum_values[i].data_len = data_len;
9581 /* keep track of the size of the array in bytes */
9583 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9586 /* housekeeping information in the reply */
9588 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9589 * the hand marshalled container size is a multiple
9590 * of 4 bytes for RPC alignment.
9594 needed += 4-(needed % 4);
9597 r_u->needed = needed;
9598 r_u->returned = num_entries;
9600 if (needed > in_size) {
9601 result = WERR_MORE_DATA;
9605 /* copy data into the reply */
9607 r_u->ctr.size = r_u->needed;
9609 r_u->ctr.size_of_array = r_u->returned;
9610 r_u->ctr.values = enum_values;
9616 free_a_printer(&printer, 2);
9621 /****************************************************************************
9622 ****************************************************************************/
9624 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9626 init_unistr(&info->name, name);
9629 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9630 UNISTR2 *environment,
9637 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9638 WERROR result = WERR_OK;
9640 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9642 if (!get_short_archi(long_archi))
9643 return WERR_INVALID_ENVIRONMENT;
9645 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9648 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9650 fill_printprocessordirectory_1(info, path);
9652 *needed += spoolss_size_printprocessordirectory_info_1(info);
9654 if (*needed > offered) {
9655 result = WERR_INSUFFICIENT_BUFFER;
9659 if (!rpcbuf_alloc_size(buffer, *needed)) {
9660 result = WERR_INSUFFICIENT_BUFFER;
9664 smb_io_printprocessordirectory_1("", buffer, info, 0);
9672 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9674 uint32 level = q_u->level;
9675 RPC_BUFFER *buffer = NULL;
9676 uint32 offered = q_u->offered;
9677 uint32 *needed = &r_u->needed;
9680 /* that's an [in out] buffer */
9682 if (!q_u->buffer && (offered!=0)) {
9683 return WERR_INVALID_PARAM;
9686 rpcbuf_move(q_u->buffer, &r_u->buffer);
9687 buffer = r_u->buffer;
9689 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9695 result = getprintprocessordirectory_level_1
9696 (&q_u->name, &q_u->environment, buffer, offered, needed);
9699 result = WERR_UNKNOWN_LEVEL;
9705 /*******************************************************************
9706 Streams the monitor UI DLL name in UNICODE
9707 *******************************************************************/
9709 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9710 RPC_BUFFER *out, uint32 *needed )
9712 const char *dllname = "tcpmonui.dll";
9714 *needed = (strlen(dllname)+1) * 2;
9716 if ( rpcbuf_get_size(out) < *needed ) {
9717 return WERR_INSUFFICIENT_BUFFER;
9720 if ( !make_monitorui_buf( out, dllname ) ) {
9727 /*******************************************************************
9728 Create a new TCP/IP port
9729 *******************************************************************/
9731 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9732 RPC_BUFFER *out, uint32 *needed )
9734 NT_PORT_DATA_1 port1;
9737 ZERO_STRUCT( port1 );
9739 /* convert to our internal port data structure */
9741 if ( !convert_port_data_1( &port1, in ) ) {
9745 /* create the device URI and call the add_port_hook() */
9747 switch ( port1.protocol ) {
9748 case PORT_PROTOCOL_DIRECT:
9749 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9752 case PORT_PROTOCOL_LPR:
9753 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9757 return WERR_UNKNOWN_PORT;
9760 return add_port_hook( token, port1.name, device_uri );
9763 /*******************************************************************
9764 *******************************************************************/
9766 struct xcv_api_table xcvtcp_cmds[] = {
9767 { "MonitorUI", xcvtcp_monitorui },
9768 { "AddPort", xcvtcp_addport},
9772 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9773 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9778 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9780 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9781 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9782 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9785 return WERR_BADFUNC;
9788 /*******************************************************************
9789 *******************************************************************/
9790 #if 0 /* don't support management using the "Local Port" monitor */
9792 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9793 RPC_BUFFER *out, uint32 *needed )
9795 const char *dllname = "localui.dll";
9797 *needed = (strlen(dllname)+1) * 2;
9799 if ( rpcbuf_get_size(out) < *needed ) {
9800 return WERR_INSUFFICIENT_BUFFER;
9803 if ( !make_monitorui_buf( out, dllname )) {
9810 /*******************************************************************
9811 *******************************************************************/
9813 struct xcv_api_table xcvlocal_cmds[] = {
9814 { "MonitorUI", xcvlocal_monitorui },
9818 struct xcv_api_table xcvlocal_cmds[] = {
9825 /*******************************************************************
9826 *******************************************************************/
9828 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9829 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9834 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9836 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9837 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9838 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9840 return WERR_BADFUNC;
9843 /*******************************************************************
9844 *******************************************************************/
9846 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9848 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9852 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9856 /* Has to be a handle to the TCP/IP port monitor */
9858 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9859 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9863 /* requires administrative access to the server */
9865 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9866 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9867 return WERR_ACCESS_DENIED;
9870 /* Get the command name. There's numerous commands supported by the
9871 TCPMON interface. */
9873 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9874 q_u->dataname.uni_str_len*2, 0);
9876 /* Allocate the outgoing buffer */
9878 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9880 switch ( Printer->printer_type ) {
9881 case SPLHND_PORTMON_TCP:
9882 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9883 &q_u->indata, &r_u->outdata, &r_u->needed );
9884 case SPLHND_PORTMON_LOCAL:
9885 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9886 &q_u->indata, &r_u->outdata, &r_u->needed );
9889 return WERR_INVALID_PRINT_MONITOR;