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(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 messaging_send_buf(smbd_messaging_context(), procid_self(),
1216 MSG_PRINTER_DRVUPGRADE,
1217 (uint8 *)drivername, len+1);
1222 /**********************************************************************
1223 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1224 over all printers, upgrading ones as necessary
1225 **********************************************************************/
1227 void do_drv_upgrade_printer(int msg_type, struct server_id src,
1228 void *buf, size_t len, void *private_data)
1232 int n_services = lp_numservices();
1234 len = MIN(len,sizeof(drivername)-1);
1235 strncpy(drivername, (const char *)buf, len);
1237 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1239 /* Iterate the printer list */
1241 for (snum=0; snum<n_services; snum++)
1243 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1246 NT_PRINTER_INFO_LEVEL *printer = NULL;
1248 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1249 if (!W_ERROR_IS_OK(result))
1252 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1254 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1256 /* all we care about currently is the change_id */
1258 result = mod_a_printer(printer, 2);
1259 if (!W_ERROR_IS_OK(result)) {
1260 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1261 dos_errstr(result)));
1265 free_a_printer(&printer, 2);
1272 /********************************************************************
1273 Update the cache for all printq's with a registered client
1275 ********************************************************************/
1277 void update_monitored_printq_cache( void )
1279 Printer_entry *printer = printers_list;
1282 /* loop through all printers and update the cache where
1283 client_connected == True */
1286 if ( (printer->printer_type == SPLHND_PRINTER)
1287 && printer->notify.client_connected )
1289 snum = print_queue_snum(printer->sharename);
1290 print_queue_status( snum, NULL, NULL );
1293 printer = printer->next;
1298 /********************************************************************
1299 Send a message to ourself about new driver being installed
1300 so we can upgrade the information for each printer bound to this
1302 ********************************************************************/
1304 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1306 int len = strlen(drivername);
1311 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1314 messaging_send_buf(smbd_messaging_context(), procid_self(),
1315 MSG_PRINTERDATA_INIT_RESET,
1316 (uint8 *)drivername, len+1);
1321 /**********************************************************************
1322 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1323 over all printers, resetting printer data as neessary
1324 **********************************************************************/
1326 void reset_all_printerdata(int msg_type, struct server_id src,
1327 void *buf, size_t len, void *private_data)
1331 int n_services = lp_numservices();
1333 len = MIN( len, sizeof(drivername)-1 );
1334 strncpy( drivername, (const char *)buf, len );
1336 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1338 /* Iterate the printer list */
1340 for ( snum=0; snum<n_services; snum++ )
1342 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1345 NT_PRINTER_INFO_LEVEL *printer = NULL;
1347 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1348 if ( !W_ERROR_IS_OK(result) )
1352 * if the printer is bound to the driver,
1353 * then reset to the new driver initdata
1356 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1358 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1360 if ( !set_driver_init(printer, 2) ) {
1361 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1362 printer->info_2->printername, printer->info_2->drivername));
1365 result = mod_a_printer( printer, 2 );
1366 if ( !W_ERROR_IS_OK(result) ) {
1367 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1368 get_dos_error_msg(result)));
1372 free_a_printer( &printer, 2 );
1381 /********************************************************************
1382 Copy routines used by convert_to_openprinterex()
1383 *******************************************************************/
1385 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1393 DEBUG (8,("dup_devmode\n"));
1395 /* bulk copy first */
1397 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1401 /* dup the pointer members separately */
1403 len = unistrlen(devmode->devicename.buffer);
1405 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1406 if (!d->devicename.buffer) {
1409 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1414 len = unistrlen(devmode->formname.buffer);
1416 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1417 if (!d->devicename.buffer) {
1420 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1424 if (devmode->driverextra) {
1425 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1426 devmode->driverextra);
1427 if (!d->dev_private) {
1431 d->dev_private = NULL;
1436 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1438 if (!new_ctr || !ctr)
1441 DEBUG(8,("copy_devmode_ctr\n"));
1443 new_ctr->size = ctr->size;
1444 new_ctr->devmode_ptr = ctr->devmode_ptr;
1446 if(ctr->devmode_ptr)
1447 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1450 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1452 if (!new_def || !def)
1455 DEBUG(8,("copy_printer_defaults\n"));
1457 new_def->datatype_ptr = def->datatype_ptr;
1459 if (def->datatype_ptr)
1460 copy_unistr2(&new_def->datatype, &def->datatype);
1462 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1464 new_def->access_required = def->access_required;
1467 /********************************************************************
1468 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1469 * SPOOL_Q_OPEN_PRINTER_EX structure
1470 ********************************************************************/
1472 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1474 if (!q_u_ex || !q_u)
1477 DEBUG(8,("convert_to_openprinterex\n"));
1479 if ( q_u->printername ) {
1480 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1481 if (q_u_ex->printername == NULL)
1483 copy_unistr2(q_u_ex->printername, q_u->printername);
1486 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1491 /********************************************************************
1492 * spoolss_open_printer
1494 * called from the spoolss dispatcher
1495 ********************************************************************/
1497 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1499 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1500 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1505 ZERO_STRUCT(q_u_ex);
1506 ZERO_STRUCT(r_u_ex);
1508 /* convert the OpenPrinter() call to OpenPrinterEx() */
1510 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1511 if (!W_ERROR_IS_OK(r_u_ex.status))
1512 return r_u_ex.status;
1514 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1516 /* convert back to OpenPrinter() */
1518 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1523 /********************************************************************
1524 ********************************************************************/
1526 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1528 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1529 POLICY_HND *handle = &r_u->handle;
1533 Printer_entry *Printer=NULL;
1535 if ( !q_u->printername )
1536 return WERR_INVALID_PRINTER_NAME;
1538 /* some sanity check because you can open a printer or a print server */
1539 /* aka: \\server\printer or \\server */
1541 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1543 DEBUGADD(3,("checking name: %s\n",name));
1545 if (!open_printer_hnd(p, handle, name, 0))
1546 return WERR_INVALID_PRINTER_NAME;
1548 Printer=find_printer_index_by_hnd(p, handle);
1550 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1551 "handle we created for printer %s\n", name ));
1552 close_printer_handle(p,handle);
1553 return WERR_INVALID_PRINTER_NAME;
1557 * First case: the user is opening the print server:
1559 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1560 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1562 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1563 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1564 * or if the user is listed in the smb.conf printer admin parameter.
1566 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1567 * client view printer folder, but does not show the MSAPW.
1569 * Note: this test needs code to check access rights here too. Jeremy
1570 * could you look at this?
1572 * Second case: the user is opening a printer:
1573 * NT doesn't let us connect to a printer if the connecting user
1574 * doesn't have print permission.
1576 * Third case: user is opening a Port Monitor
1577 * access checks same as opening a handle to the print server.
1580 switch (Printer->printer_type )
1583 case SPLHND_PORTMON_TCP:
1584 case SPLHND_PORTMON_LOCAL:
1585 /* Printserver handles use global struct... */
1589 /* Map standard access rights to object specific access rights */
1591 se_map_standard(&printer_default->access_required,
1592 &printserver_std_mapping);
1594 /* Deny any object specific bits that don't apply to print
1595 servers (i.e printer and job specific bits) */
1597 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1599 if (printer_default->access_required &
1600 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1601 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1602 close_printer_handle(p, handle);
1603 return WERR_ACCESS_DENIED;
1606 /* Allow admin access */
1608 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1610 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1612 if (!lp_ms_add_printer_wizard()) {
1613 close_printer_handle(p, handle);
1614 return WERR_ACCESS_DENIED;
1617 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1618 and not a printer admin, then fail */
1620 if ((p->pipe_user.ut.uid != 0) &&
1621 !user_has_privileges(p->pipe_user.nt_user_token,
1623 !token_contains_name_in_list(
1624 uidtoname(p->pipe_user.ut.uid), NULL,
1625 p->pipe_user.nt_user_token,
1626 lp_printer_admin(snum))) {
1627 close_printer_handle(p, handle);
1628 return WERR_ACCESS_DENIED;
1631 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1635 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1638 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1639 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1641 /* We fall through to return WERR_OK */
1644 case SPLHND_PRINTER:
1645 /* NT doesn't let us connect to a printer if the connecting user
1646 doesn't have print permission. */
1648 if (!get_printer_snum(p, handle, &snum, NULL)) {
1649 close_printer_handle(p, handle);
1653 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1655 /* map an empty access mask to the minimum access mask */
1656 if (printer_default->access_required == 0x0)
1657 printer_default->access_required = PRINTER_ACCESS_USE;
1660 * If we are not serving the printer driver for this printer,
1661 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1662 * will keep NT clients happy --jerry
1665 if (lp_use_client_driver(snum)
1666 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1668 printer_default->access_required = PRINTER_ACCESS_USE;
1671 /* check smb.conf parameters and the the sec_desc */
1673 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1674 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1675 return WERR_ACCESS_DENIED;
1678 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1679 p->pipe_user.nt_user_token, snum) ||
1680 !print_access_check(&p->pipe_user, snum,
1681 printer_default->access_required)) {
1682 DEBUG(3, ("access DENIED for printer open\n"));
1683 close_printer_handle(p, handle);
1684 return WERR_ACCESS_DENIED;
1687 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1688 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1689 close_printer_handle(p, handle);
1690 return WERR_ACCESS_DENIED;
1693 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1694 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1696 printer_default->access_required = PRINTER_ACCESS_USE;
1698 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1699 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1704 /* sanity check to prevent programmer error */
1708 Printer->access_granted = printer_default->access_required;
1711 * If the client sent a devmode in the OpenPrinter() call, then
1712 * save it here in case we get a job submission on this handle
1715 if ( (Printer->printer_type != SPLHND_SERVER)
1716 && q_u->printer_default.devmode_cont.devmode_ptr )
1718 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1719 &Printer->nt_devmode );
1722 #if 0 /* JERRY -- I'm doubtful this is really effective */
1723 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1724 optimization in Windows 2000 clients --jerry */
1726 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1727 && (RA_WIN2K == get_remote_arch()) )
1729 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1730 sys_usleep( 500000 );
1737 /****************************************************************************
1738 ****************************************************************************/
1740 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1741 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1747 /* allocate memory if needed. Messy because
1748 convert_printer_info is used to update an existing
1749 printer or build a new one */
1751 if ( !printer->info_2 ) {
1752 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1753 if ( !printer->info_2 ) {
1754 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1759 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1760 printer->info_2->setuptime = time(NULL);
1768 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1769 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1775 printer->info_3=NULL;
1776 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1780 printer->info_6=NULL;
1781 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1791 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1792 NT_DEVICEMODE **pp_nt_devmode)
1794 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1797 * Ensure nt_devmode is a valid pointer
1798 * as we will be overwriting it.
1801 if (nt_devmode == NULL) {
1802 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1803 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1807 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1808 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1810 nt_devmode->specversion=devmode->specversion;
1811 nt_devmode->driverversion=devmode->driverversion;
1812 nt_devmode->size=devmode->size;
1813 nt_devmode->fields=devmode->fields;
1814 nt_devmode->orientation=devmode->orientation;
1815 nt_devmode->papersize=devmode->papersize;
1816 nt_devmode->paperlength=devmode->paperlength;
1817 nt_devmode->paperwidth=devmode->paperwidth;
1818 nt_devmode->scale=devmode->scale;
1819 nt_devmode->copies=devmode->copies;
1820 nt_devmode->defaultsource=devmode->defaultsource;
1821 nt_devmode->printquality=devmode->printquality;
1822 nt_devmode->color=devmode->color;
1823 nt_devmode->duplex=devmode->duplex;
1824 nt_devmode->yresolution=devmode->yresolution;
1825 nt_devmode->ttoption=devmode->ttoption;
1826 nt_devmode->collate=devmode->collate;
1828 nt_devmode->logpixels=devmode->logpixels;
1829 nt_devmode->bitsperpel=devmode->bitsperpel;
1830 nt_devmode->pelswidth=devmode->pelswidth;
1831 nt_devmode->pelsheight=devmode->pelsheight;
1832 nt_devmode->displayflags=devmode->displayflags;
1833 nt_devmode->displayfrequency=devmode->displayfrequency;
1834 nt_devmode->icmmethod=devmode->icmmethod;
1835 nt_devmode->icmintent=devmode->icmintent;
1836 nt_devmode->mediatype=devmode->mediatype;
1837 nt_devmode->dithertype=devmode->dithertype;
1838 nt_devmode->reserved1=devmode->reserved1;
1839 nt_devmode->reserved2=devmode->reserved2;
1840 nt_devmode->panningwidth=devmode->panningwidth;
1841 nt_devmode->panningheight=devmode->panningheight;
1844 * Only change private and driverextra if the incoming devmode
1845 * has a new one. JRA.
1848 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1849 SAFE_FREE(nt_devmode->nt_dev_private);
1850 nt_devmode->driverextra=devmode->driverextra;
1851 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1853 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1856 *pp_nt_devmode = nt_devmode;
1861 /********************************************************************
1862 * _spoolss_enddocprinter_internal.
1863 ********************************************************************/
1865 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1867 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1871 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1875 if (!get_printer_snum(p, handle, &snum, NULL))
1878 Printer->document_started=False;
1879 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1880 /* error codes unhandled so far ... */
1885 /********************************************************************
1886 * api_spoolss_closeprinter
1887 ********************************************************************/
1889 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1891 POLICY_HND *handle = &q_u->handle;
1893 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1895 if (Printer && Printer->document_started)
1896 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1898 if (!close_printer_handle(p, handle))
1901 /* clear the returned printer handle. Observed behavior
1902 from Win2k server. Don't think this really matters.
1903 Previous code just copied the value of the closed
1906 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1911 /********************************************************************
1912 * api_spoolss_deleteprinter
1914 ********************************************************************/
1916 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1918 POLICY_HND *handle = &q_u->handle;
1919 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1922 if (Printer && Printer->document_started)
1923 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1925 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1927 result = delete_printer_handle(p, handle);
1929 update_c_setprinter(False);
1934 /*******************************************************************
1935 * static function to lookup the version id corresponding to an
1936 * long architecture string
1937 ******************************************************************/
1939 static int get_version_id (char * arch)
1942 struct table_node archi_table[]= {
1944 {"Windows 4.0", "WIN40", 0 },
1945 {"Windows NT x86", "W32X86", 2 },
1946 {"Windows NT R4000", "W32MIPS", 2 },
1947 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1948 {"Windows NT PowerPC", "W32PPC", 2 },
1949 {"Windows IA64", "IA64", 3 },
1950 {"Windows x64", "x64", 3 },
1954 for (i=0; archi_table[i].long_archi != NULL; i++)
1956 if (strcmp(arch, archi_table[i].long_archi) == 0)
1957 return (archi_table[i].version);
1963 /********************************************************************
1964 * _spoolss_deleteprinterdriver
1965 ********************************************************************/
1967 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1971 NT_PRINTER_DRIVER_INFO_LEVEL info;
1972 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1975 WERROR status_win2k = WERR_ACCESS_DENIED;
1976 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1978 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1979 and not a printer admin, then fail */
1981 if ( (p->pipe_user.ut.uid != 0)
1982 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
1983 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
1984 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
1986 return WERR_ACCESS_DENIED;
1989 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1990 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1992 /* check that we have a valid driver name first */
1994 if ((version=get_version_id(arch)) == -1)
1995 return WERR_INVALID_ENVIRONMENT;
1998 ZERO_STRUCT(info_win2k);
2000 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2002 /* try for Win2k driver if "Windows NT x86" */
2004 if ( version == 2 ) {
2006 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2007 status = WERR_UNKNOWN_PRINTER_DRIVER;
2011 /* otherwise it was a failure */
2013 status = WERR_UNKNOWN_PRINTER_DRIVER;
2019 if (printer_driver_in_use(info.info_3)) {
2020 status = WERR_PRINTER_DRIVER_IN_USE;
2026 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2028 /* if we get to here, we now have 2 driver info structures to remove */
2029 /* remove the Win2k driver first*/
2031 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2032 free_a_printer_driver( info_win2k, 3 );
2034 /* this should not have failed---if it did, report to client */
2035 if ( !W_ERROR_IS_OK(status_win2k) )
2037 status = status_win2k;
2043 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2045 /* if at least one of the deletes succeeded return OK */
2047 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2051 free_a_printer_driver( info, 3 );
2056 /********************************************************************
2057 * spoolss_deleteprinterdriverex
2058 ********************************************************************/
2060 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2064 NT_PRINTER_DRIVER_INFO_LEVEL info;
2065 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2067 uint32 flags = q_u->delete_flags;
2070 WERROR status_win2k = WERR_ACCESS_DENIED;
2071 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2073 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2074 and not a printer admin, then fail */
2076 if ( (p->pipe_user.ut.uid != 0)
2077 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2078 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2079 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2081 return WERR_ACCESS_DENIED;
2084 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2085 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2087 /* check that we have a valid driver name first */
2088 if ((version=get_version_id(arch)) == -1) {
2089 /* this is what NT returns */
2090 return WERR_INVALID_ENVIRONMENT;
2093 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2094 version = q_u->version;
2097 ZERO_STRUCT(info_win2k);
2099 status = get_a_printer_driver(&info, 3, driver, arch, version);
2101 if ( !W_ERROR_IS_OK(status) )
2104 * if the client asked for a specific version,
2105 * or this is something other than Windows NT x86,
2109 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2112 /* try for Win2k driver if "Windows NT x86" */
2115 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2116 status = WERR_UNKNOWN_PRINTER_DRIVER;
2121 if ( printer_driver_in_use(info.info_3) ) {
2122 status = WERR_PRINTER_DRIVER_IN_USE;
2127 * we have a couple of cases to consider.
2128 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2129 * then the delete should fail if **any** files overlap with
2131 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2132 * non-overlapping files
2133 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2134 * is set, the do not delete any files
2135 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2138 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2140 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2142 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2143 /* no idea of the correct error here */
2144 status = WERR_ACCESS_DENIED;
2149 /* also check for W32X86/3 if necessary; maybe we already have? */
2151 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2152 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2155 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2156 /* no idea of the correct error here */
2157 free_a_printer_driver( info_win2k, 3 );
2158 status = WERR_ACCESS_DENIED;
2162 /* if we get to here, we now have 2 driver info structures to remove */
2163 /* remove the Win2k driver first*/
2165 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2166 free_a_printer_driver( info_win2k, 3 );
2168 /* this should not have failed---if it did, report to client */
2170 if ( !W_ERROR_IS_OK(status_win2k) )
2175 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2177 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2180 free_a_printer_driver( info, 3 );
2186 /****************************************************************************
2187 Internal routine for retreiving printerdata
2188 ***************************************************************************/
2190 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2191 const char *key, const char *value, uint32 *type, uint8 **data,
2192 uint32 *needed, uint32 in_size )
2194 REGISTRY_VALUE *val;
2198 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2199 return WERR_BADFILE;
2201 *type = regval_type( val );
2203 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2205 size = regval_size( val );
2207 /* copy the min(in_size, len) */
2210 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2212 /* special case for 0 length values */
2214 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2218 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2227 DEBUG(5,("get_printer_dataex: copy done\n"));
2232 /****************************************************************************
2233 Internal routine for removing printerdata
2234 ***************************************************************************/
2236 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2238 return delete_printer_data( printer->info_2, key, value );
2241 /****************************************************************************
2242 Internal routine for storing printerdata
2243 ***************************************************************************/
2245 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2246 uint32 type, uint8 *data, int real_len )
2248 /* the registry objects enforce uniqueness based on value name */
2250 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2253 /********************************************************************
2254 GetPrinterData on a printer server Handle.
2255 ********************************************************************/
2257 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2261 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2263 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2265 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2271 if (!StrCaseCmp(value, "BeepEnabled")) {
2273 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2275 SIVAL(*data, 0, 0x00);
2280 if (!StrCaseCmp(value, "EventLog")) {
2282 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2284 /* formally was 0x1b */
2285 SIVAL(*data, 0, 0x0);
2290 if (!StrCaseCmp(value, "NetPopup")) {
2292 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2294 SIVAL(*data, 0, 0x00);
2299 if (!StrCaseCmp(value, "MajorVersion")) {
2301 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2304 /* Windows NT 4.0 seems to not allow uploading of drivers
2305 to a server that reports 0x3 as the MajorVersion.
2306 need to investigate more how Win2k gets around this .
2309 if ( RA_WINNT == get_remote_arch() )
2318 if (!StrCaseCmp(value, "MinorVersion")) {
2320 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2328 * uint32 size = 0x114
2330 * uint32 minor = [0|1]
2331 * uint32 build = [2195|2600]
2332 * extra unicode string = e.g. "Service Pack 3"
2334 if (!StrCaseCmp(value, "OSVersion")) {
2338 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2341 SIVAL(*data, 0, *needed); /* size */
2342 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2344 SIVAL(*data, 12, 2195); /* build */
2346 /* leave extra string empty */
2352 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2353 const char *string="C:\\PRINTERS";
2355 *needed = 2*(strlen(string)+1);
2356 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2358 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2360 /* it's done by hand ready to go on the wire */
2361 for (i=0; i<strlen(string); i++) {
2362 (*data)[2*i]=string[i];
2363 (*data)[2*i+1]='\0';
2368 if (!StrCaseCmp(value, "Architecture")) {
2369 const char *string="Windows NT x86";
2371 *needed = 2*(strlen(string)+1);
2372 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2374 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2375 for (i=0; i<strlen(string); i++) {
2376 (*data)[2*i]=string[i];
2377 (*data)[2*i+1]='\0';
2382 if (!StrCaseCmp(value, "DsPresent")) {
2384 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2387 /* only show the publish check box if we are a
2388 memeber of a AD domain */
2390 if ( lp_security() == SEC_ADS )
2391 SIVAL(*data, 0, 0x01);
2393 SIVAL(*data, 0, 0x00);
2399 if (!StrCaseCmp(value, "DNSMachineName")) {
2402 if (!get_mydnsfullname(hostname))
2403 return WERR_BADFILE;
2405 *needed = 2*(strlen(hostname)+1);
2406 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2408 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2409 for (i=0; i<strlen(hostname); i++) {
2410 (*data)[2*i]=hostname[i];
2411 (*data)[2*i+1]='\0';
2417 return WERR_BADFILE;
2420 /********************************************************************
2421 * spoolss_getprinterdata
2422 ********************************************************************/
2424 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2426 POLICY_HND *handle = &q_u->handle;
2427 UNISTR2 *valuename = &q_u->valuename;
2428 uint32 in_size = q_u->size;
2429 uint32 *type = &r_u->type;
2430 uint32 *out_size = &r_u->size;
2431 uint8 **data = &r_u->data;
2432 uint32 *needed = &r_u->needed;
2435 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2436 NT_PRINTER_INFO_LEVEL *printer = NULL;
2440 * Reminder: when it's a string, the length is in BYTES
2441 * even if UNICODE is negociated.
2446 *out_size = in_size;
2448 /* in case of problem, return some default values */
2453 DEBUG(4,("_spoolss_getprinterdata\n"));
2456 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2457 status = WERR_BADFID;
2461 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2463 if ( Printer->printer_type == SPLHND_SERVER )
2464 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2467 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2468 status = WERR_BADFID;
2472 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2473 if ( !W_ERROR_IS_OK(status) )
2476 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2478 if ( strequal(value, "ChangeId") ) {
2480 *needed = sizeof(uint32);
2481 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2482 status = WERR_NOMEM;
2485 SIVAL( *data, 0, printer->info_2->changeid );
2489 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2492 if (*needed > *out_size)
2493 status = WERR_MORE_DATA;
2496 if ( !W_ERROR_IS_OK(status) )
2498 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2500 /* reply this param doesn't exist */
2503 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2505 free_a_printer( &printer, 2 );
2513 /* cleanup & exit */
2516 free_a_printer( &printer, 2 );
2521 /*********************************************************
2522 Connect to the client machine.
2523 **********************************************************/
2525 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2526 struct in_addr *client_ip, const char *remote_machine)
2529 struct cli_state *the_cli;
2530 struct in_addr rm_addr;
2532 if ( is_zero_ip(*client_ip) ) {
2533 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2534 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2538 if ( ismyip( rm_addr )) {
2539 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2543 rm_addr.s_addr = client_ip->s_addr;
2544 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2545 inet_ntoa(*client_ip) ));
2548 /* setup the connection */
2550 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2551 &rm_addr, 0, "IPC$", "IPC",
2555 0, lp_client_signing(), NULL );
2557 if ( !NT_STATUS_IS_OK( ret ) ) {
2558 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2563 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2564 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2565 cli_shutdown(the_cli);
2570 * Ok - we have an anonymous connection to the IPC$ share.
2571 * Now start the NT Domain stuff :-).
2574 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2575 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2576 remote_machine, nt_errstr(ret)));
2577 cli_shutdown(the_cli);
2581 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2583 (*pp_pipe)->cli = the_cli;
2588 /***************************************************************************
2589 Connect to the client.
2590 ****************************************************************************/
2592 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2593 uint32 localprinter, uint32 type,
2594 POLICY_HND *handle, struct in_addr *client_ip)
2599 * If it's the first connection, contact the client
2600 * and connect to the IPC$ share anonymously
2602 if (smb_connections==0) {
2603 fstring unix_printer;
2605 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2607 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2610 message_register(MSG_PRINTER_NOTIFY2,
2611 receive_notify2_message_list, NULL);
2612 /* Tell the connections db we're now interested in printer
2613 * notify messages. */
2614 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2618 * Tell the specific printing tdb we want messages for this printer
2619 * by registering our PID.
2622 if (!print_notify_register_pid(snum))
2623 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2627 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2630 if (!W_ERROR_IS_OK(result))
2631 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2632 dos_errstr(result)));
2634 return (W_ERROR_IS_OK(result));
2637 /********************************************************************
2639 * ReplyFindFirstPrinterChangeNotifyEx
2641 * before replying OK: status=0 a rpc call is made to the workstation
2642 * asking ReplyOpenPrinter
2644 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2645 * called from api_spoolss_rffpcnex
2646 ********************************************************************/
2648 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2650 POLICY_HND *handle = &q_u->handle;
2651 uint32 flags = q_u->flags;
2652 uint32 options = q_u->options;
2653 UNISTR2 *localmachine = &q_u->localmachine;
2654 uint32 printerlocal = q_u->printerlocal;
2656 SPOOL_NOTIFY_OPTION *option = q_u->option;
2657 struct in_addr client_ip;
2659 /* store the notify value in the printer struct */
2661 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2664 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2668 Printer->notify.flags=flags;
2669 Printer->notify.options=options;
2670 Printer->notify.printerlocal=printerlocal;
2672 if (Printer->notify.option)
2673 free_spool_notify_option(&Printer->notify.option);
2675 Printer->notify.option=dup_spool_notify_option(option);
2677 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2678 sizeof(Printer->notify.localmachine)-1);
2680 /* Connect to the client machine and send a ReplyOpenPrinter */
2682 if ( Printer->printer_type == SPLHND_SERVER)
2684 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2685 !get_printer_snum(p, handle, &snum, NULL) )
2688 client_ip.s_addr = inet_addr(p->conn->client_address);
2690 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2691 Printer->notify.printerlocal, 1,
2692 &Printer->notify.client_hnd, &client_ip))
2693 return WERR_SERVER_UNAVAILABLE;
2695 Printer->notify.client_connected=True;
2700 /*******************************************************************
2701 * fill a notify_info_data with the servername
2702 ********************************************************************/
2704 void spoolss_notify_server_name(int snum,
2705 SPOOL_NOTIFY_INFO_DATA *data,
2706 print_queue_struct *queue,
2707 NT_PRINTER_INFO_LEVEL *printer,
2708 TALLOC_CTX *mem_ctx)
2713 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2715 data->notify_data.data.length = len;
2717 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2718 if (!data->notify_data.data.string) {
2719 data->notify_data.data.length = 0;
2723 memcpy(data->notify_data.data.string, temp, len);
2725 data->notify_data.data.string = NULL;
2729 /*******************************************************************
2730 * fill a notify_info_data with the printername (not including the servername).
2731 ********************************************************************/
2733 void spoolss_notify_printer_name(int snum,
2734 SPOOL_NOTIFY_INFO_DATA *data,
2735 print_queue_struct *queue,
2736 NT_PRINTER_INFO_LEVEL *printer,
2737 TALLOC_CTX *mem_ctx)
2742 /* the notify name should not contain the \\server\ part */
2743 char *p = strrchr(printer->info_2->printername, '\\');
2746 p = printer->info_2->printername;
2751 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2753 data->notify_data.data.length = len;
2755 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2756 if (!data->notify_data.data.string) {
2757 data->notify_data.data.length = 0;
2760 memcpy(data->notify_data.data.string, temp, len);
2762 data->notify_data.data.string = NULL;
2766 /*******************************************************************
2767 * fill a notify_info_data with the servicename
2768 ********************************************************************/
2770 void spoolss_notify_share_name(int snum,
2771 SPOOL_NOTIFY_INFO_DATA *data,
2772 print_queue_struct *queue,
2773 NT_PRINTER_INFO_LEVEL *printer,
2774 TALLOC_CTX *mem_ctx)
2779 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2781 data->notify_data.data.length = len;
2783 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2784 if (!data->notify_data.data.string) {
2785 data->notify_data.data.length = 0;
2788 memcpy(data->notify_data.data.string, temp, len);
2790 data->notify_data.data.string = NULL;
2795 /*******************************************************************
2796 * fill a notify_info_data with the port name
2797 ********************************************************************/
2799 void spoolss_notify_port_name(int snum,
2800 SPOOL_NOTIFY_INFO_DATA *data,
2801 print_queue_struct *queue,
2802 NT_PRINTER_INFO_LEVEL *printer,
2803 TALLOC_CTX *mem_ctx)
2808 /* even if it's strange, that's consistant in all the code */
2810 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2812 data->notify_data.data.length = len;
2814 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2816 if (!data->notify_data.data.string) {
2817 data->notify_data.data.length = 0;
2821 memcpy(data->notify_data.data.string, temp, len);
2823 data->notify_data.data.string = NULL;
2827 /*******************************************************************
2828 * fill a notify_info_data with the printername
2829 * but it doesn't exist, have to see what to do
2830 ********************************************************************/
2832 void spoolss_notify_driver_name(int snum,
2833 SPOOL_NOTIFY_INFO_DATA *data,
2834 print_queue_struct *queue,
2835 NT_PRINTER_INFO_LEVEL *printer,
2836 TALLOC_CTX *mem_ctx)
2841 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2843 data->notify_data.data.length = len;
2845 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2847 if (!data->notify_data.data.string) {
2848 data->notify_data.data.length = 0;
2852 memcpy(data->notify_data.data.string, temp, len);
2854 data->notify_data.data.string = NULL;
2858 /*******************************************************************
2859 * fill a notify_info_data with the comment
2860 ********************************************************************/
2862 void spoolss_notify_comment(int snum,
2863 SPOOL_NOTIFY_INFO_DATA *data,
2864 print_queue_struct *queue,
2865 NT_PRINTER_INFO_LEVEL *printer,
2866 TALLOC_CTX *mem_ctx)
2871 if (*printer->info_2->comment == '\0')
2872 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2874 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2876 data->notify_data.data.length = len;
2878 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2880 if (!data->notify_data.data.string) {
2881 data->notify_data.data.length = 0;
2885 memcpy(data->notify_data.data.string, temp, len);
2887 data->notify_data.data.string = NULL;
2891 /*******************************************************************
2892 * fill a notify_info_data with the comment
2893 * location = "Room 1, floor 2, building 3"
2894 ********************************************************************/
2896 void spoolss_notify_location(int snum,
2897 SPOOL_NOTIFY_INFO_DATA *data,
2898 print_queue_struct *queue,
2899 NT_PRINTER_INFO_LEVEL *printer,
2900 TALLOC_CTX *mem_ctx)
2905 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2907 data->notify_data.data.length = len;
2909 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2911 if (!data->notify_data.data.string) {
2912 data->notify_data.data.length = 0;
2916 memcpy(data->notify_data.data.string, temp, len);
2918 data->notify_data.data.string = NULL;
2922 /*******************************************************************
2923 * fill a notify_info_data with the device mode
2924 * jfm:xxxx don't to it for know but that's a real problem !!!
2925 ********************************************************************/
2927 static void spoolss_notify_devmode(int snum,
2928 SPOOL_NOTIFY_INFO_DATA *data,
2929 print_queue_struct *queue,
2930 NT_PRINTER_INFO_LEVEL *printer,
2931 TALLOC_CTX *mem_ctx)
2933 /* for a dummy implementation we have to zero the fields */
2934 data->notify_data.data.length = 0;
2935 data->notify_data.data.string = NULL;
2938 /*******************************************************************
2939 * fill a notify_info_data with the separator file name
2940 ********************************************************************/
2942 void spoolss_notify_sepfile(int snum,
2943 SPOOL_NOTIFY_INFO_DATA *data,
2944 print_queue_struct *queue,
2945 NT_PRINTER_INFO_LEVEL *printer,
2946 TALLOC_CTX *mem_ctx)
2951 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2953 data->notify_data.data.length = len;
2955 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2957 if (!data->notify_data.data.string) {
2958 data->notify_data.data.length = 0;
2962 memcpy(data->notify_data.data.string, temp, len);
2964 data->notify_data.data.string = NULL;
2968 /*******************************************************************
2969 * fill a notify_info_data with the print processor
2970 * jfm:xxxx return always winprint to indicate we don't do anything to it
2971 ********************************************************************/
2973 void spoolss_notify_print_processor(int snum,
2974 SPOOL_NOTIFY_INFO_DATA *data,
2975 print_queue_struct *queue,
2976 NT_PRINTER_INFO_LEVEL *printer,
2977 TALLOC_CTX *mem_ctx)
2982 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2984 data->notify_data.data.length = len;
2986 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2988 if (!data->notify_data.data.string) {
2989 data->notify_data.data.length = 0;
2993 memcpy(data->notify_data.data.string, temp, len);
2995 data->notify_data.data.string = NULL;
2999 /*******************************************************************
3000 * fill a notify_info_data with the print processor options
3001 * jfm:xxxx send an empty string
3002 ********************************************************************/
3004 void spoolss_notify_parameters(int snum,
3005 SPOOL_NOTIFY_INFO_DATA *data,
3006 print_queue_struct *queue,
3007 NT_PRINTER_INFO_LEVEL *printer,
3008 TALLOC_CTX *mem_ctx)
3013 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3015 data->notify_data.data.length = len;
3017 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3019 if (!data->notify_data.data.string) {
3020 data->notify_data.data.length = 0;
3024 memcpy(data->notify_data.data.string, temp, len);
3026 data->notify_data.data.string = NULL;
3030 /*******************************************************************
3031 * fill a notify_info_data with the data type
3032 * jfm:xxxx always send RAW as data type
3033 ********************************************************************/
3035 void spoolss_notify_datatype(int snum,
3036 SPOOL_NOTIFY_INFO_DATA *data,
3037 print_queue_struct *queue,
3038 NT_PRINTER_INFO_LEVEL *printer,
3039 TALLOC_CTX *mem_ctx)
3044 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3046 data->notify_data.data.length = len;
3048 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3050 if (!data->notify_data.data.string) {
3051 data->notify_data.data.length = 0;
3055 memcpy(data->notify_data.data.string, temp, len);
3057 data->notify_data.data.string = NULL;
3061 /*******************************************************************
3062 * fill a notify_info_data with the security descriptor
3063 * jfm:xxxx send an null pointer to say no security desc
3064 * have to implement security before !
3065 ********************************************************************/
3067 static void spoolss_notify_security_desc(int snum,
3068 SPOOL_NOTIFY_INFO_DATA *data,
3069 print_queue_struct *queue,
3070 NT_PRINTER_INFO_LEVEL *printer,
3071 TALLOC_CTX *mem_ctx)
3073 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3074 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3077 /*******************************************************************
3078 * fill a notify_info_data with the attributes
3079 * jfm:xxxx a samba printer is always shared
3080 ********************************************************************/
3082 void spoolss_notify_attributes(int snum,
3083 SPOOL_NOTIFY_INFO_DATA *data,
3084 print_queue_struct *queue,
3085 NT_PRINTER_INFO_LEVEL *printer,
3086 TALLOC_CTX *mem_ctx)
3088 data->notify_data.value[0] = printer->info_2->attributes;
3089 data->notify_data.value[1] = 0;
3092 /*******************************************************************
3093 * fill a notify_info_data with the priority
3094 ********************************************************************/
3096 static void spoolss_notify_priority(int snum,
3097 SPOOL_NOTIFY_INFO_DATA *data,
3098 print_queue_struct *queue,
3099 NT_PRINTER_INFO_LEVEL *printer,
3100 TALLOC_CTX *mem_ctx)
3102 data->notify_data.value[0] = printer->info_2->priority;
3103 data->notify_data.value[1] = 0;
3106 /*******************************************************************
3107 * fill a notify_info_data with the default priority
3108 ********************************************************************/
3110 static void spoolss_notify_default_priority(int snum,
3111 SPOOL_NOTIFY_INFO_DATA *data,
3112 print_queue_struct *queue,
3113 NT_PRINTER_INFO_LEVEL *printer,
3114 TALLOC_CTX *mem_ctx)
3116 data->notify_data.value[0] = printer->info_2->default_priority;
3117 data->notify_data.value[1] = 0;
3120 /*******************************************************************
3121 * fill a notify_info_data with the start time
3122 ********************************************************************/
3124 static void spoolss_notify_start_time(int snum,
3125 SPOOL_NOTIFY_INFO_DATA *data,
3126 print_queue_struct *queue,
3127 NT_PRINTER_INFO_LEVEL *printer,
3128 TALLOC_CTX *mem_ctx)
3130 data->notify_data.value[0] = printer->info_2->starttime;
3131 data->notify_data.value[1] = 0;
3134 /*******************************************************************
3135 * fill a notify_info_data with the until time
3136 ********************************************************************/
3138 static void spoolss_notify_until_time(int snum,
3139 SPOOL_NOTIFY_INFO_DATA *data,
3140 print_queue_struct *queue,
3141 NT_PRINTER_INFO_LEVEL *printer,
3142 TALLOC_CTX *mem_ctx)
3144 data->notify_data.value[0] = printer->info_2->untiltime;
3145 data->notify_data.value[1] = 0;
3148 /*******************************************************************
3149 * fill a notify_info_data with the status
3150 ********************************************************************/
3152 static void spoolss_notify_status(int snum,
3153 SPOOL_NOTIFY_INFO_DATA *data,
3154 print_queue_struct *queue,
3155 NT_PRINTER_INFO_LEVEL *printer,
3156 TALLOC_CTX *mem_ctx)
3158 print_status_struct status;
3160 print_queue_length(snum, &status);
3161 data->notify_data.value[0]=(uint32) status.status;
3162 data->notify_data.value[1] = 0;
3165 /*******************************************************************
3166 * fill a notify_info_data with the number of jobs queued
3167 ********************************************************************/
3169 void spoolss_notify_cjobs(int snum,
3170 SPOOL_NOTIFY_INFO_DATA *data,
3171 print_queue_struct *queue,
3172 NT_PRINTER_INFO_LEVEL *printer,
3173 TALLOC_CTX *mem_ctx)
3175 data->notify_data.value[0] = print_queue_length(snum, NULL);
3176 data->notify_data.value[1] = 0;
3179 /*******************************************************************
3180 * fill a notify_info_data with the average ppm
3181 ********************************************************************/
3183 static void spoolss_notify_average_ppm(int snum,
3184 SPOOL_NOTIFY_INFO_DATA *data,
3185 print_queue_struct *queue,
3186 NT_PRINTER_INFO_LEVEL *printer,
3187 TALLOC_CTX *mem_ctx)
3189 /* always respond 8 pages per minutes */
3190 /* a little hard ! */
3191 data->notify_data.value[0] = printer->info_2->averageppm;
3192 data->notify_data.value[1] = 0;
3195 /*******************************************************************
3196 * fill a notify_info_data with username
3197 ********************************************************************/
3199 static void spoolss_notify_username(int snum,
3200 SPOOL_NOTIFY_INFO_DATA *data,
3201 print_queue_struct *queue,
3202 NT_PRINTER_INFO_LEVEL *printer,
3203 TALLOC_CTX *mem_ctx)
3208 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3210 data->notify_data.data.length = len;
3212 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3214 if (!data->notify_data.data.string) {
3215 data->notify_data.data.length = 0;
3219 memcpy(data->notify_data.data.string, temp, len);
3221 data->notify_data.data.string = NULL;
3225 /*******************************************************************
3226 * fill a notify_info_data with job status
3227 ********************************************************************/
3229 static void spoolss_notify_job_status(int snum,
3230 SPOOL_NOTIFY_INFO_DATA *data,
3231 print_queue_struct *queue,
3232 NT_PRINTER_INFO_LEVEL *printer,
3233 TALLOC_CTX *mem_ctx)
3235 data->notify_data.value[0]=nt_printj_status(queue->status);
3236 data->notify_data.value[1] = 0;
3239 /*******************************************************************
3240 * fill a notify_info_data with job name
3241 ********************************************************************/
3243 static void spoolss_notify_job_name(int snum,
3244 SPOOL_NOTIFY_INFO_DATA *data,
3245 print_queue_struct *queue,
3246 NT_PRINTER_INFO_LEVEL *printer,
3247 TALLOC_CTX *mem_ctx)
3252 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3254 data->notify_data.data.length = len;
3256 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3258 if (!data->notify_data.data.string) {
3259 data->notify_data.data.length = 0;
3263 memcpy(data->notify_data.data.string, temp, len);
3265 data->notify_data.data.string = NULL;
3269 /*******************************************************************
3270 * fill a notify_info_data with job status
3271 ********************************************************************/
3273 static void spoolss_notify_job_status_string(int snum,
3274 SPOOL_NOTIFY_INFO_DATA *data,
3275 print_queue_struct *queue,
3276 NT_PRINTER_INFO_LEVEL *printer,
3277 TALLOC_CTX *mem_ctx)
3280 * Now we're returning job status codes we just return a "" here. JRA.
3287 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3290 switch (queue->status) {
3295 p = ""; /* NT provides the paused string */
3304 #endif /* NO LONGER NEEDED. */
3306 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3308 data->notify_data.data.length = len;
3310 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3312 if (!data->notify_data.data.string) {
3313 data->notify_data.data.length = 0;
3317 memcpy(data->notify_data.data.string, temp, len);
3319 data->notify_data.data.string = NULL;
3323 /*******************************************************************
3324 * fill a notify_info_data with job time
3325 ********************************************************************/
3327 static void spoolss_notify_job_time(int snum,
3328 SPOOL_NOTIFY_INFO_DATA *data,
3329 print_queue_struct *queue,
3330 NT_PRINTER_INFO_LEVEL *printer,
3331 TALLOC_CTX *mem_ctx)
3333 data->notify_data.value[0]=0x0;
3334 data->notify_data.value[1]=0;
3337 /*******************************************************************
3338 * fill a notify_info_data with job size
3339 ********************************************************************/
3341 static void spoolss_notify_job_size(int snum,
3342 SPOOL_NOTIFY_INFO_DATA *data,
3343 print_queue_struct *queue,
3344 NT_PRINTER_INFO_LEVEL *printer,
3345 TALLOC_CTX *mem_ctx)
3347 data->notify_data.value[0]=queue->size;
3348 data->notify_data.value[1]=0;
3351 /*******************************************************************
3352 * fill a notify_info_data with page info
3353 ********************************************************************/
3354 static void spoolss_notify_total_pages(int snum,
3355 SPOOL_NOTIFY_INFO_DATA *data,
3356 print_queue_struct *queue,
3357 NT_PRINTER_INFO_LEVEL *printer,
3358 TALLOC_CTX *mem_ctx)
3360 data->notify_data.value[0]=queue->page_count;
3361 data->notify_data.value[1]=0;
3364 /*******************************************************************
3365 * fill a notify_info_data with pages printed info.
3366 ********************************************************************/
3367 static void spoolss_notify_pages_printed(int snum,
3368 SPOOL_NOTIFY_INFO_DATA *data,
3369 print_queue_struct *queue,
3370 NT_PRINTER_INFO_LEVEL *printer,
3371 TALLOC_CTX *mem_ctx)
3373 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3374 data->notify_data.value[1]=0;
3377 /*******************************************************************
3378 Fill a notify_info_data with job position.
3379 ********************************************************************/
3381 static void spoolss_notify_job_position(int snum,
3382 SPOOL_NOTIFY_INFO_DATA *data,
3383 print_queue_struct *queue,
3384 NT_PRINTER_INFO_LEVEL *printer,
3385 TALLOC_CTX *mem_ctx)
3387 data->notify_data.value[0]=queue->job;
3388 data->notify_data.value[1]=0;
3391 /*******************************************************************
3392 Fill a notify_info_data with submitted time.
3393 ********************************************************************/
3395 static void spoolss_notify_submitted_time(int snum,
3396 SPOOL_NOTIFY_INFO_DATA *data,
3397 print_queue_struct *queue,
3398 NT_PRINTER_INFO_LEVEL *printer,
3399 TALLOC_CTX *mem_ctx)
3406 t=gmtime(&queue->time);
3408 len = sizeof(SYSTEMTIME);
3410 data->notify_data.data.length = len;
3411 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3413 if (!data->notify_data.data.string) {
3414 data->notify_data.data.length = 0;
3418 make_systemtime(&st, t);
3421 * Systemtime must be linearized as a set of UINT16's.
3422 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3425 p = (char *)data->notify_data.data.string;
3426 SSVAL(p, 0, st.year);
3427 SSVAL(p, 2, st.month);
3428 SSVAL(p, 4, st.dayofweek);
3429 SSVAL(p, 6, st.day);
3430 SSVAL(p, 8, st.hour);
3431 SSVAL(p, 10, st.minute);
3432 SSVAL(p, 12, st.second);
3433 SSVAL(p, 14, st.milliseconds);
3436 struct s_notify_info_data_table
3442 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3443 print_queue_struct *queue,
3444 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3447 /* A table describing the various print notification constants and
3448 whether the notification data is a pointer to a variable sized
3449 buffer, a one value uint32 or a two value uint32. */
3451 static const struct s_notify_info_data_table notify_info_data_table[] =
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3502 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3505 /*******************************************************************
3506 Return the size of info_data structure.
3507 ********************************************************************/
3509 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3513 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3514 if ( (notify_info_data_table[i].type == type)
3515 && (notify_info_data_table[i].field == field) ) {
3516 switch(notify_info_data_table[i].size) {
3517 case NOTIFY_ONE_VALUE:
3518 case NOTIFY_TWO_VALUE:
3523 /* The only pointer notify data I have seen on
3524 the wire is the submitted time and this has
3525 the notify size set to 4. -tpot */
3527 case NOTIFY_POINTER:
3530 case NOTIFY_SECDESC:
3536 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3541 /*******************************************************************
3542 Return the type of notify_info_data.
3543 ********************************************************************/
3545 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3549 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3550 if (notify_info_data_table[i].type == type &&
3551 notify_info_data_table[i].field == field)
3552 return notify_info_data_table[i].size;
3558 /****************************************************************************
3559 ****************************************************************************/
3561 static BOOL search_notify(uint16 type, uint16 field, int *value)
3565 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3566 if (notify_info_data_table[i].type == type &&
3567 notify_info_data_table[i].field == field &&
3568 notify_info_data_table[i].fn != NULL) {
3577 /****************************************************************************
3578 ****************************************************************************/
3580 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3582 info_data->type = type;
3583 info_data->field = field;
3584 info_data->reserved = 0;
3586 info_data->size = size_of_notify_info_data(type, field);
3587 info_data->enc_type = type_of_notify_info_data(type, field);
3592 /*******************************************************************
3594 * fill a notify_info struct with info asked
3596 ********************************************************************/
3598 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3599 snum, SPOOL_NOTIFY_OPTION_TYPE
3600 *option_type, uint32 id,
3601 TALLOC_CTX *mem_ctx)
3607 SPOOL_NOTIFY_INFO_DATA *current_data;
3608 NT_PRINTER_INFO_LEVEL *printer = NULL;
3609 print_queue_struct *queue=NULL;
3611 type=option_type->type;
3613 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3614 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3615 option_type->count, lp_servicename(snum)));
3617 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3620 for(field_num=0; field_num<option_type->count; field_num++) {
3621 field = option_type->fields[field_num];
3623 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3625 if (!search_notify(type, field, &j) )
3628 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3629 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3630 free_a_printer(&printer, 2);
3634 current_data = &info->data[info->count];
3636 construct_info_data(current_data, type, field, id);
3638 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3639 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3641 notify_info_data_table[j].fn(snum, current_data, queue,
3647 free_a_printer(&printer, 2);
3651 /*******************************************************************
3653 * fill a notify_info struct with info asked
3655 ********************************************************************/
3657 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3658 SPOOL_NOTIFY_INFO *info,
3659 NT_PRINTER_INFO_LEVEL *printer,
3660 int snum, SPOOL_NOTIFY_OPTION_TYPE
3661 *option_type, uint32 id,
3662 TALLOC_CTX *mem_ctx)
3668 SPOOL_NOTIFY_INFO_DATA *current_data;
3670 DEBUG(4,("construct_notify_jobs_info\n"));
3672 type = option_type->type;
3674 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3675 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3676 option_type->count));
3678 for(field_num=0; field_num<option_type->count; field_num++) {
3679 field = option_type->fields[field_num];
3681 if (!search_notify(type, field, &j) )
3684 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3685 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3689 current_data=&(info->data[info->count]);
3691 construct_info_data(current_data, type, field, id);
3692 notify_info_data_table[j].fn(snum, current_data, queue,
3701 * JFM: The enumeration is not that simple, it's even non obvious.
3703 * let's take an example: I want to monitor the PRINTER SERVER for
3704 * the printer's name and the number of jobs currently queued.
3705 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3706 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3708 * I have 3 printers on the back of my server.
3710 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3713 * 1 printer 1 name 1
3714 * 2 printer 1 cjob 1
3715 * 3 printer 2 name 2
3716 * 4 printer 2 cjob 2
3717 * 5 printer 3 name 3
3718 * 6 printer 3 name 3
3720 * that's the print server case, the printer case is even worse.
3723 /*******************************************************************
3725 * enumerate all printers on the printserver
3726 * fill a notify_info struct with info asked
3728 ********************************************************************/
3730 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3731 SPOOL_NOTIFY_INFO *info,
3732 TALLOC_CTX *mem_ctx)
3735 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3736 int n_services=lp_numservices();
3738 SPOOL_NOTIFY_OPTION *option;
3739 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3741 DEBUG(4,("printserver_notify_info\n"));
3746 option=Printer->notify.option;
3751 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3752 sending a ffpcn() request first */
3757 for (i=0; i<option->count; i++) {
3758 option_type=&(option->ctr.type[i]);
3760 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3763 for (snum=0; snum<n_services; snum++)
3765 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3766 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3772 * Debugging information, don't delete.
3775 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3776 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3777 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3779 for (i=0; i<info->count; i++) {
3780 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3781 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3782 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3789 /*******************************************************************
3791 * fill a notify_info struct with info asked
3793 ********************************************************************/
3795 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3796 TALLOC_CTX *mem_ctx)
3799 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3802 SPOOL_NOTIFY_OPTION *option;
3803 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3805 print_queue_struct *queue=NULL;
3806 print_status_struct status;
3808 DEBUG(4,("printer_notify_info\n"));
3813 option=Printer->notify.option;
3819 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3820 sending a ffpcn() request first */
3825 get_printer_snum(p, hnd, &snum, NULL);
3827 for (i=0; i<option->count; i++) {
3828 option_type=&option->ctr.type[i];
3830 switch ( option_type->type ) {
3831 case PRINTER_NOTIFY_TYPE:
3832 if(construct_notify_printer_info(Printer, info, snum,
3838 case JOB_NOTIFY_TYPE: {
3839 NT_PRINTER_INFO_LEVEL *printer = NULL;
3841 count = print_queue_status(snum, &queue, &status);
3843 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3846 for (j=0; j<count; j++) {
3847 construct_notify_jobs_info(&queue[j], info,
3854 free_a_printer(&printer, 2);
3864 * Debugging information, don't delete.
3867 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3868 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3869 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3871 for (i=0; i<info->count; i++) {
3872 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3873 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3874 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3880 /********************************************************************
3882 ********************************************************************/
3884 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3886 POLICY_HND *handle = &q_u->handle;
3887 SPOOL_NOTIFY_INFO *info = &r_u->info;
3889 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3890 WERROR result = WERR_BADFID;
3892 /* we always have a NOTIFY_INFO struct */
3896 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3897 OUR_HANDLE(handle)));
3901 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3904 * We are now using the change value, and
3905 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3906 * I don't have a global notification system, I'm sending back all the
3907 * informations even when _NOTHING_ has changed.
3910 /* We need to keep track of the change value to send back in
3911 RRPCN replies otherwise our updates are ignored. */
3913 Printer->notify.fnpcn = True;
3915 if (Printer->notify.client_connected) {
3916 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3917 Printer->notify.change = q_u->change;
3920 /* just ignore the SPOOL_NOTIFY_OPTION */
3922 switch (Printer->printer_type) {
3924 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3927 case SPLHND_PRINTER:
3928 result = printer_notify_info(p, handle, info, p->mem_ctx);
3932 Printer->notify.fnpcn = False;
3938 /********************************************************************
3939 * construct_printer_info_0
3940 * fill a printer_info_0 struct
3941 ********************************************************************/
3943 static BOOL construct_printer_info_0(Printer_entry *print_hnd,
3944 PRINTER_INFO_0 *printer,
3945 const struct share_params *params)
3949 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3950 counter_printer_0 *session_counter;
3951 uint32 global_counter;
3954 print_status_struct status;
3956 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
3957 lp_const_servicename(params->service))))
3960 count = print_queue_length(params->service, &status);
3962 /* check if we already have a counter for this printer */
3963 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3964 if (session_counter->snum == params->service)
3968 /* it's the first time, add it to the list */
3969 if (session_counter==NULL) {
3970 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3971 free_a_printer(&ntprinter, 2);
3974 ZERO_STRUCTP(session_counter);
3975 session_counter->snum=params->service;
3976 session_counter->counter=0;
3977 DLIST_ADD(counter_list, session_counter);
3981 session_counter->counter++;
3984 * the global_counter should be stored in a TDB as it's common to all the clients
3985 * and should be zeroed on samba startup
3987 global_counter=session_counter->counter;
3989 pstrcpy(chaine,ntprinter->info_2->printername);
3991 init_unistr(&printer->printername, chaine);
3993 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3994 init_unistr(&printer->servername, chaine);
3996 printer->cjobs = count;
3997 printer->total_jobs = 0;
3998 printer->total_bytes = 0;
4000 setuptime = (time_t)ntprinter->info_2->setuptime;
4001 t=gmtime(&setuptime);
4003 printer->year = t->tm_year+1900;
4004 printer->month = t->tm_mon+1;
4005 printer->dayofweek = t->tm_wday;
4006 printer->day = t->tm_mday;
4007 printer->hour = t->tm_hour;
4008 printer->minute = t->tm_min;
4009 printer->second = t->tm_sec;
4010 printer->milliseconds = 0;
4012 printer->global_counter = global_counter;
4013 printer->total_pages = 0;
4015 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4016 printer->major_version = 0x0005; /* NT 5 */
4017 printer->build_version = 0x0893; /* build 2195 */
4019 printer->unknown7 = 0x1;
4020 printer->unknown8 = 0x0;
4021 printer->unknown9 = 0x0;
4022 printer->session_counter = session_counter->counter;
4023 printer->unknown11 = 0x0;
4024 printer->printer_errors = 0x0; /* number of print failure */
4025 printer->unknown13 = 0x0;
4026 printer->unknown14 = 0x1;
4027 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4028 printer->unknown16 = 0x0;
4029 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4030 printer->unknown18 = 0x0;
4031 printer->status = nt_printq_status(status.status);
4032 printer->unknown20 = 0x0;
4033 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4034 printer->unknown22 = 0x0;
4035 printer->unknown23 = 0x6; /* 6 ???*/
4036 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4037 printer->unknown25 = 0;
4038 printer->unknown26 = 0;
4039 printer->unknown27 = 0;
4040 printer->unknown28 = 0;
4041 printer->unknown29 = 0;
4043 free_a_printer(&ntprinter,2);
4047 /********************************************************************
4048 * construct_printer_info_1
4049 * fill a printer_info_1 struct
4050 ********************************************************************/
4051 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags,
4052 PRINTER_INFO_1 *printer,
4053 const struct share_params *params)
4057 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4059 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4060 lp_const_servicename(params->service))))
4063 printer->flags=flags;
4065 if (*ntprinter->info_2->comment == '\0') {
4066 init_unistr(&printer->comment, lp_comment(params->service));
4067 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4068 ntprinter->info_2->drivername,
4069 lp_comment(params->service));
4072 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4073 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4074 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4077 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4079 init_unistr(&printer->description, chaine);
4080 init_unistr(&printer->name, chaine2);
4082 free_a_printer(&ntprinter,2);
4087 /****************************************************************************
4088 Free a DEVMODE struct.
4089 ****************************************************************************/
4091 static void free_dev_mode(DEVICEMODE *dev)
4096 SAFE_FREE(dev->dev_private);
4101 /****************************************************************************
4102 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4103 should be valid upon entry
4104 ****************************************************************************/
4106 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4108 if ( !devmode || !ntdevmode )
4111 init_unistr(&devmode->devicename, ntdevmode->devicename);
4113 init_unistr(&devmode->formname, ntdevmode->formname);
4115 devmode->specversion = ntdevmode->specversion;
4116 devmode->driverversion = ntdevmode->driverversion;
4117 devmode->size = ntdevmode->size;
4118 devmode->driverextra = ntdevmode->driverextra;
4119 devmode->fields = ntdevmode->fields;
4121 devmode->orientation = ntdevmode->orientation;
4122 devmode->papersize = ntdevmode->papersize;
4123 devmode->paperlength = ntdevmode->paperlength;
4124 devmode->paperwidth = ntdevmode->paperwidth;
4125 devmode->scale = ntdevmode->scale;
4126 devmode->copies = ntdevmode->copies;
4127 devmode->defaultsource = ntdevmode->defaultsource;
4128 devmode->printquality = ntdevmode->printquality;
4129 devmode->color = ntdevmode->color;
4130 devmode->duplex = ntdevmode->duplex;
4131 devmode->yresolution = ntdevmode->yresolution;
4132 devmode->ttoption = ntdevmode->ttoption;
4133 devmode->collate = ntdevmode->collate;
4134 devmode->icmmethod = ntdevmode->icmmethod;
4135 devmode->icmintent = ntdevmode->icmintent;
4136 devmode->mediatype = ntdevmode->mediatype;
4137 devmode->dithertype = ntdevmode->dithertype;
4139 if (ntdevmode->nt_dev_private != NULL) {
4140 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4147 /****************************************************************************
4148 Create a DEVMODE struct. Returns malloced memory.
4149 ****************************************************************************/
4151 DEVICEMODE *construct_dev_mode(const char *servicename)
4153 NT_PRINTER_INFO_LEVEL *printer = NULL;
4154 DEVICEMODE *devmode = NULL;
4156 DEBUG(7,("construct_dev_mode\n"));
4158 DEBUGADD(8,("getting printer characteristics\n"));
4160 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4163 if ( !printer->info_2->devmode ) {
4164 DEBUG(5, ("BONG! There was no device mode!\n"));
4168 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4169 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4173 ZERO_STRUCTP(devmode);
4175 DEBUGADD(8,("loading DEVICEMODE\n"));
4177 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4178 free_dev_mode( devmode );
4183 free_a_printer(&printer,2);
4188 /********************************************************************
4189 * construct_printer_info_2
4190 * fill a printer_info_2 struct
4191 ********************************************************************/
4193 static BOOL construct_printer_info_2(Printer_entry *print_hnd,
4194 PRINTER_INFO_2 *printer,
4195 const struct share_params *params)
4198 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4200 print_status_struct status;
4202 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4203 lp_const_servicename(params->service))))
4206 count = print_queue_length(params->service, &status);
4208 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4209 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4210 init_unistr(&printer->sharename, lp_servicename(params->service)); /* sharename */
4211 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4212 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4214 if (*ntprinter->info_2->comment == '\0')
4215 init_unistr(&printer->comment, lp_comment(params->service)); /* comment */
4217 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4219 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4220 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4221 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4222 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4223 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4225 printer->attributes = ntprinter->info_2->attributes;
4227 printer->priority = ntprinter->info_2->priority; /* priority */
4228 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4229 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4230 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4231 printer->status = nt_printq_status(status.status); /* status */
4232 printer->cjobs = count; /* jobs */
4233 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4235 if ( !(printer->devmode = construct_dev_mode(
4236 lp_const_servicename(params->service))) )
4237 DEBUG(8, ("Returning NULL Devicemode!\n"));
4239 printer->secdesc = NULL;
4241 if ( ntprinter->info_2->secdesc_buf
4242 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4244 /* don't use talloc_steal() here unless you do a deep steal of all
4245 the SEC_DESC members */
4247 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4248 ntprinter->info_2->secdesc_buf->sd );
4251 free_a_printer(&ntprinter, 2);
4256 /********************************************************************
4257 * construct_printer_info_3
4258 * fill a printer_info_3 struct
4259 ********************************************************************/
4261 static BOOL construct_printer_info_3(Printer_entry *print_hnd,
4262 PRINTER_INFO_3 **pp_printer,
4263 const struct share_params *params)
4265 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4266 PRINTER_INFO_3 *printer = NULL;
4268 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4269 lp_const_servicename(params->service))))
4273 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4274 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4275 free_a_printer(&ntprinter, 2);
4279 ZERO_STRUCTP(printer);
4281 /* These are the components of the SD we are returning. */
4283 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4284 /* don't use talloc_steal() here unless you do a deep steal of all
4285 the SEC_DESC members */
4287 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4288 ntprinter->info_2->secdesc_buf->sd );
4291 free_a_printer(&ntprinter, 2);
4293 *pp_printer = printer;
4297 /********************************************************************
4298 * construct_printer_info_4
4299 * fill a printer_info_4 struct
4300 ********************************************************************/
4302 static BOOL construct_printer_info_4(Printer_entry *print_hnd,
4303 PRINTER_INFO_4 *printer,
4304 const struct share_params *params)
4306 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4308 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4309 lp_const_servicename(params->service))))
4312 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4313 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4314 printer->attributes = ntprinter->info_2->attributes;
4316 free_a_printer(&ntprinter, 2);
4320 /********************************************************************
4321 * construct_printer_info_5
4322 * fill a printer_info_5 struct
4323 ********************************************************************/
4325 static BOOL construct_printer_info_5(Printer_entry *print_hnd,
4326 PRINTER_INFO_5 *printer,
4327 const struct share_params *params)
4329 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4331 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4332 lp_const_servicename(params->service))))
4335 init_unistr(&printer->printername, ntprinter->info_2->printername);
4336 init_unistr(&printer->portname, ntprinter->info_2->portname);
4337 printer->attributes = ntprinter->info_2->attributes;
4339 /* these two are not used by NT+ according to MSDN */
4341 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4342 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4344 free_a_printer(&ntprinter, 2);
4349 /********************************************************************
4350 * construct_printer_info_6
4351 * fill a printer_info_6 struct
4352 ********************************************************************/
4354 static BOOL construct_printer_info_6(Printer_entry *print_hnd,
4355 PRINTER_INFO_6 *printer,
4356 const struct share_params *params)
4358 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4360 print_status_struct status;
4362 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4363 lp_const_servicename(params->service))))
4366 count = print_queue_length(params->service, &status);
4368 printer->status = nt_printq_status(status.status);
4370 free_a_printer(&ntprinter, 2);
4375 /********************************************************************
4376 * construct_printer_info_7
4377 * fill a printer_info_7 struct
4378 ********************************************************************/
4380 static BOOL construct_printer_info_7(Printer_entry *print_hnd,
4381 PRINTER_INFO_7 *printer,
4382 const struct share_params *params)
4384 char *guid_str = NULL;
4387 if (is_printer_published(print_hnd, params->service, &guid)) {
4388 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4389 strupper_m(guid_str);
4390 init_unistr(&printer->guid, guid_str);
4391 printer->action = SPOOL_DS_PUBLISH;
4393 init_unistr(&printer->guid, "");
4394 printer->action = SPOOL_DS_UNPUBLISH;
4400 /********************************************************************
4401 Spoolss_enumprinters.
4402 ********************************************************************/
4404 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4407 struct share_iterator *shares;
4408 struct share_params *printer;
4409 PRINTER_INFO_1 *printers=NULL;
4410 WERROR result = WERR_OK;
4412 DEBUG(4,("enum_all_printers_info_1\n"));
4414 if (!(shares = share_list_all(NULL))) {
4415 DEBUG(5, ("Could not list printers\n"));
4416 return WERR_ACCESS_DENIED;
4419 while ((printer = next_printer(shares)) != NULL) {
4420 PRINTER_INFO_1 current_prt;
4422 DEBUG(4,("Found a printer in smb.conf: %s\n",
4423 lp_servicename(printer->service)));
4425 if (!construct_printer_info_1(NULL, flags, ¤t_prt,
4430 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1,
4431 *returned +1)) == NULL) {
4432 DEBUG(2,("enum_all_printers_info_1: failed to enlarge "
4433 "printers buffer!\n"));
4435 TALLOC_FREE(shares);
4438 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n",
4441 memcpy(&printers[*returned], ¤t_prt,
4442 sizeof(PRINTER_INFO_1));
4444 TALLOC_FREE(printer);
4447 /* check the required size. */
4448 for (i=0; i<*returned; i++)
4449 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4451 if (*needed > offered) {
4452 result = WERR_INSUFFICIENT_BUFFER;
4456 if (!rpcbuf_alloc_size(buffer, *needed)) {
4457 result = WERR_NOMEM;
4461 /* fill the buffer with the structures */
4462 for (i=0; i<*returned; i++)
4463 smb_io_printer_info_1("", buffer, &printers[i], 0);
4468 SAFE_FREE(printers);
4469 TALLOC_FREE(shares);
4471 if ( !W_ERROR_IS_OK(result) )
4477 /********************************************************************
4478 enum_all_printers_info_1_local.
4479 *********************************************************************/
4481 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4483 DEBUG(4,("enum_all_printers_info_1_local\n"));
4485 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4488 /********************************************************************
4489 enum_all_printers_info_1_name.
4490 *********************************************************************/
4492 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4496 DEBUG(4,("enum_all_printers_info_1_name\n"));
4498 if ((name[0] == '\\') && (name[1] == '\\'))
4501 if (is_myname_or_ipaddr(s)) {
4502 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4505 return WERR_INVALID_NAME;
4508 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4509 /********************************************************************
4510 enum_all_printers_info_1_remote.
4511 *********************************************************************/
4513 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4515 PRINTER_INFO_1 *printer;
4516 fstring printername;
4519 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4520 WERROR result = WERR_OK;
4522 /* JFM: currently it's more a place holder than anything else.
4523 * In the spooler world there is a notion of server registration.
4524 * the print servers are registered on the PDC (in the same domain)
4526 * We should have a TDB here. The registration is done thru an
4527 * undocumented RPC call.
4530 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4535 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4536 slprintf(desc, sizeof(desc)-1,"%s", name);
4537 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4539 init_unistr(&printer->description, desc);
4540 init_unistr(&printer->name, printername);
4541 init_unistr(&printer->comment, comment);
4542 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4544 /* check the required size. */
4545 *needed += spoolss_size_printer_info_1(printer);
4547 if (*needed > offered) {
4548 result = WERR_INSUFFICIENT_BUFFER;
4552 if (!rpcbuf_alloc_size(buffer, *needed)) {
4553 result = WERR_NOMEM;
4557 /* fill the buffer with the structures */
4558 smb_io_printer_info_1("", buffer, printer, 0);
4564 if ( !W_ERROR_IS_OK(result) )
4572 /********************************************************************
4573 enum_all_printers_info_1_network.
4574 *********************************************************************/
4576 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4580 DEBUG(4,("enum_all_printers_info_1_network\n"));
4582 /* If we respond to a enum_printers level 1 on our name with flags
4583 set to PRINTER_ENUM_REMOTE with a list of printers then these
4584 printers incorrectly appear in the APW browse list.
4585 Specifically the printers for the server appear at the workgroup
4586 level where all the other servers in the domain are
4587 listed. Windows responds to this call with a
4588 WERR_CAN_NOT_COMPLETE so we should do the same. */
4590 if (name[0] == '\\' && name[1] == '\\')
4593 if (is_myname_or_ipaddr(s))
4594 return WERR_CAN_NOT_COMPLETE;
4596 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4599 /********************************************************************
4600 * api_spoolss_enumprinters
4602 * called from api_spoolss_enumprinters (see this to understand)
4603 ********************************************************************/
4605 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4608 struct share_iterator *shares;
4609 struct share_params *printer;
4610 PRINTER_INFO_2 *printers=NULL;
4611 WERROR result = WERR_OK;
4615 if (!(shares = share_list_all(NULL))) {
4616 DEBUG(5, ("Could not list printers\n"));
4617 return WERR_ACCESS_DENIED;
4620 while ((printer = next_printer(shares)) != NULL) {
4621 PRINTER_INFO_2 current_prt;
4623 DEBUG(4,("Found a printer in smb.conf: %s\n",
4624 lp_servicename(printer->service)));
4626 if (!construct_printer_info_2(NULL, ¤t_prt,
4630 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2,
4632 DEBUG(2,("enum_all_printers_info_2: failed to enlarge "
4633 "printers buffer!\n"));
4635 TALLOC_FREE(shares);
4639 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n",
4642 memcpy(&printers[*returned], ¤t_prt,
4643 sizeof(PRINTER_INFO_2));
4645 TALLOC_FREE(printer);
4648 /* check the required size. */
4649 for (i=0; i<*returned; i++)
4650 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4652 if (*needed > offered) {
4653 result = WERR_INSUFFICIENT_BUFFER;
4657 if (!rpcbuf_alloc_size(buffer, *needed)) {
4658 result = WERR_NOMEM;
4662 /* fill the buffer with the structures */
4663 for (i=0; i<*returned; i++)
4664 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4669 for (i=0; i<*returned; i++)
4670 free_devmode(printers[i].devmode);
4672 SAFE_FREE(printers);
4673 TALLOC_FREE(shares);
4675 if ( !W_ERROR_IS_OK(result) )
4681 /********************************************************************
4682 * handle enumeration of printers at level 1
4683 ********************************************************************/
4685 static WERROR enumprinters_level1( uint32 flags, fstring name,
4686 RPC_BUFFER *buffer, uint32 offered,
4687 uint32 *needed, uint32 *returned)
4689 /* Not all the flags are equals */
4691 if (flags & PRINTER_ENUM_LOCAL)
4692 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4694 if (flags & PRINTER_ENUM_NAME)
4695 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4697 #if 0 /* JERRY - disabled for now */
4698 if (flags & PRINTER_ENUM_REMOTE)
4699 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4702 if (flags & PRINTER_ENUM_NETWORK)
4703 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4705 return WERR_OK; /* NT4sp5 does that */
4708 /********************************************************************
4709 * handle enumeration of printers at level 2
4710 ********************************************************************/
4712 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4713 RPC_BUFFER *buffer, uint32 offered,
4714 uint32 *needed, uint32 *returned)
4716 char *s = servername;
4718 if (flags & PRINTER_ENUM_LOCAL) {
4719 return enum_all_printers_info_2(buffer, offered, needed, returned);
4722 if (flags & PRINTER_ENUM_NAME) {
4723 if ((servername[0] == '\\') && (servername[1] == '\\'))
4725 if (is_myname_or_ipaddr(s))
4726 return enum_all_printers_info_2(buffer, offered, needed, returned);
4728 return WERR_INVALID_NAME;
4731 if (flags & PRINTER_ENUM_REMOTE)
4732 return WERR_UNKNOWN_LEVEL;
4737 /********************************************************************
4738 * handle enumeration of printers at level 5
4739 ********************************************************************/
4741 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4742 RPC_BUFFER *buffer, uint32 offered,
4743 uint32 *needed, uint32 *returned)
4745 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4749 /********************************************************************
4750 * api_spoolss_enumprinters
4752 * called from api_spoolss_enumprinters (see this to understand)
4753 ********************************************************************/
4755 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4757 uint32 flags = q_u->flags;
4758 UNISTR2 *servername = &q_u->servername;
4759 uint32 level = q_u->level;
4760 RPC_BUFFER *buffer = NULL;
4761 uint32 offered = q_u->offered;
4762 uint32 *needed = &r_u->needed;
4763 uint32 *returned = &r_u->returned;
4767 /* that's an [in out] buffer */
4769 if (!q_u->buffer && (offered!=0)) {
4770 return WERR_INVALID_PARAM;
4773 rpcbuf_move(q_u->buffer, &r_u->buffer);
4774 buffer = r_u->buffer;
4776 DEBUG(4,("_spoolss_enumprinters\n"));
4783 * flags==PRINTER_ENUM_NAME
4784 * if name=="" then enumerates all printers
4785 * if name!="" then enumerate the printer
4786 * flags==PRINTER_ENUM_REMOTE
4787 * name is NULL, enumerate printers
4788 * Level 2: name!="" enumerates printers, name can't be NULL
4789 * Level 3: doesn't exist
4790 * Level 4: does a local registry lookup
4791 * Level 5: same as Level 2
4794 unistr2_to_ascii(name, servername, sizeof(name)-1);
4799 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4801 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4803 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4808 return WERR_UNKNOWN_LEVEL;
4811 /****************************************************************************
4812 ****************************************************************************/
4814 static WERROR getprinter_level_0(Printer_entry *print_hnd,
4815 const struct share_params *params,
4816 RPC_BUFFER *buffer, uint32 offered,
4819 PRINTER_INFO_0 *printer=NULL;
4820 WERROR result = WERR_OK;
4822 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4825 construct_printer_info_0(print_hnd, printer, params);
4827 /* check the required size. */
4828 *needed += spoolss_size_printer_info_0(printer);
4830 if (*needed > offered) {
4831 result = WERR_INSUFFICIENT_BUFFER;
4835 if (!rpcbuf_alloc_size(buffer, *needed)) {
4836 result = WERR_NOMEM;
4840 /* fill the buffer with the structures */
4841 smb_io_printer_info_0("", buffer, printer, 0);
4851 /****************************************************************************
4852 ****************************************************************************/
4854 static WERROR getprinter_level_1(Printer_entry *print_hnd,
4855 const struct share_params *params,
4856 RPC_BUFFER *buffer, uint32 offered,
4859 PRINTER_INFO_1 *printer=NULL;
4860 WERROR result = WERR_OK;
4862 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4865 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer,
4868 /* check the required size. */
4869 *needed += spoolss_size_printer_info_1(printer);
4871 if (*needed > offered) {
4872 result = WERR_INSUFFICIENT_BUFFER;
4876 if (!rpcbuf_alloc_size(buffer, *needed)) {
4877 result = WERR_NOMEM;
4881 /* fill the buffer with the structures */
4882 smb_io_printer_info_1("", buffer, printer, 0);
4891 /****************************************************************************
4892 ****************************************************************************/
4894 static WERROR getprinter_level_2(Printer_entry *print_hnd,
4895 const struct share_params *params,
4896 RPC_BUFFER *buffer, uint32 offered,
4899 PRINTER_INFO_2 *printer=NULL;
4900 WERROR result = WERR_OK;
4902 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4905 construct_printer_info_2(print_hnd, printer, params);
4907 /* check the required size. */
4908 *needed += spoolss_size_printer_info_2(printer);
4910 if (*needed > offered) {
4911 result = WERR_INSUFFICIENT_BUFFER;
4915 if (!rpcbuf_alloc_size(buffer, *needed)) {
4916 result = WERR_NOMEM;
4920 /* fill the buffer with the structures */
4921 if (!smb_io_printer_info_2("", buffer, printer, 0))
4922 result = WERR_NOMEM;
4926 free_printer_info_2(printer);
4931 /****************************************************************************
4932 ****************************************************************************/
4934 static WERROR getprinter_level_3(Printer_entry *print_hnd,
4935 const struct share_params *params,
4936 RPC_BUFFER *buffer, uint32 offered,
4939 PRINTER_INFO_3 *printer=NULL;
4940 WERROR result = WERR_OK;
4942 if (!construct_printer_info_3(print_hnd, &printer, params))
4945 /* check the required size. */
4946 *needed += spoolss_size_printer_info_3(printer);
4948 if (*needed > offered) {
4949 result = WERR_INSUFFICIENT_BUFFER;
4953 if (!rpcbuf_alloc_size(buffer, *needed)) {
4954 result = WERR_NOMEM;
4958 /* fill the buffer with the structures */
4959 smb_io_printer_info_3("", buffer, printer, 0);
4963 free_printer_info_3(printer);
4968 /****************************************************************************
4969 ****************************************************************************/
4971 static WERROR getprinter_level_4(Printer_entry *print_hnd,
4972 const struct share_params *params,
4973 RPC_BUFFER *buffer, uint32 offered,
4976 PRINTER_INFO_4 *printer=NULL;
4977 WERROR result = WERR_OK;
4979 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4982 if (!construct_printer_info_4(print_hnd, printer, params)) {
4987 /* check the required size. */
4988 *needed += spoolss_size_printer_info_4(printer);
4990 if (*needed > offered) {
4991 result = WERR_INSUFFICIENT_BUFFER;
4995 if (!rpcbuf_alloc_size(buffer, *needed)) {
4996 result = WERR_NOMEM;
5000 /* fill the buffer with the structures */
5001 smb_io_printer_info_4("", buffer, printer, 0);
5005 free_printer_info_4(printer);
5010 /****************************************************************************
5011 ****************************************************************************/
5013 static WERROR getprinter_level_5(Printer_entry *print_hnd,
5014 const struct share_params *params,
5015 RPC_BUFFER *buffer, uint32 offered,
5018 PRINTER_INFO_5 *printer=NULL;
5019 WERROR result = WERR_OK;
5021 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
5024 if (!construct_printer_info_5(print_hnd, printer, params)) {
5025 free_printer_info_5(printer);
5029 /* check the required size. */
5030 *needed += spoolss_size_printer_info_5(printer);
5032 if (*needed > offered) {
5033 result = WERR_INSUFFICIENT_BUFFER;
5037 if (!rpcbuf_alloc_size(buffer, *needed)) {
5038 result = WERR_NOMEM;
5042 /* fill the buffer with the structures */
5043 smb_io_printer_info_5("", buffer, printer, 0);
5047 free_printer_info_5(printer);
5052 static WERROR getprinter_level_6(Printer_entry *print_hnd,
5053 const struct share_params *params,
5054 RPC_BUFFER *buffer, uint32 offered,
5057 PRINTER_INFO_6 *printer;
5058 WERROR result = WERR_OK;
5060 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5064 if (!construct_printer_info_6(print_hnd, printer, params)) {
5065 free_printer_info_6(printer);
5069 /* check the required size. */
5070 *needed += spoolss_size_printer_info_6(printer);
5072 if (*needed > offered) {
5073 result = WERR_INSUFFICIENT_BUFFER;
5077 if (!rpcbuf_alloc_size(buffer, *needed)) {
5078 result = WERR_NOMEM;
5082 /* fill the buffer with the structures */
5083 smb_io_printer_info_6("", buffer, printer, 0);
5087 free_printer_info_6(printer);
5092 static WERROR getprinter_level_7(Printer_entry *print_hnd,
5093 const struct share_params *params,
5094 RPC_BUFFER *buffer, uint32 offered,
5097 PRINTER_INFO_7 *printer=NULL;
5098 WERROR result = WERR_OK;
5100 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5103 if (!construct_printer_info_7(print_hnd, printer, params))
5106 /* check the required size. */
5107 *needed += spoolss_size_printer_info_7(printer);
5109 if (*needed > offered) {
5110 result = WERR_INSUFFICIENT_BUFFER;
5114 if (!rpcbuf_alloc_size(buffer, *needed)) {
5115 result = WERR_NOMEM;
5120 /* fill the buffer with the structures */
5121 smb_io_printer_info_7("", buffer, printer, 0);
5125 free_printer_info_7(printer);
5130 /****************************************************************************
5131 ****************************************************************************/
5133 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5135 POLICY_HND *handle = &q_u->handle;
5136 uint32 level = q_u->level;
5137 RPC_BUFFER *buffer = NULL;
5138 uint32 offered = q_u->offered;
5139 uint32 *needed = &r_u->needed;
5140 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5141 struct share_params *params;
5145 /* that's an [in out] buffer */
5147 if (!q_u->buffer && (offered!=0)) {
5148 return WERR_INVALID_PARAM;
5151 rpcbuf_move(q_u->buffer, &r_u->buffer);
5152 buffer = r_u->buffer;
5156 if (!get_printer_snum(p, handle, &snum, ¶ms))
5161 return getprinter_level_0(Printer, params, buffer, offered,
5164 return getprinter_level_1(Printer, params, buffer, offered,
5167 return getprinter_level_2(Printer, params, buffer, offered,
5170 return getprinter_level_3(Printer, params, buffer, offered,
5173 return getprinter_level_4(Printer, params, buffer, offered,
5176 return getprinter_level_5(Printer, params, buffer, offered,
5179 return getprinter_level_6(Printer, params, buffer, offered,
5182 return getprinter_level_7(Printer, params, buffer, offered,
5185 return WERR_UNKNOWN_LEVEL;
5188 /********************************************************************
5189 * fill a DRIVER_INFO_1 struct
5190 ********************************************************************/
5192 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5194 init_unistr( &info->name, driver.info_3->name);
5197 /********************************************************************
5198 * construct_printer_driver_info_1
5199 ********************************************************************/
5201 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5203 NT_PRINTER_INFO_LEVEL *printer = NULL;
5204 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5206 ZERO_STRUCT(driver);
5208 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5209 return WERR_INVALID_PRINTER_NAME;
5211 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5212 free_a_printer(&printer, 2);
5213 return WERR_UNKNOWN_PRINTER_DRIVER;
5216 fill_printer_driver_info_1(info, driver, servername, architecture);
5218 free_a_printer(&printer,2);
5223 /********************************************************************
5224 * construct_printer_driver_info_2
5225 * fill a printer_info_2 struct
5226 ********************************************************************/
5228 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5232 info->version=driver.info_3->cversion;
5234 init_unistr( &info->name, driver.info_3->name );
5235 init_unistr( &info->architecture, driver.info_3->environment );
5238 if (strlen(driver.info_3->driverpath)) {
5239 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5240 init_unistr( &info->driverpath, temp );
5242 init_unistr( &info->driverpath, "" );
5244 if (strlen(driver.info_3->datafile)) {
5245 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5246 init_unistr( &info->datafile, temp );
5248 init_unistr( &info->datafile, "" );
5250 if (strlen(driver.info_3->configfile)) {
5251 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5252 init_unistr( &info->configfile, temp );
5254 init_unistr( &info->configfile, "" );
5257 /********************************************************************
5258 * construct_printer_driver_info_2
5259 * fill a printer_info_2 struct
5260 ********************************************************************/
5262 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5264 NT_PRINTER_INFO_LEVEL *printer = NULL;
5265 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5267 ZERO_STRUCT(printer);
5268 ZERO_STRUCT(driver);
5270 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5271 return WERR_INVALID_PRINTER_NAME;
5273 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5274 free_a_printer(&printer, 2);
5275 return WERR_UNKNOWN_PRINTER_DRIVER;
5278 fill_printer_driver_info_2(info, driver, servername);
5280 free_a_printer(&printer,2);
5285 /********************************************************************
5286 * copy a strings array and convert to UNICODE
5288 * convert an array of ascii string to a UNICODE string
5289 ********************************************************************/
5291 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5298 DEBUG(6,("init_unistr_array\n"));
5309 v = ""; /* hack to handle null lists */
5312 /* hack to allow this to be used in places other than when generating
5313 the list of dependent files */
5316 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5320 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5322 /* add one extra unit16 for the second terminating NULL */
5324 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5325 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5332 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5337 /* special case for ""; we need to add both NULL's here */
5339 (*uni_array)[j++]=0x0000;
5340 (*uni_array)[j]=0x0000;
5343 DEBUGADD(6,("last one:done\n"));
5345 /* return size of array in uint16's */
5350 /********************************************************************
5351 * construct_printer_info_3
5352 * fill a printer_info_3 struct
5353 ********************************************************************/
5355 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5361 info->version=driver.info_3->cversion;
5363 init_unistr( &info->name, driver.info_3->name );
5364 init_unistr( &info->architecture, driver.info_3->environment );
5366 if (strlen(driver.info_3->driverpath)) {
5367 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5368 init_unistr( &info->driverpath, temp );
5370 init_unistr( &info->driverpath, "" );
5372 if (strlen(driver.info_3->datafile)) {
5373 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5374 init_unistr( &info->datafile, temp );
5376 init_unistr( &info->datafile, "" );
5378 if (strlen(driver.info_3->configfile)) {
5379 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5380 init_unistr( &info->configfile, temp );
5382 init_unistr( &info->configfile, "" );
5384 if (strlen(driver.info_3->helpfile)) {
5385 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5386 init_unistr( &info->helpfile, temp );
5388 init_unistr( &info->helpfile, "" );
5390 init_unistr( &info->monitorname, driver.info_3->monitorname );
5391 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5393 info->dependentfiles=NULL;
5394 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5397 /********************************************************************
5398 * construct_printer_info_3
5399 * fill a printer_info_3 struct
5400 ********************************************************************/
5402 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5404 NT_PRINTER_INFO_LEVEL *printer = NULL;
5405 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5407 ZERO_STRUCT(driver);
5409 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5410 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5411 if (!W_ERROR_IS_OK(status))
5412 return WERR_INVALID_PRINTER_NAME;
5414 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5415 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5420 * I put this code in during testing. Helpful when commenting out the
5421 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5422 * as win2k always queries the driver using an infor level of 6.
5423 * I've left it in (but ifdef'd out) because I'll probably
5424 * use it in experimentation again in the future. --jerry 22/01/2002
5427 if (!W_ERROR_IS_OK(status)) {
5429 * Is this a W2k client ?
5432 /* Yes - try again with a WinNT driver. */
5434 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5435 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5439 if (!W_ERROR_IS_OK(status)) {
5440 free_a_printer(&printer,2);
5441 return WERR_UNKNOWN_PRINTER_DRIVER;
5449 fill_printer_driver_info_3(info, driver, servername);
5451 free_a_printer(&printer,2);
5456 /********************************************************************
5457 * construct_printer_info_6
5458 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5459 ********************************************************************/
5461 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5467 memset(&nullstr, '\0', sizeof(fstring));
5469 info->version=driver.info_3->cversion;
5471 init_unistr( &info->name, driver.info_3->name );
5472 init_unistr( &info->architecture, driver.info_3->environment );
5474 if (strlen(driver.info_3->driverpath)) {
5475 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5476 init_unistr( &info->driverpath, temp );
5478 init_unistr( &info->driverpath, "" );
5480 if (strlen(driver.info_3->datafile)) {
5481 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5482 init_unistr( &info->datafile, temp );
5484 init_unistr( &info->datafile, "" );
5486 if (strlen(driver.info_3->configfile)) {
5487 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5488 init_unistr( &info->configfile, temp );
5490 init_unistr( &info->configfile, "" );
5492 if (strlen(driver.info_3->helpfile)) {
5493 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5494 init_unistr( &info->helpfile, temp );
5496 init_unistr( &info->helpfile, "" );
5498 init_unistr( &info->monitorname, driver.info_3->monitorname );
5499 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5501 info->dependentfiles = NULL;
5502 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5504 info->previousdrivernames=NULL;
5505 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5507 info->driver_date=0;
5510 info->driver_version_low=0;
5511 info->driver_version_high=0;
5513 init_unistr( &info->mfgname, "");
5514 init_unistr( &info->oem_url, "");
5515 init_unistr( &info->hardware_id, "");
5516 init_unistr( &info->provider, "");
5519 /********************************************************************
5520 * construct_printer_info_6
5521 * fill a printer_info_6 struct
5522 ********************************************************************/
5524 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5525 fstring servername, fstring architecture, uint32 version)
5527 NT_PRINTER_INFO_LEVEL *printer = NULL;
5528 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5531 ZERO_STRUCT(driver);
5533 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5535 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5537 if (!W_ERROR_IS_OK(status))
5538 return WERR_INVALID_PRINTER_NAME;
5540 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5542 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5544 if (!W_ERROR_IS_OK(status))
5547 * Is this a W2k client ?
5551 free_a_printer(&printer,2);
5552 return WERR_UNKNOWN_PRINTER_DRIVER;
5555 /* Yes - try again with a WinNT driver. */
5557 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5558 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5559 if (!W_ERROR_IS_OK(status)) {
5560 free_a_printer(&printer,2);
5561 return WERR_UNKNOWN_PRINTER_DRIVER;
5565 fill_printer_driver_info_6(info, driver, servername);
5567 free_a_printer(&printer,2);
5568 free_a_printer_driver(driver, 3);
5573 /****************************************************************************
5574 ****************************************************************************/
5576 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5578 SAFE_FREE(info->dependentfiles);
5581 /****************************************************************************
5582 ****************************************************************************/
5584 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5586 SAFE_FREE(info->dependentfiles);
5589 /****************************************************************************
5590 ****************************************************************************/
5592 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5594 DRIVER_INFO_1 *info=NULL;
5597 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5600 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5601 if (!W_ERROR_IS_OK(result))
5604 /* check the required size. */
5605 *needed += spoolss_size_printer_driver_info_1(info);
5607 if (*needed > offered) {
5608 result = WERR_INSUFFICIENT_BUFFER;
5612 if (!rpcbuf_alloc_size(buffer, *needed)) {
5613 result = WERR_NOMEM;
5617 /* fill the buffer with the structures */
5618 smb_io_printer_driver_info_1("", buffer, info, 0);
5627 /****************************************************************************
5628 ****************************************************************************/
5630 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5632 DRIVER_INFO_2 *info=NULL;
5635 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5638 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5639 if (!W_ERROR_IS_OK(result))
5642 /* check the required size. */
5643 *needed += spoolss_size_printer_driver_info_2(info);
5645 if (*needed > offered) {
5646 result = WERR_INSUFFICIENT_BUFFER;
5650 if (!rpcbuf_alloc_size(buffer, *needed)) {
5651 result = WERR_NOMEM;
5655 /* fill the buffer with the structures */
5656 smb_io_printer_driver_info_2("", buffer, info, 0);
5665 /****************************************************************************
5666 ****************************************************************************/
5668 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5675 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5676 if (!W_ERROR_IS_OK(result))
5679 /* check the required size. */
5680 *needed += spoolss_size_printer_driver_info_3(&info);
5682 if (*needed > offered) {
5683 result = WERR_INSUFFICIENT_BUFFER;
5687 if (!rpcbuf_alloc_size(buffer, *needed)) {
5688 result = WERR_NOMEM;
5692 /* fill the buffer with the structures */
5693 smb_io_printer_driver_info_3("", buffer, &info, 0);
5696 free_printer_driver_info_3(&info);
5701 /****************************************************************************
5702 ****************************************************************************/
5704 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5711 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5712 if (!W_ERROR_IS_OK(result))
5715 /* check the required size. */
5716 *needed += spoolss_size_printer_driver_info_6(&info);
5718 if (*needed > offered) {
5719 result = WERR_INSUFFICIENT_BUFFER;
5723 if (!rpcbuf_alloc_size(buffer, *needed)) {
5724 result = WERR_NOMEM;
5728 /* fill the buffer with the structures */
5729 smb_io_printer_driver_info_6("", buffer, &info, 0);
5732 free_printer_driver_info_6(&info);
5737 /****************************************************************************
5738 ****************************************************************************/
5740 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5742 POLICY_HND *handle = &q_u->handle;
5743 UNISTR2 *uni_arch = &q_u->architecture;
5744 uint32 level = q_u->level;
5745 uint32 clientmajorversion = q_u->clientmajorversion;
5746 RPC_BUFFER *buffer = NULL;
5747 uint32 offered = q_u->offered;
5748 uint32 *needed = &r_u->needed;
5749 uint32 *servermajorversion = &r_u->servermajorversion;
5750 uint32 *serverminorversion = &r_u->serverminorversion;
5751 Printer_entry *printer;
5754 fstring architecture;
5757 /* that's an [in out] buffer */
5759 if (!q_u->buffer && (offered!=0)) {
5760 return WERR_INVALID_PARAM;
5763 rpcbuf_move(q_u->buffer, &r_u->buffer);
5764 buffer = r_u->buffer;
5766 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5768 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5769 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5770 return WERR_INVALID_PRINTER_NAME;
5774 *servermajorversion = 0;
5775 *serverminorversion = 0;
5777 fstrcpy(servername, get_server_name( printer ));
5778 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5780 if (!get_printer_snum(p, handle, &snum, NULL))
5785 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5787 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5789 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5791 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5794 /* apparently this call is the equivalent of
5795 EnumPrinterDataEx() for the DsDriver key */
5800 return WERR_UNKNOWN_LEVEL;
5803 /****************************************************************************
5804 ****************************************************************************/
5806 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5808 POLICY_HND *handle = &q_u->handle;
5810 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5813 DEBUG(3,("Error in startpageprinter printer handle\n"));
5817 Printer->page_started=True;
5821 /****************************************************************************
5822 ****************************************************************************/
5824 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5826 POLICY_HND *handle = &q_u->handle;
5829 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5832 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5836 if (!get_printer_snum(p, handle, &snum, NULL))
5839 Printer->page_started=False;
5840 print_job_endpage(snum, Printer->jobid);
5845 /********************************************************************
5846 * api_spoolss_getprinter
5847 * called from the spoolss dispatcher
5849 ********************************************************************/
5851 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5853 POLICY_HND *handle = &q_u->handle;
5854 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5855 uint32 *jobid = &r_u->jobid;
5857 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5861 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5864 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5869 * a nice thing with NT is it doesn't listen to what you tell it.
5870 * when asked to send _only_ RAW datas, it tries to send datas
5873 * So I add checks like in NT Server ...
5876 if (info_1->p_datatype != 0) {
5877 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5878 if (strcmp(datatype, "RAW") != 0) {
5880 return WERR_INVALID_DATATYPE;
5884 /* get the share number of the printer */
5885 if (!get_printer_snum(p, handle, &snum, NULL)) {
5889 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5891 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5893 /* An error occured in print_job_start() so return an appropriate
5896 if (Printer->jobid == -1) {
5897 return map_werror_from_unix(errno);
5900 Printer->document_started=True;
5901 (*jobid) = Printer->jobid;
5906 /********************************************************************
5907 * api_spoolss_getprinter
5908 * called from the spoolss dispatcher
5910 ********************************************************************/
5912 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5914 POLICY_HND *handle = &q_u->handle;
5916 return _spoolss_enddocprinter_internal(p, handle);
5919 /****************************************************************************
5920 ****************************************************************************/
5922 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5924 POLICY_HND *handle = &q_u->handle;
5925 uint32 buffer_size = q_u->buffer_size;
5926 uint8 *buffer = q_u->buffer;
5927 uint32 *buffer_written = &q_u->buffer_size2;
5929 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5932 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5933 r_u->buffer_written = q_u->buffer_size2;
5937 if (!get_printer_snum(p, handle, &snum, NULL))
5940 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5941 (SMB_OFF_T)-1, (size_t)buffer_size);
5942 if (*buffer_written == (uint32)-1) {
5943 r_u->buffer_written = 0;
5944 if (errno == ENOSPC)
5945 return WERR_NO_SPOOL_SPACE;
5947 return WERR_ACCESS_DENIED;
5950 r_u->buffer_written = q_u->buffer_size2;
5955 /********************************************************************
5956 * api_spoolss_getprinter
5957 * called from the spoolss dispatcher
5959 ********************************************************************/
5961 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5965 WERROR errcode = WERR_BADFUNC;
5966 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5969 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5973 if (!get_printer_snum(p, handle, &snum, NULL))
5977 case PRINTER_CONTROL_PAUSE:
5978 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5982 case PRINTER_CONTROL_RESUME:
5983 case PRINTER_CONTROL_UNPAUSE:
5984 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5988 case PRINTER_CONTROL_PURGE:
5989 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5994 return WERR_UNKNOWN_LEVEL;
6000 /********************************************************************
6001 * api_spoolss_abortprinter
6002 * From MSDN: "Deletes printer's spool file if printer is configured
6004 ********************************************************************/
6006 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
6008 POLICY_HND *handle = &q_u->handle;
6009 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6011 WERROR errcode = WERR_OK;
6014 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
6018 if (!get_printer_snum(p, handle, &snum, NULL))
6021 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
6026 /********************************************************************
6027 * called by spoolss_api_setprinter
6028 * when updating a printer description
6029 ********************************************************************/
6031 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
6032 const SPOOL_PRINTER_INFO_LEVEL *info,
6033 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6035 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6039 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6041 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6042 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6043 OUR_HANDLE(handle)));
6045 result = WERR_BADFID;
6050 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6051 result = WERR_INVALID_PARAM;
6055 /* Check the user has permissions to change the security
6056 descriptor. By experimentation with two NT machines, the user
6057 requires Full Access to the printer to change security
6060 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6061 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6062 result = WERR_ACCESS_DENIED;
6066 /* NT seems to like setting the security descriptor even though
6067 nothing may have actually changed. */
6069 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
6071 if (DEBUGLEVEL >= 10) {
6075 the_acl = old_secdesc_ctr->sd->dacl;
6076 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6077 PRINTERNAME(snum), the_acl->num_aces));
6079 for (i = 0; i < the_acl->num_aces; i++) {
6082 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6084 DEBUG(10, ("%s 0x%08x\n", sid_str,
6085 the_acl->aces[i].access_mask));
6088 the_acl = secdesc_ctr->sd->dacl;
6091 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6092 PRINTERNAME(snum), the_acl->num_aces));
6094 for (i = 0; i < the_acl->num_aces; i++) {
6097 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6099 DEBUG(10, ("%s 0x%08x\n", sid_str,
6100 the_acl->aces[i].access_mask));
6103 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6107 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6108 if (!new_secdesc_ctr) {
6109 result = WERR_NOMEM;
6113 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6118 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6125 /********************************************************************
6126 Canonicalize printer info from a client
6128 ATTN: It does not matter what we set the servername to hear
6129 since we do the necessary work in get_a_printer() to set it to
6130 the correct value based on what the client sent in the
6131 _spoolss_open_printer_ex().
6132 ********************************************************************/
6134 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6136 fstring printername;
6139 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6140 "portname=%s drivername=%s comment=%s location=%s\n",
6141 info->servername, info->printername, info->sharename,
6142 info->portname, info->drivername, info->comment, info->location));
6144 /* we force some elements to "correct" values */
6145 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6146 fstrcpy(info->sharename, lp_servicename(snum));
6148 /* check to see if we allow printername != sharename */
6150 if ( lp_force_printername(snum) ) {
6151 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6152 global_myname(), info->sharename );
6155 /* make sure printername is in \\server\printername format */
6157 fstrcpy( printername, info->printername );
6159 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6160 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6164 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6165 global_myname(), p );
6168 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6169 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6176 /****************************************************************************
6177 ****************************************************************************/
6179 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
6181 char *cmd = lp_addport_cmd();
6185 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6186 BOOL is_print_op = False;
6189 return WERR_ACCESS_DENIED;
6192 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
6195 is_print_op = user_has_privileges( token, &se_printop );
6197 DEBUG(10,("Running [%s]\n", command));
6199 /********* BEGIN SePrintOperatorPrivilege **********/
6204 ret = smbrun(command, &fd);
6209 /********* END SePrintOperatorPrivilege **********/
6211 DEBUGADD(10,("returned [%d]\n", ret));
6216 return WERR_ACCESS_DENIED;
6222 /****************************************************************************
6223 ****************************************************************************/
6225 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6227 char *cmd = lp_addprinter_cmd();
6233 fstring remote_machine = "%m";
6234 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6235 BOOL is_print_op = False;
6237 standard_sub_basic(current_user_info.smb_name,
6238 current_user_info.domain,
6239 remote_machine,sizeof(remote_machine));
6241 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6242 cmd, printer->info_2->printername, printer->info_2->sharename,
6243 printer->info_2->portname, printer->info_2->drivername,
6244 printer->info_2->location, printer->info_2->comment, remote_machine);
6247 is_print_op = user_has_privileges( token, &se_printop );
6249 DEBUG(10,("Running [%s]\n", command));
6251 /********* BEGIN SePrintOperatorPrivilege **********/
6256 if ( (ret = smbrun(command, &fd)) == 0 ) {
6257 /* Tell everyone we updated smb.conf. */
6258 message_send_all(MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6264 /********* END SePrintOperatorPrivilege **********/
6266 DEBUGADD(10,("returned [%d]\n", ret));
6274 /* reload our services immediately */
6275 reload_services( False );
6278 /* Get lines and convert them back to dos-codepage */
6279 qlines = fd_lines_load(fd, &numlines, 0);
6280 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6283 /* Set the portname to what the script says the portname should be. */
6284 /* but don't require anything to be return from the script exit a good error code */
6287 /* Set the portname to what the script says the portname should be. */
6288 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6289 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6292 file_lines_free(qlines);
6297 /********************************************************************
6298 * Called by spoolss_api_setprinter
6299 * when updating a printer description.
6300 ********************************************************************/
6302 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6303 const SPOOL_PRINTER_INFO_LEVEL *info,
6304 DEVICEMODE *devmode)
6307 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6308 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6313 DEBUG(8,("update_printer\n"));
6318 result = WERR_BADFID;
6322 if (!get_printer_snum(p, handle, &snum, NULL)) {
6323 result = WERR_BADFID;
6327 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6328 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6329 result = WERR_BADFID;
6333 DEBUGADD(8,("Converting info_2 struct\n"));
6336 * convert_printer_info converts the incoming
6337 * info from the client and overwrites the info
6338 * just read from the tdb in the pointer 'printer'.
6341 if (!convert_printer_info(info, printer, level)) {
6342 result = WERR_NOMEM;
6347 /* we have a valid devmode
6348 convert it and link it*/
6350 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6351 if (!convert_devicemode(printer->info_2->printername, devmode,
6352 &printer->info_2->devmode)) {
6353 result = WERR_NOMEM;
6358 /* Do sanity check on the requested changes for Samba */
6360 if (!check_printer_ok(printer->info_2, snum)) {
6361 result = WERR_INVALID_PARAM;
6365 /* FIXME!!! If the driver has changed we really should verify that
6366 it is installed before doing much else --jerry */
6368 /* Check calling user has permission to update printer description */
6370 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6371 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6372 result = WERR_ACCESS_DENIED;
6376 /* Call addprinter hook */
6377 /* Check changes to see if this is really needed */
6379 if ( *lp_addprinter_cmd()
6380 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6381 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6382 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6383 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6385 /* add_printer_hook() will call reload_services() */
6387 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6388 result = WERR_ACCESS_DENIED;
6394 * When a *new* driver is bound to a printer, the drivername is used to
6395 * lookup previously saved driver initialization info, which is then
6396 * bound to the printer, simulating what happens in the Windows arch.
6398 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6400 if (!set_driver_init(printer, 2))
6402 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6403 printer->info_2->drivername));
6406 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6407 printer->info_2->drivername));
6409 notify_printer_driver(snum, printer->info_2->drivername);
6413 * flag which changes actually occured. This is a small subset of
6414 * all the possible changes. We also have to update things in the
6418 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6419 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6420 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6421 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6423 notify_printer_comment(snum, printer->info_2->comment);
6426 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6427 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6428 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6429 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6431 notify_printer_sharename(snum, printer->info_2->sharename);
6434 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6437 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6440 pname = printer->info_2->printername;
6443 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6444 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6445 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6447 notify_printer_printername( snum, pname );
6450 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6451 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6452 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6453 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6455 notify_printer_port(snum, printer->info_2->portname);
6458 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6459 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6460 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6461 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6463 notify_printer_location(snum, printer->info_2->location);
6466 /* here we need to update some more DsSpooler keys */
6467 /* uNCName, serverName, shortServerName */
6469 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6470 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6471 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6472 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6473 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6475 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6476 global_myname(), printer->info_2->sharename );
6477 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6478 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6479 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6481 /* Update printer info */
6482 result = mod_a_printer(printer, 2);
6485 free_a_printer(&printer, 2);
6486 free_a_printer(&old_printer, 2);
6492 /****************************************************************************
6493 ****************************************************************************/
6494 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6495 const SPOOL_PRINTER_INFO_LEVEL *info)
6498 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6500 Printer_entry *Printer;
6502 if ( lp_security() != SEC_ADS ) {
6503 return WERR_UNKNOWN_LEVEL;
6506 Printer = find_printer_index_by_hnd(p, handle);
6508 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6513 if (!get_printer_snum(p, handle, &snum, NULL))
6516 nt_printer_publish(Printer, snum, info7->action);
6520 return WERR_UNKNOWN_LEVEL;
6523 /****************************************************************************
6524 ****************************************************************************/
6526 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6528 POLICY_HND *handle = &q_u->handle;
6529 uint32 level = q_u->level;
6530 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6531 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6532 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6533 uint32 command = q_u->command;
6536 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6539 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6543 /* check the level */
6546 return control_printer(handle, command, p);
6548 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6549 if (!W_ERROR_IS_OK(result))
6552 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6555 return update_printer_sec(handle, level, info, p,
6558 return publish_or_unpublish_printer(p, handle, info);
6560 return WERR_UNKNOWN_LEVEL;
6564 /****************************************************************************
6565 ****************************************************************************/
6567 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6569 POLICY_HND *handle = &q_u->handle;
6570 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6573 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6577 if (Printer->notify.client_connected==True) {
6580 if ( Printer->printer_type == SPLHND_SERVER)
6582 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6583 !get_printer_snum(p, handle, &snum, NULL) )
6586 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6589 Printer->notify.flags=0;
6590 Printer->notify.options=0;
6591 Printer->notify.localmachine[0]='\0';
6592 Printer->notify.printerlocal=0;
6593 if (Printer->notify.option)
6594 free_spool_notify_option(&Printer->notify.option);
6595 Printer->notify.client_connected=False;
6600 /****************************************************************************
6601 ****************************************************************************/
6603 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6605 /* that's an [in out] buffer */
6607 if (!q_u->buffer && (q_u->offered!=0)) {
6608 return WERR_INVALID_PARAM;
6611 rpcbuf_move(q_u->buffer, &r_u->buffer);
6614 return WERR_INVALID_PARAM; /* this is what a NT server
6615 returns for AddJob. AddJob
6616 must fail on non-local
6620 /****************************************************************************
6621 ****************************************************************************/
6623 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6624 int position, int snum,
6625 const NT_PRINTER_INFO_LEVEL *ntprinter)
6629 t=gmtime(&queue->time);
6631 job_info->jobid=queue->job;
6632 init_unistr(&job_info->printername, lp_servicename(snum));
6633 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6634 init_unistr(&job_info->username, queue->fs_user);
6635 init_unistr(&job_info->document, queue->fs_file);
6636 init_unistr(&job_info->datatype, "RAW");
6637 init_unistr(&job_info->text_status, "");
6638 job_info->status=nt_printj_status(queue->status);
6639 job_info->priority=queue->priority;
6640 job_info->position=position;
6641 job_info->totalpages=queue->page_count;
6642 job_info->pagesprinted=0;
6644 make_systemtime(&job_info->submitted, t);
6647 /****************************************************************************
6648 ****************************************************************************/
6650 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6651 int position, int snum,
6652 const NT_PRINTER_INFO_LEVEL *ntprinter,
6653 DEVICEMODE *devmode)
6657 t=gmtime(&queue->time);
6659 job_info->jobid=queue->job;
6661 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6663 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6664 init_unistr(&job_info->username, queue->fs_user);
6665 init_unistr(&job_info->document, queue->fs_file);
6666 init_unistr(&job_info->notifyname, queue->fs_user);
6667 init_unistr(&job_info->datatype, "RAW");
6668 init_unistr(&job_info->printprocessor, "winprint");
6669 init_unistr(&job_info->parameters, "");
6670 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6671 init_unistr(&job_info->text_status, "");
6673 /* and here the security descriptor */
6675 job_info->status=nt_printj_status(queue->status);
6676 job_info->priority=queue->priority;
6677 job_info->position=position;
6678 job_info->starttime=0;
6679 job_info->untiltime=0;
6680 job_info->totalpages=queue->page_count;
6681 job_info->size=queue->size;
6682 make_systemtime(&(job_info->submitted), t);
6683 job_info->timeelapsed=0;
6684 job_info->pagesprinted=0;
6686 job_info->devmode = devmode;
6691 /****************************************************************************
6692 Enumjobs at level 1.
6693 ****************************************************************************/
6695 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6696 const NT_PRINTER_INFO_LEVEL *ntprinter,
6697 RPC_BUFFER *buffer, uint32 offered,
6698 uint32 *needed, uint32 *returned)
6702 WERROR result = WERR_OK;
6704 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6710 for (i=0; i<*returned; i++)
6711 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6713 /* check the required size. */
6714 for (i=0; i<*returned; i++)
6715 (*needed) += spoolss_size_job_info_1(&info[i]);
6717 if (*needed > offered) {
6718 result = WERR_INSUFFICIENT_BUFFER;
6722 if (!rpcbuf_alloc_size(buffer, *needed)) {
6723 result = WERR_NOMEM;
6727 /* fill the buffer with the structures */
6728 for (i=0; i<*returned; i++)
6729 smb_io_job_info_1("", buffer, &info[i], 0);
6735 if ( !W_ERROR_IS_OK(result) )
6741 /****************************************************************************
6742 Enumjobs at level 2.
6743 ****************************************************************************/
6745 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6746 const NT_PRINTER_INFO_LEVEL *ntprinter,
6747 RPC_BUFFER *buffer, uint32 offered,
6748 uint32 *needed, uint32 *returned)
6750 JOB_INFO_2 *info = NULL;
6752 WERROR result = WERR_OK;
6753 DEVICEMODE *devmode = NULL;
6755 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6760 /* this should not be a failure condition if the devmode is NULL */
6762 devmode = construct_dev_mode(lp_const_servicename(snum));
6764 for (i=0; i<*returned; i++)
6765 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6767 /* check the required size. */
6768 for (i=0; i<*returned; i++)
6769 (*needed) += spoolss_size_job_info_2(&info[i]);
6771 if (*needed > offered) {
6772 result = WERR_INSUFFICIENT_BUFFER;
6776 if (!rpcbuf_alloc_size(buffer, *needed)) {
6777 result = WERR_NOMEM;
6781 /* fill the buffer with the structures */
6782 for (i=0; i<*returned; i++)
6783 smb_io_job_info_2("", buffer, &info[i], 0);
6786 free_devmode(devmode);
6789 if ( !W_ERROR_IS_OK(result) )
6796 /****************************************************************************
6798 ****************************************************************************/
6800 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6802 POLICY_HND *handle = &q_u->handle;
6803 uint32 level = q_u->level;
6804 RPC_BUFFER *buffer = NULL;
6805 uint32 offered = q_u->offered;
6806 uint32 *needed = &r_u->needed;
6807 uint32 *returned = &r_u->returned;
6809 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6811 print_status_struct prt_status;
6812 print_queue_struct *queue=NULL;
6814 /* that's an [in out] buffer */
6816 if (!q_u->buffer && (offered!=0)) {
6817 return WERR_INVALID_PARAM;
6820 rpcbuf_move(q_u->buffer, &r_u->buffer);
6821 buffer = r_u->buffer;
6823 DEBUG(4,("_spoolss_enumjobs\n"));
6828 /* lookup the printer snum and tdb entry */
6830 if (!get_printer_snum(p, handle, &snum, NULL))
6833 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6834 if ( !W_ERROR_IS_OK(wret) )
6837 *returned = print_queue_status(snum, &queue, &prt_status);
6838 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6840 if (*returned == 0) {
6842 free_a_printer(&ntprinter, 2);
6848 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6851 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6855 wret = WERR_UNKNOWN_LEVEL;
6860 free_a_printer( &ntprinter, 2 );
6864 /****************************************************************************
6865 ****************************************************************************/
6867 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6872 /****************************************************************************
6873 ****************************************************************************/
6875 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6877 POLICY_HND *handle = &q_u->handle;
6878 uint32 jobid = q_u->jobid;
6879 uint32 command = q_u->command;
6882 WERROR errcode = WERR_BADFUNC;
6884 if (!get_printer_snum(p, handle, &snum, NULL)) {
6888 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6889 return WERR_INVALID_PRINTER_NAME;
6893 case JOB_CONTROL_CANCEL:
6894 case JOB_CONTROL_DELETE:
6895 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6899 case JOB_CONTROL_PAUSE:
6900 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6904 case JOB_CONTROL_RESTART:
6905 case JOB_CONTROL_RESUME:
6906 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6911 return WERR_UNKNOWN_LEVEL;
6917 /****************************************************************************
6918 Enumerates all printer drivers at level 1.
6919 ****************************************************************************/
6921 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6926 fstring *list = NULL;
6927 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6928 DRIVER_INFO_1 *driver_info_1=NULL;
6929 WERROR result = WERR_OK;
6933 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6935 ndrivers=get_ntdrivers(&list, architecture, version);
6936 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6938 if(ndrivers == -1) {
6939 SAFE_FREE(driver_info_1);
6944 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6945 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6951 for (i=0; i<ndrivers; i++) {
6953 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6954 ZERO_STRUCT(driver);
6955 status = get_a_printer_driver(&driver, 3, list[i],
6956 architecture, version);
6957 if (!W_ERROR_IS_OK(status)) {
6959 SAFE_FREE(driver_info_1);
6962 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6963 free_a_printer_driver(driver, 3);
6966 *returned+=ndrivers;
6970 /* check the required size. */
6971 for (i=0; i<*returned; i++) {
6972 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6973 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6976 if (*needed > offered) {
6977 result = WERR_INSUFFICIENT_BUFFER;
6981 if (!rpcbuf_alloc_size(buffer, *needed)) {
6982 result = WERR_NOMEM;
6986 /* fill the buffer with the driver structures */
6987 for (i=0; i<*returned; i++) {
6988 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6989 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6993 SAFE_FREE(driver_info_1);
6995 if ( !W_ERROR_IS_OK(result) )
7001 /****************************************************************************
7002 Enumerates all printer drivers at level 2.
7003 ****************************************************************************/
7005 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7010 fstring *list = NULL;
7011 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7012 DRIVER_INFO_2 *driver_info_2=NULL;
7013 WERROR result = WERR_OK;
7017 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7019 ndrivers=get_ntdrivers(&list, architecture, version);
7020 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7022 if(ndrivers == -1) {
7023 SAFE_FREE(driver_info_2);
7028 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7029 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7035 for (i=0; i<ndrivers; i++) {
7038 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7039 ZERO_STRUCT(driver);
7040 status = get_a_printer_driver(&driver, 3, list[i],
7041 architecture, version);
7042 if (!W_ERROR_IS_OK(status)) {
7044 SAFE_FREE(driver_info_2);
7047 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7048 free_a_printer_driver(driver, 3);
7051 *returned+=ndrivers;
7055 /* check the required size. */
7056 for (i=0; i<*returned; i++) {
7057 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7058 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7061 if (*needed > offered) {
7062 result = WERR_INSUFFICIENT_BUFFER;
7066 if (!rpcbuf_alloc_size(buffer, *needed)) {
7067 result = WERR_NOMEM;
7071 /* fill the buffer with the form structures */
7072 for (i=0; i<*returned; i++) {
7073 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7074 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7078 SAFE_FREE(driver_info_2);
7080 if ( !W_ERROR_IS_OK(result) )
7086 /****************************************************************************
7087 Enumerates all printer drivers at level 3.
7088 ****************************************************************************/
7090 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7095 fstring *list = NULL;
7096 DRIVER_INFO_3 *driver_info_3=NULL;
7097 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7098 WERROR result = WERR_OK;
7102 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7104 ndrivers=get_ntdrivers(&list, architecture, version);
7105 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7107 if(ndrivers == -1) {
7108 SAFE_FREE(driver_info_3);
7113 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7114 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7120 for (i=0; i<ndrivers; i++) {
7123 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7124 ZERO_STRUCT(driver);
7125 status = get_a_printer_driver(&driver, 3, list[i],
7126 architecture, version);
7127 if (!W_ERROR_IS_OK(status)) {
7129 SAFE_FREE(driver_info_3);
7132 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7133 free_a_printer_driver(driver, 3);
7136 *returned+=ndrivers;
7140 /* check the required size. */
7141 for (i=0; i<*returned; i++) {
7142 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7143 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7146 if (*needed > offered) {
7147 result = WERR_INSUFFICIENT_BUFFER;
7151 if (!rpcbuf_alloc_size(buffer, *needed)) {
7152 result = WERR_NOMEM;
7156 /* fill the buffer with the driver structures */
7157 for (i=0; i<*returned; i++) {
7158 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7159 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7163 for (i=0; i<*returned; i++) {
7164 SAFE_FREE(driver_info_3[i].dependentfiles);
7167 SAFE_FREE(driver_info_3);
7169 if ( !W_ERROR_IS_OK(result) )
7175 /****************************************************************************
7176 Enumerates all printer drivers.
7177 ****************************************************************************/
7179 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7181 uint32 level = q_u->level;
7182 RPC_BUFFER *buffer = NULL;
7183 uint32 offered = q_u->offered;
7184 uint32 *needed = &r_u->needed;
7185 uint32 *returned = &r_u->returned;
7188 fstring architecture;
7190 /* that's an [in out] buffer */
7192 if (!q_u->buffer && (offered!=0)) {
7193 return WERR_INVALID_PARAM;
7196 rpcbuf_move(q_u->buffer, &r_u->buffer);
7197 buffer = r_u->buffer;
7199 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7204 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7205 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7207 if ( !is_myname_or_ipaddr( servername ) )
7208 return WERR_UNKNOWN_PRINTER_DRIVER;
7212 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7214 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7216 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7218 return WERR_UNKNOWN_LEVEL;
7222 /****************************************************************************
7223 ****************************************************************************/
7225 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7227 form->flag=list->flag;
7228 init_unistr(&form->name, list->name);
7229 form->width=list->width;
7230 form->length=list->length;
7231 form->left=list->left;
7232 form->top=list->top;
7233 form->right=list->right;
7234 form->bottom=list->bottom;
7237 /****************************************************************************
7238 ****************************************************************************/
7240 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7242 uint32 level = q_u->level;
7243 RPC_BUFFER *buffer = NULL;
7244 uint32 offered = q_u->offered;
7245 uint32 *needed = &r_u->needed;
7246 uint32 *numofforms = &r_u->numofforms;
7247 uint32 numbuiltinforms;
7249 nt_forms_struct *list=NULL;
7250 nt_forms_struct *builtinlist=NULL;
7255 /* that's an [in out] buffer */
7257 if (!q_u->buffer && (offered!=0) ) {
7258 return WERR_INVALID_PARAM;
7261 rpcbuf_move(q_u->buffer, &r_u->buffer);
7262 buffer = r_u->buffer;
7264 DEBUG(4,("_spoolss_enumforms\n"));
7265 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7266 DEBUGADD(5,("Info level [%d]\n", level));
7268 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7269 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7270 *numofforms = get_ntforms(&list);
7271 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7272 *numofforms += numbuiltinforms;
7274 if (*numofforms == 0) {
7275 SAFE_FREE(builtinlist);
7277 return WERR_NO_MORE_ITEMS;
7282 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7283 SAFE_FREE(builtinlist);
7289 /* construct the list of form structures */
7290 for (i=0; i<numbuiltinforms; i++) {
7291 DEBUGADD(6,("Filling form number [%d]\n",i));
7292 fill_form_1(&forms_1[i], &builtinlist[i]);
7295 SAFE_FREE(builtinlist);
7297 for (; i<*numofforms; i++) {
7298 DEBUGADD(6,("Filling form number [%d]\n",i));
7299 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7304 /* check the required size. */
7305 for (i=0; i<numbuiltinforms; i++) {
7306 DEBUGADD(6,("adding form [%d]'s size\n",i));
7307 buffer_size += spoolss_size_form_1(&forms_1[i]);
7309 for (; i<*numofforms; i++) {
7310 DEBUGADD(6,("adding form [%d]'s size\n",i));
7311 buffer_size += spoolss_size_form_1(&forms_1[i]);
7314 *needed=buffer_size;
7316 if (*needed > offered) {
7319 return WERR_INSUFFICIENT_BUFFER;
7322 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7328 /* fill the buffer with the form structures */
7329 for (i=0; i<numbuiltinforms; i++) {
7330 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7331 smb_io_form_1("", buffer, &forms_1[i], 0);
7333 for (; i<*numofforms; i++) {
7334 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7335 smb_io_form_1("", buffer, &forms_1[i], 0);
7344 SAFE_FREE(builtinlist);
7345 return WERR_UNKNOWN_LEVEL;
7349 /****************************************************************************
7350 ****************************************************************************/
7352 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7354 uint32 level = q_u->level;
7355 UNISTR2 *uni_formname = &q_u->formname;
7356 RPC_BUFFER *buffer = NULL;
7357 uint32 offered = q_u->offered;
7358 uint32 *needed = &r_u->needed;
7360 nt_forms_struct *list=NULL;
7361 nt_forms_struct builtin_form;
7366 int numofforms=0, i=0;
7368 /* that's an [in out] buffer */
7370 if (!q_u->buffer && (offered!=0)) {
7371 return WERR_INVALID_PARAM;
7374 rpcbuf_move(q_u->buffer, &r_u->buffer);
7375 buffer = r_u->buffer;
7377 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7379 DEBUG(4,("_spoolss_getform\n"));
7380 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7381 DEBUGADD(5,("Info level [%d]\n", level));
7383 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7384 if (!foundBuiltin) {
7385 numofforms = get_ntforms(&list);
7386 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7388 if (numofforms == 0)
7395 fill_form_1(&form_1, &builtin_form);
7398 /* Check if the requested name is in the list of form structures */
7399 for (i=0; i<numofforms; i++) {
7401 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7403 if (strequal(form_name, list[i].name)) {
7404 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7405 fill_form_1(&form_1, &list[i]);
7411 if (i == numofforms) {
7415 /* check the required size. */
7417 *needed=spoolss_size_form_1(&form_1);
7419 if (*needed > offered)
7420 return WERR_INSUFFICIENT_BUFFER;
7422 if (!rpcbuf_alloc_size(buffer, buffer_size))
7425 /* fill the buffer with the form structures */
7426 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7427 smb_io_form_1("", buffer, &form_1, 0);
7433 return WERR_UNKNOWN_LEVEL;
7437 /****************************************************************************
7438 ****************************************************************************/
7440 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7442 init_unistr(&port->port_name, name);
7445 /****************************************************************************
7446 TODO: This probably needs distinguish between TCP/IP and Local ports
7448 ****************************************************************************/
7450 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7452 init_unistr(&port->port_name, name);
7453 init_unistr(&port->monitor_name, "Local Monitor");
7454 init_unistr(&port->description, SPL_LOCAL_PORT );
7455 port->port_type=PORT_TYPE_WRITE;
7460 /****************************************************************************
7461 wrapper around the enumer ports command
7462 ****************************************************************************/
7464 WERROR enumports_hook( int *count, char ***lines )
7466 char *cmd = lp_enumports_cmd();
7476 /* if no hook then just fill in the default port */
7479 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7480 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7485 /* we have a valid enumport command */
7487 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7489 DEBUG(10,("Running [%s]\n", command));
7490 ret = smbrun(command, &fd);
7491 DEBUG(10,("Returned [%d]\n", ret));
7496 return WERR_ACCESS_DENIED;
7500 qlines = fd_lines_load(fd, &numlines, 0);
7501 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7511 /****************************************************************************
7513 ****************************************************************************/
7515 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7517 PORT_INFO_1 *ports=NULL;
7519 WERROR result = WERR_OK;
7520 char **qlines = NULL;
7523 result = enumports_hook( &numlines, &qlines );
7524 if (!W_ERROR_IS_OK(result)) {
7525 file_lines_free(qlines);
7530 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7531 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7532 dos_errstr(WERR_NOMEM)));
7533 file_lines_free(qlines);
7537 for (i=0; i<numlines; i++) {
7538 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7539 fill_port_1(&ports[i], qlines[i]);
7542 file_lines_free(qlines);
7544 *returned = numlines;
7546 /* check the required size. */
7547 for (i=0; i<*returned; i++) {
7548 DEBUGADD(6,("adding port [%d]'s size\n", i));
7549 *needed += spoolss_size_port_info_1(&ports[i]);
7552 if (*needed > offered) {
7553 result = WERR_INSUFFICIENT_BUFFER;
7557 if (!rpcbuf_alloc_size(buffer, *needed)) {
7558 result = WERR_NOMEM;
7562 /* fill the buffer with the ports structures */
7563 for (i=0; i<*returned; i++) {
7564 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7565 smb_io_port_1("", buffer, &ports[i], 0);
7571 if ( !W_ERROR_IS_OK(result) )
7577 /****************************************************************************
7579 ****************************************************************************/
7581 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7583 PORT_INFO_2 *ports=NULL;
7585 WERROR result = WERR_OK;
7586 char **qlines = NULL;
7589 result = enumports_hook( &numlines, &qlines );
7590 if ( !W_ERROR_IS_OK(result)) {
7591 file_lines_free(qlines);
7596 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7597 file_lines_free(qlines);
7601 for (i=0; i<numlines; i++) {
7602 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7603 fill_port_2(&(ports[i]), qlines[i]);
7607 file_lines_free(qlines);
7609 *returned = numlines;
7611 /* check the required size. */
7612 for (i=0; i<*returned; i++) {
7613 DEBUGADD(6,("adding port [%d]'s size\n", i));
7614 *needed += spoolss_size_port_info_2(&ports[i]);
7617 if (*needed > offered) {
7618 result = WERR_INSUFFICIENT_BUFFER;
7622 if (!rpcbuf_alloc_size(buffer, *needed)) {
7623 result = WERR_NOMEM;
7627 /* fill the buffer with the ports structures */
7628 for (i=0; i<*returned; i++) {
7629 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7630 smb_io_port_2("", buffer, &ports[i], 0);
7636 if ( !W_ERROR_IS_OK(result) )
7642 /****************************************************************************
7644 ****************************************************************************/
7646 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7648 uint32 level = q_u->level;
7649 RPC_BUFFER *buffer = NULL;
7650 uint32 offered = q_u->offered;
7651 uint32 *needed = &r_u->needed;
7652 uint32 *returned = &r_u->returned;
7654 /* that's an [in out] buffer */
7656 if (!q_u->buffer && (offered!=0)) {
7657 return WERR_INVALID_PARAM;
7660 rpcbuf_move(q_u->buffer, &r_u->buffer);
7661 buffer = r_u->buffer;
7663 DEBUG(4,("_spoolss_enumports\n"));
7670 return enumports_level_1(buffer, offered, needed, returned);
7672 return enumports_level_2(buffer, offered, needed, returned);
7674 return WERR_UNKNOWN_LEVEL;
7678 /****************************************************************************
7679 ****************************************************************************/
7681 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7682 const SPOOL_PRINTER_INFO_LEVEL *info,
7683 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7684 uint32 user_switch, const SPOOL_USER_CTR *user,
7687 NT_PRINTER_INFO_LEVEL *printer = NULL;
7690 WERROR err = WERR_OK;
7692 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7693 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7697 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7698 if (!convert_printer_info(info, printer, 2)) {
7699 free_a_printer(&printer, 2);
7703 /* check to see if the printer already exists */
7705 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7706 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7707 printer->info_2->sharename));
7708 free_a_printer(&printer, 2);
7709 return WERR_PRINTER_ALREADY_EXISTS;
7712 /* FIXME!!! smbd should check to see if the driver is installed before
7713 trying to add a printer like this --jerry */
7715 if (*lp_addprinter_cmd() ) {
7716 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7717 free_a_printer(&printer,2);
7718 return WERR_ACCESS_DENIED;
7721 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7722 "smb.conf parameter \"addprinter command\" is defined. This"
7723 "parameter must exist for this call to succeed\n",
7724 printer->info_2->sharename ));
7727 /* use our primary netbios name since get_a_printer() will convert
7728 it to what the client expects on a case by case basis */
7730 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7731 printer->info_2->sharename);
7734 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7735 free_a_printer(&printer,2);
7736 return WERR_ACCESS_DENIED;
7739 /* you must be a printer admin to add a new printer */
7740 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7741 free_a_printer(&printer,2);
7742 return WERR_ACCESS_DENIED;
7746 * Do sanity check on the requested changes for Samba.
7749 if (!check_printer_ok(printer->info_2, snum)) {
7750 free_a_printer(&printer,2);
7751 return WERR_INVALID_PARAM;
7755 * When a printer is created, the drivername bound to the printer is used
7756 * to lookup previously saved driver initialization info, which is then
7757 * bound to the new printer, simulating what happens in the Windows arch.
7762 set_driver_init(printer, 2);
7766 /* A valid devmode was included, convert and link it
7768 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7770 if (!convert_devicemode(printer->info_2->printername, devmode,
7771 &printer->info_2->devmode))
7775 /* write the ASCII on disk */
7776 err = mod_a_printer(printer, 2);
7777 if (!W_ERROR_IS_OK(err)) {
7778 free_a_printer(&printer,2);
7782 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7783 /* Handle open failed - remove addition. */
7784 del_a_printer(printer->info_2->sharename);
7785 free_a_printer(&printer,2);
7786 return WERR_ACCESS_DENIED;
7789 update_c_setprinter(False);
7790 free_a_printer(&printer,2);
7795 /****************************************************************************
7796 ****************************************************************************/
7798 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7800 UNISTR2 *uni_srv_name = q_u->server_name;
7801 uint32 level = q_u->level;
7802 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7803 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7804 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7805 uint32 user_switch = q_u->user_switch;
7806 SPOOL_USER_CTR *user = &q_u->user_ctr;
7807 POLICY_HND *handle = &r_u->handle;
7811 /* we don't handle yet */
7812 /* but I know what to do ... */
7813 return WERR_UNKNOWN_LEVEL;
7815 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7817 user_switch, user, handle);
7819 return WERR_UNKNOWN_LEVEL;
7823 /****************************************************************************
7824 ****************************************************************************/
7826 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7828 uint32 level = q_u->level;
7829 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7830 WERROR err = WERR_OK;
7831 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7832 fstring driver_name;
7835 ZERO_STRUCT(driver);
7837 if (!convert_printer_driver_info(info, &driver, level)) {
7842 DEBUG(5,("Cleaning driver's information\n"));
7843 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7844 if (!W_ERROR_IS_OK(err))
7847 DEBUG(5,("Moving driver to final destination\n"));
7848 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7852 if (add_a_printer_driver(driver, level)!=0) {
7853 err = WERR_ACCESS_DENIED;
7858 * I think this is where he DrvUpgradePrinter() hook would be
7859 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7860 * server. Right now, we just need to send ourselves a message
7861 * to update each printer bound to this driver. --jerry
7864 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7865 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7870 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7871 * decide if the driver init data should be deleted. The rules are:
7872 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7873 * 2) delete init data only if there is no 2k/Xp driver
7874 * 3) always delete init data
7875 * The generalized rule is always use init data from the highest order driver.
7876 * It is necessary to follow the driver install by an initialization step to
7877 * finish off this process.
7880 version = driver.info_3->cversion;
7881 else if (level == 6)
7882 version = driver.info_6->version;
7887 * 9x printer driver - never delete init data
7890 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7895 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7896 * there is no 2k/Xp driver init data for this driver name.
7900 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7902 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7904 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7906 if (!del_driver_init(driver_name))
7907 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7910 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7912 free_a_printer_driver(driver1,3);
7913 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7920 * 2k or Xp printer driver - always delete init data
7923 if (!del_driver_init(driver_name))
7924 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7928 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7934 free_a_printer_driver(driver, level);
7938 /********************************************************************
7939 * spoolss_addprinterdriverex
7940 ********************************************************************/
7942 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7944 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7945 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7948 * we only support the semantics of AddPrinterDriver()
7949 * i.e. only copy files that are newer than existing ones
7952 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7953 return WERR_ACCESS_DENIED;
7955 ZERO_STRUCT(q_u_local);
7956 ZERO_STRUCT(r_u_local);
7958 /* just pass the information off to _spoolss_addprinterdriver() */
7959 q_u_local.server_name_ptr = q_u->server_name_ptr;
7960 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7961 q_u_local.level = q_u->level;
7962 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7964 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7967 /****************************************************************************
7968 ****************************************************************************/
7970 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7972 init_unistr(&info->name, name);
7975 /****************************************************************************
7976 ****************************************************************************/
7978 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7984 const char *short_archi;
7985 DRIVER_DIRECTORY_1 *info=NULL;
7986 WERROR result = WERR_OK;
7988 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7989 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7991 /* check for beginning double '\'s and that the server
7994 pservername = servername;
7995 if ( *pservername == '\\' && strlen(servername)>2 ) {
7999 if ( !is_myname_or_ipaddr( pservername ) )
8000 return WERR_INVALID_PARAM;
8002 if (!(short_archi = get_short_archi(long_archi)))
8003 return WERR_INVALID_ENVIRONMENT;
8005 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8008 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
8010 DEBUG(4,("printer driver directory: [%s]\n", path));
8012 fill_driverdir_1(info, path);
8014 *needed += spoolss_size_driverdir_info_1(info);
8016 if (*needed > offered) {
8017 result = WERR_INSUFFICIENT_BUFFER;
8021 if (!rpcbuf_alloc_size(buffer, *needed)) {
8022 result = WERR_NOMEM;
8026 smb_io_driverdir_1("", buffer, info, 0);
8034 /****************************************************************************
8035 ****************************************************************************/
8037 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8039 UNISTR2 *name = &q_u->name;
8040 UNISTR2 *uni_environment = &q_u->environment;
8041 uint32 level = q_u->level;
8042 RPC_BUFFER *buffer = NULL;
8043 uint32 offered = q_u->offered;
8044 uint32 *needed = &r_u->needed;
8046 /* that's an [in out] buffer */
8048 if (!q_u->buffer && (offered!=0)) {
8049 return WERR_INVALID_PARAM;
8052 rpcbuf_move(q_u->buffer, &r_u->buffer);
8053 buffer = r_u->buffer;
8055 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8061 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8063 return WERR_UNKNOWN_LEVEL;
8067 /****************************************************************************
8068 ****************************************************************************/
8070 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8072 POLICY_HND *handle = &q_u->handle;
8073 uint32 idx = q_u->index;
8074 uint32 in_value_len = q_u->valuesize;
8075 uint32 in_data_len = q_u->datasize;
8076 uint32 *out_max_value_len = &r_u->valuesize;
8077 uint16 **out_value = &r_u->value;
8078 uint32 *out_value_len = &r_u->realvaluesize;
8079 uint32 *out_type = &r_u->type;
8080 uint32 *out_max_data_len = &r_u->datasize;
8081 uint8 **data_out = &r_u->data;
8082 uint32 *out_data_len = &r_u->realdatasize;
8084 NT_PRINTER_INFO_LEVEL *printer = NULL;
8086 uint32 biggest_valuesize;
8087 uint32 biggest_datasize;
8089 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8092 REGISTRY_VALUE *val = NULL;
8093 NT_PRINTER_DATA *p_data;
8094 int i, key_index, num_values;
8099 *out_max_data_len = 0;
8103 DEBUG(5,("spoolss_enumprinterdata\n"));
8106 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8110 if (!get_printer_snum(p,handle, &snum, NULL))
8113 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8114 if (!W_ERROR_IS_OK(result))
8117 p_data = printer->info_2->data;
8118 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8123 * The NT machine wants to know the biggest size of value and data
8125 * cf: MSDN EnumPrinterData remark section
8128 if ( !in_value_len && !in_data_len && (key_index != -1) )
8130 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8132 biggest_valuesize = 0;
8133 biggest_datasize = 0;
8135 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8137 for ( i=0; i<num_values; i++ )
8139 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8141 name_length = strlen(val->valuename);
8142 if ( strlen(val->valuename) > biggest_valuesize )
8143 biggest_valuesize = name_length;
8145 if ( val->size > biggest_datasize )
8146 biggest_datasize = val->size;
8148 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8152 /* the value is an UNICODE string but real_value_size is the length
8153 in bytes including the trailing 0 */
8155 *out_value_len = 2 * (1+biggest_valuesize);
8156 *out_data_len = biggest_datasize;
8158 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8164 * the value len is wrong in NT sp3
8165 * that's the number of bytes not the number of unicode chars
8168 if ( key_index != -1 )
8169 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8174 /* out_value should default to "" or else NT4 has
8175 problems unmarshalling the response */
8177 *out_max_value_len=(in_value_len/sizeof(uint16));
8180 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8182 result = WERR_NOMEM;
8185 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8191 /* the data is counted in bytes */
8193 *out_max_data_len = in_data_len;
8194 *out_data_len = in_data_len;
8196 /* only allocate when given a non-zero data_len */
8198 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8200 result = WERR_NOMEM;
8204 result = WERR_NO_MORE_ITEMS;
8210 * - counted in bytes in the request
8211 * - counted in UNICODE chars in the max reply
8212 * - counted in bytes in the real size
8214 * take a pause *before* coding not *during* coding
8218 *out_max_value_len=(in_value_len/sizeof(uint16));
8220 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8222 result = WERR_NOMEM;
8226 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8234 *out_type = regval_type( val );
8236 /* data - counted in bytes */
8238 *out_max_data_len = in_data_len;
8239 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8241 result = WERR_NOMEM;
8244 data_len = regval_size(val);
8245 if ( *data_out && data_len )
8246 memcpy( *data_out, regval_data_p(val), data_len );
8247 *out_data_len = data_len;
8251 free_a_printer(&printer, 2);
8255 /****************************************************************************
8256 ****************************************************************************/
8258 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8260 POLICY_HND *handle = &q_u->handle;
8261 UNISTR2 *value = &q_u->value;
8262 uint32 type = q_u->type;
8263 uint8 *data = q_u->data;
8264 uint32 real_len = q_u->real_len;
8266 NT_PRINTER_INFO_LEVEL *printer = NULL;
8268 WERROR status = WERR_OK;
8269 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8272 DEBUG(5,("spoolss_setprinterdata\n"));
8275 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8279 if ( Printer->printer_type == SPLHND_SERVER ) {
8280 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8281 return WERR_INVALID_PARAM;
8284 if (!get_printer_snum(p,handle, &snum, NULL))
8288 * Access check : NT returns "access denied" if you make a
8289 * SetPrinterData call without the necessary privildge.
8290 * we were originally returning OK if nothing changed
8291 * which made Win2k issue **a lot** of SetPrinterData
8292 * when connecting to a printer --jerry
8295 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8297 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8298 status = WERR_ACCESS_DENIED;
8302 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8303 if (!W_ERROR_IS_OK(status))
8306 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8309 * When client side code sets a magic printer data key, detect it and save
8310 * the current printer data and the magic key's data (its the DEVMODE) for
8311 * future printer/driver initializations.
8313 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8315 /* Set devmode and printer initialization info */
8316 status = save_driver_init( printer, 2, data, real_len );
8318 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8322 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8323 type, data, real_len );
8324 if ( W_ERROR_IS_OK(status) )
8325 status = mod_a_printer(printer, 2);
8329 free_a_printer(&printer, 2);
8334 /****************************************************************************
8335 ****************************************************************************/
8337 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8339 POLICY_HND *handle = &q_u->handle;
8340 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8343 DEBUG(5,("_spoolss_resetprinter\n"));
8346 * All we do is to check to see if the handle and queue is valid.
8347 * This call really doesn't mean anything to us because we only
8348 * support RAW printing. --jerry
8352 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8356 if (!get_printer_snum(p,handle, &snum, NULL))
8360 /* blindly return success */
8365 /****************************************************************************
8366 ****************************************************************************/
8368 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8370 POLICY_HND *handle = &q_u->handle;
8371 UNISTR2 *value = &q_u->valuename;
8373 NT_PRINTER_INFO_LEVEL *printer = NULL;
8375 WERROR status = WERR_OK;
8376 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8379 DEBUG(5,("spoolss_deleteprinterdata\n"));
8382 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8386 if (!get_printer_snum(p, handle, &snum, NULL))
8389 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8390 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8391 return WERR_ACCESS_DENIED;
8394 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8395 if (!W_ERROR_IS_OK(status))
8398 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8400 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8402 if ( W_ERROR_IS_OK(status) )
8403 mod_a_printer( printer, 2 );
8405 free_a_printer(&printer, 2);
8410 /****************************************************************************
8411 ****************************************************************************/
8413 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8415 POLICY_HND *handle = &q_u->handle;
8416 FORM *form = &q_u->form;
8417 nt_forms_struct tmpForm;
8419 WERROR status = WERR_OK;
8420 NT_PRINTER_INFO_LEVEL *printer = NULL;
8423 nt_forms_struct *list=NULL;
8424 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8426 DEBUG(5,("spoolss_addform\n"));
8429 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8434 /* forms can be added on printer of on the print server handle */
8436 if ( Printer->printer_type == SPLHND_PRINTER )
8438 if (!get_printer_snum(p,handle, &snum, NULL))
8441 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8442 if (!W_ERROR_IS_OK(status))
8446 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8447 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8448 status = WERR_ACCESS_DENIED;
8452 /* can't add if builtin */
8454 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8455 status = WERR_ALREADY_EXISTS;
8459 count = get_ntforms(&list);
8461 if(!add_a_form(&list, form, &count)) {
8462 status = WERR_NOMEM;
8466 write_ntforms(&list, count);
8469 * ChangeID must always be set if this is a printer
8472 if ( Printer->printer_type == SPLHND_PRINTER )
8473 status = mod_a_printer(printer, 2);
8477 free_a_printer(&printer, 2);
8483 /****************************************************************************
8484 ****************************************************************************/
8486 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8488 POLICY_HND *handle = &q_u->handle;
8489 UNISTR2 *form_name = &q_u->name;
8490 nt_forms_struct tmpForm;
8492 nt_forms_struct *list=NULL;
8493 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8495 WERROR status = WERR_OK;
8496 NT_PRINTER_INFO_LEVEL *printer = NULL;
8498 DEBUG(5,("spoolss_deleteform\n"));
8501 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8505 /* forms can be deleted on printer of on the print server handle */
8507 if ( Printer->printer_type == SPLHND_PRINTER )
8509 if (!get_printer_snum(p,handle, &snum, NULL))
8512 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8513 if (!W_ERROR_IS_OK(status))
8517 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8518 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8519 status = WERR_ACCESS_DENIED;
8523 /* can't delete if builtin */
8525 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8526 status = WERR_INVALID_PARAM;
8530 count = get_ntforms(&list);
8532 if ( !delete_a_form(&list, form_name, &count, &status ))
8536 * ChangeID must always be set if this is a printer
8539 if ( Printer->printer_type == SPLHND_PRINTER )
8540 status = mod_a_printer(printer, 2);
8544 free_a_printer(&printer, 2);
8550 /****************************************************************************
8551 ****************************************************************************/
8553 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8555 POLICY_HND *handle = &q_u->handle;
8556 FORM *form = &q_u->form;
8557 nt_forms_struct tmpForm;
8559 WERROR status = WERR_OK;
8560 NT_PRINTER_INFO_LEVEL *printer = NULL;
8563 nt_forms_struct *list=NULL;
8564 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8566 DEBUG(5,("spoolss_setform\n"));
8569 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8573 /* forms can be modified on printer of on the print server handle */
8575 if ( Printer->printer_type == SPLHND_PRINTER )
8577 if (!get_printer_snum(p,handle, &snum, NULL))
8580 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8581 if (!W_ERROR_IS_OK(status))
8585 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8586 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8587 status = WERR_ACCESS_DENIED;
8591 /* can't set if builtin */
8592 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8593 status = WERR_INVALID_PARAM;
8597 count = get_ntforms(&list);
8598 update_a_form(&list, form, count);
8599 write_ntforms(&list, count);
8602 * ChangeID must always be set if this is a printer
8605 if ( Printer->printer_type == SPLHND_PRINTER )
8606 status = mod_a_printer(printer, 2);
8611 free_a_printer(&printer, 2);
8617 /****************************************************************************
8618 enumprintprocessors level 1.
8619 ****************************************************************************/
8621 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8623 PRINTPROCESSOR_1 *info_1=NULL;
8624 WERROR result = WERR_OK;
8626 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8631 init_unistr(&info_1->name, "winprint");
8633 *needed += spoolss_size_printprocessor_info_1(info_1);
8635 if (*needed > offered) {
8636 result = WERR_INSUFFICIENT_BUFFER;
8640 if (!rpcbuf_alloc_size(buffer, *needed)) {
8641 result = WERR_NOMEM;
8645 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8650 if ( !W_ERROR_IS_OK(result) )
8656 /****************************************************************************
8657 ****************************************************************************/
8659 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8661 uint32 level = q_u->level;
8662 RPC_BUFFER *buffer = NULL;
8663 uint32 offered = q_u->offered;
8664 uint32 *needed = &r_u->needed;
8665 uint32 *returned = &r_u->returned;
8667 /* that's an [in out] buffer */
8669 if (!q_u->buffer && (offered!=0)) {
8670 return WERR_INVALID_PARAM;
8673 rpcbuf_move(q_u->buffer, &r_u->buffer);
8674 buffer = r_u->buffer;
8676 DEBUG(5,("spoolss_enumprintprocessors\n"));
8679 * Enumerate the print processors ...
8681 * Just reply with "winprint", to keep NT happy
8682 * and I can use my nice printer checker.
8690 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8692 return WERR_UNKNOWN_LEVEL;
8696 /****************************************************************************
8697 enumprintprocdatatypes level 1.
8698 ****************************************************************************/
8700 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8702 PRINTPROCDATATYPE_1 *info_1=NULL;
8703 WERROR result = WERR_OK;
8705 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8710 init_unistr(&info_1->name, "RAW");
8712 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8714 if (*needed > offered) {
8715 result = WERR_INSUFFICIENT_BUFFER;
8719 if (!rpcbuf_alloc_size(buffer, *needed)) {
8720 result = WERR_NOMEM;
8724 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8729 if ( !W_ERROR_IS_OK(result) )
8735 /****************************************************************************
8736 ****************************************************************************/
8738 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8740 uint32 level = q_u->level;
8741 RPC_BUFFER *buffer = NULL;
8742 uint32 offered = q_u->offered;
8743 uint32 *needed = &r_u->needed;
8744 uint32 *returned = &r_u->returned;
8746 /* that's an [in out] buffer */
8748 if (!q_u->buffer && (offered!=0)) {
8749 return WERR_INVALID_PARAM;
8752 rpcbuf_move(q_u->buffer, &r_u->buffer);
8753 buffer = r_u->buffer;
8755 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8762 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8764 return WERR_UNKNOWN_LEVEL;
8768 /****************************************************************************
8769 enumprintmonitors level 1.
8770 ****************************************************************************/
8772 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8774 PRINTMONITOR_1 *info_1;
8775 WERROR result = WERR_OK;
8778 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8783 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8784 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8786 for ( i=0; i<*returned; i++ ) {
8787 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8790 if (*needed > offered) {
8791 result = WERR_INSUFFICIENT_BUFFER;
8795 if (!rpcbuf_alloc_size(buffer, *needed)) {
8796 result = WERR_NOMEM;
8800 for ( i=0; i<*returned; i++ ) {
8801 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8807 if ( !W_ERROR_IS_OK(result) )
8813 /****************************************************************************
8814 enumprintmonitors level 2.
8815 ****************************************************************************/
8817 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8819 PRINTMONITOR_2 *info_2;
8820 WERROR result = WERR_OK;
8823 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8828 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8829 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8830 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8832 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8833 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8834 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8836 for ( i=0; i<*returned; i++ ) {
8837 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8840 if (*needed > offered) {
8841 result = WERR_INSUFFICIENT_BUFFER;
8845 if (!rpcbuf_alloc_size(buffer, *needed)) {
8846 result = WERR_NOMEM;
8850 for ( i=0; i<*returned; i++ ) {
8851 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8857 if ( !W_ERROR_IS_OK(result) )
8863 /****************************************************************************
8864 ****************************************************************************/
8866 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8868 uint32 level = q_u->level;
8869 RPC_BUFFER *buffer = NULL;
8870 uint32 offered = q_u->offered;
8871 uint32 *needed = &r_u->needed;
8872 uint32 *returned = &r_u->returned;
8874 /* that's an [in out] buffer */
8876 if (!q_u->buffer && (offered!=0)) {
8877 return WERR_INVALID_PARAM;
8880 rpcbuf_move(q_u->buffer, &r_u->buffer);
8881 buffer = r_u->buffer;
8883 DEBUG(5,("spoolss_enumprintmonitors\n"));
8886 * Enumerate the print monitors ...
8888 * Just reply with "Local Port", to keep NT happy
8889 * and I can use my nice printer checker.
8897 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8899 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8901 return WERR_UNKNOWN_LEVEL;
8905 /****************************************************************************
8906 ****************************************************************************/
8908 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8909 NT_PRINTER_INFO_LEVEL *ntprinter,
8910 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8915 JOB_INFO_1 *info_1=NULL;
8916 WERROR result = WERR_OK;
8918 info_1=SMB_MALLOC_P(JOB_INFO_1);
8920 if (info_1 == NULL) {
8924 for (i=0; i<count && found==False; i++) {
8925 if ((*queue)[i].job==(int)jobid)
8931 /* NT treats not found as bad param... yet another bad choice */
8932 return WERR_INVALID_PARAM;
8935 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8937 *needed += spoolss_size_job_info_1(info_1);
8939 if (*needed > offered) {
8940 result = WERR_INSUFFICIENT_BUFFER;
8944 if (!rpcbuf_alloc_size(buffer, *needed)) {
8945 result = WERR_NOMEM;
8949 smb_io_job_info_1("", buffer, info_1, 0);
8957 /****************************************************************************
8958 ****************************************************************************/
8960 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8961 NT_PRINTER_INFO_LEVEL *ntprinter,
8962 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8969 DEVICEMODE *devmode = NULL;
8970 NT_DEVICEMODE *nt_devmode = NULL;
8972 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8975 ZERO_STRUCTP(info_2);
8977 for ( i=0; i<count && found==False; i++ )
8979 if ((*queue)[i].job == (int)jobid)
8984 /* NT treats not found as bad param... yet another bad
8986 result = WERR_INVALID_PARAM;
8991 * if the print job does not have a DEVMODE associated with it,
8992 * just use the one for the printer. A NULL devicemode is not
8993 * a failure condition
8996 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8997 devmode = construct_dev_mode(lp_const_servicename(snum));
8999 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9000 ZERO_STRUCTP( devmode );
9001 convert_nt_devicemode( devmode, nt_devmode );
9005 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9007 *needed += spoolss_size_job_info_2(info_2);
9009 if (*needed > offered) {
9010 result = WERR_INSUFFICIENT_BUFFER;
9014 if (!rpcbuf_alloc_size(buffer, *needed)) {
9015 result = WERR_NOMEM;
9019 smb_io_job_info_2("", buffer, info_2, 0);
9024 /* Cleanup allocated memory */
9026 free_job_info_2(info_2); /* Also frees devmode */
9032 /****************************************************************************
9033 ****************************************************************************/
9035 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9037 POLICY_HND *handle = &q_u->handle;
9038 uint32 jobid = q_u->jobid;
9039 uint32 level = q_u->level;
9040 RPC_BUFFER *buffer = NULL;
9041 uint32 offered = q_u->offered;
9042 uint32 *needed = &r_u->needed;
9043 WERROR wstatus = WERR_OK;
9044 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9047 print_queue_struct *queue = NULL;
9048 print_status_struct prt_status;
9050 /* that's an [in out] buffer */
9052 if (!q_u->buffer && (offered!=0)) {
9053 return WERR_INVALID_PARAM;
9056 rpcbuf_move(q_u->buffer, &r_u->buffer);
9057 buffer = r_u->buffer;
9059 DEBUG(5,("spoolss_getjob\n"));
9063 if (!get_printer_snum(p, handle, &snum, NULL))
9066 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9067 if ( !W_ERROR_IS_OK(wstatus) )
9070 count = print_queue_status(snum, &queue, &prt_status);
9072 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9073 count, prt_status.status, prt_status.message));
9077 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9078 buffer, offered, needed);
9081 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9082 buffer, offered, needed);
9085 wstatus = WERR_UNKNOWN_LEVEL;
9090 free_a_printer( &ntprinter, 2 );
9095 /********************************************************************
9096 spoolss_getprinterdataex
9098 From MSDN documentation of GetPrinterDataEx: pass request
9099 to GetPrinterData if key is "PrinterDriverData".
9100 ********************************************************************/
9102 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9104 POLICY_HND *handle = &q_u->handle;
9105 uint32 in_size = q_u->size;
9106 uint32 *type = &r_u->type;
9107 uint32 *out_size = &r_u->size;
9108 uint8 **data = &r_u->data;
9109 uint32 *needed = &r_u->needed;
9110 fstring keyname, valuename;
9112 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9114 NT_PRINTER_INFO_LEVEL *printer = NULL;
9116 WERROR status = WERR_OK;
9118 DEBUG(4,("_spoolss_getprinterdataex\n"));
9120 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
9121 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
9123 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9124 keyname, valuename));
9126 /* in case of problem, return some default values */
9130 *out_size = in_size;
9133 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9134 status = WERR_BADFID;
9138 /* Is the handle to a printer or to the server? */
9140 if (Printer->printer_type == SPLHND_SERVER) {
9141 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9142 status = WERR_INVALID_PARAM;
9146 if ( !get_printer_snum(p,handle, &snum, NULL) )
9149 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9150 if ( !W_ERROR_IS_OK(status) )
9153 /* check to see if the keyname is valid */
9154 if ( !strlen(keyname) ) {
9155 status = WERR_INVALID_PARAM;
9159 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9160 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9161 free_a_printer( &printer, 2 );
9162 status = WERR_BADFILE;
9166 /* When given a new keyname, we should just create it */
9168 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9170 if (*needed > *out_size)
9171 status = WERR_MORE_DATA;
9174 if ( !W_ERROR_IS_OK(status) )
9176 DEBUG(5, ("error: allocating %d\n", *out_size));
9178 /* reply this param doesn't exist */
9182 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9183 status = WERR_NOMEM;
9192 free_a_printer( &printer, 2 );
9197 /********************************************************************
9198 * spoolss_setprinterdataex
9199 ********************************************************************/
9201 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9203 POLICY_HND *handle = &q_u->handle;
9204 uint32 type = q_u->type;
9205 uint8 *data = q_u->data;
9206 uint32 real_len = q_u->real_len;
9208 NT_PRINTER_INFO_LEVEL *printer = NULL;
9210 WERROR status = WERR_OK;
9211 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9216 DEBUG(4,("_spoolss_setprinterdataex\n"));
9218 /* From MSDN documentation of SetPrinterDataEx: pass request to
9219 SetPrinterData if key is "PrinterDriverData" */
9222 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9226 if ( Printer->printer_type == SPLHND_SERVER ) {
9227 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9228 return WERR_INVALID_PARAM;
9231 if ( !get_printer_snum(p,handle, &snum, NULL) )
9235 * Access check : NT returns "access denied" if you make a
9236 * SetPrinterData call without the necessary privildge.
9237 * we were originally returning OK if nothing changed
9238 * which made Win2k issue **a lot** of SetPrinterData
9239 * when connecting to a printer --jerry
9242 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9244 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9245 return WERR_ACCESS_DENIED;
9248 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9249 if (!W_ERROR_IS_OK(status))
9252 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9253 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9255 /* check for OID in valuename */
9257 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9263 /* save the registry data */
9265 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9267 if ( W_ERROR_IS_OK(status) )
9269 /* save the OID if one was specified */
9271 fstrcat( keyname, "\\" );
9272 fstrcat( keyname, SPOOL_OID_KEY );
9275 * I'm not checking the status here on purpose. Don't know
9276 * if this is right, but I'm returning the status from the
9277 * previous set_printer_dataex() call. I have no idea if
9278 * this is right. --jerry
9281 set_printer_dataex( printer, keyname, valuename,
9282 REG_SZ, (uint8 *)oid_string,
9283 strlen(oid_string)+1 );
9286 status = mod_a_printer(printer, 2);
9289 free_a_printer(&printer, 2);
9295 /********************************************************************
9296 * spoolss_deleteprinterdataex
9297 ********************************************************************/
9299 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9301 POLICY_HND *handle = &q_u->handle;
9302 UNISTR2 *value = &q_u->valuename;
9303 UNISTR2 *key = &q_u->keyname;
9305 NT_PRINTER_INFO_LEVEL *printer = NULL;
9307 WERROR status = WERR_OK;
9308 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9309 pstring valuename, keyname;
9311 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9314 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9318 if (!get_printer_snum(p, handle, &snum, NULL))
9321 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9322 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9323 return WERR_ACCESS_DENIED;
9326 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9327 if (!W_ERROR_IS_OK(status))
9330 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9331 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9333 status = delete_printer_dataex( printer, keyname, valuename );
9335 if ( W_ERROR_IS_OK(status) )
9336 mod_a_printer( printer, 2 );
9338 free_a_printer(&printer, 2);
9343 /********************************************************************
9344 * spoolss_enumprinterkey
9345 ********************************************************************/
9348 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9351 fstring *keynames = NULL;
9352 uint16 *enumkeys = NULL;
9355 POLICY_HND *handle = &q_u->handle;
9356 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9357 NT_PRINTER_DATA *data;
9358 NT_PRINTER_INFO_LEVEL *printer = NULL;
9360 WERROR status = WERR_BADFILE;
9363 DEBUG(4,("_spoolss_enumprinterkey\n"));
9366 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9370 if ( !get_printer_snum(p,handle, &snum, NULL) )
9373 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9374 if (!W_ERROR_IS_OK(status))
9377 /* get the list of subkey names */
9379 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9380 data = printer->info_2->data;
9382 num_keys = get_printer_subkeys( data, key, &keynames );
9384 if ( num_keys == -1 ) {
9385 status = WERR_BADFILE;
9389 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9391 r_u->needed = printerkey_len*2;
9393 if ( q_u->size < r_u->needed ) {
9394 status = WERR_MORE_DATA;
9398 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9399 status = WERR_NOMEM;
9405 if ( q_u->size < r_u->needed )
9406 status = WERR_MORE_DATA;
9409 free_a_printer( &printer, 2 );
9410 SAFE_FREE( keynames );
9415 /********************************************************************
9416 * spoolss_deleteprinterkey
9417 ********************************************************************/
9419 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9421 POLICY_HND *handle = &q_u->handle;
9422 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9424 NT_PRINTER_INFO_LEVEL *printer = NULL;
9428 DEBUG(5,("spoolss_deleteprinterkey\n"));
9431 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9435 /* if keyname == NULL, return error */
9437 if ( !q_u->keyname.buffer )
9438 return WERR_INVALID_PARAM;
9440 if (!get_printer_snum(p, handle, &snum, NULL))
9443 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9444 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9445 return WERR_ACCESS_DENIED;
9448 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9449 if (!W_ERROR_IS_OK(status))
9452 /* delete the key and all subneys */
9454 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9456 status = delete_all_printer_data( printer->info_2, key );
9458 if ( W_ERROR_IS_OK(status) )
9459 status = mod_a_printer(printer, 2);
9461 free_a_printer( &printer, 2 );
9467 /********************************************************************
9468 * spoolss_enumprinterdataex
9469 ********************************************************************/
9471 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9473 POLICY_HND *handle = &q_u->handle;
9474 uint32 in_size = q_u->size;
9477 NT_PRINTER_INFO_LEVEL *printer = NULL;
9478 PRINTER_ENUM_VALUES *enum_values = NULL;
9479 NT_PRINTER_DATA *p_data;
9481 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9486 REGISTRY_VALUE *val;
9491 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9494 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9499 * first check for a keyname of NULL or "". Win2k seems to send
9500 * this a lot and we should send back WERR_INVALID_PARAM
9501 * no need to spend time looking up the printer in this case.
9505 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9506 if ( !strlen(key) ) {
9507 result = WERR_INVALID_PARAM;
9511 /* get the printer off of disk */
9513 if (!get_printer_snum(p,handle, &snum, NULL))
9516 ZERO_STRUCT(printer);
9517 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9518 if (!W_ERROR_IS_OK(result))
9521 /* now look for a match on the key name */
9523 p_data = printer->info_2->data;
9525 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9526 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9528 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9529 result = WERR_INVALID_PARAM;
9536 /* allocate the memory for the array of pointers -- if necessary */
9538 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9541 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9543 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9544 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9545 result = WERR_NOMEM;
9549 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9553 * loop through all params and build the array to pass
9554 * back to the client
9557 for ( i=0; i<num_entries; i++ )
9559 /* lookup the registry value */
9561 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9562 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9566 value_name = regval_name( val );
9567 init_unistr( &enum_values[i].valuename, value_name );
9568 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9569 enum_values[i].type = regval_type( val );
9571 data_len = regval_size( val );
9573 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9575 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9577 result = WERR_NOMEM;
9581 enum_values[i].data_len = data_len;
9583 /* keep track of the size of the array in bytes */
9585 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9588 /* housekeeping information in the reply */
9590 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9591 * the hand marshalled container size is a multiple
9592 * of 4 bytes for RPC alignment.
9596 needed += 4-(needed % 4);
9599 r_u->needed = needed;
9600 r_u->returned = num_entries;
9602 if (needed > in_size) {
9603 result = WERR_MORE_DATA;
9607 /* copy data into the reply */
9609 r_u->ctr.size = r_u->needed;
9611 r_u->ctr.size_of_array = r_u->returned;
9612 r_u->ctr.values = enum_values;
9618 free_a_printer(&printer, 2);
9623 /****************************************************************************
9624 ****************************************************************************/
9626 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9628 init_unistr(&info->name, name);
9631 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9632 UNISTR2 *environment,
9639 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9640 WERROR result = WERR_OK;
9642 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9644 if (!get_short_archi(long_archi))
9645 return WERR_INVALID_ENVIRONMENT;
9647 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9650 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9652 fill_printprocessordirectory_1(info, path);
9654 *needed += spoolss_size_printprocessordirectory_info_1(info);
9656 if (*needed > offered) {
9657 result = WERR_INSUFFICIENT_BUFFER;
9661 if (!rpcbuf_alloc_size(buffer, *needed)) {
9662 result = WERR_INSUFFICIENT_BUFFER;
9666 smb_io_printprocessordirectory_1("", buffer, info, 0);
9674 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9676 uint32 level = q_u->level;
9677 RPC_BUFFER *buffer = NULL;
9678 uint32 offered = q_u->offered;
9679 uint32 *needed = &r_u->needed;
9682 /* that's an [in out] buffer */
9684 if (!q_u->buffer && (offered!=0)) {
9685 return WERR_INVALID_PARAM;
9688 rpcbuf_move(q_u->buffer, &r_u->buffer);
9689 buffer = r_u->buffer;
9691 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9697 result = getprintprocessordirectory_level_1
9698 (&q_u->name, &q_u->environment, buffer, offered, needed);
9701 result = WERR_UNKNOWN_LEVEL;
9707 /*******************************************************************
9708 Streams the monitor UI DLL name in UNICODE
9709 *******************************************************************/
9711 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9712 RPC_BUFFER *out, uint32 *needed )
9714 const char *dllname = "tcpmonui.dll";
9716 *needed = (strlen(dllname)+1) * 2;
9718 if ( rpcbuf_get_size(out) < *needed ) {
9719 return WERR_INSUFFICIENT_BUFFER;
9722 if ( !make_monitorui_buf( out, dllname ) ) {
9729 /*******************************************************************
9730 Create a new TCP/IP port
9731 *******************************************************************/
9733 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9734 RPC_BUFFER *out, uint32 *needed )
9736 NT_PORT_DATA_1 port1;
9739 ZERO_STRUCT( port1 );
9741 /* convert to our internal port data structure */
9743 if ( !convert_port_data_1( &port1, in ) ) {
9747 /* create the device URI and call the add_port_hook() */
9749 switch ( port1.protocol ) {
9750 case PORT_PROTOCOL_DIRECT:
9751 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9754 case PORT_PROTOCOL_LPR:
9755 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9759 return WERR_UNKNOWN_PORT;
9762 return add_port_hook( token, port1.name, device_uri );
9765 /*******************************************************************
9766 *******************************************************************/
9768 struct xcv_api_table xcvtcp_cmds[] = {
9769 { "MonitorUI", xcvtcp_monitorui },
9770 { "AddPort", xcvtcp_addport},
9774 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9775 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9780 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9782 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9783 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9784 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9787 return WERR_BADFUNC;
9790 /*******************************************************************
9791 *******************************************************************/
9792 #if 0 /* don't support management using the "Local Port" monitor */
9794 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9795 RPC_BUFFER *out, uint32 *needed )
9797 const char *dllname = "localui.dll";
9799 *needed = (strlen(dllname)+1) * 2;
9801 if ( rpcbuf_get_size(out) < *needed ) {
9802 return WERR_INSUFFICIENT_BUFFER;
9805 if ( !make_monitorui_buf( out, dllname )) {
9812 /*******************************************************************
9813 *******************************************************************/
9815 struct xcv_api_table xcvlocal_cmds[] = {
9816 { "MonitorUI", xcvlocal_monitorui },
9820 struct xcv_api_table xcvlocal_cmds[] = {
9827 /*******************************************************************
9828 *******************************************************************/
9830 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9831 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9836 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9838 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9839 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9840 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9842 return WERR_BADFUNC;
9845 /*******************************************************************
9846 *******************************************************************/
9848 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9850 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9854 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9858 /* Has to be a handle to the TCP/IP port monitor */
9860 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9861 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9865 /* requires administrative access to the server */
9867 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9868 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9869 return WERR_ACCESS_DENIED;
9872 /* Get the command name. There's numerous commands supported by the
9873 TCPMON interface. */
9875 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9876 q_u->dataname.uni_str_len*2, 0);
9878 /* Allocate the outgoing buffer */
9880 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9882 switch ( Printer->printer_type ) {
9883 case SPLHND_PORTMON_TCP:
9884 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9885 &q_u->indata, &r_u->outdata, &r_u->needed );
9886 case SPLHND_PORTMON_LOCAL:
9887 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9888 &q_u->indata, &r_u->outdata, &r_u->needed );
9891 return WERR_INVALID_PRINT_MONITOR;