2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 extern userdom_struct current_user_info;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 const char *long_archi;
45 const char *short_archi;
49 static Printer_entry *printers_list;
51 typedef struct _counter_printer_0 {
52 struct _counter_printer_0 *next;
53 struct _counter_printer_0 *prev;
59 static counter_printer_0 *counter_list;
61 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
62 static uint32 smb_connections=0;
65 /* in printing/nt_printing.c */
67 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
69 /* API table for Xcv Monitor functions */
71 struct xcv_api_table {
73 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
77 /* translate between internal status numbers and NT status numbers */
78 static int nt_printj_status(int v)
84 return JOB_STATUS_PAUSED;
86 return JOB_STATUS_SPOOLING;
88 return JOB_STATUS_PRINTING;
90 return JOB_STATUS_ERROR;
92 return JOB_STATUS_DELETING;
94 return JOB_STATUS_OFFLINE;
96 return JOB_STATUS_PAPEROUT;
98 return JOB_STATUS_PRINTED;
100 return JOB_STATUS_DELETED;
102 return JOB_STATUS_BLOCKED;
103 case LPQ_USER_INTERVENTION:
104 return JOB_STATUS_USER_INTERVENTION;
109 static int nt_printq_status(int v)
113 return PRINTER_STATUS_PAUSED;
122 /****************************************************************************
123 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
124 ****************************************************************************/
126 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
131 SAFE_FREE((*pp)->ctr.type);
135 /***************************************************************************
136 Disconnect from the client
137 ****************************************************************************/
139 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
144 * Tell the specific printing tdb we no longer want messages for this printer
145 * by deregistering our PID.
148 if (!print_notify_deregister_pid(snum))
149 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
151 /* weird if the test succeds !!! */
152 if (smb_connections==0) {
153 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
157 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
159 if (!W_ERROR_IS_OK(result))
160 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
161 dos_errstr(result)));
163 /* if it's the last connection, deconnect the IPC$ share */
164 if (smb_connections==1) {
166 cli_shutdown( notify_cli_pipe->cli );
167 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
169 message_deregister(MSG_PRINTER_NOTIFY2);
171 /* Tell the connections db we're no longer interested in
172 * printer notify messages. */
174 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
180 /****************************************************************************
181 Functions to free a printer entry datastruct.
182 ****************************************************************************/
184 static void free_printer_entry(void *ptr)
186 Printer_entry *Printer = (Printer_entry *)ptr;
188 if (Printer->notify.client_connected==True) {
191 if ( Printer->printer_type == SPLHND_SERVER) {
193 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
194 } else if (Printer->printer_type == SPLHND_PRINTER) {
195 snum = print_queue_snum(Printer->sharename);
197 srv_spoolss_replycloseprinter(snum,
198 &Printer->notify.client_hnd);
202 Printer->notify.flags=0;
203 Printer->notify.options=0;
204 Printer->notify.localmachine[0]='\0';
205 Printer->notify.printerlocal=0;
206 free_spool_notify_option(&Printer->notify.option);
207 Printer->notify.option=NULL;
208 Printer->notify.client_connected=False;
210 free_nt_devicemode( &Printer->nt_devmode );
211 free_a_printer( &Printer->printer_info, 2 );
213 talloc_destroy( Printer->ctx );
215 /* Remove from the internal list. */
216 DLIST_REMOVE(printers_list, Printer);
221 /****************************************************************************
222 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
223 ****************************************************************************/
225 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
227 SPOOL_NOTIFY_OPTION *new_sp = NULL;
232 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
239 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
241 if (!new_sp->ctr.type) {
250 /****************************************************************************
251 find printer index by handle
252 ****************************************************************************/
254 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
256 Printer_entry *find_printer = NULL;
258 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
259 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
266 /****************************************************************************
267 Close printer index by handle.
268 ****************************************************************************/
270 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
272 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
275 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
279 close_policy_hnd(p, hnd);
284 /****************************************************************************
285 Delete a printer given a handle.
286 ****************************************************************************/
287 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
289 char *cmd = lp_deleteprinter_cmd();
292 SE_PRIV se_printop = SE_PRINT_OPERATOR;
293 BOOL is_print_op = False;
295 /* can't fail if we don't try */
300 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
303 is_print_op = user_has_privileges( token, &se_printop );
305 DEBUG(10,("Running [%s]\n", command));
307 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
312 if ( (ret = smbrun(command, NULL)) == 0 ) {
313 /* Tell everyone we updated smb.conf. */
314 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
320 /********** END SePrintOperatorPrivlege BLOCK **********/
322 DEBUGADD(10,("returned [%d]\n", ret));
325 return WERR_BADFID; /* What to return here? */
327 /* go ahead and re-read the services immediately */
328 reload_services( False );
330 if ( share_defined( sharename ) )
331 return WERR_ACCESS_DENIED;
336 /****************************************************************************
337 Delete a printer given a handle.
338 ****************************************************************************/
340 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
342 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
345 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
350 * It turns out that Windows allows delete printer on a handle
351 * opened by an admin user, then used on a pipe handle created
352 * by an anonymous user..... but they're working on security.... riiight !
356 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
357 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
358 return WERR_ACCESS_DENIED;
361 /* this does not need a become root since the access check has been
362 done on the handle already */
364 if (del_a_printer( Printer->sharename ) != 0) {
365 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
369 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
372 /****************************************************************************
373 Return the snum of a printer corresponding to an handle.
374 ****************************************************************************/
376 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
377 struct share_params **params)
379 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
382 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
386 switch (Printer->printer_type) {
388 DEBUG(4,("short name:%s\n", Printer->sharename));
389 *number = print_queue_snum(Printer->sharename);
390 if ((*number != -1) && (params != NULL)) {
391 *params = get_share_params(tmp_talloc_ctx(),
393 if (*params == NULL) {
397 return (*number != -1);
405 /****************************************************************************
406 Set printer handle type.
407 Check if it's \\server or \\server\printer
408 ****************************************************************************/
410 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
412 DEBUG(3,("Setting printer type=%s\n", handlename));
414 if ( strlen(handlename) < 3 ) {
415 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
419 /* it's a print server */
420 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
421 DEBUGADD(4,("Printer is a print server\n"));
422 Printer->printer_type = SPLHND_SERVER;
424 /* it's a printer (set_printer_hnd_name() will handle port monitors */
426 DEBUGADD(4,("Printer is a printer\n"));
427 Printer->printer_type = SPLHND_PRINTER;
433 /****************************************************************************
434 Set printer handle name.. Accept names like \\server, \\server\printer,
435 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
436 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
437 XcvDataPort() interface.
438 ****************************************************************************/
440 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
443 int n_services=lp_numservices();
444 char *aprinter, *printername;
445 const char *servername;
448 NT_PRINTER_INFO_LEVEL *printer = NULL;
451 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
453 aprinter = handlename;
454 if ( *handlename == '\\' ) {
455 servername = handlename + 2;
456 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
465 /* save the servername to fill in replies on this handle */
467 if ( !is_myname_or_ipaddr( servername ) )
470 fstrcpy( Printer->servername, servername );
472 if ( Printer->printer_type == SPLHND_SERVER )
475 if ( Printer->printer_type != SPLHND_PRINTER )
478 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
480 /* check for the Port Monitor Interface */
482 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
483 Printer->printer_type = SPLHND_PORTMON_TCP;
484 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
487 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
488 Printer->printer_type = SPLHND_PORTMON_LOCAL;
489 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
493 /* Search all sharenames first as this is easier than pulling
494 the printer_info_2 off of disk. Don't use find_service() since
495 that calls out to map_username() */
497 /* do another loop to look for printernames */
499 for (snum=0; !found && snum<n_services; snum++) {
501 /* no point going on if this is not a printer */
503 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
506 fstrcpy(sname, lp_servicename(snum));
507 if ( strequal( aprinter, sname ) ) {
512 /* no point looking up the printer object if
513 we aren't allowing printername != sharename */
515 if ( lp_force_printername(snum) )
518 fstrcpy(sname, lp_servicename(snum));
521 result = get_a_printer( NULL, &printer, 2, sname );
522 if ( !W_ERROR_IS_OK(result) ) {
523 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
524 sname, dos_errstr(result)));
528 /* printername is always returned as \\server\printername */
529 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
530 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
531 printer->info_2->printername));
532 free_a_printer( &printer, 2);
538 if ( strequal(printername, aprinter) ) {
539 free_a_printer( &printer, 2);
544 DEBUGADD(10, ("printername: %s\n", printername));
546 free_a_printer( &printer, 2);
549 free_a_printer( &printer, 2);
552 DEBUGADD(4,("Printer not found\n"));
556 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
558 fstrcpy(Printer->sharename, sname);
563 /****************************************************************************
564 Find first available printer slot. creates a printer handle for you.
565 ****************************************************************************/
567 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
569 Printer_entry *new_printer;
571 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
573 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
576 ZERO_STRUCTP(new_printer);
578 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
579 SAFE_FREE(new_printer);
583 /* Add to the internal list. */
584 DLIST_ADD(printers_list, new_printer);
586 new_printer->notify.option=NULL;
588 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
589 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
590 close_printer_handle(p, hnd);
594 if (!set_printer_hnd_printertype(new_printer, name)) {
595 close_printer_handle(p, hnd);
599 if (!set_printer_hnd_name(new_printer, name)) {
600 close_printer_handle(p, hnd);
604 new_printer->access_granted = access_granted;
606 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
611 /***************************************************************************
612 check to see if the client motify handle is monitoring the notification
613 given by (notify_type, notify_field).
614 **************************************************************************/
616 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
622 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
625 SPOOL_NOTIFY_OPTION *option = p->notify.option;
629 * Flags should always be zero when the change notify
630 * is registered by the client's spooler. A user Win32 app
631 * might use the flags though instead of the NOTIFY_OPTION_INFO
640 return is_monitoring_event_flags(
641 p->notify.flags, notify_type, notify_field);
643 for (i = 0; i < option->count; i++) {
645 /* Check match for notify_type */
647 if (option->ctr.type[i].type != notify_type)
650 /* Check match for field */
652 for (j = 0; j < option->ctr.type[i].count; j++) {
653 if (option->ctr.type[i].fields[j] == notify_field) {
659 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
660 p->servername, p->sharename, notify_type, notify_field));
665 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
667 static void notify_one_value(struct spoolss_notify_msg *msg,
668 SPOOL_NOTIFY_INFO_DATA *data,
671 data->notify_data.value[0] = msg->notify.value[0];
672 data->notify_data.value[1] = 0;
675 static void notify_string(struct spoolss_notify_msg *msg,
676 SPOOL_NOTIFY_INFO_DATA *data,
681 /* The length of the message includes the trailing \0 */
683 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
685 data->notify_data.data.length = msg->len * 2;
686 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
688 if (!data->notify_data.data.string) {
689 data->notify_data.data.length = 0;
693 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
696 static void notify_system_time(struct spoolss_notify_msg *msg,
697 SPOOL_NOTIFY_INFO_DATA *data,
703 if (msg->len != sizeof(time_t)) {
704 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
709 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
710 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
714 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
715 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
720 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
725 data->notify_data.data.length = prs_offset(&ps);
726 data->notify_data.data.string = (uint16 *)
727 TALLOC(mem_ctx, prs_offset(&ps));
728 if (!data->notify_data.data.string) {
733 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
738 struct notify2_message_table {
740 void (*fn)(struct spoolss_notify_msg *msg,
741 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
744 static struct notify2_message_table printer_notify_table[] = {
745 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
746 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
747 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
748 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
749 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
750 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
751 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
752 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
753 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
754 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
755 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
756 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
757 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
758 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
759 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
760 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
761 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
762 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
763 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
766 static struct notify2_message_table job_notify_table[] = {
767 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
768 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
769 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
770 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
771 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
772 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
773 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
774 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
775 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
776 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
777 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
778 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
779 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
780 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
781 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
782 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
783 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
784 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
785 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
786 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
787 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
788 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
789 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
790 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
794 /***********************************************************************
795 Allocate talloc context for container object
796 **********************************************************************/
798 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
803 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
808 /***********************************************************************
809 release all allocated memory and zero out structure
810 **********************************************************************/
812 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
818 talloc_destroy(ctr->ctx);
825 /***********************************************************************
826 **********************************************************************/
828 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
836 /***********************************************************************
837 **********************************************************************/
839 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
841 if ( !ctr || !ctr->msg_groups )
844 if ( idx >= ctr->num_groups )
847 return &ctr->msg_groups[idx];
851 /***********************************************************************
852 How many groups of change messages do we have ?
853 **********************************************************************/
855 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
860 return ctr->num_groups;
863 /***********************************************************************
864 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
865 **********************************************************************/
867 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
869 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
870 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
871 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
877 /* loop over all groups looking for a matching printer name */
879 for ( i=0; i<ctr->num_groups; i++ ) {
880 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
884 /* add a new group? */
886 if ( i == ctr->num_groups ) {
889 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
890 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
893 ctr->msg_groups = groups;
895 /* clear the new entry and set the printer name */
897 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
898 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
901 /* add the change messages; 'i' is the correct index now regardless */
903 msg_grp = &ctr->msg_groups[i];
907 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
908 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
911 msg_grp->msgs = msg_list;
913 new_slot = msg_grp->num_msgs-1;
914 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
916 /* need to allocate own copy of data */
919 msg_grp->msgs[new_slot].notify.data = (char *)
920 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
922 return ctr->num_groups;
925 /***********************************************************************
926 Send a change notication message on all handles which have a call
928 **********************************************************************/
930 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
933 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
934 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
935 SPOOLSS_NOTIFY_MSG *messages;
936 int sending_msg_count;
939 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
943 messages = msg_group->msgs;
946 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
950 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
952 /* loop over all printers */
954 for (p = printers_list; p; p = p->next) {
955 SPOOL_NOTIFY_INFO_DATA *data;
960 /* Is there notification on this handle? */
962 if ( !p->notify.client_connected )
965 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
967 /* For this printer? Print servers always receive
970 if ( ( p->printer_type == SPLHND_PRINTER ) &&
971 ( !strequal(msg_group->printername, p->sharename) ) )
974 DEBUG(10,("Our printer\n"));
976 /* allocate the max entries possible */
978 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
985 /* build the array of change notifications */
987 sending_msg_count = 0;
989 for ( i=0; i<msg_group->num_msgs; i++ ) {
990 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
992 /* Are we monitoring this event? */
994 if (!is_monitoring_event(p, msg->type, msg->field))
1000 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1001 msg->type, msg->field, p->sharename));
1004 * if the is a printer notification handle and not a job notification
1005 * type, then set the id to 0. Other wise just use what was specified
1008 * When registering change notification on a print server handle
1009 * we always need to send back the id (snum) matching the printer
1010 * for which the change took place. For change notify registered
1011 * on a printer handle, this does not matter and the id should be 0.
1016 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1022 /* Convert unix jobid to smb jobid */
1024 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1025 id = sysjob_to_jobid(msg->id);
1028 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1033 construct_info_data( &data[data_len], msg->type, msg->field, id );
1036 case PRINTER_NOTIFY_TYPE:
1037 if ( printer_notify_table[msg->field].fn )
1038 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1041 case JOB_NOTIFY_TYPE:
1042 if ( job_notify_table[msg->field].fn )
1043 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1047 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1054 if ( sending_msg_count ) {
1055 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1056 data_len, data, p->notify.change, 0 );
1061 DEBUG(8,("send_notify2_changes: Exit...\n"));
1065 /***********************************************************************
1066 **********************************************************************/
1068 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1071 uint32 tv_sec, tv_usec;
1074 /* Unpack message */
1076 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1079 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1081 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1084 tdb_unpack((char *)buf + offset, len - offset, "dd",
1085 &msg->notify.value[0], &msg->notify.value[1]);
1087 tdb_unpack((char *)buf + offset, len - offset, "B",
1088 &msg->len, &msg->notify.data);
1090 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1091 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1093 tv->tv_sec = tv_sec;
1094 tv->tv_usec = tv_usec;
1097 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1098 msg->notify.value[1]));
1100 dump_data(3, msg->notify.data, msg->len);
1105 /********************************************************************
1106 Receive a notify2 message list
1107 ********************************************************************/
1109 static void receive_notify2_message_list(int msg_type, struct process_id src,
1110 void *msg, size_t len)
1112 size_t msg_count, i;
1113 char *buf = (char *)msg;
1116 SPOOLSS_NOTIFY_MSG notify;
1117 SPOOLSS_NOTIFY_MSG_CTR messages;
1121 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1125 msg_count = IVAL(buf, 0);
1128 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1130 if (msg_count == 0) {
1131 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1135 /* initialize the container */
1137 ZERO_STRUCT( messages );
1138 notify_msg_ctr_init( &messages );
1141 * build message groups for each printer identified
1142 * in a change_notify msg. Remember that a PCN message
1143 * includes the handle returned for the srv_spoolss_replyopenprinter()
1144 * call. Therefore messages are grouped according to printer handle.
1147 for ( i=0; i<msg_count; i++ ) {
1148 struct timeval msg_tv;
1150 if (msg_ptr + 4 - buf > len) {
1151 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1155 msg_len = IVAL(msg_ptr,0);
1158 if (msg_ptr + msg_len - buf > len) {
1159 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1163 /* unpack messages */
1165 ZERO_STRUCT( notify );
1166 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1169 /* add to correct list in container */
1171 notify_msg_ctr_addmsg( &messages, ¬ify );
1173 /* free memory that might have been allocated by notify2_unpack_msg() */
1175 if ( notify.len != 0 )
1176 SAFE_FREE( notify.notify.data );
1179 /* process each group of messages */
1181 num_groups = notify_msg_ctr_numgroups( &messages );
1182 for ( i=0; i<num_groups; i++ )
1183 send_notify2_changes( &messages, i );
1188 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1190 notify_msg_ctr_destroy( &messages );
1195 /********************************************************************
1196 Send a message to ourself about new driver being installed
1197 so we can upgrade the information for each printer bound to this
1199 ********************************************************************/
1201 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1203 int len = strlen(drivername);
1208 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1211 message_send_pid(pid_to_procid(sys_getpid()),
1212 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1217 /**********************************************************************
1218 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1219 over all printers, upgrading ones as necessary
1220 **********************************************************************/
1222 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1226 int n_services = lp_numservices();
1228 len = MIN(len,sizeof(drivername)-1);
1229 strncpy(drivername, (const char *)buf, len);
1231 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1233 /* Iterate the printer list */
1235 for (snum=0; snum<n_services; snum++)
1237 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1240 NT_PRINTER_INFO_LEVEL *printer = NULL;
1242 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1243 if (!W_ERROR_IS_OK(result))
1246 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1248 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1250 /* all we care about currently is the change_id */
1252 result = mod_a_printer(printer, 2);
1253 if (!W_ERROR_IS_OK(result)) {
1254 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1255 dos_errstr(result)));
1259 free_a_printer(&printer, 2);
1266 /********************************************************************
1267 Update the cache for all printq's with a registered client
1269 ********************************************************************/
1271 void update_monitored_printq_cache( void )
1273 Printer_entry *printer = printers_list;
1276 /* loop through all printers and update the cache where
1277 client_connected == True */
1280 if ( (printer->printer_type == SPLHND_PRINTER)
1281 && printer->notify.client_connected )
1283 snum = print_queue_snum(printer->sharename);
1284 print_queue_status( snum, NULL, NULL );
1287 printer = printer->next;
1292 /********************************************************************
1293 Send a message to ourself about new driver being installed
1294 so we can upgrade the information for each printer bound to this
1296 ********************************************************************/
1298 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1300 int len = strlen(drivername);
1305 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1308 message_send_pid(pid_to_procid(sys_getpid()),
1309 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1314 /**********************************************************************
1315 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1316 over all printers, resetting printer data as neessary
1317 **********************************************************************/
1319 void reset_all_printerdata(int msg_type, struct process_id src,
1320 void *buf, size_t len)
1324 int n_services = lp_numservices();
1326 len = MIN( len, sizeof(drivername)-1 );
1327 strncpy( drivername, (const char *)buf, len );
1329 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1331 /* Iterate the printer list */
1333 for ( snum=0; snum<n_services; snum++ )
1335 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1338 NT_PRINTER_INFO_LEVEL *printer = NULL;
1340 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1341 if ( !W_ERROR_IS_OK(result) )
1345 * if the printer is bound to the driver,
1346 * then reset to the new driver initdata
1349 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1351 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1353 if ( !set_driver_init(printer, 2) ) {
1354 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1355 printer->info_2->printername, printer->info_2->drivername));
1358 result = mod_a_printer( printer, 2 );
1359 if ( !W_ERROR_IS_OK(result) ) {
1360 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1361 get_dos_error_msg(result)));
1365 free_a_printer( &printer, 2 );
1374 /********************************************************************
1375 Copy routines used by convert_to_openprinterex()
1376 *******************************************************************/
1378 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1386 DEBUG (8,("dup_devmode\n"));
1388 /* bulk copy first */
1390 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1394 /* dup the pointer members separately */
1396 len = unistrlen(devmode->devicename.buffer);
1398 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1399 if (!d->devicename.buffer) {
1402 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1407 len = unistrlen(devmode->formname.buffer);
1409 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1410 if (!d->devicename.buffer) {
1413 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1417 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1418 devmode->driverextra);
1419 if (!d->dev_private) {
1425 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1427 if (!new_ctr || !ctr)
1430 DEBUG(8,("copy_devmode_ctr\n"));
1432 new_ctr->size = ctr->size;
1433 new_ctr->devmode_ptr = ctr->devmode_ptr;
1435 if(ctr->devmode_ptr)
1436 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1439 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1441 if (!new_def || !def)
1444 DEBUG(8,("copy_printer_defaults\n"));
1446 new_def->datatype_ptr = def->datatype_ptr;
1448 if (def->datatype_ptr)
1449 copy_unistr2(&new_def->datatype, &def->datatype);
1451 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1453 new_def->access_required = def->access_required;
1456 /********************************************************************
1457 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1458 * SPOOL_Q_OPEN_PRINTER_EX structure
1459 ********************************************************************/
1461 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1463 if (!q_u_ex || !q_u)
1466 DEBUG(8,("convert_to_openprinterex\n"));
1468 if ( q_u->printername ) {
1469 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1470 if (q_u_ex->printername == NULL)
1472 copy_unistr2(q_u_ex->printername, q_u->printername);
1475 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1480 /********************************************************************
1481 * spoolss_open_printer
1483 * called from the spoolss dispatcher
1484 ********************************************************************/
1486 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1488 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1489 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1494 ZERO_STRUCT(q_u_ex);
1495 ZERO_STRUCT(r_u_ex);
1497 /* convert the OpenPrinter() call to OpenPrinterEx() */
1499 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1500 if (!W_ERROR_IS_OK(r_u_ex.status))
1501 return r_u_ex.status;
1503 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1505 /* convert back to OpenPrinter() */
1507 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1512 /********************************************************************
1513 ********************************************************************/
1515 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1517 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1518 POLICY_HND *handle = &r_u->handle;
1522 Printer_entry *Printer=NULL;
1524 if ( !q_u->printername )
1525 return WERR_INVALID_PRINTER_NAME;
1527 /* some sanity check because you can open a printer or a print server */
1528 /* aka: \\server\printer or \\server */
1530 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1532 DEBUGADD(3,("checking name: %s\n",name));
1534 if (!open_printer_hnd(p, handle, name, 0))
1535 return WERR_INVALID_PRINTER_NAME;
1537 Printer=find_printer_index_by_hnd(p, handle);
1539 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1540 "handle we created for printer %s\n", name ));
1541 close_printer_handle(p,handle);
1542 return WERR_INVALID_PRINTER_NAME;
1546 * First case: the user is opening the print server:
1548 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1549 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1551 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1552 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1553 * or if the user is listed in the smb.conf printer admin parameter.
1555 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1556 * client view printer folder, but does not show the MSAPW.
1558 * Note: this test needs code to check access rights here too. Jeremy
1559 * could you look at this?
1561 * Second case: the user is opening a printer:
1562 * NT doesn't let us connect to a printer if the connecting user
1563 * doesn't have print permission.
1565 * Third case: user is opening a Port Monitor
1566 * access checks same as opening a handle to the print server.
1569 switch (Printer->printer_type )
1572 case SPLHND_PORTMON_TCP:
1573 case SPLHND_PORTMON_LOCAL:
1574 /* Printserver handles use global struct... */
1578 /* Map standard access rights to object specific access rights */
1580 se_map_standard(&printer_default->access_required,
1581 &printserver_std_mapping);
1583 /* Deny any object specific bits that don't apply to print
1584 servers (i.e printer and job specific bits) */
1586 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1588 if (printer_default->access_required &
1589 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1590 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1591 close_printer_handle(p, handle);
1592 return WERR_ACCESS_DENIED;
1595 /* Allow admin access */
1597 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1599 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1601 if (!lp_ms_add_printer_wizard()) {
1602 close_printer_handle(p, handle);
1603 return WERR_ACCESS_DENIED;
1606 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1607 and not a printer admin, then fail */
1609 if ((p->pipe_user.ut.uid != 0) &&
1610 !user_has_privileges(p->pipe_user.nt_user_token,
1612 !token_contains_name_in_list(
1613 uidtoname(p->pipe_user.ut.uid), NULL,
1614 p->pipe_user.nt_user_token,
1615 lp_printer_admin(snum))) {
1616 close_printer_handle(p, handle);
1617 return WERR_ACCESS_DENIED;
1620 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1624 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1627 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1628 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1630 /* We fall through to return WERR_OK */
1633 case SPLHND_PRINTER:
1634 /* NT doesn't let us connect to a printer if the connecting user
1635 doesn't have print permission. */
1637 if (!get_printer_snum(p, handle, &snum, NULL)) {
1638 close_printer_handle(p, handle);
1642 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1644 /* map an empty access mask to the minimum access mask */
1645 if (printer_default->access_required == 0x0)
1646 printer_default->access_required = PRINTER_ACCESS_USE;
1649 * If we are not serving the printer driver for this printer,
1650 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1651 * will keep NT clients happy --jerry
1654 if (lp_use_client_driver(snum)
1655 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1657 printer_default->access_required = PRINTER_ACCESS_USE;
1660 /* check smb.conf parameters and the the sec_desc */
1662 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1663 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1664 return WERR_ACCESS_DENIED;
1667 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1668 p->pipe_user.nt_user_token, snum) ||
1669 !print_access_check(&p->pipe_user, snum,
1670 printer_default->access_required)) {
1671 DEBUG(3, ("access DENIED for printer open\n"));
1672 close_printer_handle(p, handle);
1673 return WERR_ACCESS_DENIED;
1676 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1677 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1678 close_printer_handle(p, handle);
1679 return WERR_ACCESS_DENIED;
1682 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1683 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1685 printer_default->access_required = PRINTER_ACCESS_USE;
1687 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1688 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1693 /* sanity check to prevent programmer error */
1697 Printer->access_granted = printer_default->access_required;
1700 * If the client sent a devmode in the OpenPrinter() call, then
1701 * save it here in case we get a job submission on this handle
1704 if ( (Printer->printer_type != SPLHND_SERVER)
1705 && q_u->printer_default.devmode_cont.devmode_ptr )
1707 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1708 &Printer->nt_devmode );
1711 #if 0 /* JERRY -- I'm doubtful this is really effective */
1712 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1713 optimization in Windows 2000 clients --jerry */
1715 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1716 && (RA_WIN2K == get_remote_arch()) )
1718 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1719 sys_usleep( 500000 );
1726 /****************************************************************************
1727 ****************************************************************************/
1729 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1730 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1736 /* allocate memory if needed. Messy because
1737 convert_printer_info is used to update an existing
1738 printer or build a new one */
1740 if ( !printer->info_2 ) {
1741 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1742 if ( !printer->info_2 ) {
1743 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1748 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1749 printer->info_2->setuptime = time(NULL);
1757 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1758 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1764 printer->info_3=NULL;
1765 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1769 printer->info_6=NULL;
1770 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1780 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1781 NT_DEVICEMODE **pp_nt_devmode)
1783 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1786 * Ensure nt_devmode is a valid pointer
1787 * as we will be overwriting it.
1790 if (nt_devmode == NULL) {
1791 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1792 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1796 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1797 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1799 nt_devmode->specversion=devmode->specversion;
1800 nt_devmode->driverversion=devmode->driverversion;
1801 nt_devmode->size=devmode->size;
1802 nt_devmode->fields=devmode->fields;
1803 nt_devmode->orientation=devmode->orientation;
1804 nt_devmode->papersize=devmode->papersize;
1805 nt_devmode->paperlength=devmode->paperlength;
1806 nt_devmode->paperwidth=devmode->paperwidth;
1807 nt_devmode->scale=devmode->scale;
1808 nt_devmode->copies=devmode->copies;
1809 nt_devmode->defaultsource=devmode->defaultsource;
1810 nt_devmode->printquality=devmode->printquality;
1811 nt_devmode->color=devmode->color;
1812 nt_devmode->duplex=devmode->duplex;
1813 nt_devmode->yresolution=devmode->yresolution;
1814 nt_devmode->ttoption=devmode->ttoption;
1815 nt_devmode->collate=devmode->collate;
1817 nt_devmode->logpixels=devmode->logpixels;
1818 nt_devmode->bitsperpel=devmode->bitsperpel;
1819 nt_devmode->pelswidth=devmode->pelswidth;
1820 nt_devmode->pelsheight=devmode->pelsheight;
1821 nt_devmode->displayflags=devmode->displayflags;
1822 nt_devmode->displayfrequency=devmode->displayfrequency;
1823 nt_devmode->icmmethod=devmode->icmmethod;
1824 nt_devmode->icmintent=devmode->icmintent;
1825 nt_devmode->mediatype=devmode->mediatype;
1826 nt_devmode->dithertype=devmode->dithertype;
1827 nt_devmode->reserved1=devmode->reserved1;
1828 nt_devmode->reserved2=devmode->reserved2;
1829 nt_devmode->panningwidth=devmode->panningwidth;
1830 nt_devmode->panningheight=devmode->panningheight;
1833 * Only change private and driverextra if the incoming devmode
1834 * has a new one. JRA.
1837 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1838 SAFE_FREE(nt_devmode->nt_dev_private);
1839 nt_devmode->driverextra=devmode->driverextra;
1840 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1842 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1845 *pp_nt_devmode = nt_devmode;
1850 /********************************************************************
1851 * _spoolss_enddocprinter_internal.
1852 ********************************************************************/
1854 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1856 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1860 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1864 if (!get_printer_snum(p, handle, &snum, NULL))
1867 Printer->document_started=False;
1868 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1869 /* error codes unhandled so far ... */
1874 /********************************************************************
1875 * api_spoolss_closeprinter
1876 ********************************************************************/
1878 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1880 POLICY_HND *handle = &q_u->handle;
1882 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1884 if (Printer && Printer->document_started)
1885 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1887 if (!close_printer_handle(p, handle))
1890 /* clear the returned printer handle. Observed behavior
1891 from Win2k server. Don't think this really matters.
1892 Previous code just copied the value of the closed
1895 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1900 /********************************************************************
1901 * api_spoolss_deleteprinter
1903 ********************************************************************/
1905 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1907 POLICY_HND *handle = &q_u->handle;
1908 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1911 if (Printer && Printer->document_started)
1912 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1914 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1916 result = delete_printer_handle(p, handle);
1918 update_c_setprinter(False);
1923 /*******************************************************************
1924 * static function to lookup the version id corresponding to an
1925 * long architecture string
1926 ******************************************************************/
1928 static int get_version_id (char * arch)
1931 struct table_node archi_table[]= {
1933 {"Windows 4.0", "WIN40", 0 },
1934 {"Windows NT x86", "W32X86", 2 },
1935 {"Windows NT R4000", "W32MIPS", 2 },
1936 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1937 {"Windows NT PowerPC", "W32PPC", 2 },
1938 {"Windows IA64", "IA64", 3 },
1939 {"Windows x64", "x64", 3 },
1943 for (i=0; archi_table[i].long_archi != NULL; i++)
1945 if (strcmp(arch, archi_table[i].long_archi) == 0)
1946 return (archi_table[i].version);
1952 /********************************************************************
1953 * _spoolss_deleteprinterdriver
1954 ********************************************************************/
1956 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1960 NT_PRINTER_DRIVER_INFO_LEVEL info;
1961 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1964 WERROR status_win2k = WERR_ACCESS_DENIED;
1965 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1967 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1968 and not a printer admin, then fail */
1970 if ( (p->pipe_user.ut.uid != 0)
1971 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
1972 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
1973 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
1975 return WERR_ACCESS_DENIED;
1978 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1979 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1981 /* check that we have a valid driver name first */
1983 if ((version=get_version_id(arch)) == -1)
1984 return WERR_INVALID_ENVIRONMENT;
1987 ZERO_STRUCT(info_win2k);
1989 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1991 /* try for Win2k driver if "Windows NT x86" */
1993 if ( version == 2 ) {
1995 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1996 status = WERR_UNKNOWN_PRINTER_DRIVER;
2000 /* otherwise it was a failure */
2002 status = WERR_UNKNOWN_PRINTER_DRIVER;
2008 if (printer_driver_in_use(info.info_3)) {
2009 status = WERR_PRINTER_DRIVER_IN_USE;
2015 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2017 /* if we get to here, we now have 2 driver info structures to remove */
2018 /* remove the Win2k driver first*/
2020 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2021 free_a_printer_driver( info_win2k, 3 );
2023 /* this should not have failed---if it did, report to client */
2024 if ( !W_ERROR_IS_OK(status_win2k) )
2026 status = status_win2k;
2032 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2034 /* if at least one of the deletes succeeded return OK */
2036 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2040 free_a_printer_driver( info, 3 );
2045 /********************************************************************
2046 * spoolss_deleteprinterdriverex
2047 ********************************************************************/
2049 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2053 NT_PRINTER_DRIVER_INFO_LEVEL info;
2054 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2056 uint32 flags = q_u->delete_flags;
2059 WERROR status_win2k = WERR_ACCESS_DENIED;
2060 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2062 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2063 and not a printer admin, then fail */
2065 if ( (p->pipe_user.ut.uid != 0)
2066 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2067 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2068 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2070 return WERR_ACCESS_DENIED;
2073 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2074 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2076 /* check that we have a valid driver name first */
2077 if ((version=get_version_id(arch)) == -1) {
2078 /* this is what NT returns */
2079 return WERR_INVALID_ENVIRONMENT;
2082 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2083 version = q_u->version;
2086 ZERO_STRUCT(info_win2k);
2088 status = get_a_printer_driver(&info, 3, driver, arch, version);
2090 if ( !W_ERROR_IS_OK(status) )
2093 * if the client asked for a specific version,
2094 * or this is something other than Windows NT x86,
2098 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2101 /* try for Win2k driver if "Windows NT x86" */
2104 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2105 status = WERR_UNKNOWN_PRINTER_DRIVER;
2110 if ( printer_driver_in_use(info.info_3) ) {
2111 status = WERR_PRINTER_DRIVER_IN_USE;
2116 * we have a couple of cases to consider.
2117 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2118 * then the delete should fail if **any** files overlap with
2120 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2121 * non-overlapping files
2122 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2123 * is set, the do not delete any files
2124 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2127 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2129 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2131 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2132 /* no idea of the correct error here */
2133 status = WERR_ACCESS_DENIED;
2138 /* also check for W32X86/3 if necessary; maybe we already have? */
2140 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2141 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2144 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2145 /* no idea of the correct error here */
2146 free_a_printer_driver( info_win2k, 3 );
2147 status = WERR_ACCESS_DENIED;
2151 /* if we get to here, we now have 2 driver info structures to remove */
2152 /* remove the Win2k driver first*/
2154 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2155 free_a_printer_driver( info_win2k, 3 );
2157 /* this should not have failed---if it did, report to client */
2159 if ( !W_ERROR_IS_OK(status_win2k) )
2164 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2166 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2169 free_a_printer_driver( info, 3 );
2175 /****************************************************************************
2176 Internal routine for retreiving printerdata
2177 ***************************************************************************/
2179 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2180 const char *key, const char *value, uint32 *type, uint8 **data,
2181 uint32 *needed, uint32 in_size )
2183 REGISTRY_VALUE *val;
2187 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2188 return WERR_BADFILE;
2190 *type = regval_type( val );
2192 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2194 size = regval_size( val );
2196 /* copy the min(in_size, len) */
2199 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2201 /* special case for 0 length values */
2203 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2207 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2216 DEBUG(5,("get_printer_dataex: copy done\n"));
2221 /****************************************************************************
2222 Internal routine for removing printerdata
2223 ***************************************************************************/
2225 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2227 return delete_printer_data( printer->info_2, key, value );
2230 /****************************************************************************
2231 Internal routine for storing printerdata
2232 ***************************************************************************/
2234 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2235 uint32 type, uint8 *data, int real_len )
2237 /* the registry objects enforce uniqueness based on value name */
2239 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2242 /********************************************************************
2243 GetPrinterData on a printer server Handle.
2244 ********************************************************************/
2246 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2250 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2252 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2254 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2260 if (!StrCaseCmp(value, "BeepEnabled")) {
2262 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2264 SIVAL(*data, 0, 0x00);
2269 if (!StrCaseCmp(value, "EventLog")) {
2271 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2273 /* formally was 0x1b */
2274 SIVAL(*data, 0, 0x0);
2279 if (!StrCaseCmp(value, "NetPopup")) {
2281 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2283 SIVAL(*data, 0, 0x00);
2288 if (!StrCaseCmp(value, "MajorVersion")) {
2290 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2293 /* Windows NT 4.0 seems to not allow uploading of drivers
2294 to a server that reports 0x3 as the MajorVersion.
2295 need to investigate more how Win2k gets around this .
2298 if ( RA_WINNT == get_remote_arch() )
2307 if (!StrCaseCmp(value, "MinorVersion")) {
2309 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2317 * uint32 size = 0x114
2319 * uint32 minor = [0|1]
2320 * uint32 build = [2195|2600]
2321 * extra unicode string = e.g. "Service Pack 3"
2323 if (!StrCaseCmp(value, "OSVersion")) {
2327 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2330 SIVAL(*data, 0, *needed); /* size */
2331 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2333 SIVAL(*data, 12, 2195); /* build */
2335 /* leave extra string empty */
2341 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2342 const char *string="C:\\PRINTERS";
2344 *needed = 2*(strlen(string)+1);
2345 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2347 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2349 /* it's done by hand ready to go on the wire */
2350 for (i=0; i<strlen(string); i++) {
2351 (*data)[2*i]=string[i];
2352 (*data)[2*i+1]='\0';
2357 if (!StrCaseCmp(value, "Architecture")) {
2358 const char *string="Windows NT x86";
2360 *needed = 2*(strlen(string)+1);
2361 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2363 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2364 for (i=0; i<strlen(string); i++) {
2365 (*data)[2*i]=string[i];
2366 (*data)[2*i+1]='\0';
2371 if (!StrCaseCmp(value, "DsPresent")) {
2373 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2376 /* only show the publish check box if we are a
2377 memeber of a AD domain */
2379 if ( lp_security() == SEC_ADS )
2380 SIVAL(*data, 0, 0x01);
2382 SIVAL(*data, 0, 0x00);
2388 if (!StrCaseCmp(value, "DNSMachineName")) {
2391 if (!get_mydnsfullname(hostname))
2392 return WERR_BADFILE;
2394 *needed = 2*(strlen(hostname)+1);
2395 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2397 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2398 for (i=0; i<strlen(hostname); i++) {
2399 (*data)[2*i]=hostname[i];
2400 (*data)[2*i+1]='\0';
2406 return WERR_BADFILE;
2409 /********************************************************************
2410 * spoolss_getprinterdata
2411 ********************************************************************/
2413 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2415 POLICY_HND *handle = &q_u->handle;
2416 UNISTR2 *valuename = &q_u->valuename;
2417 uint32 in_size = q_u->size;
2418 uint32 *type = &r_u->type;
2419 uint32 *out_size = &r_u->size;
2420 uint8 **data = &r_u->data;
2421 uint32 *needed = &r_u->needed;
2424 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2425 NT_PRINTER_INFO_LEVEL *printer = NULL;
2429 * Reminder: when it's a string, the length is in BYTES
2430 * even if UNICODE is negociated.
2435 *out_size = in_size;
2437 /* in case of problem, return some default values */
2442 DEBUG(4,("_spoolss_getprinterdata\n"));
2445 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2446 status = WERR_BADFID;
2450 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2452 if ( Printer->printer_type == SPLHND_SERVER )
2453 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2456 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2457 status = WERR_BADFID;
2461 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2462 if ( !W_ERROR_IS_OK(status) )
2465 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2467 if ( strequal(value, "ChangeId") ) {
2469 *needed = sizeof(uint32);
2470 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2471 status = WERR_NOMEM;
2474 SIVAL( *data, 0, printer->info_2->changeid );
2478 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2481 if (*needed > *out_size)
2482 status = WERR_MORE_DATA;
2485 if ( !W_ERROR_IS_OK(status) )
2487 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2489 /* reply this param doesn't exist */
2492 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2494 free_a_printer( &printer, 2 );
2503 /* cleanup & exit */
2506 free_a_printer( &printer, 2 );
2511 /*********************************************************
2512 Connect to the client machine.
2513 **********************************************************/
2515 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2516 struct in_addr *client_ip, const char *remote_machine)
2519 struct cli_state *the_cli;
2520 struct in_addr rm_addr;
2522 if ( is_zero_ip(*client_ip) ) {
2523 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2524 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2528 if ( ismyip( rm_addr )) {
2529 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2533 rm_addr.s_addr = client_ip->s_addr;
2534 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2535 inet_ntoa(*client_ip) ));
2538 /* setup the connection */
2540 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2541 &rm_addr, 0, "IPC$", "IPC",
2545 0, lp_client_signing(), NULL );
2547 if ( !NT_STATUS_IS_OK( ret ) ) {
2548 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2553 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2554 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2555 cli_shutdown(the_cli);
2560 * Ok - we have an anonymous connection to the IPC$ share.
2561 * Now start the NT Domain stuff :-).
2564 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2565 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2566 remote_machine, nt_errstr(ret)));
2567 cli_shutdown(the_cli);
2571 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2573 (*pp_pipe)->cli = the_cli;
2578 /***************************************************************************
2579 Connect to the client.
2580 ****************************************************************************/
2582 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2583 uint32 localprinter, uint32 type,
2584 POLICY_HND *handle, struct in_addr *client_ip)
2589 * If it's the first connection, contact the client
2590 * and connect to the IPC$ share anonymously
2592 if (smb_connections==0) {
2593 fstring unix_printer;
2595 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2597 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2600 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2601 /* Tell the connections db we're now interested in printer
2602 * notify messages. */
2603 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2607 * Tell the specific printing tdb we want messages for this printer
2608 * by registering our PID.
2611 if (!print_notify_register_pid(snum))
2612 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2616 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2619 if (!W_ERROR_IS_OK(result))
2620 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2621 dos_errstr(result)));
2623 return (W_ERROR_IS_OK(result));
2626 /********************************************************************
2628 * ReplyFindFirstPrinterChangeNotifyEx
2630 * before replying OK: status=0 a rpc call is made to the workstation
2631 * asking ReplyOpenPrinter
2633 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2634 * called from api_spoolss_rffpcnex
2635 ********************************************************************/
2637 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2639 POLICY_HND *handle = &q_u->handle;
2640 uint32 flags = q_u->flags;
2641 uint32 options = q_u->options;
2642 UNISTR2 *localmachine = &q_u->localmachine;
2643 uint32 printerlocal = q_u->printerlocal;
2645 SPOOL_NOTIFY_OPTION *option = q_u->option;
2646 struct in_addr client_ip;
2648 /* store the notify value in the printer struct */
2650 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2653 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2657 Printer->notify.flags=flags;
2658 Printer->notify.options=options;
2659 Printer->notify.printerlocal=printerlocal;
2661 if (Printer->notify.option)
2662 free_spool_notify_option(&Printer->notify.option);
2664 Printer->notify.option=dup_spool_notify_option(option);
2666 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2667 sizeof(Printer->notify.localmachine)-1);
2669 /* Connect to the client machine and send a ReplyOpenPrinter */
2671 if ( Printer->printer_type == SPLHND_SERVER)
2673 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2674 !get_printer_snum(p, handle, &snum, NULL) )
2677 client_ip.s_addr = inet_addr(p->conn->client_address);
2679 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2680 Printer->notify.printerlocal, 1,
2681 &Printer->notify.client_hnd, &client_ip))
2682 return WERR_SERVER_UNAVAILABLE;
2684 Printer->notify.client_connected=True;
2689 /*******************************************************************
2690 * fill a notify_info_data with the servername
2691 ********************************************************************/
2693 void spoolss_notify_server_name(int snum,
2694 SPOOL_NOTIFY_INFO_DATA *data,
2695 print_queue_struct *queue,
2696 NT_PRINTER_INFO_LEVEL *printer,
2697 TALLOC_CTX *mem_ctx)
2702 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2704 data->notify_data.data.length = len;
2705 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2707 if (!data->notify_data.data.string) {
2708 data->notify_data.data.length = 0;
2712 memcpy(data->notify_data.data.string, temp, len);
2715 /*******************************************************************
2716 * fill a notify_info_data with the printername (not including the servername).
2717 ********************************************************************/
2719 void spoolss_notify_printer_name(int snum,
2720 SPOOL_NOTIFY_INFO_DATA *data,
2721 print_queue_struct *queue,
2722 NT_PRINTER_INFO_LEVEL *printer,
2723 TALLOC_CTX *mem_ctx)
2728 /* the notify name should not contain the \\server\ part */
2729 char *p = strrchr(printer->info_2->printername, '\\');
2732 p = printer->info_2->printername;
2737 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2739 data->notify_data.data.length = len;
2740 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2742 if (!data->notify_data.data.string) {
2743 data->notify_data.data.length = 0;
2747 memcpy(data->notify_data.data.string, temp, len);
2750 /*******************************************************************
2751 * fill a notify_info_data with the servicename
2752 ********************************************************************/
2754 void spoolss_notify_share_name(int snum,
2755 SPOOL_NOTIFY_INFO_DATA *data,
2756 print_queue_struct *queue,
2757 NT_PRINTER_INFO_LEVEL *printer,
2758 TALLOC_CTX *mem_ctx)
2763 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2765 data->notify_data.data.length = len;
2766 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2768 if (!data->notify_data.data.string) {
2769 data->notify_data.data.length = 0;
2773 memcpy(data->notify_data.data.string, temp, len);
2776 /*******************************************************************
2777 * fill a notify_info_data with the port name
2778 ********************************************************************/
2780 void spoolss_notify_port_name(int snum,
2781 SPOOL_NOTIFY_INFO_DATA *data,
2782 print_queue_struct *queue,
2783 NT_PRINTER_INFO_LEVEL *printer,
2784 TALLOC_CTX *mem_ctx)
2789 /* even if it's strange, that's consistant in all the code */
2791 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2793 data->notify_data.data.length = len;
2794 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2796 if (!data->notify_data.data.string) {
2797 data->notify_data.data.length = 0;
2801 memcpy(data->notify_data.data.string, temp, len);
2804 /*******************************************************************
2805 * fill a notify_info_data with the printername
2806 * but it doesn't exist, have to see what to do
2807 ********************************************************************/
2809 void spoolss_notify_driver_name(int snum,
2810 SPOOL_NOTIFY_INFO_DATA *data,
2811 print_queue_struct *queue,
2812 NT_PRINTER_INFO_LEVEL *printer,
2813 TALLOC_CTX *mem_ctx)
2818 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2820 data->notify_data.data.length = len;
2821 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2823 if (!data->notify_data.data.string) {
2824 data->notify_data.data.length = 0;
2828 memcpy(data->notify_data.data.string, temp, len);
2831 /*******************************************************************
2832 * fill a notify_info_data with the comment
2833 ********************************************************************/
2835 void spoolss_notify_comment(int snum,
2836 SPOOL_NOTIFY_INFO_DATA *data,
2837 print_queue_struct *queue,
2838 NT_PRINTER_INFO_LEVEL *printer,
2839 TALLOC_CTX *mem_ctx)
2844 if (*printer->info_2->comment == '\0')
2845 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2847 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2849 data->notify_data.data.length = len;
2850 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2852 if (!data->notify_data.data.string) {
2853 data->notify_data.data.length = 0;
2857 memcpy(data->notify_data.data.string, temp, len);
2860 /*******************************************************************
2861 * fill a notify_info_data with the comment
2862 * location = "Room 1, floor 2, building 3"
2863 ********************************************************************/
2865 void spoolss_notify_location(int snum,
2866 SPOOL_NOTIFY_INFO_DATA *data,
2867 print_queue_struct *queue,
2868 NT_PRINTER_INFO_LEVEL *printer,
2869 TALLOC_CTX *mem_ctx)
2874 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2876 data->notify_data.data.length = len;
2877 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2879 if (!data->notify_data.data.string) {
2880 data->notify_data.data.length = 0;
2884 memcpy(data->notify_data.data.string, temp, len);
2887 /*******************************************************************
2888 * fill a notify_info_data with the device mode
2889 * jfm:xxxx don't to it for know but that's a real problem !!!
2890 ********************************************************************/
2892 static void spoolss_notify_devmode(int snum,
2893 SPOOL_NOTIFY_INFO_DATA *data,
2894 print_queue_struct *queue,
2895 NT_PRINTER_INFO_LEVEL *printer,
2896 TALLOC_CTX *mem_ctx)
2898 /* for a dummy implementation we have to zero the fields */
2899 data->notify_data.data.length = 0;
2900 data->notify_data.data.string = NULL;
2903 /*******************************************************************
2904 * fill a notify_info_data with the separator file name
2905 ********************************************************************/
2907 void spoolss_notify_sepfile(int snum,
2908 SPOOL_NOTIFY_INFO_DATA *data,
2909 print_queue_struct *queue,
2910 NT_PRINTER_INFO_LEVEL *printer,
2911 TALLOC_CTX *mem_ctx)
2916 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2918 data->notify_data.data.length = len;
2919 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2921 if (!data->notify_data.data.string) {
2922 data->notify_data.data.length = 0;
2926 memcpy(data->notify_data.data.string, temp, len);
2929 /*******************************************************************
2930 * fill a notify_info_data with the print processor
2931 * jfm:xxxx return always winprint to indicate we don't do anything to it
2932 ********************************************************************/
2934 void spoolss_notify_print_processor(int snum,
2935 SPOOL_NOTIFY_INFO_DATA *data,
2936 print_queue_struct *queue,
2937 NT_PRINTER_INFO_LEVEL *printer,
2938 TALLOC_CTX *mem_ctx)
2943 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2945 data->notify_data.data.length = len;
2946 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2948 if (!data->notify_data.data.string) {
2949 data->notify_data.data.length = 0;
2953 memcpy(data->notify_data.data.string, temp, len);
2956 /*******************************************************************
2957 * fill a notify_info_data with the print processor options
2958 * jfm:xxxx send an empty string
2959 ********************************************************************/
2961 void spoolss_notify_parameters(int snum,
2962 SPOOL_NOTIFY_INFO_DATA *data,
2963 print_queue_struct *queue,
2964 NT_PRINTER_INFO_LEVEL *printer,
2965 TALLOC_CTX *mem_ctx)
2970 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2972 data->notify_data.data.length = len;
2973 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2975 if (!data->notify_data.data.string) {
2976 data->notify_data.data.length = 0;
2980 memcpy(data->notify_data.data.string, temp, len);
2983 /*******************************************************************
2984 * fill a notify_info_data with the data type
2985 * jfm:xxxx always send RAW as data type
2986 ********************************************************************/
2988 void spoolss_notify_datatype(int snum,
2989 SPOOL_NOTIFY_INFO_DATA *data,
2990 print_queue_struct *queue,
2991 NT_PRINTER_INFO_LEVEL *printer,
2992 TALLOC_CTX *mem_ctx)
2997 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2999 data->notify_data.data.length = len;
3000 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3002 if (!data->notify_data.data.string) {
3003 data->notify_data.data.length = 0;
3007 memcpy(data->notify_data.data.string, temp, len);
3010 /*******************************************************************
3011 * fill a notify_info_data with the security descriptor
3012 * jfm:xxxx send an null pointer to say no security desc
3013 * have to implement security before !
3014 ********************************************************************/
3016 static void spoolss_notify_security_desc(int snum,
3017 SPOOL_NOTIFY_INFO_DATA *data,
3018 print_queue_struct *queue,
3019 NT_PRINTER_INFO_LEVEL *printer,
3020 TALLOC_CTX *mem_ctx)
3022 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3023 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3026 /*******************************************************************
3027 * fill a notify_info_data with the attributes
3028 * jfm:xxxx a samba printer is always shared
3029 ********************************************************************/
3031 void spoolss_notify_attributes(int snum,
3032 SPOOL_NOTIFY_INFO_DATA *data,
3033 print_queue_struct *queue,
3034 NT_PRINTER_INFO_LEVEL *printer,
3035 TALLOC_CTX *mem_ctx)
3037 data->notify_data.value[0] = printer->info_2->attributes;
3038 data->notify_data.value[1] = 0;
3041 /*******************************************************************
3042 * fill a notify_info_data with the priority
3043 ********************************************************************/
3045 static void spoolss_notify_priority(int snum,
3046 SPOOL_NOTIFY_INFO_DATA *data,
3047 print_queue_struct *queue,
3048 NT_PRINTER_INFO_LEVEL *printer,
3049 TALLOC_CTX *mem_ctx)
3051 data->notify_data.value[0] = printer->info_2->priority;
3052 data->notify_data.value[1] = 0;
3055 /*******************************************************************
3056 * fill a notify_info_data with the default priority
3057 ********************************************************************/
3059 static void spoolss_notify_default_priority(int snum,
3060 SPOOL_NOTIFY_INFO_DATA *data,
3061 print_queue_struct *queue,
3062 NT_PRINTER_INFO_LEVEL *printer,
3063 TALLOC_CTX *mem_ctx)
3065 data->notify_data.value[0] = printer->info_2->default_priority;
3066 data->notify_data.value[1] = 0;
3069 /*******************************************************************
3070 * fill a notify_info_data with the start time
3071 ********************************************************************/
3073 static void spoolss_notify_start_time(int snum,
3074 SPOOL_NOTIFY_INFO_DATA *data,
3075 print_queue_struct *queue,
3076 NT_PRINTER_INFO_LEVEL *printer,
3077 TALLOC_CTX *mem_ctx)
3079 data->notify_data.value[0] = printer->info_2->starttime;
3080 data->notify_data.value[1] = 0;
3083 /*******************************************************************
3084 * fill a notify_info_data with the until time
3085 ********************************************************************/
3087 static void spoolss_notify_until_time(int snum,
3088 SPOOL_NOTIFY_INFO_DATA *data,
3089 print_queue_struct *queue,
3090 NT_PRINTER_INFO_LEVEL *printer,
3091 TALLOC_CTX *mem_ctx)
3093 data->notify_data.value[0] = printer->info_2->untiltime;
3094 data->notify_data.value[1] = 0;
3097 /*******************************************************************
3098 * fill a notify_info_data with the status
3099 ********************************************************************/
3101 static void spoolss_notify_status(int snum,
3102 SPOOL_NOTIFY_INFO_DATA *data,
3103 print_queue_struct *queue,
3104 NT_PRINTER_INFO_LEVEL *printer,
3105 TALLOC_CTX *mem_ctx)
3107 print_status_struct status;
3109 print_queue_length(snum, &status);
3110 data->notify_data.value[0]=(uint32) status.status;
3111 data->notify_data.value[1] = 0;
3114 /*******************************************************************
3115 * fill a notify_info_data with the number of jobs queued
3116 ********************************************************************/
3118 void spoolss_notify_cjobs(int snum,
3119 SPOOL_NOTIFY_INFO_DATA *data,
3120 print_queue_struct *queue,
3121 NT_PRINTER_INFO_LEVEL *printer,
3122 TALLOC_CTX *mem_ctx)
3124 data->notify_data.value[0] = print_queue_length(snum, NULL);
3125 data->notify_data.value[1] = 0;
3128 /*******************************************************************
3129 * fill a notify_info_data with the average ppm
3130 ********************************************************************/
3132 static void spoolss_notify_average_ppm(int snum,
3133 SPOOL_NOTIFY_INFO_DATA *data,
3134 print_queue_struct *queue,
3135 NT_PRINTER_INFO_LEVEL *printer,
3136 TALLOC_CTX *mem_ctx)
3138 /* always respond 8 pages per minutes */
3139 /* a little hard ! */
3140 data->notify_data.value[0] = printer->info_2->averageppm;
3141 data->notify_data.value[1] = 0;
3144 /*******************************************************************
3145 * fill a notify_info_data with username
3146 ********************************************************************/
3148 static void spoolss_notify_username(int snum,
3149 SPOOL_NOTIFY_INFO_DATA *data,
3150 print_queue_struct *queue,
3151 NT_PRINTER_INFO_LEVEL *printer,
3152 TALLOC_CTX *mem_ctx)
3157 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3159 data->notify_data.data.length = len;
3160 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3162 if (!data->notify_data.data.string) {
3163 data->notify_data.data.length = 0;
3167 memcpy(data->notify_data.data.string, temp, len);
3170 /*******************************************************************
3171 * fill a notify_info_data with job status
3172 ********************************************************************/
3174 static void spoolss_notify_job_status(int snum,
3175 SPOOL_NOTIFY_INFO_DATA *data,
3176 print_queue_struct *queue,
3177 NT_PRINTER_INFO_LEVEL *printer,
3178 TALLOC_CTX *mem_ctx)
3180 data->notify_data.value[0]=nt_printj_status(queue->status);
3181 data->notify_data.value[1] = 0;
3184 /*******************************************************************
3185 * fill a notify_info_data with job name
3186 ********************************************************************/
3188 static void spoolss_notify_job_name(int snum,
3189 SPOOL_NOTIFY_INFO_DATA *data,
3190 print_queue_struct *queue,
3191 NT_PRINTER_INFO_LEVEL *printer,
3192 TALLOC_CTX *mem_ctx)
3197 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3199 data->notify_data.data.length = len;
3200 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3202 if (!data->notify_data.data.string) {
3203 data->notify_data.data.length = 0;
3207 memcpy(data->notify_data.data.string, temp, len);
3210 /*******************************************************************
3211 * fill a notify_info_data with job status
3212 ********************************************************************/
3214 static void spoolss_notify_job_status_string(int snum,
3215 SPOOL_NOTIFY_INFO_DATA *data,
3216 print_queue_struct *queue,
3217 NT_PRINTER_INFO_LEVEL *printer,
3218 TALLOC_CTX *mem_ctx)
3221 * Now we're returning job status codes we just return a "" here. JRA.
3228 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3231 switch (queue->status) {
3236 p = ""; /* NT provides the paused string */
3245 #endif /* NO LONGER NEEDED. */
3247 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3249 data->notify_data.data.length = len;
3250 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3252 if (!data->notify_data.data.string) {
3253 data->notify_data.data.length = 0;
3257 memcpy(data->notify_data.data.string, temp, len);
3260 /*******************************************************************
3261 * fill a notify_info_data with job time
3262 ********************************************************************/
3264 static void spoolss_notify_job_time(int snum,
3265 SPOOL_NOTIFY_INFO_DATA *data,
3266 print_queue_struct *queue,
3267 NT_PRINTER_INFO_LEVEL *printer,
3268 TALLOC_CTX *mem_ctx)
3270 data->notify_data.value[0]=0x0;
3271 data->notify_data.value[1]=0;
3274 /*******************************************************************
3275 * fill a notify_info_data with job size
3276 ********************************************************************/
3278 static void spoolss_notify_job_size(int snum,
3279 SPOOL_NOTIFY_INFO_DATA *data,
3280 print_queue_struct *queue,
3281 NT_PRINTER_INFO_LEVEL *printer,
3282 TALLOC_CTX *mem_ctx)
3284 data->notify_data.value[0]=queue->size;
3285 data->notify_data.value[1]=0;
3288 /*******************************************************************
3289 * fill a notify_info_data with page info
3290 ********************************************************************/
3291 static void spoolss_notify_total_pages(int snum,
3292 SPOOL_NOTIFY_INFO_DATA *data,
3293 print_queue_struct *queue,
3294 NT_PRINTER_INFO_LEVEL *printer,
3295 TALLOC_CTX *mem_ctx)
3297 data->notify_data.value[0]=queue->page_count;
3298 data->notify_data.value[1]=0;
3301 /*******************************************************************
3302 * fill a notify_info_data with pages printed info.
3303 ********************************************************************/
3304 static void spoolss_notify_pages_printed(int snum,
3305 SPOOL_NOTIFY_INFO_DATA *data,
3306 print_queue_struct *queue,
3307 NT_PRINTER_INFO_LEVEL *printer,
3308 TALLOC_CTX *mem_ctx)
3310 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3311 data->notify_data.value[1]=0;
3314 /*******************************************************************
3315 Fill a notify_info_data with job position.
3316 ********************************************************************/
3318 static void spoolss_notify_job_position(int snum,
3319 SPOOL_NOTIFY_INFO_DATA *data,
3320 print_queue_struct *queue,
3321 NT_PRINTER_INFO_LEVEL *printer,
3322 TALLOC_CTX *mem_ctx)
3324 data->notify_data.value[0]=queue->job;
3325 data->notify_data.value[1]=0;
3328 /*******************************************************************
3329 Fill a notify_info_data with submitted time.
3330 ********************************************************************/
3332 static void spoolss_notify_submitted_time(int snum,
3333 SPOOL_NOTIFY_INFO_DATA *data,
3334 print_queue_struct *queue,
3335 NT_PRINTER_INFO_LEVEL *printer,
3336 TALLOC_CTX *mem_ctx)
3343 t=gmtime(&queue->time);
3345 len = sizeof(SYSTEMTIME);
3347 data->notify_data.data.length = len;
3348 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3350 if (!data->notify_data.data.string) {
3351 data->notify_data.data.length = 0;
3355 make_systemtime(&st, t);
3358 * Systemtime must be linearized as a set of UINT16's.
3359 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3362 p = (char *)data->notify_data.data.string;
3363 SSVAL(p, 0, st.year);
3364 SSVAL(p, 2, st.month);
3365 SSVAL(p, 4, st.dayofweek);
3366 SSVAL(p, 6, st.day);
3367 SSVAL(p, 8, st.hour);
3368 SSVAL(p, 10, st.minute);
3369 SSVAL(p, 12, st.second);
3370 SSVAL(p, 14, st.milliseconds);
3373 struct s_notify_info_data_table
3379 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3380 print_queue_struct *queue,
3381 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3384 /* A table describing the various print notification constants and
3385 whether the notification data is a pointer to a variable sized
3386 buffer, a one value uint32 or a two value uint32. */
3388 static const struct s_notify_info_data_table notify_info_data_table[] =
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3439 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3442 /*******************************************************************
3443 Return the size of info_data structure.
3444 ********************************************************************/
3446 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3450 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3451 if ( (notify_info_data_table[i].type == type)
3452 && (notify_info_data_table[i].field == field) ) {
3453 switch(notify_info_data_table[i].size) {
3454 case NOTIFY_ONE_VALUE:
3455 case NOTIFY_TWO_VALUE:
3460 /* The only pointer notify data I have seen on
3461 the wire is the submitted time and this has
3462 the notify size set to 4. -tpot */
3464 case NOTIFY_POINTER:
3467 case NOTIFY_SECDESC:
3473 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3478 /*******************************************************************
3479 Return the type of notify_info_data.
3480 ********************************************************************/
3482 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3486 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3487 if (notify_info_data_table[i].type == type &&
3488 notify_info_data_table[i].field == field)
3489 return notify_info_data_table[i].size;
3495 /****************************************************************************
3496 ****************************************************************************/
3498 static BOOL search_notify(uint16 type, uint16 field, int *value)
3502 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3503 if (notify_info_data_table[i].type == type &&
3504 notify_info_data_table[i].field == field &&
3505 notify_info_data_table[i].fn != NULL) {
3514 /****************************************************************************
3515 ****************************************************************************/
3517 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3519 info_data->type = type;
3520 info_data->field = field;
3521 info_data->reserved = 0;
3523 info_data->size = size_of_notify_info_data(type, field);
3524 info_data->enc_type = type_of_notify_info_data(type, field);
3529 /*******************************************************************
3531 * fill a notify_info struct with info asked
3533 ********************************************************************/
3535 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3536 snum, SPOOL_NOTIFY_OPTION_TYPE
3537 *option_type, uint32 id,
3538 TALLOC_CTX *mem_ctx)
3544 SPOOL_NOTIFY_INFO_DATA *current_data;
3545 NT_PRINTER_INFO_LEVEL *printer = NULL;
3546 print_queue_struct *queue=NULL;
3548 type=option_type->type;
3550 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3551 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3552 option_type->count, lp_servicename(snum)));
3554 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3557 for(field_num=0; field_num<option_type->count; field_num++) {
3558 field = option_type->fields[field_num];
3560 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3562 if (!search_notify(type, field, &j) )
3565 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3566 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3567 free_a_printer(&printer, 2);
3571 current_data = &info->data[info->count];
3573 construct_info_data(current_data, type, field, id);
3575 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3576 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3578 notify_info_data_table[j].fn(snum, current_data, queue,
3584 free_a_printer(&printer, 2);
3588 /*******************************************************************
3590 * fill a notify_info struct with info asked
3592 ********************************************************************/
3594 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3595 SPOOL_NOTIFY_INFO *info,
3596 NT_PRINTER_INFO_LEVEL *printer,
3597 int snum, SPOOL_NOTIFY_OPTION_TYPE
3598 *option_type, uint32 id,
3599 TALLOC_CTX *mem_ctx)
3605 SPOOL_NOTIFY_INFO_DATA *current_data;
3607 DEBUG(4,("construct_notify_jobs_info\n"));
3609 type = option_type->type;
3611 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3612 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3613 option_type->count));
3615 for(field_num=0; field_num<option_type->count; field_num++) {
3616 field = option_type->fields[field_num];
3618 if (!search_notify(type, field, &j) )
3621 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3622 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3626 current_data=&(info->data[info->count]);
3628 construct_info_data(current_data, type, field, id);
3629 notify_info_data_table[j].fn(snum, current_data, queue,
3638 * JFM: The enumeration is not that simple, it's even non obvious.
3640 * let's take an example: I want to monitor the PRINTER SERVER for
3641 * the printer's name and the number of jobs currently queued.
3642 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3643 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3645 * I have 3 printers on the back of my server.
3647 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3650 * 1 printer 1 name 1
3651 * 2 printer 1 cjob 1
3652 * 3 printer 2 name 2
3653 * 4 printer 2 cjob 2
3654 * 5 printer 3 name 3
3655 * 6 printer 3 name 3
3657 * that's the print server case, the printer case is even worse.
3660 /*******************************************************************
3662 * enumerate all printers on the printserver
3663 * fill a notify_info struct with info asked
3665 ********************************************************************/
3667 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3668 SPOOL_NOTIFY_INFO *info,
3669 TALLOC_CTX *mem_ctx)
3672 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3673 int n_services=lp_numservices();
3675 SPOOL_NOTIFY_OPTION *option;
3676 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3678 DEBUG(4,("printserver_notify_info\n"));
3683 option=Printer->notify.option;
3688 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3689 sending a ffpcn() request first */
3694 for (i=0; i<option->count; i++) {
3695 option_type=&(option->ctr.type[i]);
3697 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3700 for (snum=0; snum<n_services; snum++)
3702 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3703 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3709 * Debugging information, don't delete.
3712 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3713 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3714 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3716 for (i=0; i<info->count; i++) {
3717 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3718 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3719 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3726 /*******************************************************************
3728 * fill a notify_info struct with info asked
3730 ********************************************************************/
3732 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3733 TALLOC_CTX *mem_ctx)
3736 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3739 SPOOL_NOTIFY_OPTION *option;
3740 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3742 print_queue_struct *queue=NULL;
3743 print_status_struct status;
3745 DEBUG(4,("printer_notify_info\n"));
3750 option=Printer->notify.option;
3756 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3757 sending a ffpcn() request first */
3762 get_printer_snum(p, hnd, &snum, NULL);
3764 for (i=0; i<option->count; i++) {
3765 option_type=&option->ctr.type[i];
3767 switch ( option_type->type ) {
3768 case PRINTER_NOTIFY_TYPE:
3769 if(construct_notify_printer_info(Printer, info, snum,
3775 case JOB_NOTIFY_TYPE: {
3776 NT_PRINTER_INFO_LEVEL *printer = NULL;
3778 count = print_queue_status(snum, &queue, &status);
3780 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3783 for (j=0; j<count; j++) {
3784 construct_notify_jobs_info(&queue[j], info,
3791 free_a_printer(&printer, 2);
3801 * Debugging information, don't delete.
3804 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3805 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3806 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3808 for (i=0; i<info->count; i++) {
3809 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3810 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3811 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3817 /********************************************************************
3819 ********************************************************************/
3821 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3823 POLICY_HND *handle = &q_u->handle;
3824 SPOOL_NOTIFY_INFO *info = &r_u->info;
3826 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3827 WERROR result = WERR_BADFID;
3829 /* we always have a NOTIFY_INFO struct */
3833 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3834 OUR_HANDLE(handle)));
3838 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3841 * We are now using the change value, and
3842 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3843 * I don't have a global notification system, I'm sending back all the
3844 * informations even when _NOTHING_ has changed.
3847 /* We need to keep track of the change value to send back in
3848 RRPCN replies otherwise our updates are ignored. */
3850 Printer->notify.fnpcn = True;
3852 if (Printer->notify.client_connected) {
3853 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3854 Printer->notify.change = q_u->change;
3857 /* just ignore the SPOOL_NOTIFY_OPTION */
3859 switch (Printer->printer_type) {
3861 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3864 case SPLHND_PRINTER:
3865 result = printer_notify_info(p, handle, info, p->mem_ctx);
3869 Printer->notify.fnpcn = False;
3875 /********************************************************************
3876 * construct_printer_info_0
3877 * fill a printer_info_0 struct
3878 ********************************************************************/
3880 static BOOL construct_printer_info_0(Printer_entry *print_hnd,
3881 PRINTER_INFO_0 *printer,
3882 const struct share_params *params)
3886 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3887 counter_printer_0 *session_counter;
3888 uint32 global_counter;
3891 print_status_struct status;
3893 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
3894 lp_const_servicename(params->service))))
3897 count = print_queue_length(params->service, &status);
3899 /* check if we already have a counter for this printer */
3900 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3901 if (session_counter->snum == params->service)
3905 /* it's the first time, add it to the list */
3906 if (session_counter==NULL) {
3907 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3908 free_a_printer(&ntprinter, 2);
3911 ZERO_STRUCTP(session_counter);
3912 session_counter->snum=params->service;
3913 session_counter->counter=0;
3914 DLIST_ADD(counter_list, session_counter);
3918 session_counter->counter++;
3921 * the global_counter should be stored in a TDB as it's common to all the clients
3922 * and should be zeroed on samba startup
3924 global_counter=session_counter->counter;
3926 pstrcpy(chaine,ntprinter->info_2->printername);
3928 init_unistr(&printer->printername, chaine);
3930 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3931 init_unistr(&printer->servername, chaine);
3933 printer->cjobs = count;
3934 printer->total_jobs = 0;
3935 printer->total_bytes = 0;
3937 setuptime = (time_t)ntprinter->info_2->setuptime;
3938 t=gmtime(&setuptime);
3940 printer->year = t->tm_year+1900;
3941 printer->month = t->tm_mon+1;
3942 printer->dayofweek = t->tm_wday;
3943 printer->day = t->tm_mday;
3944 printer->hour = t->tm_hour;
3945 printer->minute = t->tm_min;
3946 printer->second = t->tm_sec;
3947 printer->milliseconds = 0;
3949 printer->global_counter = global_counter;
3950 printer->total_pages = 0;
3952 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3953 printer->major_version = 0x0005; /* NT 5 */
3954 printer->build_version = 0x0893; /* build 2195 */
3956 printer->unknown7 = 0x1;
3957 printer->unknown8 = 0x0;
3958 printer->unknown9 = 0x0;
3959 printer->session_counter = session_counter->counter;
3960 printer->unknown11 = 0x0;
3961 printer->printer_errors = 0x0; /* number of print failure */
3962 printer->unknown13 = 0x0;
3963 printer->unknown14 = 0x1;
3964 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3965 printer->unknown16 = 0x0;
3966 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3967 printer->unknown18 = 0x0;
3968 printer->status = nt_printq_status(status.status);
3969 printer->unknown20 = 0x0;
3970 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3971 printer->unknown22 = 0x0;
3972 printer->unknown23 = 0x6; /* 6 ???*/
3973 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3974 printer->unknown25 = 0;
3975 printer->unknown26 = 0;
3976 printer->unknown27 = 0;
3977 printer->unknown28 = 0;
3978 printer->unknown29 = 0;
3980 free_a_printer(&ntprinter,2);
3984 /********************************************************************
3985 * construct_printer_info_1
3986 * fill a printer_info_1 struct
3987 ********************************************************************/
3988 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags,
3989 PRINTER_INFO_1 *printer,
3990 const struct share_params *params)
3994 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3996 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
3997 lp_const_servicename(params->service))))
4000 printer->flags=flags;
4002 if (*ntprinter->info_2->comment == '\0') {
4003 init_unistr(&printer->comment, lp_comment(params->service));
4004 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4005 ntprinter->info_2->drivername,
4006 lp_comment(params->service));
4009 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4010 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4011 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4014 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4016 init_unistr(&printer->description, chaine);
4017 init_unistr(&printer->name, chaine2);
4019 free_a_printer(&ntprinter,2);
4024 /****************************************************************************
4025 Free a DEVMODE struct.
4026 ****************************************************************************/
4028 static void free_dev_mode(DEVICEMODE *dev)
4033 SAFE_FREE(dev->dev_private);
4038 /****************************************************************************
4039 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4040 should be valid upon entry
4041 ****************************************************************************/
4043 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4045 if ( !devmode || !ntdevmode )
4048 init_unistr(&devmode->devicename, ntdevmode->devicename);
4050 init_unistr(&devmode->formname, ntdevmode->formname);
4052 devmode->specversion = ntdevmode->specversion;
4053 devmode->driverversion = ntdevmode->driverversion;
4054 devmode->size = ntdevmode->size;
4055 devmode->driverextra = ntdevmode->driverextra;
4056 devmode->fields = ntdevmode->fields;
4058 devmode->orientation = ntdevmode->orientation;
4059 devmode->papersize = ntdevmode->papersize;
4060 devmode->paperlength = ntdevmode->paperlength;
4061 devmode->paperwidth = ntdevmode->paperwidth;
4062 devmode->scale = ntdevmode->scale;
4063 devmode->copies = ntdevmode->copies;
4064 devmode->defaultsource = ntdevmode->defaultsource;
4065 devmode->printquality = ntdevmode->printquality;
4066 devmode->color = ntdevmode->color;
4067 devmode->duplex = ntdevmode->duplex;
4068 devmode->yresolution = ntdevmode->yresolution;
4069 devmode->ttoption = ntdevmode->ttoption;
4070 devmode->collate = ntdevmode->collate;
4071 devmode->icmmethod = ntdevmode->icmmethod;
4072 devmode->icmintent = ntdevmode->icmintent;
4073 devmode->mediatype = ntdevmode->mediatype;
4074 devmode->dithertype = ntdevmode->dithertype;
4076 if (ntdevmode->nt_dev_private != NULL) {
4077 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4084 /****************************************************************************
4085 Create a DEVMODE struct. Returns malloced memory.
4086 ****************************************************************************/
4088 DEVICEMODE *construct_dev_mode(const char *servicename)
4090 NT_PRINTER_INFO_LEVEL *printer = NULL;
4091 DEVICEMODE *devmode = NULL;
4093 DEBUG(7,("construct_dev_mode\n"));
4095 DEBUGADD(8,("getting printer characteristics\n"));
4097 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4100 if ( !printer->info_2->devmode ) {
4101 DEBUG(5, ("BONG! There was no device mode!\n"));
4105 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4106 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4110 ZERO_STRUCTP(devmode);
4112 DEBUGADD(8,("loading DEVICEMODE\n"));
4114 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4115 free_dev_mode( devmode );
4120 free_a_printer(&printer,2);
4125 /********************************************************************
4126 * construct_printer_info_2
4127 * fill a printer_info_2 struct
4128 ********************************************************************/
4130 static BOOL construct_printer_info_2(Printer_entry *print_hnd,
4131 PRINTER_INFO_2 *printer,
4132 const struct share_params *params)
4135 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4137 print_status_struct status;
4139 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4140 lp_const_servicename(params->service))))
4143 count = print_queue_length(params->service, &status);
4145 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4146 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4147 init_unistr(&printer->sharename, lp_servicename(params->service)); /* sharename */
4148 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4149 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4151 if (*ntprinter->info_2->comment == '\0')
4152 init_unistr(&printer->comment, lp_comment(params->service)); /* comment */
4154 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4156 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4157 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4158 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4159 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4160 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4162 printer->attributes = ntprinter->info_2->attributes;
4164 printer->priority = ntprinter->info_2->priority; /* priority */
4165 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4166 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4167 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4168 printer->status = nt_printq_status(status.status); /* status */
4169 printer->cjobs = count; /* jobs */
4170 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4172 if ( !(printer->devmode = construct_dev_mode(
4173 lp_const_servicename(params->service))) )
4174 DEBUG(8, ("Returning NULL Devicemode!\n"));
4176 printer->secdesc = NULL;
4178 if ( ntprinter->info_2->secdesc_buf
4179 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4181 /* don't use talloc_steal() here unless you do a deep steal of all
4182 the SEC_DESC members */
4184 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4185 ntprinter->info_2->secdesc_buf->sd );
4188 free_a_printer(&ntprinter, 2);
4193 /********************************************************************
4194 * construct_printer_info_3
4195 * fill a printer_info_3 struct
4196 ********************************************************************/
4198 static BOOL construct_printer_info_3(Printer_entry *print_hnd,
4199 PRINTER_INFO_3 **pp_printer,
4200 const struct share_params *params)
4202 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4203 PRINTER_INFO_3 *printer = NULL;
4205 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4206 lp_const_servicename(params->service))))
4210 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4211 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4212 free_a_printer(&ntprinter, 2);
4216 ZERO_STRUCTP(printer);
4218 /* These are the components of the SD we are returning. */
4220 printer->flags = 0x4;
4222 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4223 /* don't use talloc_steal() here unless you do a deep steal of all
4224 the SEC_DESC members */
4226 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4227 ntprinter->info_2->secdesc_buf->sd );
4230 free_a_printer(&ntprinter, 2);
4232 *pp_printer = printer;
4236 /********************************************************************
4237 * construct_printer_info_4
4238 * fill a printer_info_4 struct
4239 ********************************************************************/
4241 static BOOL construct_printer_info_4(Printer_entry *print_hnd,
4242 PRINTER_INFO_4 *printer,
4243 const struct share_params *params)
4245 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4247 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4248 lp_const_servicename(params->service))))
4251 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4252 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4253 printer->attributes = ntprinter->info_2->attributes;
4255 free_a_printer(&ntprinter, 2);
4259 /********************************************************************
4260 * construct_printer_info_5
4261 * fill a printer_info_5 struct
4262 ********************************************************************/
4264 static BOOL construct_printer_info_5(Printer_entry *print_hnd,
4265 PRINTER_INFO_5 *printer,
4266 const struct share_params *params)
4268 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4270 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4271 lp_const_servicename(params->service))))
4274 init_unistr(&printer->printername, ntprinter->info_2->printername);
4275 init_unistr(&printer->portname, ntprinter->info_2->portname);
4276 printer->attributes = ntprinter->info_2->attributes;
4278 /* these two are not used by NT+ according to MSDN */
4280 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4281 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4283 free_a_printer(&ntprinter, 2);
4288 /********************************************************************
4289 * construct_printer_info_6
4290 * fill a printer_info_6 struct
4291 ********************************************************************/
4293 static BOOL construct_printer_info_6(Printer_entry *print_hnd,
4294 PRINTER_INFO_6 *printer,
4295 const struct share_params *params)
4297 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4299 print_status_struct status;
4301 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4302 lp_const_servicename(params->service))))
4305 count = print_queue_length(params->service, &status);
4307 printer->status = nt_printq_status(status.status);
4309 free_a_printer(&ntprinter, 2);
4314 /********************************************************************
4315 * construct_printer_info_7
4316 * fill a printer_info_7 struct
4317 ********************************************************************/
4319 static BOOL construct_printer_info_7(Printer_entry *print_hnd,
4320 PRINTER_INFO_7 *printer,
4321 const struct share_params *params)
4323 char *guid_str = NULL;
4326 if (is_printer_published(print_hnd, params->service, &guid)) {
4327 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4328 strupper_m(guid_str);
4329 init_unistr(&printer->guid, guid_str);
4330 printer->action = SPOOL_DS_PUBLISH;
4332 init_unistr(&printer->guid, "");
4333 printer->action = SPOOL_DS_UNPUBLISH;
4339 /********************************************************************
4340 Spoolss_enumprinters.
4341 ********************************************************************/
4343 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4347 int n_services=lp_numservices();
4348 PRINTER_INFO_1 *printers=NULL;
4349 WERROR result = WERR_OK;
4351 DEBUG(4,("enum_all_printers_info_1\n"));
4353 for (snum=0; snum<n_services; snum++) {
4354 PRINTER_INFO_1 current_prt;
4355 struct share_params params;
4356 params.service = snum;
4358 if (!lp_browseable(snum) || !lp_snum_ok(snum) ||
4359 !lp_print_ok(snum) ) {
4363 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4364 lp_servicename(snum), snum));
4366 if (!construct_printer_info_1(NULL, flags, ¤t_prt,
4371 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1,
4372 *returned +1)) == NULL) {
4373 DEBUG(2,("enum_all_printers_info_1: failed to enlarge "
4374 "printers buffer!\n"));
4378 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n",
4381 memcpy(&printers[*returned], ¤t_prt,
4382 sizeof(PRINTER_INFO_1));
4386 /* check the required size. */
4387 for (i=0; i<*returned; i++)
4388 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4390 if (*needed > offered) {
4391 result = WERR_INSUFFICIENT_BUFFER;
4395 if (!rpcbuf_alloc_size(buffer, *needed)) {
4396 result = WERR_NOMEM;
4400 /* fill the buffer with the structures */
4401 for (i=0; i<*returned; i++)
4402 smb_io_printer_info_1("", buffer, &printers[i], 0);
4407 SAFE_FREE(printers);
4409 if ( !W_ERROR_IS_OK(result) )
4415 /********************************************************************
4416 enum_all_printers_info_1_local.
4417 *********************************************************************/
4419 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4421 DEBUG(4,("enum_all_printers_info_1_local\n"));
4423 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4426 /********************************************************************
4427 enum_all_printers_info_1_name.
4428 *********************************************************************/
4430 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4434 DEBUG(4,("enum_all_printers_info_1_name\n"));
4436 if ((name[0] == '\\') && (name[1] == '\\'))
4439 if (is_myname_or_ipaddr(s)) {
4440 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4443 return WERR_INVALID_NAME;
4446 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4447 /********************************************************************
4448 enum_all_printers_info_1_remote.
4449 *********************************************************************/
4451 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4453 PRINTER_INFO_1 *printer;
4454 fstring printername;
4457 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4458 WERROR result = WERR_OK;
4460 /* JFM: currently it's more a place holder than anything else.
4461 * In the spooler world there is a notion of server registration.
4462 * the print servers are registered on the PDC (in the same domain)
4464 * We should have a TDB here. The registration is done thru an
4465 * undocumented RPC call.
4468 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4473 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4474 slprintf(desc, sizeof(desc)-1,"%s", name);
4475 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4477 init_unistr(&printer->description, desc);
4478 init_unistr(&printer->name, printername);
4479 init_unistr(&printer->comment, comment);
4480 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4482 /* check the required size. */
4483 *needed += spoolss_size_printer_info_1(printer);
4485 if (*needed > offered) {
4486 result = WERR_INSUFFICIENT_BUFFER;
4490 if (!rpcbuf_alloc_size(buffer, *needed)) {
4491 result = WERR_NOMEM;
4495 /* fill the buffer with the structures */
4496 smb_io_printer_info_1("", buffer, printer, 0);
4502 if ( !W_ERROR_IS_OK(result) )
4510 /********************************************************************
4511 enum_all_printers_info_1_network.
4512 *********************************************************************/
4514 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4518 DEBUG(4,("enum_all_printers_info_1_network\n"));
4520 /* If we respond to a enum_printers level 1 on our name with flags
4521 set to PRINTER_ENUM_REMOTE with a list of printers then these
4522 printers incorrectly appear in the APW browse list.
4523 Specifically the printers for the server appear at the workgroup
4524 level where all the other servers in the domain are
4525 listed. Windows responds to this call with a
4526 WERR_CAN_NOT_COMPLETE so we should do the same. */
4528 if (name[0] == '\\' && name[1] == '\\')
4531 if (is_myname_or_ipaddr(s))
4532 return WERR_CAN_NOT_COMPLETE;
4534 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4537 /********************************************************************
4538 * api_spoolss_enumprinters
4540 * called from api_spoolss_enumprinters (see this to understand)
4541 ********************************************************************/
4543 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4547 int n_services=lp_numservices();
4548 PRINTER_INFO_2 *printers=NULL;
4549 WERROR result = WERR_OK;
4553 for (snum=0; snum<n_services; snum++) {
4554 PRINTER_INFO_2 current_prt;
4555 struct share_params params;
4556 params.service = snum;
4557 if (!lp_browseable(snum) || !lp_snum_ok(snum) ||
4558 !lp_print_ok(snum) ) {
4561 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4562 lp_servicename(snum), snum));
4564 if (!construct_printer_info_2(NULL, ¤t_prt,
4568 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2,
4570 DEBUG(2,("enum_all_printers_info_2: failed to enlarge "
4571 "printers buffer!\n"));
4576 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n",
4579 memcpy(&printers[*returned], ¤t_prt,
4580 sizeof(PRINTER_INFO_2));
4584 /* check the required size. */
4585 for (i=0; i<*returned; i++)
4586 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4588 if (*needed > offered) {
4589 result = WERR_INSUFFICIENT_BUFFER;
4593 if (!rpcbuf_alloc_size(buffer, *needed)) {
4594 result = WERR_NOMEM;
4598 /* fill the buffer with the structures */
4599 for (i=0; i<*returned; i++)
4600 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4605 for (i=0; i<*returned; i++)
4606 free_devmode(printers[i].devmode);
4608 SAFE_FREE(printers);
4610 if ( !W_ERROR_IS_OK(result) )
4616 /********************************************************************
4617 * handle enumeration of printers at level 1
4618 ********************************************************************/
4620 static WERROR enumprinters_level1( uint32 flags, fstring name,
4621 RPC_BUFFER *buffer, uint32 offered,
4622 uint32 *needed, uint32 *returned)
4624 /* Not all the flags are equals */
4626 if (flags & PRINTER_ENUM_LOCAL)
4627 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4629 if (flags & PRINTER_ENUM_NAME)
4630 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4632 #if 0 /* JERRY - disabled for now */
4633 if (flags & PRINTER_ENUM_REMOTE)
4634 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4637 if (flags & PRINTER_ENUM_NETWORK)
4638 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4640 return WERR_OK; /* NT4sp5 does that */
4643 /********************************************************************
4644 * handle enumeration of printers at level 2
4645 ********************************************************************/
4647 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4648 RPC_BUFFER *buffer, uint32 offered,
4649 uint32 *needed, uint32 *returned)
4651 char *s = servername;
4653 if (flags & PRINTER_ENUM_LOCAL) {
4654 return enum_all_printers_info_2(buffer, offered, needed, returned);
4657 if (flags & PRINTER_ENUM_NAME) {
4658 if ((servername[0] == '\\') && (servername[1] == '\\'))
4660 if (is_myname_or_ipaddr(s))
4661 return enum_all_printers_info_2(buffer, offered, needed, returned);
4663 return WERR_INVALID_NAME;
4666 if (flags & PRINTER_ENUM_REMOTE)
4667 return WERR_UNKNOWN_LEVEL;
4672 /********************************************************************
4673 * handle enumeration of printers at level 5
4674 ********************************************************************/
4676 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4677 RPC_BUFFER *buffer, uint32 offered,
4678 uint32 *needed, uint32 *returned)
4680 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4684 /********************************************************************
4685 * api_spoolss_enumprinters
4687 * called from api_spoolss_enumprinters (see this to understand)
4688 ********************************************************************/
4690 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4692 uint32 flags = q_u->flags;
4693 UNISTR2 *servername = &q_u->servername;
4694 uint32 level = q_u->level;
4695 RPC_BUFFER *buffer = NULL;
4696 uint32 offered = q_u->offered;
4697 uint32 *needed = &r_u->needed;
4698 uint32 *returned = &r_u->returned;
4702 /* that's an [in out] buffer */
4704 if (!q_u->buffer && (offered!=0)) {
4705 return WERR_INVALID_PARAM;
4708 rpcbuf_move(q_u->buffer, &r_u->buffer);
4709 buffer = r_u->buffer;
4711 DEBUG(4,("_spoolss_enumprinters\n"));
4718 * flags==PRINTER_ENUM_NAME
4719 * if name=="" then enumerates all printers
4720 * if name!="" then enumerate the printer
4721 * flags==PRINTER_ENUM_REMOTE
4722 * name is NULL, enumerate printers
4723 * Level 2: name!="" enumerates printers, name can't be NULL
4724 * Level 3: doesn't exist
4725 * Level 4: does a local registry lookup
4726 * Level 5: same as Level 2
4729 unistr2_to_ascii(name, servername, sizeof(name)-1);
4734 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4736 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4738 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4743 return WERR_UNKNOWN_LEVEL;
4746 /****************************************************************************
4747 ****************************************************************************/
4749 static WERROR getprinter_level_0(Printer_entry *print_hnd,
4750 const struct share_params *params,
4751 RPC_BUFFER *buffer, uint32 offered,
4754 PRINTER_INFO_0 *printer=NULL;
4755 WERROR result = WERR_OK;
4757 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4760 construct_printer_info_0(print_hnd, printer, params);
4762 /* check the required size. */
4763 *needed += spoolss_size_printer_info_0(printer);
4765 if (*needed > offered) {
4766 result = WERR_INSUFFICIENT_BUFFER;
4770 if (!rpcbuf_alloc_size(buffer, *needed)) {
4771 result = WERR_NOMEM;
4775 /* fill the buffer with the structures */
4776 smb_io_printer_info_0("", buffer, printer, 0);
4786 /****************************************************************************
4787 ****************************************************************************/
4789 static WERROR getprinter_level_1(Printer_entry *print_hnd,
4790 const struct share_params *params,
4791 RPC_BUFFER *buffer, uint32 offered,
4794 PRINTER_INFO_1 *printer=NULL;
4795 WERROR result = WERR_OK;
4797 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4800 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer,
4803 /* check the required size. */
4804 *needed += spoolss_size_printer_info_1(printer);
4806 if (*needed > offered) {
4807 result = WERR_INSUFFICIENT_BUFFER;
4811 if (!rpcbuf_alloc_size(buffer, *needed)) {
4812 result = WERR_NOMEM;
4816 /* fill the buffer with the structures */
4817 smb_io_printer_info_1("", buffer, printer, 0);
4826 /****************************************************************************
4827 ****************************************************************************/
4829 static WERROR getprinter_level_2(Printer_entry *print_hnd,
4830 const struct share_params *params,
4831 RPC_BUFFER *buffer, uint32 offered,
4834 PRINTER_INFO_2 *printer=NULL;
4835 WERROR result = WERR_OK;
4837 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4840 construct_printer_info_2(print_hnd, printer, params);
4842 /* check the required size. */
4843 *needed += spoolss_size_printer_info_2(printer);
4845 if (*needed > offered) {
4846 result = WERR_INSUFFICIENT_BUFFER;
4850 if (!rpcbuf_alloc_size(buffer, *needed)) {
4851 result = WERR_NOMEM;
4855 /* fill the buffer with the structures */
4856 if (!smb_io_printer_info_2("", buffer, printer, 0))
4857 result = WERR_NOMEM;
4861 free_printer_info_2(printer);
4866 /****************************************************************************
4867 ****************************************************************************/
4869 static WERROR getprinter_level_3(Printer_entry *print_hnd,
4870 const struct share_params *params,
4871 RPC_BUFFER *buffer, uint32 offered,
4874 PRINTER_INFO_3 *printer=NULL;
4875 WERROR result = WERR_OK;
4877 if (!construct_printer_info_3(print_hnd, &printer, params))
4880 /* check the required size. */
4881 *needed += spoolss_size_printer_info_3(printer);
4883 if (*needed > offered) {
4884 result = WERR_INSUFFICIENT_BUFFER;
4888 if (!rpcbuf_alloc_size(buffer, *needed)) {
4889 result = WERR_NOMEM;
4893 /* fill the buffer with the structures */
4894 smb_io_printer_info_3("", buffer, printer, 0);
4898 free_printer_info_3(printer);
4903 /****************************************************************************
4904 ****************************************************************************/
4906 static WERROR getprinter_level_4(Printer_entry *print_hnd,
4907 const struct share_params *params,
4908 RPC_BUFFER *buffer, uint32 offered,
4911 PRINTER_INFO_4 *printer=NULL;
4912 WERROR result = WERR_OK;
4914 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4917 if (!construct_printer_info_4(print_hnd, printer, params)) {
4922 /* check the required size. */
4923 *needed += spoolss_size_printer_info_4(printer);
4925 if (*needed > offered) {
4926 result = WERR_INSUFFICIENT_BUFFER;
4930 if (!rpcbuf_alloc_size(buffer, *needed)) {
4931 result = WERR_NOMEM;
4935 /* fill the buffer with the structures */
4936 smb_io_printer_info_4("", buffer, printer, 0);
4940 free_printer_info_4(printer);
4945 /****************************************************************************
4946 ****************************************************************************/
4948 static WERROR getprinter_level_5(Printer_entry *print_hnd,
4949 const struct share_params *params,
4950 RPC_BUFFER *buffer, uint32 offered,
4953 PRINTER_INFO_5 *printer=NULL;
4954 WERROR result = WERR_OK;
4956 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4959 if (!construct_printer_info_5(print_hnd, printer, params)) {
4960 free_printer_info_5(printer);
4964 /* check the required size. */
4965 *needed += spoolss_size_printer_info_5(printer);
4967 if (*needed > offered) {
4968 result = WERR_INSUFFICIENT_BUFFER;
4972 if (!rpcbuf_alloc_size(buffer, *needed)) {
4973 result = WERR_NOMEM;
4977 /* fill the buffer with the structures */
4978 smb_io_printer_info_5("", buffer, printer, 0);
4982 free_printer_info_5(printer);
4987 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4988 const struct share_params *params,
4989 RPC_BUFFER *buffer, uint32 offered,
4992 PRINTER_INFO_6 *printer;
4993 WERROR result = WERR_OK;
4995 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4999 if (!construct_printer_info_6(print_hnd, printer, params)) {
5000 free_printer_info_6(printer);
5004 /* check the required size. */
5005 *needed += spoolss_size_printer_info_6(printer);
5007 if (*needed > offered) {
5008 result = WERR_INSUFFICIENT_BUFFER;
5012 if (!rpcbuf_alloc_size(buffer, *needed)) {
5013 result = WERR_NOMEM;
5017 /* fill the buffer with the structures */
5018 smb_io_printer_info_6("", buffer, printer, 0);
5022 free_printer_info_6(printer);
5027 static WERROR getprinter_level_7(Printer_entry *print_hnd,
5028 const struct share_params *params,
5029 RPC_BUFFER *buffer, uint32 offered,
5032 PRINTER_INFO_7 *printer=NULL;
5033 WERROR result = WERR_OK;
5035 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5038 if (!construct_printer_info_7(print_hnd, printer, params))
5041 /* check the required size. */
5042 *needed += spoolss_size_printer_info_7(printer);
5044 if (*needed > offered) {
5045 result = WERR_INSUFFICIENT_BUFFER;
5049 if (!rpcbuf_alloc_size(buffer, *needed)) {
5050 result = WERR_NOMEM;
5055 /* fill the buffer with the structures */
5056 smb_io_printer_info_7("", buffer, printer, 0);
5060 free_printer_info_7(printer);
5065 /****************************************************************************
5066 ****************************************************************************/
5068 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5070 POLICY_HND *handle = &q_u->handle;
5071 uint32 level = q_u->level;
5072 RPC_BUFFER *buffer = NULL;
5073 uint32 offered = q_u->offered;
5074 uint32 *needed = &r_u->needed;
5075 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5076 struct share_params *params;
5080 /* that's an [in out] buffer */
5082 if (!q_u->buffer && (offered!=0)) {
5083 return WERR_INVALID_PARAM;
5086 rpcbuf_move(q_u->buffer, &r_u->buffer);
5087 buffer = r_u->buffer;
5091 if (!get_printer_snum(p, handle, &snum, ¶ms))
5096 return getprinter_level_0(Printer, params, buffer, offered,
5099 return getprinter_level_1(Printer, params, buffer, offered,
5102 return getprinter_level_2(Printer, params, buffer, offered,
5105 return getprinter_level_3(Printer, params, buffer, offered,
5108 return getprinter_level_4(Printer, params, buffer, offered,
5111 return getprinter_level_5(Printer, params, buffer, offered,
5114 return getprinter_level_6(Printer, params, buffer, offered,
5117 return getprinter_level_7(Printer, params, buffer, offered,
5120 return WERR_UNKNOWN_LEVEL;
5123 /********************************************************************
5124 * fill a DRIVER_INFO_1 struct
5125 ********************************************************************/
5127 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5129 init_unistr( &info->name, driver.info_3->name);
5132 /********************************************************************
5133 * construct_printer_driver_info_1
5134 ********************************************************************/
5136 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5138 NT_PRINTER_INFO_LEVEL *printer = NULL;
5139 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5141 ZERO_STRUCT(driver);
5143 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5144 return WERR_INVALID_PRINTER_NAME;
5146 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5147 free_a_printer(&printer, 2);
5148 return WERR_UNKNOWN_PRINTER_DRIVER;
5151 fill_printer_driver_info_1(info, driver, servername, architecture);
5153 free_a_printer(&printer,2);
5158 /********************************************************************
5159 * construct_printer_driver_info_2
5160 * fill a printer_info_2 struct
5161 ********************************************************************/
5163 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5167 info->version=driver.info_3->cversion;
5169 init_unistr( &info->name, driver.info_3->name );
5170 init_unistr( &info->architecture, driver.info_3->environment );
5173 if (strlen(driver.info_3->driverpath)) {
5174 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5175 init_unistr( &info->driverpath, temp );
5177 init_unistr( &info->driverpath, "" );
5179 if (strlen(driver.info_3->datafile)) {
5180 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5181 init_unistr( &info->datafile, temp );
5183 init_unistr( &info->datafile, "" );
5185 if (strlen(driver.info_3->configfile)) {
5186 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5187 init_unistr( &info->configfile, temp );
5189 init_unistr( &info->configfile, "" );
5192 /********************************************************************
5193 * construct_printer_driver_info_2
5194 * fill a printer_info_2 struct
5195 ********************************************************************/
5197 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5199 NT_PRINTER_INFO_LEVEL *printer = NULL;
5200 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5202 ZERO_STRUCT(printer);
5203 ZERO_STRUCT(driver);
5205 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5206 return WERR_INVALID_PRINTER_NAME;
5208 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5209 free_a_printer(&printer, 2);
5210 return WERR_UNKNOWN_PRINTER_DRIVER;
5213 fill_printer_driver_info_2(info, driver, servername);
5215 free_a_printer(&printer,2);
5220 /********************************************************************
5221 * copy a strings array and convert to UNICODE
5223 * convert an array of ascii string to a UNICODE string
5224 ********************************************************************/
5226 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5233 DEBUG(6,("init_unistr_array\n"));
5244 v = ""; /* hack to handle null lists */
5247 /* hack to allow this to be used in places other than when generating
5248 the list of dependent files */
5251 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5255 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5257 /* add one extra unit16 for the second terminating NULL */
5259 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5260 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5267 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5272 /* special case for ""; we need to add both NULL's here */
5274 (*uni_array)[j++]=0x0000;
5275 (*uni_array)[j]=0x0000;
5278 DEBUGADD(6,("last one:done\n"));
5280 /* return size of array in uint16's */
5285 /********************************************************************
5286 * construct_printer_info_3
5287 * fill a printer_info_3 struct
5288 ********************************************************************/
5290 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5296 info->version=driver.info_3->cversion;
5298 init_unistr( &info->name, driver.info_3->name );
5299 init_unistr( &info->architecture, driver.info_3->environment );
5301 if (strlen(driver.info_3->driverpath)) {
5302 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5303 init_unistr( &info->driverpath, temp );
5305 init_unistr( &info->driverpath, "" );
5307 if (strlen(driver.info_3->datafile)) {
5308 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5309 init_unistr( &info->datafile, temp );
5311 init_unistr( &info->datafile, "" );
5313 if (strlen(driver.info_3->configfile)) {
5314 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5315 init_unistr( &info->configfile, temp );
5317 init_unistr( &info->configfile, "" );
5319 if (strlen(driver.info_3->helpfile)) {
5320 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5321 init_unistr( &info->helpfile, temp );
5323 init_unistr( &info->helpfile, "" );
5325 init_unistr( &info->monitorname, driver.info_3->monitorname );
5326 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5328 info->dependentfiles=NULL;
5329 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5332 /********************************************************************
5333 * construct_printer_info_3
5334 * fill a printer_info_3 struct
5335 ********************************************************************/
5337 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5339 NT_PRINTER_INFO_LEVEL *printer = NULL;
5340 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5342 ZERO_STRUCT(driver);
5344 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5345 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5346 if (!W_ERROR_IS_OK(status))
5347 return WERR_INVALID_PRINTER_NAME;
5349 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5350 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5355 * I put this code in during testing. Helpful when commenting out the
5356 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5357 * as win2k always queries the driver using an infor level of 6.
5358 * I've left it in (but ifdef'd out) because I'll probably
5359 * use it in experimentation again in the future. --jerry 22/01/2002
5362 if (!W_ERROR_IS_OK(status)) {
5364 * Is this a W2k client ?
5367 /* Yes - try again with a WinNT driver. */
5369 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5370 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5374 if (!W_ERROR_IS_OK(status)) {
5375 free_a_printer(&printer,2);
5376 return WERR_UNKNOWN_PRINTER_DRIVER;
5384 fill_printer_driver_info_3(info, driver, servername);
5386 free_a_printer(&printer,2);
5391 /********************************************************************
5392 * construct_printer_info_6
5393 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5394 ********************************************************************/
5396 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5402 memset(&nullstr, '\0', sizeof(fstring));
5404 info->version=driver.info_3->cversion;
5406 init_unistr( &info->name, driver.info_3->name );
5407 init_unistr( &info->architecture, driver.info_3->environment );
5409 if (strlen(driver.info_3->driverpath)) {
5410 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5411 init_unistr( &info->driverpath, temp );
5413 init_unistr( &info->driverpath, "" );
5415 if (strlen(driver.info_3->datafile)) {
5416 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5417 init_unistr( &info->datafile, temp );
5419 init_unistr( &info->datafile, "" );
5421 if (strlen(driver.info_3->configfile)) {
5422 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5423 init_unistr( &info->configfile, temp );
5425 init_unistr( &info->configfile, "" );
5427 if (strlen(driver.info_3->helpfile)) {
5428 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5429 init_unistr( &info->helpfile, temp );
5431 init_unistr( &info->helpfile, "" );
5433 init_unistr( &info->monitorname, driver.info_3->monitorname );
5434 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5436 info->dependentfiles = NULL;
5437 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5439 info->previousdrivernames=NULL;
5440 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5442 info->driver_date=0;
5445 info->driver_version_low=0;
5446 info->driver_version_high=0;
5448 init_unistr( &info->mfgname, "");
5449 init_unistr( &info->oem_url, "");
5450 init_unistr( &info->hardware_id, "");
5451 init_unistr( &info->provider, "");
5454 /********************************************************************
5455 * construct_printer_info_6
5456 * fill a printer_info_6 struct
5457 ********************************************************************/
5459 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5460 fstring servername, fstring architecture, uint32 version)
5462 NT_PRINTER_INFO_LEVEL *printer = NULL;
5463 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5466 ZERO_STRUCT(driver);
5468 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5470 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5472 if (!W_ERROR_IS_OK(status))
5473 return WERR_INVALID_PRINTER_NAME;
5475 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5477 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5479 if (!W_ERROR_IS_OK(status))
5482 * Is this a W2k client ?
5486 free_a_printer(&printer,2);
5487 return WERR_UNKNOWN_PRINTER_DRIVER;
5490 /* Yes - try again with a WinNT driver. */
5492 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5493 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5494 if (!W_ERROR_IS_OK(status)) {
5495 free_a_printer(&printer,2);
5496 return WERR_UNKNOWN_PRINTER_DRIVER;
5500 fill_printer_driver_info_6(info, driver, servername);
5502 free_a_printer(&printer,2);
5503 free_a_printer_driver(driver, 3);
5508 /****************************************************************************
5509 ****************************************************************************/
5511 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5513 SAFE_FREE(info->dependentfiles);
5516 /****************************************************************************
5517 ****************************************************************************/
5519 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5521 SAFE_FREE(info->dependentfiles);
5524 /****************************************************************************
5525 ****************************************************************************/
5527 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5529 DRIVER_INFO_1 *info=NULL;
5532 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5535 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5536 if (!W_ERROR_IS_OK(result))
5539 /* check the required size. */
5540 *needed += spoolss_size_printer_driver_info_1(info);
5542 if (*needed > offered) {
5543 result = WERR_INSUFFICIENT_BUFFER;
5547 if (!rpcbuf_alloc_size(buffer, *needed)) {
5548 result = WERR_NOMEM;
5552 /* fill the buffer with the structures */
5553 smb_io_printer_driver_info_1("", buffer, info, 0);
5562 /****************************************************************************
5563 ****************************************************************************/
5565 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5567 DRIVER_INFO_2 *info=NULL;
5570 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5573 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5574 if (!W_ERROR_IS_OK(result))
5577 /* check the required size. */
5578 *needed += spoolss_size_printer_driver_info_2(info);
5580 if (*needed > offered) {
5581 result = WERR_INSUFFICIENT_BUFFER;
5585 if (!rpcbuf_alloc_size(buffer, *needed)) {
5586 result = WERR_NOMEM;
5590 /* fill the buffer with the structures */
5591 smb_io_printer_driver_info_2("", buffer, info, 0);
5600 /****************************************************************************
5601 ****************************************************************************/
5603 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5610 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5611 if (!W_ERROR_IS_OK(result))
5614 /* check the required size. */
5615 *needed += spoolss_size_printer_driver_info_3(&info);
5617 if (*needed > offered) {
5618 result = WERR_INSUFFICIENT_BUFFER;
5622 if (!rpcbuf_alloc_size(buffer, *needed)) {
5623 result = WERR_NOMEM;
5627 /* fill the buffer with the structures */
5628 smb_io_printer_driver_info_3("", buffer, &info, 0);
5631 free_printer_driver_info_3(&info);
5636 /****************************************************************************
5637 ****************************************************************************/
5639 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5646 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5647 if (!W_ERROR_IS_OK(result))
5650 /* check the required size. */
5651 *needed += spoolss_size_printer_driver_info_6(&info);
5653 if (*needed > offered) {
5654 result = WERR_INSUFFICIENT_BUFFER;
5658 if (!rpcbuf_alloc_size(buffer, *needed)) {
5659 result = WERR_NOMEM;
5663 /* fill the buffer with the structures */
5664 smb_io_printer_driver_info_6("", buffer, &info, 0);
5667 free_printer_driver_info_6(&info);
5672 /****************************************************************************
5673 ****************************************************************************/
5675 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5677 POLICY_HND *handle = &q_u->handle;
5678 UNISTR2 *uni_arch = &q_u->architecture;
5679 uint32 level = q_u->level;
5680 uint32 clientmajorversion = q_u->clientmajorversion;
5681 RPC_BUFFER *buffer = NULL;
5682 uint32 offered = q_u->offered;
5683 uint32 *needed = &r_u->needed;
5684 uint32 *servermajorversion = &r_u->servermajorversion;
5685 uint32 *serverminorversion = &r_u->serverminorversion;
5686 Printer_entry *printer;
5689 fstring architecture;
5692 /* that's an [in out] buffer */
5694 if (!q_u->buffer && (offered!=0)) {
5695 return WERR_INVALID_PARAM;
5698 rpcbuf_move(q_u->buffer, &r_u->buffer);
5699 buffer = r_u->buffer;
5701 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5703 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5704 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5705 return WERR_INVALID_PRINTER_NAME;
5709 *servermajorversion = 0;
5710 *serverminorversion = 0;
5712 fstrcpy(servername, get_server_name( printer ));
5713 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5715 if (!get_printer_snum(p, handle, &snum, NULL))
5720 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5722 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5724 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5726 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5729 /* apparently this call is the equivalent of
5730 EnumPrinterDataEx() for the DsDriver key */
5735 return WERR_UNKNOWN_LEVEL;
5738 /****************************************************************************
5739 ****************************************************************************/
5741 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5743 POLICY_HND *handle = &q_u->handle;
5745 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5748 DEBUG(3,("Error in startpageprinter printer handle\n"));
5752 Printer->page_started=True;
5756 /****************************************************************************
5757 ****************************************************************************/
5759 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5761 POLICY_HND *handle = &q_u->handle;
5764 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5767 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5771 if (!get_printer_snum(p, handle, &snum, NULL))
5774 Printer->page_started=False;
5775 print_job_endpage(snum, Printer->jobid);
5780 /********************************************************************
5781 * api_spoolss_getprinter
5782 * called from the spoolss dispatcher
5784 ********************************************************************/
5786 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5788 POLICY_HND *handle = &q_u->handle;
5789 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5790 uint32 *jobid = &r_u->jobid;
5792 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5796 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5799 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5804 * a nice thing with NT is it doesn't listen to what you tell it.
5805 * when asked to send _only_ RAW datas, it tries to send datas
5808 * So I add checks like in NT Server ...
5811 if (info_1->p_datatype != 0) {
5812 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5813 if (strcmp(datatype, "RAW") != 0) {
5815 return WERR_INVALID_DATATYPE;
5819 /* get the share number of the printer */
5820 if (!get_printer_snum(p, handle, &snum, NULL)) {
5824 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5826 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5828 /* An error occured in print_job_start() so return an appropriate
5831 if (Printer->jobid == -1) {
5832 return map_werror_from_unix(errno);
5835 Printer->document_started=True;
5836 (*jobid) = Printer->jobid;
5841 /********************************************************************
5842 * api_spoolss_getprinter
5843 * called from the spoolss dispatcher
5845 ********************************************************************/
5847 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5849 POLICY_HND *handle = &q_u->handle;
5851 return _spoolss_enddocprinter_internal(p, handle);
5854 /****************************************************************************
5855 ****************************************************************************/
5857 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5859 POLICY_HND *handle = &q_u->handle;
5860 uint32 buffer_size = q_u->buffer_size;
5861 uint8 *buffer = q_u->buffer;
5862 uint32 *buffer_written = &q_u->buffer_size2;
5864 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5867 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5868 r_u->buffer_written = q_u->buffer_size2;
5872 if (!get_printer_snum(p, handle, &snum, NULL))
5875 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5876 (SMB_OFF_T)-1, (size_t)buffer_size);
5877 if (*buffer_written == (uint32)-1) {
5878 r_u->buffer_written = 0;
5879 if (errno == ENOSPC)
5880 return WERR_NO_SPOOL_SPACE;
5882 return WERR_ACCESS_DENIED;
5885 r_u->buffer_written = q_u->buffer_size2;
5890 /********************************************************************
5891 * api_spoolss_getprinter
5892 * called from the spoolss dispatcher
5894 ********************************************************************/
5896 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5900 WERROR errcode = WERR_BADFUNC;
5901 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5904 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5908 if (!get_printer_snum(p, handle, &snum, NULL))
5912 case PRINTER_CONTROL_PAUSE:
5913 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5917 case PRINTER_CONTROL_RESUME:
5918 case PRINTER_CONTROL_UNPAUSE:
5919 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5923 case PRINTER_CONTROL_PURGE:
5924 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5929 return WERR_UNKNOWN_LEVEL;
5935 /********************************************************************
5936 * api_spoolss_abortprinter
5937 * From MSDN: "Deletes printer's spool file if printer is configured
5939 ********************************************************************/
5941 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5943 POLICY_HND *handle = &q_u->handle;
5944 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5946 WERROR errcode = WERR_OK;
5949 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5953 if (!get_printer_snum(p, handle, &snum, NULL))
5956 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5961 /********************************************************************
5962 * called by spoolss_api_setprinter
5963 * when updating a printer description
5964 ********************************************************************/
5966 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5967 const SPOOL_PRINTER_INFO_LEVEL *info,
5968 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5970 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5974 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5976 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5977 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5978 OUR_HANDLE(handle)));
5980 result = WERR_BADFID;
5984 /* Check the user has permissions to change the security
5985 descriptor. By experimentation with two NT machines, the user
5986 requires Full Access to the printer to change security
5989 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5990 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5991 result = WERR_ACCESS_DENIED;
5995 /* NT seems to like setting the security descriptor even though
5996 nothing may have actually changed. */
5998 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
6000 if (DEBUGLEVEL >= 10) {
6004 the_acl = old_secdesc_ctr->sd->dacl;
6005 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6006 PRINTERNAME(snum), the_acl->num_aces));
6008 for (i = 0; i < the_acl->num_aces; i++) {
6011 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6013 DEBUG(10, ("%s 0x%08x\n", sid_str,
6014 the_acl->aces[i].access_mask));
6017 the_acl = secdesc_ctr->sd->dacl;
6020 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6021 PRINTERNAME(snum), the_acl->num_aces));
6023 for (i = 0; i < the_acl->num_aces; i++) {
6026 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6028 DEBUG(10, ("%s 0x%08x\n", sid_str,
6029 the_acl->aces[i].access_mask));
6032 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6036 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6037 if (!new_secdesc_ctr) {
6038 result = WERR_NOMEM;
6042 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6047 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6054 /********************************************************************
6055 Canonicalize printer info from a client
6057 ATTN: It does not matter what we set the servername to hear
6058 since we do the necessary work in get_a_printer() to set it to
6059 the correct value based on what the client sent in the
6060 _spoolss_open_printer_ex().
6061 ********************************************************************/
6063 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6065 fstring printername;
6068 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6069 "portname=%s drivername=%s comment=%s location=%s\n",
6070 info->servername, info->printername, info->sharename,
6071 info->portname, info->drivername, info->comment, info->location));
6073 /* we force some elements to "correct" values */
6074 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6075 fstrcpy(info->sharename, lp_servicename(snum));
6077 /* check to see if we allow printername != sharename */
6079 if ( lp_force_printername(snum) ) {
6080 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6081 global_myname(), info->sharename );
6084 /* make sure printername is in \\server\printername format */
6086 fstrcpy( printername, info->printername );
6088 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6089 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6093 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6094 global_myname(), p );
6097 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6098 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6105 /****************************************************************************
6106 ****************************************************************************/
6108 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
6110 char *cmd = lp_addport_cmd();
6114 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6115 BOOL is_print_op = False;
6118 return WERR_ACCESS_DENIED;
6121 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
6124 is_print_op = user_has_privileges( token, &se_printop );
6126 DEBUG(10,("Running [%s]\n", command));
6128 /********* BEGIN SePrintOperatorPrivilege **********/
6133 ret = smbrun(command, &fd);
6138 /********* END SePrintOperatorPrivilege **********/
6140 DEBUGADD(10,("returned [%d]\n", ret));
6145 return WERR_ACCESS_DENIED;
6151 /****************************************************************************
6152 ****************************************************************************/
6154 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6156 char *cmd = lp_addprinter_cmd();
6162 fstring remote_machine = "%m";
6163 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6164 BOOL is_print_op = False;
6166 standard_sub_basic(current_user_info.smb_name,
6167 current_user_info.domain,
6168 remote_machine,sizeof(remote_machine));
6170 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6171 cmd, printer->info_2->printername, printer->info_2->sharename,
6172 printer->info_2->portname, printer->info_2->drivername,
6173 printer->info_2->location, printer->info_2->comment, remote_machine);
6176 is_print_op = user_has_privileges( token, &se_printop );
6178 DEBUG(10,("Running [%s]\n", command));
6180 /********* BEGIN SePrintOperatorPrivilege **********/
6185 if ( (ret = smbrun(command, &fd)) == 0 ) {
6186 /* Tell everyone we updated smb.conf. */
6187 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6193 /********* END SePrintOperatorPrivilege **********/
6195 DEBUGADD(10,("returned [%d]\n", ret));
6203 /* reload our services immediately */
6204 reload_services( False );
6207 /* Get lines and convert them back to dos-codepage */
6208 qlines = fd_lines_load(fd, &numlines, 0);
6209 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6212 /* Set the portname to what the script says the portname should be. */
6213 /* but don't require anything to be return from the script exit a good error code */
6216 /* Set the portname to what the script says the portname should be. */
6217 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6218 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6221 file_lines_free(qlines);
6226 /********************************************************************
6227 * Called by spoolss_api_setprinter
6228 * when updating a printer description.
6229 ********************************************************************/
6231 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6232 const SPOOL_PRINTER_INFO_LEVEL *info,
6233 DEVICEMODE *devmode)
6236 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6237 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6242 DEBUG(8,("update_printer\n"));
6247 result = WERR_BADFID;
6251 if (!get_printer_snum(p, handle, &snum, NULL)) {
6252 result = WERR_BADFID;
6256 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6257 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6258 result = WERR_BADFID;
6262 DEBUGADD(8,("Converting info_2 struct\n"));
6265 * convert_printer_info converts the incoming
6266 * info from the client and overwrites the info
6267 * just read from the tdb in the pointer 'printer'.
6270 if (!convert_printer_info(info, printer, level)) {
6271 result = WERR_NOMEM;
6276 /* we have a valid devmode
6277 convert it and link it*/
6279 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6280 if (!convert_devicemode(printer->info_2->printername, devmode,
6281 &printer->info_2->devmode)) {
6282 result = WERR_NOMEM;
6287 /* Do sanity check on the requested changes for Samba */
6289 if (!check_printer_ok(printer->info_2, snum)) {
6290 result = WERR_INVALID_PARAM;
6294 /* FIXME!!! If the driver has changed we really should verify that
6295 it is installed before doing much else --jerry */
6297 /* Check calling user has permission to update printer description */
6299 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6300 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6301 result = WERR_ACCESS_DENIED;
6305 /* Call addprinter hook */
6306 /* Check changes to see if this is really needed */
6308 if ( *lp_addprinter_cmd()
6309 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6310 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6311 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6312 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6314 /* add_printer_hook() will call reload_services() */
6316 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6317 result = WERR_ACCESS_DENIED;
6323 * When a *new* driver is bound to a printer, the drivername is used to
6324 * lookup previously saved driver initialization info, which is then
6325 * bound to the printer, simulating what happens in the Windows arch.
6327 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6329 if (!set_driver_init(printer, 2))
6331 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6332 printer->info_2->drivername));
6335 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6336 printer->info_2->drivername));
6338 notify_printer_driver(snum, printer->info_2->drivername);
6342 * flag which changes actually occured. This is a small subset of
6343 * all the possible changes. We also have to update things in the
6347 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6348 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6349 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6350 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6352 notify_printer_comment(snum, printer->info_2->comment);
6355 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6356 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6357 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6358 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6360 notify_printer_sharename(snum, printer->info_2->sharename);
6363 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6366 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6369 pname = printer->info_2->printername;
6372 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6373 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6374 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6376 notify_printer_printername( snum, pname );
6379 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6380 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6381 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6382 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6384 notify_printer_port(snum, printer->info_2->portname);
6387 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6388 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6389 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6390 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6392 notify_printer_location(snum, printer->info_2->location);
6395 /* here we need to update some more DsSpooler keys */
6396 /* uNCName, serverName, shortServerName */
6398 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6399 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6400 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6401 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6402 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6404 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6405 global_myname(), printer->info_2->sharename );
6406 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6407 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6408 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6410 /* Update printer info */
6411 result = mod_a_printer(printer, 2);
6414 free_a_printer(&printer, 2);
6415 free_a_printer(&old_printer, 2);
6421 /****************************************************************************
6422 ****************************************************************************/
6423 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6424 const SPOOL_PRINTER_INFO_LEVEL *info)
6427 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6429 Printer_entry *Printer;
6431 if ( lp_security() != SEC_ADS ) {
6432 return WERR_UNKNOWN_LEVEL;
6435 Printer = find_printer_index_by_hnd(p, handle);
6437 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6442 if (!get_printer_snum(p, handle, &snum, NULL))
6445 nt_printer_publish(Printer, snum, info7->action);
6449 return WERR_UNKNOWN_LEVEL;
6452 /****************************************************************************
6453 ****************************************************************************/
6455 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6457 POLICY_HND *handle = &q_u->handle;
6458 uint32 level = q_u->level;
6459 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6460 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6461 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6462 uint32 command = q_u->command;
6465 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6468 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6472 /* check the level */
6475 return control_printer(handle, command, p);
6477 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6478 if (!W_ERROR_IS_OK(result))
6481 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6484 return update_printer_sec(handle, level, info, p,
6487 return publish_or_unpublish_printer(p, handle, info);
6489 return WERR_UNKNOWN_LEVEL;
6493 /****************************************************************************
6494 ****************************************************************************/
6496 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6498 POLICY_HND *handle = &q_u->handle;
6499 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6502 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6506 if (Printer->notify.client_connected==True) {
6509 if ( Printer->printer_type == SPLHND_SERVER)
6511 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6512 !get_printer_snum(p, handle, &snum, NULL) )
6515 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6518 Printer->notify.flags=0;
6519 Printer->notify.options=0;
6520 Printer->notify.localmachine[0]='\0';
6521 Printer->notify.printerlocal=0;
6522 if (Printer->notify.option)
6523 free_spool_notify_option(&Printer->notify.option);
6524 Printer->notify.client_connected=False;
6529 /****************************************************************************
6530 ****************************************************************************/
6532 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6534 /* that's an [in out] buffer */
6536 if (!q_u->buffer && (q_u->offered!=0)) {
6537 return WERR_INVALID_PARAM;
6540 rpcbuf_move(q_u->buffer, &r_u->buffer);
6543 return WERR_INVALID_PARAM; /* this is what a NT server
6544 returns for AddJob. AddJob
6545 must fail on non-local
6549 /****************************************************************************
6550 ****************************************************************************/
6552 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6553 int position, int snum,
6554 const NT_PRINTER_INFO_LEVEL *ntprinter)
6558 t=gmtime(&queue->time);
6560 job_info->jobid=queue->job;
6561 init_unistr(&job_info->printername, lp_servicename(snum));
6562 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6563 init_unistr(&job_info->username, queue->fs_user);
6564 init_unistr(&job_info->document, queue->fs_file);
6565 init_unistr(&job_info->datatype, "RAW");
6566 init_unistr(&job_info->text_status, "");
6567 job_info->status=nt_printj_status(queue->status);
6568 job_info->priority=queue->priority;
6569 job_info->position=position;
6570 job_info->totalpages=queue->page_count;
6571 job_info->pagesprinted=0;
6573 make_systemtime(&job_info->submitted, t);
6576 /****************************************************************************
6577 ****************************************************************************/
6579 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6580 int position, int snum,
6581 const NT_PRINTER_INFO_LEVEL *ntprinter,
6582 DEVICEMODE *devmode)
6586 t=gmtime(&queue->time);
6588 job_info->jobid=queue->job;
6590 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6592 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6593 init_unistr(&job_info->username, queue->fs_user);
6594 init_unistr(&job_info->document, queue->fs_file);
6595 init_unistr(&job_info->notifyname, queue->fs_user);
6596 init_unistr(&job_info->datatype, "RAW");
6597 init_unistr(&job_info->printprocessor, "winprint");
6598 init_unistr(&job_info->parameters, "");
6599 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6600 init_unistr(&job_info->text_status, "");
6602 /* and here the security descriptor */
6604 job_info->status=nt_printj_status(queue->status);
6605 job_info->priority=queue->priority;
6606 job_info->position=position;
6607 job_info->starttime=0;
6608 job_info->untiltime=0;
6609 job_info->totalpages=queue->page_count;
6610 job_info->size=queue->size;
6611 make_systemtime(&(job_info->submitted), t);
6612 job_info->timeelapsed=0;
6613 job_info->pagesprinted=0;
6615 job_info->devmode = devmode;
6620 /****************************************************************************
6621 Enumjobs at level 1.
6622 ****************************************************************************/
6624 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6625 const NT_PRINTER_INFO_LEVEL *ntprinter,
6626 RPC_BUFFER *buffer, uint32 offered,
6627 uint32 *needed, uint32 *returned)
6631 WERROR result = WERR_OK;
6633 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6639 for (i=0; i<*returned; i++)
6640 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6642 /* check the required size. */
6643 for (i=0; i<*returned; i++)
6644 (*needed) += spoolss_size_job_info_1(&info[i]);
6646 if (*needed > offered) {
6647 result = WERR_INSUFFICIENT_BUFFER;
6651 if (!rpcbuf_alloc_size(buffer, *needed)) {
6652 result = WERR_NOMEM;
6656 /* fill the buffer with the structures */
6657 for (i=0; i<*returned; i++)
6658 smb_io_job_info_1("", buffer, &info[i], 0);
6664 if ( !W_ERROR_IS_OK(result) )
6670 /****************************************************************************
6671 Enumjobs at level 2.
6672 ****************************************************************************/
6674 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6675 const NT_PRINTER_INFO_LEVEL *ntprinter,
6676 RPC_BUFFER *buffer, uint32 offered,
6677 uint32 *needed, uint32 *returned)
6679 JOB_INFO_2 *info = NULL;
6681 WERROR result = WERR_OK;
6682 DEVICEMODE *devmode = NULL;
6684 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6689 /* this should not be a failure condition if the devmode is NULL */
6691 devmode = construct_dev_mode(lp_const_servicename(snum));
6693 for (i=0; i<*returned; i++)
6694 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6696 /* check the required size. */
6697 for (i=0; i<*returned; i++)
6698 (*needed) += spoolss_size_job_info_2(&info[i]);
6700 if (*needed > offered) {
6701 result = WERR_INSUFFICIENT_BUFFER;
6705 if (!rpcbuf_alloc_size(buffer, *needed)) {
6706 result = WERR_NOMEM;
6710 /* fill the buffer with the structures */
6711 for (i=0; i<*returned; i++)
6712 smb_io_job_info_2("", buffer, &info[i], 0);
6715 free_devmode(devmode);
6718 if ( !W_ERROR_IS_OK(result) )
6725 /****************************************************************************
6727 ****************************************************************************/
6729 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6731 POLICY_HND *handle = &q_u->handle;
6732 uint32 level = q_u->level;
6733 RPC_BUFFER *buffer = NULL;
6734 uint32 offered = q_u->offered;
6735 uint32 *needed = &r_u->needed;
6736 uint32 *returned = &r_u->returned;
6738 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6740 print_status_struct prt_status;
6741 print_queue_struct *queue=NULL;
6743 /* that's an [in out] buffer */
6745 if (!q_u->buffer && (offered!=0)) {
6746 return WERR_INVALID_PARAM;
6749 rpcbuf_move(q_u->buffer, &r_u->buffer);
6750 buffer = r_u->buffer;
6752 DEBUG(4,("_spoolss_enumjobs\n"));
6757 /* lookup the printer snum and tdb entry */
6759 if (!get_printer_snum(p, handle, &snum, NULL))
6762 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6763 if ( !W_ERROR_IS_OK(wret) )
6766 *returned = print_queue_status(snum, &queue, &prt_status);
6767 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6769 if (*returned == 0) {
6771 free_a_printer(&ntprinter, 2);
6777 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6780 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6784 wret = WERR_UNKNOWN_LEVEL;
6789 free_a_printer( &ntprinter, 2 );
6793 /****************************************************************************
6794 ****************************************************************************/
6796 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6801 /****************************************************************************
6802 ****************************************************************************/
6804 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6806 POLICY_HND *handle = &q_u->handle;
6807 uint32 jobid = q_u->jobid;
6808 uint32 command = q_u->command;
6811 WERROR errcode = WERR_BADFUNC;
6813 if (!get_printer_snum(p, handle, &snum, NULL)) {
6817 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6818 return WERR_INVALID_PRINTER_NAME;
6822 case JOB_CONTROL_CANCEL:
6823 case JOB_CONTROL_DELETE:
6824 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6828 case JOB_CONTROL_PAUSE:
6829 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6833 case JOB_CONTROL_RESTART:
6834 case JOB_CONTROL_RESUME:
6835 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6840 return WERR_UNKNOWN_LEVEL;
6846 /****************************************************************************
6847 Enumerates all printer drivers at level 1.
6848 ****************************************************************************/
6850 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6855 fstring *list = NULL;
6856 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6857 DRIVER_INFO_1 *driver_info_1=NULL;
6858 WERROR result = WERR_OK;
6862 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6864 ndrivers=get_ntdrivers(&list, architecture, version);
6865 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6867 if(ndrivers == -1) {
6868 SAFE_FREE(driver_info_1);
6873 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6874 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6880 for (i=0; i<ndrivers; i++) {
6882 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6883 ZERO_STRUCT(driver);
6884 status = get_a_printer_driver(&driver, 3, list[i],
6885 architecture, version);
6886 if (!W_ERROR_IS_OK(status)) {
6888 SAFE_FREE(driver_info_1);
6891 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6892 free_a_printer_driver(driver, 3);
6895 *returned+=ndrivers;
6899 /* check the required size. */
6900 for (i=0; i<*returned; i++) {
6901 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6902 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6905 if (*needed > offered) {
6906 result = WERR_INSUFFICIENT_BUFFER;
6910 if (!rpcbuf_alloc_size(buffer, *needed)) {
6911 result = WERR_NOMEM;
6915 /* fill the buffer with the driver structures */
6916 for (i=0; i<*returned; i++) {
6917 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6918 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6922 SAFE_FREE(driver_info_1);
6924 if ( !W_ERROR_IS_OK(result) )
6930 /****************************************************************************
6931 Enumerates all printer drivers at level 2.
6932 ****************************************************************************/
6934 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6939 fstring *list = NULL;
6940 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6941 DRIVER_INFO_2 *driver_info_2=NULL;
6942 WERROR result = WERR_OK;
6946 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6948 ndrivers=get_ntdrivers(&list, architecture, version);
6949 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6951 if(ndrivers == -1) {
6952 SAFE_FREE(driver_info_2);
6957 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6958 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6964 for (i=0; i<ndrivers; i++) {
6967 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6968 ZERO_STRUCT(driver);
6969 status = get_a_printer_driver(&driver, 3, list[i],
6970 architecture, version);
6971 if (!W_ERROR_IS_OK(status)) {
6973 SAFE_FREE(driver_info_2);
6976 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6977 free_a_printer_driver(driver, 3);
6980 *returned+=ndrivers;
6984 /* check the required size. */
6985 for (i=0; i<*returned; i++) {
6986 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6987 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6990 if (*needed > offered) {
6991 result = WERR_INSUFFICIENT_BUFFER;
6995 if (!rpcbuf_alloc_size(buffer, *needed)) {
6996 result = WERR_NOMEM;
7000 /* fill the buffer with the form structures */
7001 for (i=0; i<*returned; i++) {
7002 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7003 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7007 SAFE_FREE(driver_info_2);
7009 if ( !W_ERROR_IS_OK(result) )
7015 /****************************************************************************
7016 Enumerates all printer drivers at level 3.
7017 ****************************************************************************/
7019 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7024 fstring *list = NULL;
7025 DRIVER_INFO_3 *driver_info_3=NULL;
7026 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7027 WERROR result = WERR_OK;
7031 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7033 ndrivers=get_ntdrivers(&list, architecture, version);
7034 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7036 if(ndrivers == -1) {
7037 SAFE_FREE(driver_info_3);
7042 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7043 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7049 for (i=0; i<ndrivers; i++) {
7052 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7053 ZERO_STRUCT(driver);
7054 status = get_a_printer_driver(&driver, 3, list[i],
7055 architecture, version);
7056 if (!W_ERROR_IS_OK(status)) {
7058 SAFE_FREE(driver_info_3);
7061 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7062 free_a_printer_driver(driver, 3);
7065 *returned+=ndrivers;
7069 /* check the required size. */
7070 for (i=0; i<*returned; i++) {
7071 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7072 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7075 if (*needed > offered) {
7076 result = WERR_INSUFFICIENT_BUFFER;
7080 if (!rpcbuf_alloc_size(buffer, *needed)) {
7081 result = WERR_NOMEM;
7085 /* fill the buffer with the driver structures */
7086 for (i=0; i<*returned; i++) {
7087 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7088 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7092 for (i=0; i<*returned; i++) {
7093 SAFE_FREE(driver_info_3[i].dependentfiles);
7096 SAFE_FREE(driver_info_3);
7098 if ( !W_ERROR_IS_OK(result) )
7104 /****************************************************************************
7105 Enumerates all printer drivers.
7106 ****************************************************************************/
7108 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7110 uint32 level = q_u->level;
7111 RPC_BUFFER *buffer = NULL;
7112 uint32 offered = q_u->offered;
7113 uint32 *needed = &r_u->needed;
7114 uint32 *returned = &r_u->returned;
7117 fstring architecture;
7119 /* that's an [in out] buffer */
7121 if (!q_u->buffer && (offered!=0)) {
7122 return WERR_INVALID_PARAM;
7125 rpcbuf_move(q_u->buffer, &r_u->buffer);
7126 buffer = r_u->buffer;
7128 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7133 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7134 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7136 if ( !is_myname_or_ipaddr( servername ) )
7137 return WERR_UNKNOWN_PRINTER_DRIVER;
7141 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7143 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7145 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7147 return WERR_UNKNOWN_LEVEL;
7151 /****************************************************************************
7152 ****************************************************************************/
7154 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7156 form->flag=list->flag;
7157 init_unistr(&form->name, list->name);
7158 form->width=list->width;
7159 form->length=list->length;
7160 form->left=list->left;
7161 form->top=list->top;
7162 form->right=list->right;
7163 form->bottom=list->bottom;
7166 /****************************************************************************
7167 ****************************************************************************/
7169 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7171 uint32 level = q_u->level;
7172 RPC_BUFFER *buffer = NULL;
7173 uint32 offered = q_u->offered;
7174 uint32 *needed = &r_u->needed;
7175 uint32 *numofforms = &r_u->numofforms;
7176 uint32 numbuiltinforms;
7178 nt_forms_struct *list=NULL;
7179 nt_forms_struct *builtinlist=NULL;
7184 /* that's an [in out] buffer */
7186 if (!q_u->buffer && (offered!=0) ) {
7187 return WERR_INVALID_PARAM;
7190 rpcbuf_move(q_u->buffer, &r_u->buffer);
7191 buffer = r_u->buffer;
7193 DEBUG(4,("_spoolss_enumforms\n"));
7194 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7195 DEBUGADD(5,("Info level [%d]\n", level));
7197 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7198 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7199 *numofforms = get_ntforms(&list);
7200 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7201 *numofforms += numbuiltinforms;
7203 if (*numofforms == 0) {
7204 SAFE_FREE(builtinlist);
7206 return WERR_NO_MORE_ITEMS;
7211 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7212 SAFE_FREE(builtinlist);
7218 /* construct the list of form structures */
7219 for (i=0; i<numbuiltinforms; i++) {
7220 DEBUGADD(6,("Filling form number [%d]\n",i));
7221 fill_form_1(&forms_1[i], &builtinlist[i]);
7224 SAFE_FREE(builtinlist);
7226 for (; i<*numofforms; i++) {
7227 DEBUGADD(6,("Filling form number [%d]\n",i));
7228 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7233 /* check the required size. */
7234 for (i=0; i<numbuiltinforms; i++) {
7235 DEBUGADD(6,("adding form [%d]'s size\n",i));
7236 buffer_size += spoolss_size_form_1(&forms_1[i]);
7238 for (; i<*numofforms; i++) {
7239 DEBUGADD(6,("adding form [%d]'s size\n",i));
7240 buffer_size += spoolss_size_form_1(&forms_1[i]);
7243 *needed=buffer_size;
7245 if (*needed > offered) {
7248 return WERR_INSUFFICIENT_BUFFER;
7251 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7257 /* fill the buffer with the form structures */
7258 for (i=0; i<numbuiltinforms; i++) {
7259 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7260 smb_io_form_1("", buffer, &forms_1[i], 0);
7262 for (; i<*numofforms; i++) {
7263 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7264 smb_io_form_1("", buffer, &forms_1[i], 0);
7273 SAFE_FREE(builtinlist);
7274 return WERR_UNKNOWN_LEVEL;
7278 /****************************************************************************
7279 ****************************************************************************/
7281 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7283 uint32 level = q_u->level;
7284 UNISTR2 *uni_formname = &q_u->formname;
7285 RPC_BUFFER *buffer = NULL;
7286 uint32 offered = q_u->offered;
7287 uint32 *needed = &r_u->needed;
7289 nt_forms_struct *list=NULL;
7290 nt_forms_struct builtin_form;
7295 int numofforms=0, i=0;
7297 /* that's an [in out] buffer */
7299 if (!q_u->buffer && (offered!=0)) {
7300 return WERR_INVALID_PARAM;
7303 rpcbuf_move(q_u->buffer, &r_u->buffer);
7304 buffer = r_u->buffer;
7306 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7308 DEBUG(4,("_spoolss_getform\n"));
7309 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7310 DEBUGADD(5,("Info level [%d]\n", level));
7312 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7313 if (!foundBuiltin) {
7314 numofforms = get_ntforms(&list);
7315 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7317 if (numofforms == 0)
7324 fill_form_1(&form_1, &builtin_form);
7327 /* Check if the requested name is in the list of form structures */
7328 for (i=0; i<numofforms; i++) {
7330 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7332 if (strequal(form_name, list[i].name)) {
7333 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7334 fill_form_1(&form_1, &list[i]);
7340 if (i == numofforms) {
7344 /* check the required size. */
7346 *needed=spoolss_size_form_1(&form_1);
7348 if (*needed > offered)
7349 return WERR_INSUFFICIENT_BUFFER;
7351 if (!rpcbuf_alloc_size(buffer, buffer_size))
7354 /* fill the buffer with the form structures */
7355 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7356 smb_io_form_1("", buffer, &form_1, 0);
7362 return WERR_UNKNOWN_LEVEL;
7366 /****************************************************************************
7367 ****************************************************************************/
7369 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7371 init_unistr(&port->port_name, name);
7374 /****************************************************************************
7375 TODO: This probably needs distinguish between TCP/IP and Local ports
7377 ****************************************************************************/
7379 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7381 init_unistr(&port->port_name, name);
7382 init_unistr(&port->monitor_name, "Local Monitor");
7383 init_unistr(&port->description, SPL_LOCAL_PORT );
7384 port->port_type=PORT_TYPE_WRITE;
7389 /****************************************************************************
7390 wrapper around the enumer ports command
7391 ****************************************************************************/
7393 WERROR enumports_hook( int *count, char ***lines )
7395 char *cmd = lp_enumports_cmd();
7405 /* if no hook then just fill in the default port */
7408 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7409 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7414 /* we have a valid enumport command */
7416 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7418 DEBUG(10,("Running [%s]\n", command));
7419 ret = smbrun(command, &fd);
7420 DEBUG(10,("Returned [%d]\n", ret));
7425 return WERR_ACCESS_DENIED;
7429 qlines = fd_lines_load(fd, &numlines, 0);
7430 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7440 /****************************************************************************
7442 ****************************************************************************/
7444 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7446 PORT_INFO_1 *ports=NULL;
7448 WERROR result = WERR_OK;
7449 char **qlines = NULL;
7452 result = enumports_hook( &numlines, &qlines );
7453 if (!W_ERROR_IS_OK(result)) {
7454 file_lines_free(qlines);
7459 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7460 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7461 dos_errstr(WERR_NOMEM)));
7462 file_lines_free(qlines);
7466 for (i=0; i<numlines; i++) {
7467 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7468 fill_port_1(&ports[i], qlines[i]);
7471 file_lines_free(qlines);
7473 *returned = numlines;
7475 /* check the required size. */
7476 for (i=0; i<*returned; i++) {
7477 DEBUGADD(6,("adding port [%d]'s size\n", i));
7478 *needed += spoolss_size_port_info_1(&ports[i]);
7481 if (*needed > offered) {
7482 result = WERR_INSUFFICIENT_BUFFER;
7486 if (!rpcbuf_alloc_size(buffer, *needed)) {
7487 result = WERR_NOMEM;
7491 /* fill the buffer with the ports structures */
7492 for (i=0; i<*returned; i++) {
7493 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7494 smb_io_port_1("", buffer, &ports[i], 0);
7500 if ( !W_ERROR_IS_OK(result) )
7506 /****************************************************************************
7508 ****************************************************************************/
7510 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7512 PORT_INFO_2 *ports=NULL;
7514 WERROR result = WERR_OK;
7515 char **qlines = NULL;
7518 result = enumports_hook( &numlines, &qlines );
7519 if ( !W_ERROR_IS_OK(result)) {
7520 file_lines_free(qlines);
7525 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7526 file_lines_free(qlines);
7530 for (i=0; i<numlines; i++) {
7531 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7532 fill_port_2(&(ports[i]), qlines[i]);
7536 file_lines_free(qlines);
7538 *returned = numlines;
7540 /* check the required size. */
7541 for (i=0; i<*returned; i++) {
7542 DEBUGADD(6,("adding port [%d]'s size\n", i));
7543 *needed += spoolss_size_port_info_2(&ports[i]);
7546 if (*needed > offered) {
7547 result = WERR_INSUFFICIENT_BUFFER;
7551 if (!rpcbuf_alloc_size(buffer, *needed)) {
7552 result = WERR_NOMEM;
7556 /* fill the buffer with the ports structures */
7557 for (i=0; i<*returned; i++) {
7558 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7559 smb_io_port_2("", buffer, &ports[i], 0);
7565 if ( !W_ERROR_IS_OK(result) )
7571 /****************************************************************************
7573 ****************************************************************************/
7575 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7577 uint32 level = q_u->level;
7578 RPC_BUFFER *buffer = NULL;
7579 uint32 offered = q_u->offered;
7580 uint32 *needed = &r_u->needed;
7581 uint32 *returned = &r_u->returned;
7583 /* that's an [in out] buffer */
7585 if (!q_u->buffer && (offered!=0)) {
7586 return WERR_INVALID_PARAM;
7589 rpcbuf_move(q_u->buffer, &r_u->buffer);
7590 buffer = r_u->buffer;
7592 DEBUG(4,("_spoolss_enumports\n"));
7599 return enumports_level_1(buffer, offered, needed, returned);
7601 return enumports_level_2(buffer, offered, needed, returned);
7603 return WERR_UNKNOWN_LEVEL;
7607 /****************************************************************************
7608 ****************************************************************************/
7610 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7611 const SPOOL_PRINTER_INFO_LEVEL *info,
7612 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7613 uint32 user_switch, const SPOOL_USER_CTR *user,
7616 NT_PRINTER_INFO_LEVEL *printer = NULL;
7619 WERROR err = WERR_OK;
7621 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7622 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7626 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7627 if (!convert_printer_info(info, printer, 2)) {
7628 free_a_printer(&printer, 2);
7632 /* check to see if the printer already exists */
7634 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7635 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7636 printer->info_2->sharename));
7637 free_a_printer(&printer, 2);
7638 return WERR_PRINTER_ALREADY_EXISTS;
7641 /* FIXME!!! smbd should check to see if the driver is installed before
7642 trying to add a printer like this --jerry */
7644 if (*lp_addprinter_cmd() ) {
7645 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7646 free_a_printer(&printer,2);
7647 return WERR_ACCESS_DENIED;
7650 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7651 "smb.conf parameter \"addprinter command\" is defined. This"
7652 "parameter must exist for this call to succeed\n",
7653 printer->info_2->sharename ));
7656 /* use our primary netbios name since get_a_printer() will convert
7657 it to what the client expects on a case by case basis */
7659 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7660 printer->info_2->sharename);
7663 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7664 free_a_printer(&printer,2);
7665 return WERR_ACCESS_DENIED;
7668 /* you must be a printer admin to add a new printer */
7669 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7670 free_a_printer(&printer,2);
7671 return WERR_ACCESS_DENIED;
7675 * Do sanity check on the requested changes for Samba.
7678 if (!check_printer_ok(printer->info_2, snum)) {
7679 free_a_printer(&printer,2);
7680 return WERR_INVALID_PARAM;
7684 * When a printer is created, the drivername bound to the printer is used
7685 * to lookup previously saved driver initialization info, which is then
7686 * bound to the new printer, simulating what happens in the Windows arch.
7691 set_driver_init(printer, 2);
7695 /* A valid devmode was included, convert and link it
7697 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7699 if (!convert_devicemode(printer->info_2->printername, devmode,
7700 &printer->info_2->devmode))
7704 /* write the ASCII on disk */
7705 err = mod_a_printer(printer, 2);
7706 if (!W_ERROR_IS_OK(err)) {
7707 free_a_printer(&printer,2);
7711 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7712 /* Handle open failed - remove addition. */
7713 del_a_printer(printer->info_2->sharename);
7714 free_a_printer(&printer,2);
7715 return WERR_ACCESS_DENIED;
7718 update_c_setprinter(False);
7719 free_a_printer(&printer,2);
7724 /****************************************************************************
7725 ****************************************************************************/
7727 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7729 UNISTR2 *uni_srv_name = q_u->server_name;
7730 uint32 level = q_u->level;
7731 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7732 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7733 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7734 uint32 user_switch = q_u->user_switch;
7735 SPOOL_USER_CTR *user = &q_u->user_ctr;
7736 POLICY_HND *handle = &r_u->handle;
7740 /* we don't handle yet */
7741 /* but I know what to do ... */
7742 return WERR_UNKNOWN_LEVEL;
7744 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7746 user_switch, user, handle);
7748 return WERR_UNKNOWN_LEVEL;
7752 /****************************************************************************
7753 ****************************************************************************/
7755 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7757 uint32 level = q_u->level;
7758 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7759 WERROR err = WERR_OK;
7760 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7761 fstring driver_name;
7764 ZERO_STRUCT(driver);
7766 if (!convert_printer_driver_info(info, &driver, level)) {
7771 DEBUG(5,("Cleaning driver's information\n"));
7772 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7773 if (!W_ERROR_IS_OK(err))
7776 DEBUG(5,("Moving driver to final destination\n"));
7777 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7781 if (add_a_printer_driver(driver, level)!=0) {
7782 err = WERR_ACCESS_DENIED;
7787 * I think this is where he DrvUpgradePrinter() hook would be
7788 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7789 * server. Right now, we just need to send ourselves a message
7790 * to update each printer bound to this driver. --jerry
7793 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7794 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7799 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7800 * decide if the driver init data should be deleted. The rules are:
7801 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7802 * 2) delete init data only if there is no 2k/Xp driver
7803 * 3) always delete init data
7804 * The generalized rule is always use init data from the highest order driver.
7805 * It is necessary to follow the driver install by an initialization step to
7806 * finish off this process.
7809 version = driver.info_3->cversion;
7810 else if (level == 6)
7811 version = driver.info_6->version;
7816 * 9x printer driver - never delete init data
7819 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7824 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7825 * there is no 2k/Xp driver init data for this driver name.
7829 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7831 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7833 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7835 if (!del_driver_init(driver_name))
7836 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7839 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7841 free_a_printer_driver(driver1,3);
7842 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7849 * 2k or Xp printer driver - always delete init data
7852 if (!del_driver_init(driver_name))
7853 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7857 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7863 free_a_printer_driver(driver, level);
7867 /********************************************************************
7868 * spoolss_addprinterdriverex
7869 ********************************************************************/
7871 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7873 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7874 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7877 * we only support the semantics of AddPrinterDriver()
7878 * i.e. only copy files that are newer than existing ones
7881 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7882 return WERR_ACCESS_DENIED;
7884 ZERO_STRUCT(q_u_local);
7885 ZERO_STRUCT(r_u_local);
7887 /* just pass the information off to _spoolss_addprinterdriver() */
7888 q_u_local.server_name_ptr = q_u->server_name_ptr;
7889 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7890 q_u_local.level = q_u->level;
7891 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7893 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7896 /****************************************************************************
7897 ****************************************************************************/
7899 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7901 init_unistr(&info->name, name);
7904 /****************************************************************************
7905 ****************************************************************************/
7907 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7913 const char *short_archi;
7914 DRIVER_DIRECTORY_1 *info=NULL;
7915 WERROR result = WERR_OK;
7917 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7918 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7920 /* check for beginning double '\'s and that the server
7923 pservername = servername;
7924 if ( *pservername == '\\' && strlen(servername)>2 ) {
7928 if ( !is_myname_or_ipaddr( pservername ) )
7929 return WERR_INVALID_PARAM;
7931 if (!(short_archi = get_short_archi(long_archi)))
7932 return WERR_INVALID_ENVIRONMENT;
7934 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7937 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7939 DEBUG(4,("printer driver directory: [%s]\n", path));
7941 fill_driverdir_1(info, path);
7943 *needed += spoolss_size_driverdir_info_1(info);
7945 if (*needed > offered) {
7946 result = WERR_INSUFFICIENT_BUFFER;
7950 if (!rpcbuf_alloc_size(buffer, *needed)) {
7951 result = WERR_NOMEM;
7955 smb_io_driverdir_1("", buffer, info, 0);
7963 /****************************************************************************
7964 ****************************************************************************/
7966 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7968 UNISTR2 *name = &q_u->name;
7969 UNISTR2 *uni_environment = &q_u->environment;
7970 uint32 level = q_u->level;
7971 RPC_BUFFER *buffer = NULL;
7972 uint32 offered = q_u->offered;
7973 uint32 *needed = &r_u->needed;
7975 /* that's an [in out] buffer */
7977 if (!q_u->buffer && (offered!=0)) {
7978 return WERR_INVALID_PARAM;
7981 rpcbuf_move(q_u->buffer, &r_u->buffer);
7982 buffer = r_u->buffer;
7984 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7990 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7992 return WERR_UNKNOWN_LEVEL;
7996 /****************************************************************************
7997 ****************************************************************************/
7999 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8001 POLICY_HND *handle = &q_u->handle;
8002 uint32 idx = q_u->index;
8003 uint32 in_value_len = q_u->valuesize;
8004 uint32 in_data_len = q_u->datasize;
8005 uint32 *out_max_value_len = &r_u->valuesize;
8006 uint16 **out_value = &r_u->value;
8007 uint32 *out_value_len = &r_u->realvaluesize;
8008 uint32 *out_type = &r_u->type;
8009 uint32 *out_max_data_len = &r_u->datasize;
8010 uint8 **data_out = &r_u->data;
8011 uint32 *out_data_len = &r_u->realdatasize;
8013 NT_PRINTER_INFO_LEVEL *printer = NULL;
8015 uint32 biggest_valuesize;
8016 uint32 biggest_datasize;
8018 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8021 REGISTRY_VALUE *val = NULL;
8022 NT_PRINTER_DATA *p_data;
8023 int i, key_index, num_values;
8028 *out_max_data_len = 0;
8032 DEBUG(5,("spoolss_enumprinterdata\n"));
8035 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8039 if (!get_printer_snum(p,handle, &snum, NULL))
8042 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8043 if (!W_ERROR_IS_OK(result))
8046 p_data = printer->info_2->data;
8047 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8052 * The NT machine wants to know the biggest size of value and data
8054 * cf: MSDN EnumPrinterData remark section
8057 if ( !in_value_len && !in_data_len && (key_index != -1) )
8059 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8061 biggest_valuesize = 0;
8062 biggest_datasize = 0;
8064 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8066 for ( i=0; i<num_values; i++ )
8068 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8070 name_length = strlen(val->valuename);
8071 if ( strlen(val->valuename) > biggest_valuesize )
8072 biggest_valuesize = name_length;
8074 if ( val->size > biggest_datasize )
8075 biggest_datasize = val->size;
8077 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8081 /* the value is an UNICODE string but real_value_size is the length
8082 in bytes including the trailing 0 */
8084 *out_value_len = 2 * (1+biggest_valuesize);
8085 *out_data_len = biggest_datasize;
8087 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8093 * the value len is wrong in NT sp3
8094 * that's the number of bytes not the number of unicode chars
8097 if ( key_index != -1 )
8098 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8103 /* out_value should default to "" or else NT4 has
8104 problems unmarshalling the response */
8106 *out_max_value_len=(in_value_len/sizeof(uint16));
8108 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8110 result = WERR_NOMEM;
8114 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8116 /* the data is counted in bytes */
8118 *out_max_data_len = in_data_len;
8119 *out_data_len = in_data_len;
8121 /* only allocate when given a non-zero data_len */
8123 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8125 result = WERR_NOMEM;
8129 result = WERR_NO_MORE_ITEMS;
8135 * - counted in bytes in the request
8136 * - counted in UNICODE chars in the max reply
8137 * - counted in bytes in the real size
8139 * take a pause *before* coding not *during* coding
8143 *out_max_value_len=(in_value_len/sizeof(uint16));
8144 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8146 result = WERR_NOMEM;
8150 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8154 *out_type = regval_type( val );
8156 /* data - counted in bytes */
8158 *out_max_data_len = in_data_len;
8159 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8161 result = WERR_NOMEM;
8164 data_len = regval_size(val);
8166 memcpy( *data_out, regval_data_p(val), data_len );
8167 *out_data_len = data_len;
8171 free_a_printer(&printer, 2);
8175 /****************************************************************************
8176 ****************************************************************************/
8178 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8180 POLICY_HND *handle = &q_u->handle;
8181 UNISTR2 *value = &q_u->value;
8182 uint32 type = q_u->type;
8183 uint8 *data = q_u->data;
8184 uint32 real_len = q_u->real_len;
8186 NT_PRINTER_INFO_LEVEL *printer = NULL;
8188 WERROR status = WERR_OK;
8189 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8192 DEBUG(5,("spoolss_setprinterdata\n"));
8195 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8199 if ( Printer->printer_type == SPLHND_SERVER ) {
8200 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8201 return WERR_INVALID_PARAM;
8204 if (!get_printer_snum(p,handle, &snum, NULL))
8208 * Access check : NT returns "access denied" if you make a
8209 * SetPrinterData call without the necessary privildge.
8210 * we were originally returning OK if nothing changed
8211 * which made Win2k issue **a lot** of SetPrinterData
8212 * when connecting to a printer --jerry
8215 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8217 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8218 status = WERR_ACCESS_DENIED;
8222 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8223 if (!W_ERROR_IS_OK(status))
8226 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8229 * When client side code sets a magic printer data key, detect it and save
8230 * the current printer data and the magic key's data (its the DEVMODE) for
8231 * future printer/driver initializations.
8233 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8235 /* Set devmode and printer initialization info */
8236 status = save_driver_init( printer, 2, data, real_len );
8238 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8242 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8243 type, data, real_len );
8244 if ( W_ERROR_IS_OK(status) )
8245 status = mod_a_printer(printer, 2);
8249 free_a_printer(&printer, 2);
8254 /****************************************************************************
8255 ****************************************************************************/
8257 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8259 POLICY_HND *handle = &q_u->handle;
8260 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8263 DEBUG(5,("_spoolss_resetprinter\n"));
8266 * All we do is to check to see if the handle and queue is valid.
8267 * This call really doesn't mean anything to us because we only
8268 * support RAW printing. --jerry
8272 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8276 if (!get_printer_snum(p,handle, &snum, NULL))
8280 /* blindly return success */
8285 /****************************************************************************
8286 ****************************************************************************/
8288 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8290 POLICY_HND *handle = &q_u->handle;
8291 UNISTR2 *value = &q_u->valuename;
8293 NT_PRINTER_INFO_LEVEL *printer = NULL;
8295 WERROR status = WERR_OK;
8296 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8299 DEBUG(5,("spoolss_deleteprinterdata\n"));
8302 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8306 if (!get_printer_snum(p, handle, &snum, NULL))
8309 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8310 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8311 return WERR_ACCESS_DENIED;
8314 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8315 if (!W_ERROR_IS_OK(status))
8318 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8320 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8322 if ( W_ERROR_IS_OK(status) )
8323 mod_a_printer( printer, 2 );
8325 free_a_printer(&printer, 2);
8330 /****************************************************************************
8331 ****************************************************************************/
8333 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8335 POLICY_HND *handle = &q_u->handle;
8336 FORM *form = &q_u->form;
8337 nt_forms_struct tmpForm;
8339 WERROR status = WERR_OK;
8340 NT_PRINTER_INFO_LEVEL *printer = NULL;
8343 nt_forms_struct *list=NULL;
8344 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8346 DEBUG(5,("spoolss_addform\n"));
8349 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8354 /* forms can be added on printer of on the print server handle */
8356 if ( Printer->printer_type == SPLHND_PRINTER )
8358 if (!get_printer_snum(p,handle, &snum, NULL))
8361 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8362 if (!W_ERROR_IS_OK(status))
8366 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8367 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8368 status = WERR_ACCESS_DENIED;
8372 /* can't add if builtin */
8374 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8375 status = WERR_ALREADY_EXISTS;
8379 count = get_ntforms(&list);
8381 if(!add_a_form(&list, form, &count)) {
8382 status = WERR_NOMEM;
8386 write_ntforms(&list, count);
8389 * ChangeID must always be set if this is a printer
8392 if ( Printer->printer_type == SPLHND_PRINTER )
8393 status = mod_a_printer(printer, 2);
8397 free_a_printer(&printer, 2);
8403 /****************************************************************************
8404 ****************************************************************************/
8406 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8408 POLICY_HND *handle = &q_u->handle;
8409 UNISTR2 *form_name = &q_u->name;
8410 nt_forms_struct tmpForm;
8412 nt_forms_struct *list=NULL;
8413 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8415 WERROR status = WERR_OK;
8416 NT_PRINTER_INFO_LEVEL *printer = NULL;
8418 DEBUG(5,("spoolss_deleteform\n"));
8421 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8425 /* forms can be deleted on printer of on the print server handle */
8427 if ( Printer->printer_type == SPLHND_PRINTER )
8429 if (!get_printer_snum(p,handle, &snum, NULL))
8432 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8433 if (!W_ERROR_IS_OK(status))
8437 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8438 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8439 status = WERR_ACCESS_DENIED;
8443 /* can't delete if builtin */
8445 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8446 status = WERR_INVALID_PARAM;
8450 count = get_ntforms(&list);
8452 if ( !delete_a_form(&list, form_name, &count, &status ))
8456 * ChangeID must always be set if this is a printer
8459 if ( Printer->printer_type == SPLHND_PRINTER )
8460 status = mod_a_printer(printer, 2);
8464 free_a_printer(&printer, 2);
8470 /****************************************************************************
8471 ****************************************************************************/
8473 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8475 POLICY_HND *handle = &q_u->handle;
8476 FORM *form = &q_u->form;
8477 nt_forms_struct tmpForm;
8479 WERROR status = WERR_OK;
8480 NT_PRINTER_INFO_LEVEL *printer = NULL;
8483 nt_forms_struct *list=NULL;
8484 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8486 DEBUG(5,("spoolss_setform\n"));
8489 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8493 /* forms can be modified on printer of on the print server handle */
8495 if ( Printer->printer_type == SPLHND_PRINTER )
8497 if (!get_printer_snum(p,handle, &snum, NULL))
8500 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8501 if (!W_ERROR_IS_OK(status))
8505 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8506 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8507 status = WERR_ACCESS_DENIED;
8511 /* can't set if builtin */
8512 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8513 status = WERR_INVALID_PARAM;
8517 count = get_ntforms(&list);
8518 update_a_form(&list, form, count);
8519 write_ntforms(&list, count);
8522 * ChangeID must always be set if this is a printer
8525 if ( Printer->printer_type == SPLHND_PRINTER )
8526 status = mod_a_printer(printer, 2);
8531 free_a_printer(&printer, 2);
8537 /****************************************************************************
8538 enumprintprocessors level 1.
8539 ****************************************************************************/
8541 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8543 PRINTPROCESSOR_1 *info_1=NULL;
8544 WERROR result = WERR_OK;
8546 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8551 init_unistr(&info_1->name, "winprint");
8553 *needed += spoolss_size_printprocessor_info_1(info_1);
8555 if (*needed > offered) {
8556 result = WERR_INSUFFICIENT_BUFFER;
8560 if (!rpcbuf_alloc_size(buffer, *needed)) {
8561 result = WERR_NOMEM;
8565 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8570 if ( !W_ERROR_IS_OK(result) )
8576 /****************************************************************************
8577 ****************************************************************************/
8579 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8581 uint32 level = q_u->level;
8582 RPC_BUFFER *buffer = NULL;
8583 uint32 offered = q_u->offered;
8584 uint32 *needed = &r_u->needed;
8585 uint32 *returned = &r_u->returned;
8587 /* that's an [in out] buffer */
8589 if (!q_u->buffer && (offered!=0)) {
8590 return WERR_INVALID_PARAM;
8593 rpcbuf_move(q_u->buffer, &r_u->buffer);
8594 buffer = r_u->buffer;
8596 DEBUG(5,("spoolss_enumprintprocessors\n"));
8599 * Enumerate the print processors ...
8601 * Just reply with "winprint", to keep NT happy
8602 * and I can use my nice printer checker.
8610 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8612 return WERR_UNKNOWN_LEVEL;
8616 /****************************************************************************
8617 enumprintprocdatatypes level 1.
8618 ****************************************************************************/
8620 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8622 PRINTPROCDATATYPE_1 *info_1=NULL;
8623 WERROR result = WERR_NOMEM;
8625 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8630 init_unistr(&info_1->name, "RAW");
8632 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8634 if (*needed > offered) {
8635 result = WERR_INSUFFICIENT_BUFFER;
8639 if (!rpcbuf_alloc_size(buffer, *needed)) {
8640 result = WERR_NOMEM;
8644 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8649 if ( !W_ERROR_IS_OK(result) )
8655 /****************************************************************************
8656 ****************************************************************************/
8658 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8660 uint32 level = q_u->level;
8661 RPC_BUFFER *buffer = NULL;
8662 uint32 offered = q_u->offered;
8663 uint32 *needed = &r_u->needed;
8664 uint32 *returned = &r_u->returned;
8666 /* that's an [in out] buffer */
8668 if (!q_u->buffer && (offered!=0)) {
8669 return WERR_INVALID_PARAM;
8672 rpcbuf_move(q_u->buffer, &r_u->buffer);
8673 buffer = r_u->buffer;
8675 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8682 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8684 return WERR_UNKNOWN_LEVEL;
8688 /****************************************************************************
8689 enumprintmonitors level 1.
8690 ****************************************************************************/
8692 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8694 PRINTMONITOR_1 *info_1;
8695 WERROR result = WERR_OK;
8698 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8703 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8704 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8706 for ( i=0; i<*returned; i++ ) {
8707 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8710 if (*needed > offered) {
8711 result = WERR_INSUFFICIENT_BUFFER;
8715 if (!rpcbuf_alloc_size(buffer, *needed)) {
8716 result = WERR_NOMEM;
8720 for ( i=0; i<*returned; i++ ) {
8721 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8727 if ( !W_ERROR_IS_OK(result) )
8733 /****************************************************************************
8734 enumprintmonitors level 2.
8735 ****************************************************************************/
8737 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8739 PRINTMONITOR_2 *info_2;
8740 WERROR result = WERR_OK;
8743 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8748 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8749 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8750 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8752 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8753 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8754 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8756 for ( i=0; i<*returned; i++ ) {
8757 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8760 if (*needed > offered) {
8761 result = WERR_INSUFFICIENT_BUFFER;
8765 if (!rpcbuf_alloc_size(buffer, *needed)) {
8766 result = WERR_NOMEM;
8770 for ( i=0; i<*returned; i++ ) {
8771 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8777 if ( !W_ERROR_IS_OK(result) )
8783 /****************************************************************************
8784 ****************************************************************************/
8786 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8788 uint32 level = q_u->level;
8789 RPC_BUFFER *buffer = NULL;
8790 uint32 offered = q_u->offered;
8791 uint32 *needed = &r_u->needed;
8792 uint32 *returned = &r_u->returned;
8794 /* that's an [in out] buffer */
8796 if (!q_u->buffer && (offered!=0)) {
8797 return WERR_INVALID_PARAM;
8800 rpcbuf_move(q_u->buffer, &r_u->buffer);
8801 buffer = r_u->buffer;
8803 DEBUG(5,("spoolss_enumprintmonitors\n"));
8806 * Enumerate the print monitors ...
8808 * Just reply with "Local Port", to keep NT happy
8809 * and I can use my nice printer checker.
8817 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8819 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8821 return WERR_UNKNOWN_LEVEL;
8825 /****************************************************************************
8826 ****************************************************************************/
8828 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8829 NT_PRINTER_INFO_LEVEL *ntprinter,
8830 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8835 JOB_INFO_1 *info_1=NULL;
8836 WERROR result = WERR_OK;
8838 info_1=SMB_MALLOC_P(JOB_INFO_1);
8840 if (info_1 == NULL) {
8844 for (i=0; i<count && found==False; i++) {
8845 if ((*queue)[i].job==(int)jobid)
8851 /* NT treats not found as bad param... yet another bad choice */
8852 return WERR_INVALID_PARAM;
8855 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8857 *needed += spoolss_size_job_info_1(info_1);
8859 if (*needed > offered) {
8860 result = WERR_INSUFFICIENT_BUFFER;
8864 if (!rpcbuf_alloc_size(buffer, *needed)) {
8865 result = WERR_NOMEM;
8869 smb_io_job_info_1("", buffer, info_1, 0);
8877 /****************************************************************************
8878 ****************************************************************************/
8880 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8881 NT_PRINTER_INFO_LEVEL *ntprinter,
8882 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8889 DEVICEMODE *devmode = NULL;
8890 NT_DEVICEMODE *nt_devmode = NULL;
8892 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8895 ZERO_STRUCTP(info_2);
8897 for ( i=0; i<count && found==False; i++ )
8899 if ((*queue)[i].job == (int)jobid)
8904 /* NT treats not found as bad param... yet another bad
8906 result = WERR_INVALID_PARAM;
8911 * if the print job does not have a DEVMODE associated with it,
8912 * just use the one for the printer. A NULL devicemode is not
8913 * a failure condition
8916 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8917 devmode = construct_dev_mode(lp_const_servicename(snum));
8919 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8920 ZERO_STRUCTP( devmode );
8921 convert_nt_devicemode( devmode, nt_devmode );
8925 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8927 *needed += spoolss_size_job_info_2(info_2);
8929 if (*needed > offered) {
8930 result = WERR_INSUFFICIENT_BUFFER;
8934 if (!rpcbuf_alloc_size(buffer, *needed)) {
8935 result = WERR_NOMEM;
8939 smb_io_job_info_2("", buffer, info_2, 0);
8944 /* Cleanup allocated memory */
8946 free_job_info_2(info_2); /* Also frees devmode */
8952 /****************************************************************************
8953 ****************************************************************************/
8955 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8957 POLICY_HND *handle = &q_u->handle;
8958 uint32 jobid = q_u->jobid;
8959 uint32 level = q_u->level;
8960 RPC_BUFFER *buffer = NULL;
8961 uint32 offered = q_u->offered;
8962 uint32 *needed = &r_u->needed;
8963 WERROR wstatus = WERR_OK;
8964 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8967 print_queue_struct *queue = NULL;
8968 print_status_struct prt_status;
8970 /* that's an [in out] buffer */
8972 if (!q_u->buffer && (offered!=0)) {
8973 return WERR_INVALID_PARAM;
8976 rpcbuf_move(q_u->buffer, &r_u->buffer);
8977 buffer = r_u->buffer;
8979 DEBUG(5,("spoolss_getjob\n"));
8983 if (!get_printer_snum(p, handle, &snum, NULL))
8986 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8987 if ( !W_ERROR_IS_OK(wstatus) )
8990 count = print_queue_status(snum, &queue, &prt_status);
8992 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8993 count, prt_status.status, prt_status.message));
8997 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8998 buffer, offered, needed);
9001 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9002 buffer, offered, needed);
9005 wstatus = WERR_UNKNOWN_LEVEL;
9010 free_a_printer( &ntprinter, 2 );
9015 /********************************************************************
9016 spoolss_getprinterdataex
9018 From MSDN documentation of GetPrinterDataEx: pass request
9019 to GetPrinterData if key is "PrinterDriverData".
9020 ********************************************************************/
9022 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9024 POLICY_HND *handle = &q_u->handle;
9025 uint32 in_size = q_u->size;
9026 uint32 *type = &r_u->type;
9027 uint32 *out_size = &r_u->size;
9028 uint8 **data = &r_u->data;
9029 uint32 *needed = &r_u->needed;
9030 fstring keyname, valuename;
9032 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9034 NT_PRINTER_INFO_LEVEL *printer = NULL;
9036 WERROR status = WERR_OK;
9038 DEBUG(4,("_spoolss_getprinterdataex\n"));
9040 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
9041 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
9043 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9044 keyname, valuename));
9046 /* in case of problem, return some default values */
9050 *out_size = in_size;
9053 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9054 status = WERR_BADFID;
9058 /* Is the handle to a printer or to the server? */
9060 if (Printer->printer_type == SPLHND_SERVER) {
9061 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9062 status = WERR_INVALID_PARAM;
9066 if ( !get_printer_snum(p,handle, &snum, NULL) )
9069 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9070 if ( !W_ERROR_IS_OK(status) )
9073 /* check to see if the keyname is valid */
9074 if ( !strlen(keyname) ) {
9075 status = WERR_INVALID_PARAM;
9079 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9080 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9081 free_a_printer( &printer, 2 );
9082 status = WERR_BADFILE;
9086 /* When given a new keyname, we should just create it */
9088 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9090 if (*needed > *out_size)
9091 status = WERR_MORE_DATA;
9094 if ( !W_ERROR_IS_OK(status) )
9096 DEBUG(5, ("error: allocating %d\n", *out_size));
9098 /* reply this param doesn't exist */
9102 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9103 status = WERR_NOMEM;
9113 free_a_printer( &printer, 2 );
9118 /********************************************************************
9119 * spoolss_setprinterdataex
9120 ********************************************************************/
9122 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9124 POLICY_HND *handle = &q_u->handle;
9125 uint32 type = q_u->type;
9126 uint8 *data = q_u->data;
9127 uint32 real_len = q_u->real_len;
9129 NT_PRINTER_INFO_LEVEL *printer = NULL;
9131 WERROR status = WERR_OK;
9132 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9137 DEBUG(4,("_spoolss_setprinterdataex\n"));
9139 /* From MSDN documentation of SetPrinterDataEx: pass request to
9140 SetPrinterData if key is "PrinterDriverData" */
9143 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9147 if ( Printer->printer_type == SPLHND_SERVER ) {
9148 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9149 return WERR_INVALID_PARAM;
9152 if ( !get_printer_snum(p,handle, &snum, NULL) )
9156 * Access check : NT returns "access denied" if you make a
9157 * SetPrinterData call without the necessary privildge.
9158 * we were originally returning OK if nothing changed
9159 * which made Win2k issue **a lot** of SetPrinterData
9160 * when connecting to a printer --jerry
9163 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9165 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9166 return WERR_ACCESS_DENIED;
9169 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9170 if (!W_ERROR_IS_OK(status))
9173 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9174 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9176 /* check for OID in valuename */
9178 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9184 /* save the registry data */
9186 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9188 if ( W_ERROR_IS_OK(status) )
9190 /* save the OID if one was specified */
9192 fstrcat( keyname, "\\" );
9193 fstrcat( keyname, SPOOL_OID_KEY );
9196 * I'm not checking the status here on purpose. Don't know
9197 * if this is right, but I'm returning the status from the
9198 * previous set_printer_dataex() call. I have no idea if
9199 * this is right. --jerry
9202 set_printer_dataex( printer, keyname, valuename,
9203 REG_SZ, (uint8 *)oid_string,
9204 strlen(oid_string)+1 );
9207 status = mod_a_printer(printer, 2);
9210 free_a_printer(&printer, 2);
9216 /********************************************************************
9217 * spoolss_deleteprinterdataex
9218 ********************************************************************/
9220 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9222 POLICY_HND *handle = &q_u->handle;
9223 UNISTR2 *value = &q_u->valuename;
9224 UNISTR2 *key = &q_u->keyname;
9226 NT_PRINTER_INFO_LEVEL *printer = NULL;
9228 WERROR status = WERR_OK;
9229 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9230 pstring valuename, keyname;
9232 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9235 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9239 if (!get_printer_snum(p, handle, &snum, NULL))
9242 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9243 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9244 return WERR_ACCESS_DENIED;
9247 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9248 if (!W_ERROR_IS_OK(status))
9251 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9252 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9254 status = delete_printer_dataex( printer, keyname, valuename );
9256 if ( W_ERROR_IS_OK(status) )
9257 mod_a_printer( printer, 2 );
9259 free_a_printer(&printer, 2);
9264 /********************************************************************
9265 * spoolss_enumprinterkey
9266 ********************************************************************/
9269 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9272 fstring *keynames = NULL;
9273 uint16 *enumkeys = NULL;
9276 POLICY_HND *handle = &q_u->handle;
9277 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9278 NT_PRINTER_DATA *data;
9279 NT_PRINTER_INFO_LEVEL *printer = NULL;
9281 WERROR status = WERR_BADFILE;
9284 DEBUG(4,("_spoolss_enumprinterkey\n"));
9287 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9291 if ( !get_printer_snum(p,handle, &snum, NULL) )
9294 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9295 if (!W_ERROR_IS_OK(status))
9298 /* get the list of subkey names */
9300 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9301 data = printer->info_2->data;
9303 num_keys = get_printer_subkeys( data, key, &keynames );
9305 if ( num_keys == -1 ) {
9306 status = WERR_BADFILE;
9310 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9312 r_u->needed = printerkey_len*2;
9314 if ( q_u->size < r_u->needed ) {
9315 status = WERR_MORE_DATA;
9319 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9320 status = WERR_NOMEM;
9326 if ( q_u->size < r_u->needed )
9327 status = WERR_MORE_DATA;
9330 free_a_printer( &printer, 2 );
9331 SAFE_FREE( keynames );
9336 /********************************************************************
9337 * spoolss_deleteprinterkey
9338 ********************************************************************/
9340 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9342 POLICY_HND *handle = &q_u->handle;
9343 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9345 NT_PRINTER_INFO_LEVEL *printer = NULL;
9349 DEBUG(5,("spoolss_deleteprinterkey\n"));
9352 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9356 /* if keyname == NULL, return error */
9358 if ( !q_u->keyname.buffer )
9359 return WERR_INVALID_PARAM;
9361 if (!get_printer_snum(p, handle, &snum, NULL))
9364 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9365 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9366 return WERR_ACCESS_DENIED;
9369 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9370 if (!W_ERROR_IS_OK(status))
9373 /* delete the key and all subneys */
9375 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9377 status = delete_all_printer_data( printer->info_2, key );
9379 if ( W_ERROR_IS_OK(status) )
9380 status = mod_a_printer(printer, 2);
9382 free_a_printer( &printer, 2 );
9388 /********************************************************************
9389 * spoolss_enumprinterdataex
9390 ********************************************************************/
9392 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9394 POLICY_HND *handle = &q_u->handle;
9395 uint32 in_size = q_u->size;
9398 NT_PRINTER_INFO_LEVEL *printer = NULL;
9399 PRINTER_ENUM_VALUES *enum_values = NULL;
9400 NT_PRINTER_DATA *p_data;
9402 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9407 REGISTRY_VALUE *val;
9412 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9415 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9420 * first check for a keyname of NULL or "". Win2k seems to send
9421 * this a lot and we should send back WERR_INVALID_PARAM
9422 * no need to spend time looking up the printer in this case.
9426 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9427 if ( !strlen(key) ) {
9428 result = WERR_INVALID_PARAM;
9432 /* get the printer off of disk */
9434 if (!get_printer_snum(p,handle, &snum, NULL))
9437 ZERO_STRUCT(printer);
9438 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9439 if (!W_ERROR_IS_OK(result))
9442 /* now look for a match on the key name */
9444 p_data = printer->info_2->data;
9446 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9447 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9449 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9450 result = WERR_INVALID_PARAM;
9457 /* allocate the memory for the array of pointers -- if necessary */
9459 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9462 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9464 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9465 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9466 result = WERR_NOMEM;
9470 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9474 * loop through all params and build the array to pass
9475 * back to the client
9478 for ( i=0; i<num_entries; i++ )
9480 /* lookup the registry value */
9482 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9483 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9487 value_name = regval_name( val );
9488 init_unistr( &enum_values[i].valuename, value_name );
9489 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9490 enum_values[i].type = regval_type( val );
9492 data_len = regval_size( val );
9494 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9496 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9498 result = WERR_NOMEM;
9502 enum_values[i].data_len = data_len;
9504 /* keep track of the size of the array in bytes */
9506 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9509 /* housekeeping information in the reply */
9511 r_u->needed = needed;
9512 r_u->returned = num_entries;
9514 if (needed > in_size) {
9515 result = WERR_MORE_DATA;
9519 /* copy data into the reply */
9521 r_u->ctr.size = r_u->needed;
9522 r_u->ctr.size_of_array = r_u->returned;
9523 r_u->ctr.values = enum_values;
9529 free_a_printer(&printer, 2);
9534 /****************************************************************************
9535 ****************************************************************************/
9537 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9539 init_unistr(&info->name, name);
9542 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9543 UNISTR2 *environment,
9550 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9551 WERROR result = WERR_OK;
9553 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9555 if (!get_short_archi(long_archi))
9556 return WERR_INVALID_ENVIRONMENT;
9558 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9561 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9563 fill_printprocessordirectory_1(info, path);
9565 *needed += spoolss_size_printprocessordirectory_info_1(info);
9567 if (*needed > offered) {
9568 result = WERR_INSUFFICIENT_BUFFER;
9572 if (!rpcbuf_alloc_size(buffer, *needed)) {
9573 result = WERR_INSUFFICIENT_BUFFER;
9577 smb_io_printprocessordirectory_1("", buffer, info, 0);
9585 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9587 uint32 level = q_u->level;
9588 RPC_BUFFER *buffer = NULL;
9589 uint32 offered = q_u->offered;
9590 uint32 *needed = &r_u->needed;
9593 /* that's an [in out] buffer */
9595 if (!q_u->buffer && (offered!=0)) {
9596 return WERR_INVALID_PARAM;
9599 rpcbuf_move(q_u->buffer, &r_u->buffer);
9600 buffer = r_u->buffer;
9602 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9608 result = getprintprocessordirectory_level_1
9609 (&q_u->name, &q_u->environment, buffer, offered, needed);
9612 result = WERR_UNKNOWN_LEVEL;
9618 /*******************************************************************
9619 Streams the monitor UI DLL name in UNICODE
9620 *******************************************************************/
9622 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9623 RPC_BUFFER *out, uint32 *needed )
9625 const char *dllname = "tcpmonui.dll";
9627 *needed = (strlen(dllname)+1) * 2;
9629 if ( rpcbuf_get_size(out) < *needed ) {
9630 return WERR_INSUFFICIENT_BUFFER;
9633 if ( !make_monitorui_buf( out, dllname ) ) {
9640 /*******************************************************************
9641 Create a new TCP/IP port
9642 *******************************************************************/
9644 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9645 RPC_BUFFER *out, uint32 *needed )
9647 NT_PORT_DATA_1 port1;
9650 ZERO_STRUCT( port1 );
9652 /* convert to our internal port data structure */
9654 if ( !convert_port_data_1( &port1, in ) ) {
9658 /* create the device URI and call the add_port_hook() */
9660 switch ( port1.protocol ) {
9661 case PORT_PROTOCOL_DIRECT:
9662 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9665 case PORT_PROTOCOL_LPR:
9666 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9670 return WERR_UNKNOWN_PORT;
9673 return add_port_hook( token, port1.name, device_uri );
9676 /*******************************************************************
9677 *******************************************************************/
9679 struct xcv_api_table xcvtcp_cmds[] = {
9680 { "MonitorUI", xcvtcp_monitorui },
9681 { "AddPort", xcvtcp_addport},
9685 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9686 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9691 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9693 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9694 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9695 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9698 return WERR_BADFUNC;
9701 /*******************************************************************
9702 *******************************************************************/
9703 #if 0 /* don't support management using the "Local Port" monitor */
9705 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9706 RPC_BUFFER *out, uint32 *needed )
9708 const char *dllname = "localui.dll";
9710 *needed = (strlen(dllname)+1) * 2;
9712 if ( rpcbuf_get_size(out) < *needed ) {
9713 return WERR_INSUFFICIENT_BUFFER;
9716 if ( !make_monitorui_buf( out, dllname )) {
9723 /*******************************************************************
9724 *******************************************************************/
9726 struct xcv_api_table xcvlocal_cmds[] = {
9727 { "MonitorUI", xcvlocal_monitorui },
9731 struct xcv_api_table xcvlocal_cmds[] = {
9738 /*******************************************************************
9739 *******************************************************************/
9741 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9742 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9747 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9749 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9750 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9751 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9753 return WERR_BADFUNC;
9756 /*******************************************************************
9757 *******************************************************************/
9759 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9761 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9765 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9769 /* Has to be a handle to the TCP/IP port monitor */
9771 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9772 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9776 /* requires administrative access to the server */
9778 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9779 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9780 return WERR_ACCESS_DENIED;
9783 /* Get the command name. There's numerous commands supported by the
9784 TCPMON interface. */
9786 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9787 q_u->dataname.uni_str_len*2, 0);
9789 /* Allocate the outgoing buffer */
9791 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9793 switch ( Printer->printer_type ) {
9794 case SPLHND_PORTMON_TCP:
9795 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9796 &q_u->indata, &r_u->outdata, &r_u->needed );
9797 case SPLHND_PORTMON_LOCAL:
9798 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9799 &q_u->indata, &r_u->outdata, &r_u->needed );
9802 return WERR_INVALID_PRINT_MONITOR;