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 3 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, see <http://www.gnu.org/licenses/>.
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26 up, all the errors returned are DOS errors, not NT status codes. */
30 extern userdom_struct current_user_info;
33 #define DBGC_CLASS DBGC_RPC_SRV
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
43 const char *long_archi;
44 const char *short_archi;
48 static Printer_entry *printers_list;
50 typedef struct _counter_printer_0 {
51 struct _counter_printer_0 *next;
52 struct _counter_printer_0 *prev;
58 static counter_printer_0 *counter_list;
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
64 /* in printing/nt_printing.c */
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
68 /* API table for Xcv Monitor functions */
70 struct xcv_api_table {
72 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
76 /* translate between internal status numbers and NT status numbers */
77 static int nt_printj_status(int v)
83 return JOB_STATUS_PAUSED;
85 return JOB_STATUS_SPOOLING;
87 return JOB_STATUS_PRINTING;
89 return JOB_STATUS_ERROR;
91 return JOB_STATUS_DELETING;
93 return JOB_STATUS_OFFLINE;
95 return JOB_STATUS_PAPEROUT;
97 return JOB_STATUS_PRINTED;
99 return JOB_STATUS_DELETED;
101 return JOB_STATUS_BLOCKED;
102 case LPQ_USER_INTERVENTION:
103 return JOB_STATUS_USER_INTERVENTION;
108 static int nt_printq_status(int v)
112 return PRINTER_STATUS_PAUSED;
121 /****************************************************************************
122 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
123 ****************************************************************************/
125 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
130 SAFE_FREE((*pp)->ctr.type);
134 /***************************************************************************
135 Disconnect from the client
136 ****************************************************************************/
138 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
143 * Tell the specific printing tdb we no longer want messages for this printer
144 * by deregistering our PID.
147 if (!print_notify_deregister_pid(snum))
148 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
150 /* weird if the test succeds !!! */
151 if (smb_connections==0) {
152 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
156 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
158 if (!W_ERROR_IS_OK(result))
159 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
160 dos_errstr(result)));
162 /* if it's the last connection, deconnect the IPC$ share */
163 if (smb_connections==1) {
165 cli_shutdown( notify_cli_pipe->cli );
166 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
168 messaging_deregister(smbd_messaging_context(),
169 MSG_PRINTER_NOTIFY2, NULL);
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(smbd_messaging_context(),
315 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
321 /********** END SePrintOperatorPrivlege BLOCK **********/
323 DEBUGADD(10,("returned [%d]\n", ret));
326 return WERR_BADFID; /* What to return here? */
328 /* go ahead and re-read the services immediately */
329 reload_services( False );
331 if ( lp_servicenumber( sharename ) < 0 )
332 return WERR_ACCESS_DENIED;
337 /****************************************************************************
338 Delete a printer given a handle.
339 ****************************************************************************/
341 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
343 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
346 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
351 * It turns out that Windows allows delete printer on a handle
352 * opened by an admin user, then used on a pipe handle created
353 * by an anonymous user..... but they're working on security.... riiight !
357 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
358 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
359 return WERR_ACCESS_DENIED;
362 /* this does not need a become root since the access check has been
363 done on the handle already */
365 if (del_a_printer( Printer->sharename ) != 0) {
366 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
370 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
373 /****************************************************************************
374 Return the snum of a printer corresponding to an handle.
375 ****************************************************************************/
377 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
378 struct share_params **params)
380 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
383 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
387 switch (Printer->printer_type) {
389 DEBUG(4,("short name:%s\n", Printer->sharename));
390 *number = print_queue_snum(Printer->sharename);
391 return (*number != -1);
399 /****************************************************************************
400 Set printer handle type.
401 Check if it's \\server or \\server\printer
402 ****************************************************************************/
404 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
406 DEBUG(3,("Setting printer type=%s\n", handlename));
408 if ( strlen(handlename) < 3 ) {
409 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
413 /* it's a print server */
414 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
415 DEBUGADD(4,("Printer is a print server\n"));
416 Printer->printer_type = SPLHND_SERVER;
418 /* it's a printer (set_printer_hnd_name() will handle port monitors */
420 DEBUGADD(4,("Printer is a printer\n"));
421 Printer->printer_type = SPLHND_PRINTER;
427 /****************************************************************************
428 Set printer handle name.. Accept names like \\server, \\server\printer,
429 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
430 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
431 XcvDataPort() interface.
432 ****************************************************************************/
434 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
437 int n_services=lp_numservices();
438 char *aprinter, *printername;
439 const char *servername;
442 NT_PRINTER_INFO_LEVEL *printer = NULL;
445 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
447 aprinter = handlename;
448 if ( *handlename == '\\' ) {
449 servername = handlename + 2;
450 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
459 /* save the servername to fill in replies on this handle */
461 if ( !is_myname_or_ipaddr( servername ) )
464 fstrcpy( Printer->servername, servername );
466 if ( Printer->printer_type == SPLHND_SERVER )
469 if ( Printer->printer_type != SPLHND_PRINTER )
472 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
474 /* check for the Port Monitor Interface */
476 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
477 Printer->printer_type = SPLHND_PORTMON_TCP;
478 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
481 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
482 Printer->printer_type = SPLHND_PORTMON_LOCAL;
483 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
487 /* Search all sharenames first as this is easier than pulling
488 the printer_info_2 off of disk. Don't use find_service() since
489 that calls out to map_username() */
491 /* do another loop to look for printernames */
493 for (snum=0; !found && snum<n_services; snum++) {
495 /* no point going on if this is not a printer */
497 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
500 fstrcpy(sname, lp_servicename(snum));
501 if ( strequal( aprinter, sname ) ) {
506 /* no point looking up the printer object if
507 we aren't allowing printername != sharename */
509 if ( lp_force_printername(snum) )
512 fstrcpy(sname, lp_servicename(snum));
515 result = get_a_printer( NULL, &printer, 2, sname );
516 if ( !W_ERROR_IS_OK(result) ) {
517 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
518 sname, dos_errstr(result)));
522 /* printername is always returned as \\server\printername */
523 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
524 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
525 printer->info_2->printername));
526 free_a_printer( &printer, 2);
532 if ( strequal(printername, aprinter) ) {
533 free_a_printer( &printer, 2);
538 DEBUGADD(10, ("printername: %s\n", printername));
540 free_a_printer( &printer, 2);
543 free_a_printer( &printer, 2);
546 DEBUGADD(4,("Printer not found\n"));
550 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
552 fstrcpy(Printer->sharename, sname);
557 /****************************************************************************
558 Find first available printer slot. creates a printer handle for you.
559 ****************************************************************************/
561 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
563 Printer_entry *new_printer;
565 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
567 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
570 ZERO_STRUCTP(new_printer);
572 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
573 SAFE_FREE(new_printer);
577 /* Add to the internal list. */
578 DLIST_ADD(printers_list, new_printer);
580 new_printer->notify.option=NULL;
582 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
583 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
584 close_printer_handle(p, hnd);
588 if (!set_printer_hnd_printertype(new_printer, name)) {
589 close_printer_handle(p, hnd);
593 if (!set_printer_hnd_name(new_printer, name)) {
594 close_printer_handle(p, hnd);
598 new_printer->access_granted = access_granted;
600 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
605 /***************************************************************************
606 check to see if the client motify handle is monitoring the notification
607 given by (notify_type, notify_field).
608 **************************************************************************/
610 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
616 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
619 SPOOL_NOTIFY_OPTION *option = p->notify.option;
623 * Flags should always be zero when the change notify
624 * is registered by the client's spooler. A user Win32 app
625 * might use the flags though instead of the NOTIFY_OPTION_INFO
634 return is_monitoring_event_flags(
635 p->notify.flags, notify_type, notify_field);
637 for (i = 0; i < option->count; i++) {
639 /* Check match for notify_type */
641 if (option->ctr.type[i].type != notify_type)
644 /* Check match for field */
646 for (j = 0; j < option->ctr.type[i].count; j++) {
647 if (option->ctr.type[i].fields[j] == notify_field) {
653 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
654 p->servername, p->sharename, notify_type, notify_field));
659 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
661 static void notify_one_value(struct spoolss_notify_msg *msg,
662 SPOOL_NOTIFY_INFO_DATA *data,
665 data->notify_data.value[0] = msg->notify.value[0];
666 data->notify_data.value[1] = 0;
669 static void notify_string(struct spoolss_notify_msg *msg,
670 SPOOL_NOTIFY_INFO_DATA *data,
675 /* The length of the message includes the trailing \0 */
677 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
679 data->notify_data.data.length = msg->len * 2;
680 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
682 if (!data->notify_data.data.string) {
683 data->notify_data.data.length = 0;
687 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
690 static void notify_system_time(struct spoolss_notify_msg *msg,
691 SPOOL_NOTIFY_INFO_DATA *data,
697 if (msg->len != sizeof(time_t)) {
698 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
703 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
704 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
708 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
709 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
714 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
719 data->notify_data.data.length = prs_offset(&ps);
720 if (prs_offset(&ps)) {
721 data->notify_data.data.string = (uint16 *)
722 TALLOC(mem_ctx, prs_offset(&ps));
723 if (!data->notify_data.data.string) {
727 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
729 data->notify_data.data.string = NULL;
735 struct notify2_message_table {
737 void (*fn)(struct spoolss_notify_msg *msg,
738 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
741 static struct notify2_message_table printer_notify_table[] = {
742 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
743 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
744 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
745 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
746 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
747 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
748 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
749 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
750 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
751 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
752 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
753 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
754 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
755 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
756 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
757 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
758 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
759 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
760 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
763 static struct notify2_message_table job_notify_table[] = {
764 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
765 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
766 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
767 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
768 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
769 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
770 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
771 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
772 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
773 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
774 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
775 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
776 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
777 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
778 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
779 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
780 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
781 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
782 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
783 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
784 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
785 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
786 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
787 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
791 /***********************************************************************
792 Allocate talloc context for container object
793 **********************************************************************/
795 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
800 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
805 /***********************************************************************
806 release all allocated memory and zero out structure
807 **********************************************************************/
809 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
815 talloc_destroy(ctr->ctx);
822 /***********************************************************************
823 **********************************************************************/
825 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
833 /***********************************************************************
834 **********************************************************************/
836 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
838 if ( !ctr || !ctr->msg_groups )
841 if ( idx >= ctr->num_groups )
844 return &ctr->msg_groups[idx];
848 /***********************************************************************
849 How many groups of change messages do we have ?
850 **********************************************************************/
852 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
857 return ctr->num_groups;
860 /***********************************************************************
861 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
862 **********************************************************************/
864 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
866 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
867 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
868 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
874 /* loop over all groups looking for a matching printer name */
876 for ( i=0; i<ctr->num_groups; i++ ) {
877 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
881 /* add a new group? */
883 if ( i == ctr->num_groups ) {
886 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
887 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
890 ctr->msg_groups = groups;
892 /* clear the new entry and set the printer name */
894 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
895 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
898 /* add the change messages; 'i' is the correct index now regardless */
900 msg_grp = &ctr->msg_groups[i];
904 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
905 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
908 msg_grp->msgs = msg_list;
910 new_slot = msg_grp->num_msgs-1;
911 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
913 /* need to allocate own copy of data */
916 msg_grp->msgs[new_slot].notify.data = (char *)
917 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
919 return ctr->num_groups;
922 /***********************************************************************
923 Send a change notication message on all handles which have a call
925 **********************************************************************/
927 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
930 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
931 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
932 SPOOLSS_NOTIFY_MSG *messages;
933 int sending_msg_count;
936 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
940 messages = msg_group->msgs;
943 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
947 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
949 /* loop over all printers */
951 for (p = printers_list; p; p = p->next) {
952 SPOOL_NOTIFY_INFO_DATA *data;
957 /* Is there notification on this handle? */
959 if ( !p->notify.client_connected )
962 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
964 /* For this printer? Print servers always receive
967 if ( ( p->printer_type == SPLHND_PRINTER ) &&
968 ( !strequal(msg_group->printername, p->sharename) ) )
971 DEBUG(10,("Our printer\n"));
973 /* allocate the max entries possible */
975 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
982 /* build the array of change notifications */
984 sending_msg_count = 0;
986 for ( i=0; i<msg_group->num_msgs; i++ ) {
987 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
989 /* Are we monitoring this event? */
991 if (!is_monitoring_event(p, msg->type, msg->field))
997 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
998 msg->type, msg->field, p->sharename));
1001 * if the is a printer notification handle and not a job notification
1002 * type, then set the id to 0. Other wise just use what was specified
1005 * When registering change notification on a print server handle
1006 * we always need to send back the id (snum) matching the printer
1007 * for which the change took place. For change notify registered
1008 * on a printer handle, this does not matter and the id should be 0.
1013 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1019 /* Convert unix jobid to smb jobid */
1021 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1022 id = sysjob_to_jobid(msg->id);
1025 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1030 construct_info_data( &data[data_len], msg->type, msg->field, id );
1033 case PRINTER_NOTIFY_TYPE:
1034 if ( printer_notify_table[msg->field].fn )
1035 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1038 case JOB_NOTIFY_TYPE:
1039 if ( job_notify_table[msg->field].fn )
1040 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1044 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1051 if ( sending_msg_count ) {
1052 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1053 data_len, data, p->notify.change, 0 );
1058 DEBUG(8,("send_notify2_changes: Exit...\n"));
1062 /***********************************************************************
1063 **********************************************************************/
1065 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1068 uint32 tv_sec, tv_usec;
1071 /* Unpack message */
1073 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1076 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1078 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1081 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1082 &msg->notify.value[0], &msg->notify.value[1]);
1084 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1085 &msg->len, &msg->notify.data);
1087 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1088 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1090 tv->tv_sec = tv_sec;
1091 tv->tv_usec = tv_usec;
1094 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1095 msg->notify.value[1]));
1097 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1102 /********************************************************************
1103 Receive a notify2 message list
1104 ********************************************************************/
1106 static void receive_notify2_message_list(struct messaging_context *msg,
1109 struct server_id server_id,
1112 size_t msg_count, i;
1113 char *buf = (char *)data->data;
1116 SPOOLSS_NOTIFY_MSG notify;
1117 SPOOLSS_NOTIFY_MSG_CTR messages;
1120 if (data->length < 4) {
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 > data->length) {
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 > data->length) {
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 messaging_send_buf(smbd_messaging_context(), procid_self(),
1212 MSG_PRINTER_DRVUPGRADE,
1213 (uint8 *)drivername, len+1);
1218 /**********************************************************************
1219 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1220 over all printers, upgrading ones as necessary
1221 **********************************************************************/
1223 void do_drv_upgrade_printer(struct messaging_context *msg,
1226 struct server_id server_id,
1231 int n_services = lp_numservices();
1234 len = MIN(data->length,sizeof(drivername)-1);
1235 strncpy(drivername, (const char *)data->data, len);
1237 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1239 /* Iterate the printer list */
1241 for (snum=0; snum<n_services; snum++)
1243 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1246 NT_PRINTER_INFO_LEVEL *printer = NULL;
1248 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1249 if (!W_ERROR_IS_OK(result))
1252 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1254 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1256 /* all we care about currently is the change_id */
1258 result = mod_a_printer(printer, 2);
1259 if (!W_ERROR_IS_OK(result)) {
1260 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1261 dos_errstr(result)));
1265 free_a_printer(&printer, 2);
1272 /********************************************************************
1273 Update the cache for all printq's with a registered client
1275 ********************************************************************/
1277 void update_monitored_printq_cache( void )
1279 Printer_entry *printer = printers_list;
1282 /* loop through all printers and update the cache where
1283 client_connected == True */
1286 if ( (printer->printer_type == SPLHND_PRINTER)
1287 && printer->notify.client_connected )
1289 snum = print_queue_snum(printer->sharename);
1290 print_queue_status( snum, NULL, NULL );
1293 printer = printer->next;
1298 /********************************************************************
1299 Send a message to ourself about new driver being installed
1300 so we can upgrade the information for each printer bound to this
1302 ********************************************************************/
1304 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1306 int len = strlen(drivername);
1311 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1314 messaging_send_buf(smbd_messaging_context(), procid_self(),
1315 MSG_PRINTERDATA_INIT_RESET,
1316 (uint8 *)drivername, len+1);
1321 /**********************************************************************
1322 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1323 over all printers, resetting printer data as neessary
1324 **********************************************************************/
1326 void reset_all_printerdata(struct messaging_context *msg,
1329 struct server_id server_id,
1334 int n_services = lp_numservices();
1337 len = MIN( data->length, sizeof(drivername)-1 );
1338 strncpy( drivername, (const char *)data->data, len );
1340 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1342 /* Iterate the printer list */
1344 for ( snum=0; snum<n_services; snum++ )
1346 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1349 NT_PRINTER_INFO_LEVEL *printer = NULL;
1351 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1352 if ( !W_ERROR_IS_OK(result) )
1356 * if the printer is bound to the driver,
1357 * then reset to the new driver initdata
1360 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1362 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1364 if ( !set_driver_init(printer, 2) ) {
1365 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1366 printer->info_2->printername, printer->info_2->drivername));
1369 result = mod_a_printer( printer, 2 );
1370 if ( !W_ERROR_IS_OK(result) ) {
1371 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1372 get_dos_error_msg(result)));
1376 free_a_printer( &printer, 2 );
1385 /********************************************************************
1386 Copy routines used by convert_to_openprinterex()
1387 *******************************************************************/
1389 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1397 DEBUG (8,("dup_devmode\n"));
1399 /* bulk copy first */
1401 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1405 /* dup the pointer members separately */
1407 len = unistrlen(devmode->devicename.buffer);
1409 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1410 if (!d->devicename.buffer) {
1413 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1418 len = unistrlen(devmode->formname.buffer);
1420 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1421 if (!d->devicename.buffer) {
1424 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1428 if (devmode->driverextra) {
1429 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1430 devmode->driverextra);
1431 if (!d->dev_private) {
1435 d->dev_private = NULL;
1440 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1442 if (!new_ctr || !ctr)
1445 DEBUG(8,("copy_devmode_ctr\n"));
1447 new_ctr->size = ctr->size;
1448 new_ctr->devmode_ptr = ctr->devmode_ptr;
1450 if(ctr->devmode_ptr)
1451 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1454 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1456 if (!new_def || !def)
1459 DEBUG(8,("copy_printer_defaults\n"));
1461 new_def->datatype_ptr = def->datatype_ptr;
1463 if (def->datatype_ptr)
1464 copy_unistr2(&new_def->datatype, &def->datatype);
1466 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1468 new_def->access_required = def->access_required;
1471 /********************************************************************
1472 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1473 * SPOOL_Q_OPEN_PRINTER_EX structure
1474 ********************************************************************/
1476 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1478 if (!q_u_ex || !q_u)
1481 DEBUG(8,("convert_to_openprinterex\n"));
1483 if ( q_u->printername ) {
1484 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1485 if (q_u_ex->printername == NULL)
1487 copy_unistr2(q_u_ex->printername, q_u->printername);
1490 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1495 /********************************************************************
1496 * spoolss_open_printer
1498 * called from the spoolss dispatcher
1499 ********************************************************************/
1501 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1503 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1504 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1509 ZERO_STRUCT(q_u_ex);
1510 ZERO_STRUCT(r_u_ex);
1512 /* convert the OpenPrinter() call to OpenPrinterEx() */
1514 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1515 if (!W_ERROR_IS_OK(r_u_ex.status))
1516 return r_u_ex.status;
1518 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1520 /* convert back to OpenPrinter() */
1522 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1527 /********************************************************************
1528 ********************************************************************/
1530 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1532 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1533 POLICY_HND *handle = &r_u->handle;
1537 Printer_entry *Printer=NULL;
1539 if ( !q_u->printername )
1540 return WERR_INVALID_PRINTER_NAME;
1542 /* some sanity check because you can open a printer or a print server */
1543 /* aka: \\server\printer or \\server */
1545 unistr2_to_ascii(name, q_u->printername, sizeof(name));
1547 DEBUGADD(3,("checking name: %s\n",name));
1549 if (!open_printer_hnd(p, handle, name, 0))
1550 return WERR_INVALID_PRINTER_NAME;
1552 Printer=find_printer_index_by_hnd(p, handle);
1554 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1555 "handle we created for printer %s\n", name ));
1556 close_printer_handle(p,handle);
1557 return WERR_INVALID_PRINTER_NAME;
1561 * First case: the user is opening the print server:
1563 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1564 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1566 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1567 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1568 * or if the user is listed in the smb.conf printer admin parameter.
1570 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1571 * client view printer folder, but does not show the MSAPW.
1573 * Note: this test needs code to check access rights here too. Jeremy
1574 * could you look at this?
1576 * Second case: the user is opening a printer:
1577 * NT doesn't let us connect to a printer if the connecting user
1578 * doesn't have print permission.
1580 * Third case: user is opening a Port Monitor
1581 * access checks same as opening a handle to the print server.
1584 switch (Printer->printer_type )
1587 case SPLHND_PORTMON_TCP:
1588 case SPLHND_PORTMON_LOCAL:
1589 /* Printserver handles use global struct... */
1593 /* Map standard access rights to object specific access rights */
1595 se_map_standard(&printer_default->access_required,
1596 &printserver_std_mapping);
1598 /* Deny any object specific bits that don't apply to print
1599 servers (i.e printer and job specific bits) */
1601 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1603 if (printer_default->access_required &
1604 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1605 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1606 close_printer_handle(p, handle);
1607 return WERR_ACCESS_DENIED;
1610 /* Allow admin access */
1612 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1614 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1616 if (!lp_ms_add_printer_wizard()) {
1617 close_printer_handle(p, handle);
1618 return WERR_ACCESS_DENIED;
1621 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1622 and not a printer admin, then fail */
1624 if ((p->pipe_user.ut.uid != 0) &&
1625 !user_has_privileges(p->pipe_user.nt_user_token,
1627 !token_contains_name_in_list(
1628 uidtoname(p->pipe_user.ut.uid), NULL,
1629 p->pipe_user.nt_user_token,
1630 lp_printer_admin(snum))) {
1631 close_printer_handle(p, handle);
1632 return WERR_ACCESS_DENIED;
1635 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1639 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1642 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1643 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1645 /* We fall through to return WERR_OK */
1648 case SPLHND_PRINTER:
1649 /* NT doesn't let us connect to a printer if the connecting user
1650 doesn't have print permission. */
1652 if (!get_printer_snum(p, handle, &snum, NULL)) {
1653 close_printer_handle(p, handle);
1657 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1659 /* map an empty access mask to the minimum access mask */
1660 if (printer_default->access_required == 0x0)
1661 printer_default->access_required = PRINTER_ACCESS_USE;
1664 * If we are not serving the printer driver for this printer,
1665 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1666 * will keep NT clients happy --jerry
1669 if (lp_use_client_driver(snum)
1670 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1672 printer_default->access_required = PRINTER_ACCESS_USE;
1675 /* check smb.conf parameters and the the sec_desc */
1677 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1678 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1679 return WERR_ACCESS_DENIED;
1682 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1683 p->pipe_user.nt_user_token, snum) ||
1684 !print_access_check(&p->pipe_user, snum,
1685 printer_default->access_required)) {
1686 DEBUG(3, ("access DENIED for printer open\n"));
1687 close_printer_handle(p, handle);
1688 return WERR_ACCESS_DENIED;
1691 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1692 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1693 close_printer_handle(p, handle);
1694 return WERR_ACCESS_DENIED;
1697 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1698 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1700 printer_default->access_required = PRINTER_ACCESS_USE;
1702 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1703 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1708 /* sanity check to prevent programmer error */
1712 Printer->access_granted = printer_default->access_required;
1715 * If the client sent a devmode in the OpenPrinter() call, then
1716 * save it here in case we get a job submission on this handle
1719 if ( (Printer->printer_type != SPLHND_SERVER)
1720 && q_u->printer_default.devmode_cont.devmode_ptr )
1722 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1723 &Printer->nt_devmode );
1726 #if 0 /* JERRY -- I'm doubtful this is really effective */
1727 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1728 optimization in Windows 2000 clients --jerry */
1730 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1731 && (RA_WIN2K == get_remote_arch()) )
1733 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1734 sys_usleep( 500000 );
1741 /****************************************************************************
1742 ****************************************************************************/
1744 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1745 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1751 /* allocate memory if needed. Messy because
1752 convert_printer_info is used to update an existing
1753 printer or build a new one */
1755 if ( !printer->info_2 ) {
1756 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1757 if ( !printer->info_2 ) {
1758 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1763 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1764 printer->info_2->setuptime = time(NULL);
1772 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1773 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1779 printer->info_3=NULL;
1780 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1784 printer->info_6=NULL;
1785 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1795 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1796 NT_DEVICEMODE **pp_nt_devmode)
1798 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1801 * Ensure nt_devmode is a valid pointer
1802 * as we will be overwriting it.
1805 if (nt_devmode == NULL) {
1806 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1807 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1811 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1812 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1814 nt_devmode->specversion=devmode->specversion;
1815 nt_devmode->driverversion=devmode->driverversion;
1816 nt_devmode->size=devmode->size;
1817 nt_devmode->fields=devmode->fields;
1818 nt_devmode->orientation=devmode->orientation;
1819 nt_devmode->papersize=devmode->papersize;
1820 nt_devmode->paperlength=devmode->paperlength;
1821 nt_devmode->paperwidth=devmode->paperwidth;
1822 nt_devmode->scale=devmode->scale;
1823 nt_devmode->copies=devmode->copies;
1824 nt_devmode->defaultsource=devmode->defaultsource;
1825 nt_devmode->printquality=devmode->printquality;
1826 nt_devmode->color=devmode->color;
1827 nt_devmode->duplex=devmode->duplex;
1828 nt_devmode->yresolution=devmode->yresolution;
1829 nt_devmode->ttoption=devmode->ttoption;
1830 nt_devmode->collate=devmode->collate;
1832 nt_devmode->logpixels=devmode->logpixels;
1833 nt_devmode->bitsperpel=devmode->bitsperpel;
1834 nt_devmode->pelswidth=devmode->pelswidth;
1835 nt_devmode->pelsheight=devmode->pelsheight;
1836 nt_devmode->displayflags=devmode->displayflags;
1837 nt_devmode->displayfrequency=devmode->displayfrequency;
1838 nt_devmode->icmmethod=devmode->icmmethod;
1839 nt_devmode->icmintent=devmode->icmintent;
1840 nt_devmode->mediatype=devmode->mediatype;
1841 nt_devmode->dithertype=devmode->dithertype;
1842 nt_devmode->reserved1=devmode->reserved1;
1843 nt_devmode->reserved2=devmode->reserved2;
1844 nt_devmode->panningwidth=devmode->panningwidth;
1845 nt_devmode->panningheight=devmode->panningheight;
1848 * Only change private and driverextra if the incoming devmode
1849 * has a new one. JRA.
1852 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1853 SAFE_FREE(nt_devmode->nt_dev_private);
1854 nt_devmode->driverextra=devmode->driverextra;
1855 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1857 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1860 *pp_nt_devmode = nt_devmode;
1865 /********************************************************************
1866 * _spoolss_enddocprinter_internal.
1867 ********************************************************************/
1869 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1871 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1875 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1879 if (!get_printer_snum(p, handle, &snum, NULL))
1882 Printer->document_started=False;
1883 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1884 /* error codes unhandled so far ... */
1889 /********************************************************************
1890 * api_spoolss_closeprinter
1891 ********************************************************************/
1893 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1895 POLICY_HND *handle = &q_u->handle;
1897 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1899 if (Printer && Printer->document_started)
1900 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1902 if (!close_printer_handle(p, handle))
1905 /* clear the returned printer handle. Observed behavior
1906 from Win2k server. Don't think this really matters.
1907 Previous code just copied the value of the closed
1910 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1915 /********************************************************************
1916 * api_spoolss_deleteprinter
1918 ********************************************************************/
1920 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1922 POLICY_HND *handle = &q_u->handle;
1923 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1926 if (Printer && Printer->document_started)
1927 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1929 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1931 result = delete_printer_handle(p, handle);
1933 update_c_setprinter(False);
1938 /*******************************************************************
1939 * static function to lookup the version id corresponding to an
1940 * long architecture string
1941 ******************************************************************/
1943 static int get_version_id (char * arch)
1946 struct table_node archi_table[]= {
1948 {"Windows 4.0", "WIN40", 0 },
1949 {"Windows NT x86", "W32X86", 2 },
1950 {"Windows NT R4000", "W32MIPS", 2 },
1951 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1952 {"Windows NT PowerPC", "W32PPC", 2 },
1953 {"Windows IA64", "IA64", 3 },
1954 {"Windows x64", "x64", 3 },
1958 for (i=0; archi_table[i].long_archi != NULL; i++)
1960 if (strcmp(arch, archi_table[i].long_archi) == 0)
1961 return (archi_table[i].version);
1967 /********************************************************************
1968 * _spoolss_deleteprinterdriver
1969 ********************************************************************/
1971 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1975 NT_PRINTER_DRIVER_INFO_LEVEL info;
1976 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1979 WERROR status_win2k = WERR_ACCESS_DENIED;
1980 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1982 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1983 and not a printer admin, then fail */
1985 if ( (p->pipe_user.ut.uid != 0)
1986 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
1987 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
1988 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
1990 return WERR_ACCESS_DENIED;
1993 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
1994 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
1996 /* check that we have a valid driver name first */
1998 if ((version=get_version_id(arch)) == -1)
1999 return WERR_INVALID_ENVIRONMENT;
2002 ZERO_STRUCT(info_win2k);
2004 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2006 /* try for Win2k driver if "Windows NT x86" */
2008 if ( version == 2 ) {
2010 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2011 status = WERR_UNKNOWN_PRINTER_DRIVER;
2015 /* otherwise it was a failure */
2017 status = WERR_UNKNOWN_PRINTER_DRIVER;
2023 if (printer_driver_in_use(info.info_3)) {
2024 status = WERR_PRINTER_DRIVER_IN_USE;
2030 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2032 /* if we get to here, we now have 2 driver info structures to remove */
2033 /* remove the Win2k driver first*/
2035 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2036 free_a_printer_driver( info_win2k, 3 );
2038 /* this should not have failed---if it did, report to client */
2039 if ( !W_ERROR_IS_OK(status_win2k) )
2041 status = status_win2k;
2047 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2049 /* if at least one of the deletes succeeded return OK */
2051 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2055 free_a_printer_driver( info, 3 );
2060 /********************************************************************
2061 * spoolss_deleteprinterdriverex
2062 ********************************************************************/
2064 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2068 NT_PRINTER_DRIVER_INFO_LEVEL info;
2069 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2071 uint32 flags = q_u->delete_flags;
2074 WERROR status_win2k = WERR_ACCESS_DENIED;
2075 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2077 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2078 and not a printer admin, then fail */
2080 if ( (p->pipe_user.ut.uid != 0)
2081 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2082 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2083 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2085 return WERR_ACCESS_DENIED;
2088 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2089 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2091 /* check that we have a valid driver name first */
2092 if ((version=get_version_id(arch)) == -1) {
2093 /* this is what NT returns */
2094 return WERR_INVALID_ENVIRONMENT;
2097 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2098 version = q_u->version;
2101 ZERO_STRUCT(info_win2k);
2103 status = get_a_printer_driver(&info, 3, driver, arch, version);
2105 if ( !W_ERROR_IS_OK(status) )
2108 * if the client asked for a specific version,
2109 * or this is something other than Windows NT x86,
2113 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2116 /* try for Win2k driver if "Windows NT x86" */
2119 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2120 status = WERR_UNKNOWN_PRINTER_DRIVER;
2125 if ( printer_driver_in_use(info.info_3) ) {
2126 status = WERR_PRINTER_DRIVER_IN_USE;
2131 * we have a couple of cases to consider.
2132 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2133 * then the delete should fail if **any** files overlap with
2135 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2136 * non-overlapping files
2137 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2138 * is set, the do not delete any files
2139 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2142 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2144 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2146 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2147 /* no idea of the correct error here */
2148 status = WERR_ACCESS_DENIED;
2153 /* also check for W32X86/3 if necessary; maybe we already have? */
2155 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2156 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2159 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2160 /* no idea of the correct error here */
2161 free_a_printer_driver( info_win2k, 3 );
2162 status = WERR_ACCESS_DENIED;
2166 /* if we get to here, we now have 2 driver info structures to remove */
2167 /* remove the Win2k driver first*/
2169 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2170 free_a_printer_driver( info_win2k, 3 );
2172 /* this should not have failed---if it did, report to client */
2174 if ( !W_ERROR_IS_OK(status_win2k) )
2179 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2181 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2184 free_a_printer_driver( info, 3 );
2190 /****************************************************************************
2191 Internal routine for retreiving printerdata
2192 ***************************************************************************/
2194 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2195 const char *key, const char *value, uint32 *type, uint8 **data,
2196 uint32 *needed, uint32 in_size )
2198 REGISTRY_VALUE *val;
2202 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2203 return WERR_BADFILE;
2205 *type = regval_type( val );
2207 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2209 size = regval_size( val );
2211 /* copy the min(in_size, len) */
2214 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2216 /* special case for 0 length values */
2218 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2222 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2231 DEBUG(5,("get_printer_dataex: copy done\n"));
2236 /****************************************************************************
2237 Internal routine for removing printerdata
2238 ***************************************************************************/
2240 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2242 return delete_printer_data( printer->info_2, key, value );
2245 /****************************************************************************
2246 Internal routine for storing printerdata
2247 ***************************************************************************/
2249 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2250 uint32 type, uint8 *data, int real_len )
2252 /* the registry objects enforce uniqueness based on value name */
2254 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2257 /********************************************************************
2258 GetPrinterData on a printer server Handle.
2259 ********************************************************************/
2261 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2265 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2267 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2269 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2271 SIVAL(*data, 0, 0x00);
2276 if (!StrCaseCmp(value, "BeepEnabled")) {
2278 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2280 SIVAL(*data, 0, 0x00);
2285 if (!StrCaseCmp(value, "EventLog")) {
2287 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2289 /* formally was 0x1b */
2290 SIVAL(*data, 0, 0x0);
2295 if (!StrCaseCmp(value, "NetPopup")) {
2297 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2299 SIVAL(*data, 0, 0x00);
2304 if (!StrCaseCmp(value, "MajorVersion")) {
2306 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2309 /* Windows NT 4.0 seems to not allow uploading of drivers
2310 to a server that reports 0x3 as the MajorVersion.
2311 need to investigate more how Win2k gets around this .
2314 if ( RA_WINNT == get_remote_arch() )
2323 if (!StrCaseCmp(value, "MinorVersion")) {
2325 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2333 * uint32 size = 0x114
2335 * uint32 minor = [0|1]
2336 * uint32 build = [2195|2600]
2337 * extra unicode string = e.g. "Service Pack 3"
2339 if (!StrCaseCmp(value, "OSVersion")) {
2343 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2346 SIVAL(*data, 0, *needed); /* size */
2347 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2349 SIVAL(*data, 12, 2195); /* build */
2351 /* leave extra string empty */
2357 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2358 const char *string="C:\\PRINTERS";
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);
2365 /* it's done by hand ready to go on the wire */
2366 for (i=0; i<strlen(string); i++) {
2367 (*data)[2*i]=string[i];
2368 (*data)[2*i+1]='\0';
2373 if (!StrCaseCmp(value, "Architecture")) {
2374 const char *string="Windows NT x86";
2376 *needed = 2*(strlen(string)+1);
2377 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2379 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2380 for (i=0; i<strlen(string); i++) {
2381 (*data)[2*i]=string[i];
2382 (*data)[2*i+1]='\0';
2387 if (!StrCaseCmp(value, "DsPresent")) {
2389 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2392 /* only show the publish check box if we are a
2393 memeber of a AD domain */
2395 if ( lp_security() == SEC_ADS )
2396 SIVAL(*data, 0, 0x01);
2398 SIVAL(*data, 0, 0x00);
2404 if (!StrCaseCmp(value, "DNSMachineName")) {
2407 if (!get_mydnsfullname(hostname))
2408 return WERR_BADFILE;
2410 *needed = 2*(strlen(hostname)+1);
2411 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2413 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2414 for (i=0; i<strlen(hostname); i++) {
2415 (*data)[2*i]=hostname[i];
2416 (*data)[2*i+1]='\0';
2422 return WERR_BADFILE;
2425 /********************************************************************
2426 * spoolss_getprinterdata
2427 ********************************************************************/
2429 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2431 POLICY_HND *handle = &q_u->handle;
2432 UNISTR2 *valuename = &q_u->valuename;
2433 uint32 in_size = q_u->size;
2434 uint32 *type = &r_u->type;
2435 uint32 *out_size = &r_u->size;
2436 uint8 **data = &r_u->data;
2437 uint32 *needed = &r_u->needed;
2440 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2441 NT_PRINTER_INFO_LEVEL *printer = NULL;
2445 * Reminder: when it's a string, the length is in BYTES
2446 * even if UNICODE is negociated.
2451 *out_size = in_size;
2453 /* in case of problem, return some default values */
2458 DEBUG(4,("_spoolss_getprinterdata\n"));
2461 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2462 status = WERR_BADFID;
2466 unistr2_to_ascii(value, valuename, sizeof(value));
2468 if ( Printer->printer_type == SPLHND_SERVER )
2469 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2472 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2473 status = WERR_BADFID;
2477 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2478 if ( !W_ERROR_IS_OK(status) )
2481 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2483 if ( strequal(value, "ChangeId") ) {
2485 *needed = sizeof(uint32);
2486 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2487 status = WERR_NOMEM;
2490 SIVAL( *data, 0, printer->info_2->changeid );
2494 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2497 if (*needed > *out_size)
2498 status = WERR_MORE_DATA;
2501 if ( !W_ERROR_IS_OK(status) )
2503 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2505 /* reply this param doesn't exist */
2508 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2510 free_a_printer( &printer, 2 );
2518 /* cleanup & exit */
2521 free_a_printer( &printer, 2 );
2526 /*********************************************************
2527 Connect to the client machine.
2528 **********************************************************/
2530 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2531 struct in_addr *client_ip, const char *remote_machine)
2534 struct cli_state *the_cli;
2535 struct in_addr rm_addr;
2537 if ( is_zero_ip(*client_ip) ) {
2538 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2539 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2543 if ( ismyip( rm_addr )) {
2544 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2548 rm_addr.s_addr = client_ip->s_addr;
2549 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2550 inet_ntoa(*client_ip) ));
2553 /* setup the connection */
2555 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2556 &rm_addr, 0, "IPC$", "IPC",
2560 0, lp_client_signing(), NULL );
2562 if ( !NT_STATUS_IS_OK( ret ) ) {
2563 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2568 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2569 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2570 cli_shutdown(the_cli);
2575 * Ok - we have an anonymous connection to the IPC$ share.
2576 * Now start the NT Domain stuff :-).
2579 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2580 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2581 remote_machine, nt_errstr(ret)));
2582 cli_shutdown(the_cli);
2586 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2588 (*pp_pipe)->cli = the_cli;
2593 /***************************************************************************
2594 Connect to the client.
2595 ****************************************************************************/
2597 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2598 uint32 localprinter, uint32 type,
2599 POLICY_HND *handle, struct in_addr *client_ip)
2604 * If it's the first connection, contact the client
2605 * and connect to the IPC$ share anonymously
2607 if (smb_connections==0) {
2608 fstring unix_printer;
2610 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2612 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2615 messaging_register(smbd_messaging_context(), NULL,
2616 MSG_PRINTER_NOTIFY2,
2617 receive_notify2_message_list);
2618 /* Tell the connections db we're now interested in printer
2619 * notify messages. */
2620 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2624 * Tell the specific printing tdb we want messages for this printer
2625 * by registering our PID.
2628 if (!print_notify_register_pid(snum))
2629 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2633 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2636 if (!W_ERROR_IS_OK(result))
2637 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2638 dos_errstr(result)));
2640 return (W_ERROR_IS_OK(result));
2643 /********************************************************************
2645 * ReplyFindFirstPrinterChangeNotifyEx
2647 * before replying OK: status=0 a rpc call is made to the workstation
2648 * asking ReplyOpenPrinter
2650 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2651 * called from api_spoolss_rffpcnex
2652 ********************************************************************/
2654 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2656 POLICY_HND *handle = &q_u->handle;
2657 uint32 flags = q_u->flags;
2658 uint32 options = q_u->options;
2659 UNISTR2 *localmachine = &q_u->localmachine;
2660 uint32 printerlocal = q_u->printerlocal;
2662 SPOOL_NOTIFY_OPTION *option = q_u->option;
2663 struct in_addr client_ip;
2665 /* store the notify value in the printer struct */
2667 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2670 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2674 Printer->notify.flags=flags;
2675 Printer->notify.options=options;
2676 Printer->notify.printerlocal=printerlocal;
2678 if (Printer->notify.option)
2679 free_spool_notify_option(&Printer->notify.option);
2681 Printer->notify.option=dup_spool_notify_option(option);
2683 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2684 sizeof(Printer->notify.localmachine));
2686 /* Connect to the client machine and send a ReplyOpenPrinter */
2688 if ( Printer->printer_type == SPLHND_SERVER)
2690 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2691 !get_printer_snum(p, handle, &snum, NULL) )
2694 client_ip.s_addr = inet_addr(p->conn->client_address);
2696 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2697 Printer->notify.printerlocal, 1,
2698 &Printer->notify.client_hnd, &client_ip))
2699 return WERR_SERVER_UNAVAILABLE;
2701 Printer->notify.client_connected=True;
2706 /*******************************************************************
2707 * fill a notify_info_data with the servername
2708 ********************************************************************/
2710 void spoolss_notify_server_name(int snum,
2711 SPOOL_NOTIFY_INFO_DATA *data,
2712 print_queue_struct *queue,
2713 NT_PRINTER_INFO_LEVEL *printer,
2714 TALLOC_CTX *mem_ctx)
2719 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2721 data->notify_data.data.length = len;
2723 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2724 if (!data->notify_data.data.string) {
2725 data->notify_data.data.length = 0;
2729 memcpy(data->notify_data.data.string, temp, len);
2731 data->notify_data.data.string = NULL;
2735 /*******************************************************************
2736 * fill a notify_info_data with the printername (not including the servername).
2737 ********************************************************************/
2739 void spoolss_notify_printer_name(int snum,
2740 SPOOL_NOTIFY_INFO_DATA *data,
2741 print_queue_struct *queue,
2742 NT_PRINTER_INFO_LEVEL *printer,
2743 TALLOC_CTX *mem_ctx)
2748 /* the notify name should not contain the \\server\ part */
2749 char *p = strrchr(printer->info_2->printername, '\\');
2752 p = printer->info_2->printername;
2757 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2759 data->notify_data.data.length = len;
2761 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2762 if (!data->notify_data.data.string) {
2763 data->notify_data.data.length = 0;
2766 memcpy(data->notify_data.data.string, temp, len);
2768 data->notify_data.data.string = NULL;
2772 /*******************************************************************
2773 * fill a notify_info_data with the servicename
2774 ********************************************************************/
2776 void spoolss_notify_share_name(int snum,
2777 SPOOL_NOTIFY_INFO_DATA *data,
2778 print_queue_struct *queue,
2779 NT_PRINTER_INFO_LEVEL *printer,
2780 TALLOC_CTX *mem_ctx)
2785 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2787 data->notify_data.data.length = len;
2789 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2790 if (!data->notify_data.data.string) {
2791 data->notify_data.data.length = 0;
2794 memcpy(data->notify_data.data.string, temp, len);
2796 data->notify_data.data.string = NULL;
2801 /*******************************************************************
2802 * fill a notify_info_data with the port name
2803 ********************************************************************/
2805 void spoolss_notify_port_name(int snum,
2806 SPOOL_NOTIFY_INFO_DATA *data,
2807 print_queue_struct *queue,
2808 NT_PRINTER_INFO_LEVEL *printer,
2809 TALLOC_CTX *mem_ctx)
2814 /* even if it's strange, that's consistant in all the code */
2816 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2818 data->notify_data.data.length = len;
2820 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2822 if (!data->notify_data.data.string) {
2823 data->notify_data.data.length = 0;
2827 memcpy(data->notify_data.data.string, temp, len);
2829 data->notify_data.data.string = NULL;
2833 /*******************************************************************
2834 * fill a notify_info_data with the printername
2835 * but it doesn't exist, have to see what to do
2836 ********************************************************************/
2838 void spoolss_notify_driver_name(int snum,
2839 SPOOL_NOTIFY_INFO_DATA *data,
2840 print_queue_struct *queue,
2841 NT_PRINTER_INFO_LEVEL *printer,
2842 TALLOC_CTX *mem_ctx)
2847 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2849 data->notify_data.data.length = len;
2851 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2853 if (!data->notify_data.data.string) {
2854 data->notify_data.data.length = 0;
2858 memcpy(data->notify_data.data.string, temp, len);
2860 data->notify_data.data.string = NULL;
2864 /*******************************************************************
2865 * fill a notify_info_data with the comment
2866 ********************************************************************/
2868 void spoolss_notify_comment(int snum,
2869 SPOOL_NOTIFY_INFO_DATA *data,
2870 print_queue_struct *queue,
2871 NT_PRINTER_INFO_LEVEL *printer,
2872 TALLOC_CTX *mem_ctx)
2877 if (*printer->info_2->comment == '\0')
2878 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2880 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2882 data->notify_data.data.length = len;
2884 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2886 if (!data->notify_data.data.string) {
2887 data->notify_data.data.length = 0;
2891 memcpy(data->notify_data.data.string, temp, len);
2893 data->notify_data.data.string = NULL;
2897 /*******************************************************************
2898 * fill a notify_info_data with the comment
2899 * location = "Room 1, floor 2, building 3"
2900 ********************************************************************/
2902 void spoolss_notify_location(int snum,
2903 SPOOL_NOTIFY_INFO_DATA *data,
2904 print_queue_struct *queue,
2905 NT_PRINTER_INFO_LEVEL *printer,
2906 TALLOC_CTX *mem_ctx)
2911 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2913 data->notify_data.data.length = len;
2915 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2917 if (!data->notify_data.data.string) {
2918 data->notify_data.data.length = 0;
2922 memcpy(data->notify_data.data.string, temp, len);
2924 data->notify_data.data.string = NULL;
2928 /*******************************************************************
2929 * fill a notify_info_data with the device mode
2930 * jfm:xxxx don't to it for know but that's a real problem !!!
2931 ********************************************************************/
2933 static void spoolss_notify_devmode(int snum,
2934 SPOOL_NOTIFY_INFO_DATA *data,
2935 print_queue_struct *queue,
2936 NT_PRINTER_INFO_LEVEL *printer,
2937 TALLOC_CTX *mem_ctx)
2939 /* for a dummy implementation we have to zero the fields */
2940 data->notify_data.data.length = 0;
2941 data->notify_data.data.string = NULL;
2944 /*******************************************************************
2945 * fill a notify_info_data with the separator file name
2946 ********************************************************************/
2948 void spoolss_notify_sepfile(int snum,
2949 SPOOL_NOTIFY_INFO_DATA *data,
2950 print_queue_struct *queue,
2951 NT_PRINTER_INFO_LEVEL *printer,
2952 TALLOC_CTX *mem_ctx)
2957 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2959 data->notify_data.data.length = len;
2961 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2963 if (!data->notify_data.data.string) {
2964 data->notify_data.data.length = 0;
2968 memcpy(data->notify_data.data.string, temp, len);
2970 data->notify_data.data.string = NULL;
2974 /*******************************************************************
2975 * fill a notify_info_data with the print processor
2976 * jfm:xxxx return always winprint to indicate we don't do anything to it
2977 ********************************************************************/
2979 void spoolss_notify_print_processor(int snum,
2980 SPOOL_NOTIFY_INFO_DATA *data,
2981 print_queue_struct *queue,
2982 NT_PRINTER_INFO_LEVEL *printer,
2983 TALLOC_CTX *mem_ctx)
2988 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2990 data->notify_data.data.length = len;
2992 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2994 if (!data->notify_data.data.string) {
2995 data->notify_data.data.length = 0;
2999 memcpy(data->notify_data.data.string, temp, len);
3001 data->notify_data.data.string = NULL;
3005 /*******************************************************************
3006 * fill a notify_info_data with the print processor options
3007 * jfm:xxxx send an empty string
3008 ********************************************************************/
3010 void spoolss_notify_parameters(int snum,
3011 SPOOL_NOTIFY_INFO_DATA *data,
3012 print_queue_struct *queue,
3013 NT_PRINTER_INFO_LEVEL *printer,
3014 TALLOC_CTX *mem_ctx)
3019 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3021 data->notify_data.data.length = len;
3023 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3025 if (!data->notify_data.data.string) {
3026 data->notify_data.data.length = 0;
3030 memcpy(data->notify_data.data.string, temp, len);
3032 data->notify_data.data.string = NULL;
3036 /*******************************************************************
3037 * fill a notify_info_data with the data type
3038 * jfm:xxxx always send RAW as data type
3039 ********************************************************************/
3041 void spoolss_notify_datatype(int snum,
3042 SPOOL_NOTIFY_INFO_DATA *data,
3043 print_queue_struct *queue,
3044 NT_PRINTER_INFO_LEVEL *printer,
3045 TALLOC_CTX *mem_ctx)
3050 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3052 data->notify_data.data.length = len;
3054 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3056 if (!data->notify_data.data.string) {
3057 data->notify_data.data.length = 0;
3061 memcpy(data->notify_data.data.string, temp, len);
3063 data->notify_data.data.string = NULL;
3067 /*******************************************************************
3068 * fill a notify_info_data with the security descriptor
3069 * jfm:xxxx send an null pointer to say no security desc
3070 * have to implement security before !
3071 ********************************************************************/
3073 static void spoolss_notify_security_desc(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.sd.size = printer->info_2->secdesc_buf->sd_size;
3080 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3083 /*******************************************************************
3084 * fill a notify_info_data with the attributes
3085 * jfm:xxxx a samba printer is always shared
3086 ********************************************************************/
3088 void spoolss_notify_attributes(int snum,
3089 SPOOL_NOTIFY_INFO_DATA *data,
3090 print_queue_struct *queue,
3091 NT_PRINTER_INFO_LEVEL *printer,
3092 TALLOC_CTX *mem_ctx)
3094 data->notify_data.value[0] = printer->info_2->attributes;
3095 data->notify_data.value[1] = 0;
3098 /*******************************************************************
3099 * fill a notify_info_data with the priority
3100 ********************************************************************/
3102 static void spoolss_notify_priority(int snum,
3103 SPOOL_NOTIFY_INFO_DATA *data,
3104 print_queue_struct *queue,
3105 NT_PRINTER_INFO_LEVEL *printer,
3106 TALLOC_CTX *mem_ctx)
3108 data->notify_data.value[0] = printer->info_2->priority;
3109 data->notify_data.value[1] = 0;
3112 /*******************************************************************
3113 * fill a notify_info_data with the default priority
3114 ********************************************************************/
3116 static void spoolss_notify_default_priority(int snum,
3117 SPOOL_NOTIFY_INFO_DATA *data,
3118 print_queue_struct *queue,
3119 NT_PRINTER_INFO_LEVEL *printer,
3120 TALLOC_CTX *mem_ctx)
3122 data->notify_data.value[0] = printer->info_2->default_priority;
3123 data->notify_data.value[1] = 0;
3126 /*******************************************************************
3127 * fill a notify_info_data with the start time
3128 ********************************************************************/
3130 static void spoolss_notify_start_time(int snum,
3131 SPOOL_NOTIFY_INFO_DATA *data,
3132 print_queue_struct *queue,
3133 NT_PRINTER_INFO_LEVEL *printer,
3134 TALLOC_CTX *mem_ctx)
3136 data->notify_data.value[0] = printer->info_2->starttime;
3137 data->notify_data.value[1] = 0;
3140 /*******************************************************************
3141 * fill a notify_info_data with the until time
3142 ********************************************************************/
3144 static void spoolss_notify_until_time(int snum,
3145 SPOOL_NOTIFY_INFO_DATA *data,
3146 print_queue_struct *queue,
3147 NT_PRINTER_INFO_LEVEL *printer,
3148 TALLOC_CTX *mem_ctx)
3150 data->notify_data.value[0] = printer->info_2->untiltime;
3151 data->notify_data.value[1] = 0;
3154 /*******************************************************************
3155 * fill a notify_info_data with the status
3156 ********************************************************************/
3158 static void spoolss_notify_status(int snum,
3159 SPOOL_NOTIFY_INFO_DATA *data,
3160 print_queue_struct *queue,
3161 NT_PRINTER_INFO_LEVEL *printer,
3162 TALLOC_CTX *mem_ctx)
3164 print_status_struct status;
3166 print_queue_length(snum, &status);
3167 data->notify_data.value[0]=(uint32) status.status;
3168 data->notify_data.value[1] = 0;
3171 /*******************************************************************
3172 * fill a notify_info_data with the number of jobs queued
3173 ********************************************************************/
3175 void spoolss_notify_cjobs(int snum,
3176 SPOOL_NOTIFY_INFO_DATA *data,
3177 print_queue_struct *queue,
3178 NT_PRINTER_INFO_LEVEL *printer,
3179 TALLOC_CTX *mem_ctx)
3181 data->notify_data.value[0] = print_queue_length(snum, NULL);
3182 data->notify_data.value[1] = 0;
3185 /*******************************************************************
3186 * fill a notify_info_data with the average ppm
3187 ********************************************************************/
3189 static void spoolss_notify_average_ppm(int snum,
3190 SPOOL_NOTIFY_INFO_DATA *data,
3191 print_queue_struct *queue,
3192 NT_PRINTER_INFO_LEVEL *printer,
3193 TALLOC_CTX *mem_ctx)
3195 /* always respond 8 pages per minutes */
3196 /* a little hard ! */
3197 data->notify_data.value[0] = printer->info_2->averageppm;
3198 data->notify_data.value[1] = 0;
3201 /*******************************************************************
3202 * fill a notify_info_data with username
3203 ********************************************************************/
3205 static void spoolss_notify_username(int snum,
3206 SPOOL_NOTIFY_INFO_DATA *data,
3207 print_queue_struct *queue,
3208 NT_PRINTER_INFO_LEVEL *printer,
3209 TALLOC_CTX *mem_ctx)
3214 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3216 data->notify_data.data.length = len;
3218 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3220 if (!data->notify_data.data.string) {
3221 data->notify_data.data.length = 0;
3225 memcpy(data->notify_data.data.string, temp, len);
3227 data->notify_data.data.string = NULL;
3231 /*******************************************************************
3232 * fill a notify_info_data with job status
3233 ********************************************************************/
3235 static void spoolss_notify_job_status(int snum,
3236 SPOOL_NOTIFY_INFO_DATA *data,
3237 print_queue_struct *queue,
3238 NT_PRINTER_INFO_LEVEL *printer,
3239 TALLOC_CTX *mem_ctx)
3241 data->notify_data.value[0]=nt_printj_status(queue->status);
3242 data->notify_data.value[1] = 0;
3245 /*******************************************************************
3246 * fill a notify_info_data with job name
3247 ********************************************************************/
3249 static void spoolss_notify_job_name(int snum,
3250 SPOOL_NOTIFY_INFO_DATA *data,
3251 print_queue_struct *queue,
3252 NT_PRINTER_INFO_LEVEL *printer,
3253 TALLOC_CTX *mem_ctx)
3258 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3260 data->notify_data.data.length = len;
3262 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3264 if (!data->notify_data.data.string) {
3265 data->notify_data.data.length = 0;
3269 memcpy(data->notify_data.data.string, temp, len);
3271 data->notify_data.data.string = NULL;
3275 /*******************************************************************
3276 * fill a notify_info_data with job status
3277 ********************************************************************/
3279 static void spoolss_notify_job_status_string(int snum,
3280 SPOOL_NOTIFY_INFO_DATA *data,
3281 print_queue_struct *queue,
3282 NT_PRINTER_INFO_LEVEL *printer,
3283 TALLOC_CTX *mem_ctx)
3286 * Now we're returning job status codes we just return a "" here. JRA.
3293 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3296 switch (queue->status) {
3301 p = ""; /* NT provides the paused string */
3310 #endif /* NO LONGER NEEDED. */
3312 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3314 data->notify_data.data.length = len;
3316 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3318 if (!data->notify_data.data.string) {
3319 data->notify_data.data.length = 0;
3323 memcpy(data->notify_data.data.string, temp, len);
3325 data->notify_data.data.string = NULL;
3329 /*******************************************************************
3330 * fill a notify_info_data with job time
3331 ********************************************************************/
3333 static void spoolss_notify_job_time(int snum,
3334 SPOOL_NOTIFY_INFO_DATA *data,
3335 print_queue_struct *queue,
3336 NT_PRINTER_INFO_LEVEL *printer,
3337 TALLOC_CTX *mem_ctx)
3339 data->notify_data.value[0]=0x0;
3340 data->notify_data.value[1]=0;
3343 /*******************************************************************
3344 * fill a notify_info_data with job size
3345 ********************************************************************/
3347 static void spoolss_notify_job_size(int snum,
3348 SPOOL_NOTIFY_INFO_DATA *data,
3349 print_queue_struct *queue,
3350 NT_PRINTER_INFO_LEVEL *printer,
3351 TALLOC_CTX *mem_ctx)
3353 data->notify_data.value[0]=queue->size;
3354 data->notify_data.value[1]=0;
3357 /*******************************************************************
3358 * fill a notify_info_data with page info
3359 ********************************************************************/
3360 static void spoolss_notify_total_pages(int snum,
3361 SPOOL_NOTIFY_INFO_DATA *data,
3362 print_queue_struct *queue,
3363 NT_PRINTER_INFO_LEVEL *printer,
3364 TALLOC_CTX *mem_ctx)
3366 data->notify_data.value[0]=queue->page_count;
3367 data->notify_data.value[1]=0;
3370 /*******************************************************************
3371 * fill a notify_info_data with pages printed info.
3372 ********************************************************************/
3373 static void spoolss_notify_pages_printed(int snum,
3374 SPOOL_NOTIFY_INFO_DATA *data,
3375 print_queue_struct *queue,
3376 NT_PRINTER_INFO_LEVEL *printer,
3377 TALLOC_CTX *mem_ctx)
3379 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3380 data->notify_data.value[1]=0;
3383 /*******************************************************************
3384 Fill a notify_info_data with job position.
3385 ********************************************************************/
3387 static void spoolss_notify_job_position(int snum,
3388 SPOOL_NOTIFY_INFO_DATA *data,
3389 print_queue_struct *queue,
3390 NT_PRINTER_INFO_LEVEL *printer,
3391 TALLOC_CTX *mem_ctx)
3393 data->notify_data.value[0]=queue->job;
3394 data->notify_data.value[1]=0;
3397 /*******************************************************************
3398 Fill a notify_info_data with submitted time.
3399 ********************************************************************/
3401 static void spoolss_notify_submitted_time(int snum,
3402 SPOOL_NOTIFY_INFO_DATA *data,
3403 print_queue_struct *queue,
3404 NT_PRINTER_INFO_LEVEL *printer,
3405 TALLOC_CTX *mem_ctx)
3412 t=gmtime(&queue->time);
3414 len = sizeof(SYSTEMTIME);
3416 data->notify_data.data.length = len;
3417 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3419 if (!data->notify_data.data.string) {
3420 data->notify_data.data.length = 0;
3424 make_systemtime(&st, t);
3427 * Systemtime must be linearized as a set of UINT16's.
3428 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3431 p = (char *)data->notify_data.data.string;
3432 SSVAL(p, 0, st.year);
3433 SSVAL(p, 2, st.month);
3434 SSVAL(p, 4, st.dayofweek);
3435 SSVAL(p, 6, st.day);
3436 SSVAL(p, 8, st.hour);
3437 SSVAL(p, 10, st.minute);
3438 SSVAL(p, 12, st.second);
3439 SSVAL(p, 14, st.milliseconds);
3442 struct s_notify_info_data_table
3448 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3449 print_queue_struct *queue,
3450 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3453 /* A table describing the various print notification constants and
3454 whether the notification data is a pointer to a variable sized
3455 buffer, a one value uint32 or a two value uint32. */
3457 static const struct s_notify_info_data_table notify_info_data_table[] =
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3508 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3511 /*******************************************************************
3512 Return the size of info_data structure.
3513 ********************************************************************/
3515 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3519 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3520 if ( (notify_info_data_table[i].type == type)
3521 && (notify_info_data_table[i].field == field) ) {
3522 switch(notify_info_data_table[i].size) {
3523 case NOTIFY_ONE_VALUE:
3524 case NOTIFY_TWO_VALUE:
3529 /* The only pointer notify data I have seen on
3530 the wire is the submitted time and this has
3531 the notify size set to 4. -tpot */
3533 case NOTIFY_POINTER:
3536 case NOTIFY_SECDESC:
3542 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3547 /*******************************************************************
3548 Return the type of notify_info_data.
3549 ********************************************************************/
3551 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3555 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3556 if (notify_info_data_table[i].type == type &&
3557 notify_info_data_table[i].field == field)
3558 return notify_info_data_table[i].size;
3564 /****************************************************************************
3565 ****************************************************************************/
3567 static BOOL search_notify(uint16 type, uint16 field, int *value)
3571 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3572 if (notify_info_data_table[i].type == type &&
3573 notify_info_data_table[i].field == field &&
3574 notify_info_data_table[i].fn != NULL) {
3583 /****************************************************************************
3584 ****************************************************************************/
3586 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3588 info_data->type = type;
3589 info_data->field = field;
3590 info_data->reserved = 0;
3592 info_data->size = size_of_notify_info_data(type, field);
3593 info_data->enc_type = type_of_notify_info_data(type, field);
3598 /*******************************************************************
3600 * fill a notify_info struct with info asked
3602 ********************************************************************/
3604 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3605 snum, SPOOL_NOTIFY_OPTION_TYPE
3606 *option_type, uint32 id,
3607 TALLOC_CTX *mem_ctx)
3613 SPOOL_NOTIFY_INFO_DATA *current_data;
3614 NT_PRINTER_INFO_LEVEL *printer = NULL;
3615 print_queue_struct *queue=NULL;
3617 type=option_type->type;
3619 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3620 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3621 option_type->count, lp_servicename(snum)));
3623 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3626 for(field_num=0; field_num<option_type->count; field_num++) {
3627 field = option_type->fields[field_num];
3629 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3631 if (!search_notify(type, field, &j) )
3634 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3635 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3636 free_a_printer(&printer, 2);
3640 current_data = &info->data[info->count];
3642 construct_info_data(current_data, type, field, id);
3644 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3645 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3647 notify_info_data_table[j].fn(snum, current_data, queue,
3653 free_a_printer(&printer, 2);
3657 /*******************************************************************
3659 * fill a notify_info struct with info asked
3661 ********************************************************************/
3663 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3664 SPOOL_NOTIFY_INFO *info,
3665 NT_PRINTER_INFO_LEVEL *printer,
3666 int snum, SPOOL_NOTIFY_OPTION_TYPE
3667 *option_type, uint32 id,
3668 TALLOC_CTX *mem_ctx)
3674 SPOOL_NOTIFY_INFO_DATA *current_data;
3676 DEBUG(4,("construct_notify_jobs_info\n"));
3678 type = option_type->type;
3680 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3681 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3682 option_type->count));
3684 for(field_num=0; field_num<option_type->count; field_num++) {
3685 field = option_type->fields[field_num];
3687 if (!search_notify(type, field, &j) )
3690 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3691 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3695 current_data=&(info->data[info->count]);
3697 construct_info_data(current_data, type, field, id);
3698 notify_info_data_table[j].fn(snum, current_data, queue,
3707 * JFM: The enumeration is not that simple, it's even non obvious.
3709 * let's take an example: I want to monitor the PRINTER SERVER for
3710 * the printer's name and the number of jobs currently queued.
3711 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3712 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3714 * I have 3 printers on the back of my server.
3716 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3719 * 1 printer 1 name 1
3720 * 2 printer 1 cjob 1
3721 * 3 printer 2 name 2
3722 * 4 printer 2 cjob 2
3723 * 5 printer 3 name 3
3724 * 6 printer 3 name 3
3726 * that's the print server case, the printer case is even worse.
3729 /*******************************************************************
3731 * enumerate all printers on the printserver
3732 * fill a notify_info struct with info asked
3734 ********************************************************************/
3736 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3737 SPOOL_NOTIFY_INFO *info,
3738 TALLOC_CTX *mem_ctx)
3741 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3742 int n_services=lp_numservices();
3744 SPOOL_NOTIFY_OPTION *option;
3745 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3747 DEBUG(4,("printserver_notify_info\n"));
3752 option=Printer->notify.option;
3757 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3758 sending a ffpcn() request first */
3763 for (i=0; i<option->count; i++) {
3764 option_type=&(option->ctr.type[i]);
3766 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3769 for (snum=0; snum<n_services; snum++)
3771 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3772 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3778 * Debugging information, don't delete.
3781 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3782 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3783 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3785 for (i=0; i<info->count; i++) {
3786 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3787 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3788 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3795 /*******************************************************************
3797 * fill a notify_info struct with info asked
3799 ********************************************************************/
3801 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3802 TALLOC_CTX *mem_ctx)
3805 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3808 SPOOL_NOTIFY_OPTION *option;
3809 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3811 print_queue_struct *queue=NULL;
3812 print_status_struct status;
3814 DEBUG(4,("printer_notify_info\n"));
3819 option=Printer->notify.option;
3825 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3826 sending a ffpcn() request first */
3831 get_printer_snum(p, hnd, &snum, NULL);
3833 for (i=0; i<option->count; i++) {
3834 option_type=&option->ctr.type[i];
3836 switch ( option_type->type ) {
3837 case PRINTER_NOTIFY_TYPE:
3838 if(construct_notify_printer_info(Printer, info, snum,
3844 case JOB_NOTIFY_TYPE: {
3845 NT_PRINTER_INFO_LEVEL *printer = NULL;
3847 count = print_queue_status(snum, &queue, &status);
3849 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3852 for (j=0; j<count; j++) {
3853 construct_notify_jobs_info(&queue[j], info,
3860 free_a_printer(&printer, 2);
3870 * Debugging information, don't delete.
3873 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3874 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3875 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3877 for (i=0; i<info->count; i++) {
3878 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3879 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3880 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3886 /********************************************************************
3888 ********************************************************************/
3890 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3892 POLICY_HND *handle = &q_u->handle;
3893 SPOOL_NOTIFY_INFO *info = &r_u->info;
3895 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3896 WERROR result = WERR_BADFID;
3898 /* we always have a NOTIFY_INFO struct */
3902 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3903 OUR_HANDLE(handle)));
3907 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3910 * We are now using the change value, and
3911 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3912 * I don't have a global notification system, I'm sending back all the
3913 * informations even when _NOTHING_ has changed.
3916 /* We need to keep track of the change value to send back in
3917 RRPCN replies otherwise our updates are ignored. */
3919 Printer->notify.fnpcn = True;
3921 if (Printer->notify.client_connected) {
3922 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3923 Printer->notify.change = q_u->change;
3926 /* just ignore the SPOOL_NOTIFY_OPTION */
3928 switch (Printer->printer_type) {
3930 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3933 case SPLHND_PRINTER:
3934 result = printer_notify_info(p, handle, info, p->mem_ctx);
3938 Printer->notify.fnpcn = False;
3944 /********************************************************************
3945 * construct_printer_info_0
3946 * fill a printer_info_0 struct
3947 ********************************************************************/
3949 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3953 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3954 counter_printer_0 *session_counter;
3955 uint32 global_counter;
3958 print_status_struct status;
3960 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3963 count = print_queue_length(snum, &status);
3965 /* check if we already have a counter for this printer */
3966 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3967 if (session_counter->snum == snum)
3971 /* it's the first time, add it to the list */
3972 if (session_counter==NULL) {
3973 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3974 free_a_printer(&ntprinter, 2);
3977 ZERO_STRUCTP(session_counter);
3978 session_counter->snum=snum;
3979 session_counter->counter=0;
3980 DLIST_ADD(counter_list, session_counter);
3984 session_counter->counter++;
3987 * the global_counter should be stored in a TDB as it's common to all the clients
3988 * and should be zeroed on samba startup
3990 global_counter=session_counter->counter;
3992 pstrcpy(chaine,ntprinter->info_2->printername);
3994 init_unistr(&printer->printername, chaine);
3996 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3997 init_unistr(&printer->servername, chaine);
3999 printer->cjobs = count;
4000 printer->total_jobs = 0;
4001 printer->total_bytes = 0;
4003 setuptime = (time_t)ntprinter->info_2->setuptime;
4004 t=gmtime(&setuptime);
4006 printer->year = t->tm_year+1900;
4007 printer->month = t->tm_mon+1;
4008 printer->dayofweek = t->tm_wday;
4009 printer->day = t->tm_mday;
4010 printer->hour = t->tm_hour;
4011 printer->minute = t->tm_min;
4012 printer->second = t->tm_sec;
4013 printer->milliseconds = 0;
4015 printer->global_counter = global_counter;
4016 printer->total_pages = 0;
4018 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4019 printer->major_version = 0x0005; /* NT 5 */
4020 printer->build_version = 0x0893; /* build 2195 */
4022 printer->unknown7 = 0x1;
4023 printer->unknown8 = 0x0;
4024 printer->unknown9 = 0x0;
4025 printer->session_counter = session_counter->counter;
4026 printer->unknown11 = 0x0;
4027 printer->printer_errors = 0x0; /* number of print failure */
4028 printer->unknown13 = 0x0;
4029 printer->unknown14 = 0x1;
4030 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4031 printer->unknown16 = 0x0;
4032 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4033 printer->unknown18 = 0x0;
4034 printer->status = nt_printq_status(status.status);
4035 printer->unknown20 = 0x0;
4036 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4037 printer->unknown22 = 0x0;
4038 printer->unknown23 = 0x6; /* 6 ???*/
4039 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4040 printer->unknown25 = 0;
4041 printer->unknown26 = 0;
4042 printer->unknown27 = 0;
4043 printer->unknown28 = 0;
4044 printer->unknown29 = 0;
4046 free_a_printer(&ntprinter,2);
4050 /********************************************************************
4051 * construct_printer_info_1
4052 * fill a printer_info_1 struct
4053 ********************************************************************/
4054 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4058 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4060 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4063 printer->flags=flags;
4065 if (*ntprinter->info_2->comment == '\0') {
4066 init_unistr(&printer->comment, lp_comment(snum));
4067 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4068 ntprinter->info_2->drivername, lp_comment(snum));
4071 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4072 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4073 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4076 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4078 init_unistr(&printer->description, chaine);
4079 init_unistr(&printer->name, chaine2);
4081 free_a_printer(&ntprinter,2);
4086 /****************************************************************************
4087 Free a DEVMODE struct.
4088 ****************************************************************************/
4090 static void free_dev_mode(DEVICEMODE *dev)
4095 SAFE_FREE(dev->dev_private);
4100 /****************************************************************************
4101 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4102 should be valid upon entry
4103 ****************************************************************************/
4105 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4107 if ( !devmode || !ntdevmode )
4110 init_unistr(&devmode->devicename, ntdevmode->devicename);
4112 init_unistr(&devmode->formname, ntdevmode->formname);
4114 devmode->specversion = ntdevmode->specversion;
4115 devmode->driverversion = ntdevmode->driverversion;
4116 devmode->size = ntdevmode->size;
4117 devmode->driverextra = ntdevmode->driverextra;
4118 devmode->fields = ntdevmode->fields;
4120 devmode->orientation = ntdevmode->orientation;
4121 devmode->papersize = ntdevmode->papersize;
4122 devmode->paperlength = ntdevmode->paperlength;
4123 devmode->paperwidth = ntdevmode->paperwidth;
4124 devmode->scale = ntdevmode->scale;
4125 devmode->copies = ntdevmode->copies;
4126 devmode->defaultsource = ntdevmode->defaultsource;
4127 devmode->printquality = ntdevmode->printquality;
4128 devmode->color = ntdevmode->color;
4129 devmode->duplex = ntdevmode->duplex;
4130 devmode->yresolution = ntdevmode->yresolution;
4131 devmode->ttoption = ntdevmode->ttoption;
4132 devmode->collate = ntdevmode->collate;
4133 devmode->icmmethod = ntdevmode->icmmethod;
4134 devmode->icmintent = ntdevmode->icmintent;
4135 devmode->mediatype = ntdevmode->mediatype;
4136 devmode->dithertype = ntdevmode->dithertype;
4138 if (ntdevmode->nt_dev_private != NULL) {
4139 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4146 /****************************************************************************
4147 Create a DEVMODE struct. Returns malloced memory.
4148 ****************************************************************************/
4150 DEVICEMODE *construct_dev_mode(const char *servicename)
4152 NT_PRINTER_INFO_LEVEL *printer = NULL;
4153 DEVICEMODE *devmode = NULL;
4155 DEBUG(7,("construct_dev_mode\n"));
4157 DEBUGADD(8,("getting printer characteristics\n"));
4159 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4162 if ( !printer->info_2->devmode ) {
4163 DEBUG(5, ("BONG! There was no device mode!\n"));
4167 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4168 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4172 ZERO_STRUCTP(devmode);
4174 DEBUGADD(8,("loading DEVICEMODE\n"));
4176 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4177 free_dev_mode( devmode );
4182 free_a_printer(&printer,2);
4187 /********************************************************************
4188 * construct_printer_info_2
4189 * fill a printer_info_2 struct
4190 ********************************************************************/
4192 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4195 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4197 print_status_struct status;
4199 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4202 count = print_queue_length(snum, &status);
4204 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4205 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4206 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4207 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4208 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4210 if (*ntprinter->info_2->comment == '\0')
4211 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4213 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4215 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4216 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4217 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4218 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4219 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4221 printer->attributes = ntprinter->info_2->attributes;
4223 printer->priority = ntprinter->info_2->priority; /* priority */
4224 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4225 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4226 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4227 printer->status = nt_printq_status(status.status); /* status */
4228 printer->cjobs = count; /* jobs */
4229 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4231 if ( !(printer->devmode = construct_dev_mode(
4232 lp_const_servicename(snum))) )
4233 DEBUG(8, ("Returning NULL Devicemode!\n"));
4235 printer->secdesc = NULL;
4237 if ( ntprinter->info_2->secdesc_buf
4238 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4240 /* don't use talloc_steal() here unless you do a deep steal of all
4241 the SEC_DESC members */
4243 printer->secdesc = dup_sec_desc( talloc_tos(),
4244 ntprinter->info_2->secdesc_buf->sd );
4247 free_a_printer(&ntprinter, 2);
4252 /********************************************************************
4253 * construct_printer_info_3
4254 * fill a printer_info_3 struct
4255 ********************************************************************/
4257 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4259 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4260 PRINTER_INFO_3 *printer = NULL;
4262 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4266 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4267 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4268 free_a_printer(&ntprinter, 2);
4272 ZERO_STRUCTP(printer);
4274 /* These are the components of the SD we are returning. */
4276 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4277 /* don't use talloc_steal() here unless you do a deep steal of all
4278 the SEC_DESC members */
4280 printer->secdesc = dup_sec_desc( talloc_tos(),
4281 ntprinter->info_2->secdesc_buf->sd );
4284 free_a_printer(&ntprinter, 2);
4286 *pp_printer = printer;
4290 /********************************************************************
4291 * construct_printer_info_4
4292 * fill a printer_info_4 struct
4293 ********************************************************************/
4295 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4297 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4299 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4302 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4303 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4304 printer->attributes = ntprinter->info_2->attributes;
4306 free_a_printer(&ntprinter, 2);
4310 /********************************************************************
4311 * construct_printer_info_5
4312 * fill a printer_info_5 struct
4313 ********************************************************************/
4315 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4317 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4319 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4322 init_unistr(&printer->printername, ntprinter->info_2->printername);
4323 init_unistr(&printer->portname, ntprinter->info_2->portname);
4324 printer->attributes = ntprinter->info_2->attributes;
4326 /* these two are not used by NT+ according to MSDN */
4328 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4329 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4331 free_a_printer(&ntprinter, 2);
4336 /********************************************************************
4337 * construct_printer_info_6
4338 * fill a printer_info_6 struct
4339 ********************************************************************/
4341 static BOOL construct_printer_info_6(Printer_entry *print_hnd,
4342 PRINTER_INFO_6 *printer,
4345 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4347 print_status_struct status;
4349 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4350 lp_const_servicename(snum))))
4353 count = print_queue_length(snum, &status);
4355 printer->status = nt_printq_status(status.status);
4357 free_a_printer(&ntprinter, 2);
4362 /********************************************************************
4363 * construct_printer_info_7
4364 * fill a printer_info_7 struct
4365 ********************************************************************/
4367 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4369 char *guid_str = NULL;
4372 if (is_printer_published(print_hnd, snum, &guid)) {
4373 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4374 strupper_m(guid_str);
4375 init_unistr(&printer->guid, guid_str);
4376 printer->action = SPOOL_DS_PUBLISH;
4378 init_unistr(&printer->guid, "");
4379 printer->action = SPOOL_DS_UNPUBLISH;
4385 /********************************************************************
4386 Spoolss_enumprinters.
4387 ********************************************************************/
4389 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4393 int n_services=lp_numservices();
4394 PRINTER_INFO_1 *printers=NULL;
4395 PRINTER_INFO_1 current_prt;
4396 WERROR result = WERR_OK;
4398 DEBUG(4,("enum_all_printers_info_1\n"));
4400 for (snum=0; snum<n_services; snum++) {
4401 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4402 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4404 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4405 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4406 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4410 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4412 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4418 /* check the required size. */
4419 for (i=0; i<*returned; i++)
4420 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4422 if (*needed > offered) {
4423 result = WERR_INSUFFICIENT_BUFFER;
4427 if (!rpcbuf_alloc_size(buffer, *needed)) {
4428 result = WERR_NOMEM;
4432 /* fill the buffer with the structures */
4433 for (i=0; i<*returned; i++)
4434 smb_io_printer_info_1("", buffer, &printers[i], 0);
4439 SAFE_FREE(printers);
4441 if ( !W_ERROR_IS_OK(result) )
4447 /********************************************************************
4448 enum_all_printers_info_1_local.
4449 *********************************************************************/
4451 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4453 DEBUG(4,("enum_all_printers_info_1_local\n"));
4455 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4458 /********************************************************************
4459 enum_all_printers_info_1_name.
4460 *********************************************************************/
4462 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4466 DEBUG(4,("enum_all_printers_info_1_name\n"));
4468 if ((name[0] == '\\') && (name[1] == '\\'))
4471 if (is_myname_or_ipaddr(s)) {
4472 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4475 return WERR_INVALID_NAME;
4478 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4479 /********************************************************************
4480 enum_all_printers_info_1_remote.
4481 *********************************************************************/
4483 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4485 PRINTER_INFO_1 *printer;
4486 fstring printername;
4489 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4490 WERROR result = WERR_OK;
4492 /* JFM: currently it's more a place holder than anything else.
4493 * In the spooler world there is a notion of server registration.
4494 * the print servers are registered on the PDC (in the same domain)
4496 * We should have a TDB here. The registration is done thru an
4497 * undocumented RPC call.
4500 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4505 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4506 slprintf(desc, sizeof(desc)-1,"%s", name);
4507 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4509 init_unistr(&printer->description, desc);
4510 init_unistr(&printer->name, printername);
4511 init_unistr(&printer->comment, comment);
4512 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4514 /* check the required size. */
4515 *needed += spoolss_size_printer_info_1(printer);
4517 if (*needed > offered) {
4518 result = WERR_INSUFFICIENT_BUFFER;
4522 if (!rpcbuf_alloc_size(buffer, *needed)) {
4523 result = WERR_NOMEM;
4527 /* fill the buffer with the structures */
4528 smb_io_printer_info_1("", buffer, printer, 0);
4534 if ( !W_ERROR_IS_OK(result) )
4542 /********************************************************************
4543 enum_all_printers_info_1_network.
4544 *********************************************************************/
4546 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4550 DEBUG(4,("enum_all_printers_info_1_network\n"));
4552 /* If we respond to a enum_printers level 1 on our name with flags
4553 set to PRINTER_ENUM_REMOTE with a list of printers then these
4554 printers incorrectly appear in the APW browse list.
4555 Specifically the printers for the server appear at the workgroup
4556 level where all the other servers in the domain are
4557 listed. Windows responds to this call with a
4558 WERR_CAN_NOT_COMPLETE so we should do the same. */
4560 if (name[0] == '\\' && name[1] == '\\')
4563 if (is_myname_or_ipaddr(s))
4564 return WERR_CAN_NOT_COMPLETE;
4566 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4569 /********************************************************************
4570 * api_spoolss_enumprinters
4572 * called from api_spoolss_enumprinters (see this to understand)
4573 ********************************************************************/
4575 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4579 int n_services=lp_numservices();
4580 PRINTER_INFO_2 *printers=NULL;
4581 PRINTER_INFO_2 current_prt;
4582 WERROR result = WERR_OK;
4586 for (snum=0; snum<n_services; snum++) {
4587 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4588 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4590 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4591 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4592 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4597 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4599 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4606 /* check the required size. */
4607 for (i=0; i<*returned; i++)
4608 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4610 if (*needed > offered) {
4611 result = WERR_INSUFFICIENT_BUFFER;
4615 if (!rpcbuf_alloc_size(buffer, *needed)) {
4616 result = WERR_NOMEM;
4620 /* fill the buffer with the structures */
4621 for (i=0; i<*returned; i++)
4622 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4627 for (i=0; i<*returned; i++)
4628 free_devmode(printers[i].devmode);
4630 SAFE_FREE(printers);
4632 if ( !W_ERROR_IS_OK(result) )
4638 /********************************************************************
4639 * handle enumeration of printers at level 1
4640 ********************************************************************/
4642 static WERROR enumprinters_level1( uint32 flags, fstring name,
4643 RPC_BUFFER *buffer, uint32 offered,
4644 uint32 *needed, uint32 *returned)
4646 /* Not all the flags are equals */
4648 if (flags & PRINTER_ENUM_LOCAL)
4649 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4651 if (flags & PRINTER_ENUM_NAME)
4652 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4654 #if 0 /* JERRY - disabled for now */
4655 if (flags & PRINTER_ENUM_REMOTE)
4656 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4659 if (flags & PRINTER_ENUM_NETWORK)
4660 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4662 return WERR_OK; /* NT4sp5 does that */
4665 /********************************************************************
4666 * handle enumeration of printers at level 2
4667 ********************************************************************/
4669 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4670 RPC_BUFFER *buffer, uint32 offered,
4671 uint32 *needed, uint32 *returned)
4673 char *s = servername;
4675 if (flags & PRINTER_ENUM_LOCAL) {
4676 return enum_all_printers_info_2(buffer, offered, needed, returned);
4679 if (flags & PRINTER_ENUM_NAME) {
4680 if ((servername[0] == '\\') && (servername[1] == '\\'))
4682 if (is_myname_or_ipaddr(s))
4683 return enum_all_printers_info_2(buffer, offered, needed, returned);
4685 return WERR_INVALID_NAME;
4688 if (flags & PRINTER_ENUM_REMOTE)
4689 return WERR_UNKNOWN_LEVEL;
4694 /********************************************************************
4695 * handle enumeration of printers at level 5
4696 ********************************************************************/
4698 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4699 RPC_BUFFER *buffer, uint32 offered,
4700 uint32 *needed, uint32 *returned)
4702 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4706 /********************************************************************
4707 * api_spoolss_enumprinters
4709 * called from api_spoolss_enumprinters (see this to understand)
4710 ********************************************************************/
4712 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4714 uint32 flags = q_u->flags;
4715 UNISTR2 *servername = &q_u->servername;
4716 uint32 level = q_u->level;
4717 RPC_BUFFER *buffer = NULL;
4718 uint32 offered = q_u->offered;
4719 uint32 *needed = &r_u->needed;
4720 uint32 *returned = &r_u->returned;
4724 /* that's an [in out] buffer */
4726 if (!q_u->buffer && (offered!=0)) {
4727 return WERR_INVALID_PARAM;
4730 rpcbuf_move(q_u->buffer, &r_u->buffer);
4731 buffer = r_u->buffer;
4733 DEBUG(4,("_spoolss_enumprinters\n"));
4740 * flags==PRINTER_ENUM_NAME
4741 * if name=="" then enumerates all printers
4742 * if name!="" then enumerate the printer
4743 * flags==PRINTER_ENUM_REMOTE
4744 * name is NULL, enumerate printers
4745 * Level 2: name!="" enumerates printers, name can't be NULL
4746 * Level 3: doesn't exist
4747 * Level 4: does a local registry lookup
4748 * Level 5: same as Level 2
4751 unistr2_to_ascii(name, servername, sizeof(name));
4756 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4758 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4760 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4765 return WERR_UNKNOWN_LEVEL;
4768 /****************************************************************************
4769 ****************************************************************************/
4771 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4773 PRINTER_INFO_0 *printer=NULL;
4774 WERROR result = WERR_OK;
4776 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4779 construct_printer_info_0(print_hnd, printer, snum);
4781 /* check the required size. */
4782 *needed += spoolss_size_printer_info_0(printer);
4784 if (*needed > offered) {
4785 result = WERR_INSUFFICIENT_BUFFER;
4789 if (!rpcbuf_alloc_size(buffer, *needed)) {
4790 result = WERR_NOMEM;
4794 /* fill the buffer with the structures */
4795 smb_io_printer_info_0("", buffer, printer, 0);
4805 /****************************************************************************
4806 ****************************************************************************/
4808 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4810 PRINTER_INFO_1 *printer=NULL;
4811 WERROR result = WERR_OK;
4813 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4816 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4818 /* check the required size. */
4819 *needed += spoolss_size_printer_info_1(printer);
4821 if (*needed > offered) {
4822 result = WERR_INSUFFICIENT_BUFFER;
4826 if (!rpcbuf_alloc_size(buffer, *needed)) {
4827 result = WERR_NOMEM;
4831 /* fill the buffer with the structures */
4832 smb_io_printer_info_1("", buffer, printer, 0);
4841 /****************************************************************************
4842 ****************************************************************************/
4844 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4846 PRINTER_INFO_2 *printer=NULL;
4847 WERROR result = WERR_OK;
4849 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4852 construct_printer_info_2(print_hnd, printer, snum);
4854 /* check the required size. */
4855 *needed += spoolss_size_printer_info_2(printer);
4857 if (*needed > offered) {
4858 result = WERR_INSUFFICIENT_BUFFER;
4862 if (!rpcbuf_alloc_size(buffer, *needed)) {
4863 result = WERR_NOMEM;
4867 /* fill the buffer with the structures */
4868 if (!smb_io_printer_info_2("", buffer, printer, 0))
4869 result = WERR_NOMEM;
4873 free_printer_info_2(printer);
4878 /****************************************************************************
4879 ****************************************************************************/
4881 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4883 PRINTER_INFO_3 *printer=NULL;
4884 WERROR result = WERR_OK;
4886 if (!construct_printer_info_3(print_hnd, &printer, snum))
4889 /* check the required size. */
4890 *needed += spoolss_size_printer_info_3(printer);
4892 if (*needed > offered) {
4893 result = WERR_INSUFFICIENT_BUFFER;
4897 if (!rpcbuf_alloc_size(buffer, *needed)) {
4898 result = WERR_NOMEM;
4902 /* fill the buffer with the structures */
4903 smb_io_printer_info_3("", buffer, printer, 0);
4907 free_printer_info_3(printer);
4912 /****************************************************************************
4913 ****************************************************************************/
4915 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4917 PRINTER_INFO_4 *printer=NULL;
4918 WERROR result = WERR_OK;
4920 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4923 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4928 /* check the required size. */
4929 *needed += spoolss_size_printer_info_4(printer);
4931 if (*needed > offered) {
4932 result = WERR_INSUFFICIENT_BUFFER;
4936 if (!rpcbuf_alloc_size(buffer, *needed)) {
4937 result = WERR_NOMEM;
4941 /* fill the buffer with the structures */
4942 smb_io_printer_info_4("", buffer, printer, 0);
4946 free_printer_info_4(printer);
4951 /****************************************************************************
4952 ****************************************************************************/
4954 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4956 PRINTER_INFO_5 *printer=NULL;
4957 WERROR result = WERR_OK;
4959 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4962 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4963 free_printer_info_5(printer);
4967 /* check the required size. */
4968 *needed += spoolss_size_printer_info_5(printer);
4970 if (*needed > offered) {
4971 result = WERR_INSUFFICIENT_BUFFER;
4975 if (!rpcbuf_alloc_size(buffer, *needed)) {
4976 result = WERR_NOMEM;
4980 /* fill the buffer with the structures */
4981 smb_io_printer_info_5("", buffer, printer, 0);
4985 free_printer_info_5(printer);
4990 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4992 RPC_BUFFER *buffer, uint32 offered,
4995 PRINTER_INFO_6 *printer;
4996 WERROR result = WERR_OK;
4998 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5002 if (!construct_printer_info_6(print_hnd, printer, snum)) {
5003 free_printer_info_6(printer);
5007 /* check the required size. */
5008 *needed += spoolss_size_printer_info_6(printer);
5010 if (*needed > offered) {
5011 result = WERR_INSUFFICIENT_BUFFER;
5015 if (!rpcbuf_alloc_size(buffer, *needed)) {
5016 result = WERR_NOMEM;
5020 /* fill the buffer with the structures */
5021 smb_io_printer_info_6("", buffer, printer, 0);
5025 free_printer_info_6(printer);
5030 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
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, snum))
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);
5079 /* that's an [in out] buffer */
5081 if (!q_u->buffer && (offered!=0)) {
5082 return WERR_INVALID_PARAM;
5085 rpcbuf_move(q_u->buffer, &r_u->buffer);
5086 buffer = r_u->buffer;
5090 if (!get_printer_snum(p, handle, &snum, NULL))
5095 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5097 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5099 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5101 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5103 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5105 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5107 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5109 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5111 return WERR_UNKNOWN_LEVEL;
5114 /********************************************************************
5115 * fill a DRIVER_INFO_1 struct
5116 ********************************************************************/
5118 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5120 init_unistr( &info->name, driver.info_3->name);
5123 /********************************************************************
5124 * construct_printer_driver_info_1
5125 ********************************************************************/
5127 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5129 NT_PRINTER_INFO_LEVEL *printer = NULL;
5130 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5132 ZERO_STRUCT(driver);
5134 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5135 return WERR_INVALID_PRINTER_NAME;
5137 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5138 free_a_printer(&printer, 2);
5139 return WERR_UNKNOWN_PRINTER_DRIVER;
5142 fill_printer_driver_info_1(info, driver, servername, architecture);
5144 free_a_printer(&printer,2);
5149 /********************************************************************
5150 * construct_printer_driver_info_2
5151 * fill a printer_info_2 struct
5152 ********************************************************************/
5154 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5158 info->version=driver.info_3->cversion;
5160 init_unistr( &info->name, driver.info_3->name );
5161 init_unistr( &info->architecture, driver.info_3->environment );
5164 if (strlen(driver.info_3->driverpath)) {
5165 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5166 init_unistr( &info->driverpath, temp );
5168 init_unistr( &info->driverpath, "" );
5170 if (strlen(driver.info_3->datafile)) {
5171 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5172 init_unistr( &info->datafile, temp );
5174 init_unistr( &info->datafile, "" );
5176 if (strlen(driver.info_3->configfile)) {
5177 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5178 init_unistr( &info->configfile, temp );
5180 init_unistr( &info->configfile, "" );
5183 /********************************************************************
5184 * construct_printer_driver_info_2
5185 * fill a printer_info_2 struct
5186 ********************************************************************/
5188 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5190 NT_PRINTER_INFO_LEVEL *printer = NULL;
5191 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5193 ZERO_STRUCT(printer);
5194 ZERO_STRUCT(driver);
5196 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5197 return WERR_INVALID_PRINTER_NAME;
5199 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5200 free_a_printer(&printer, 2);
5201 return WERR_UNKNOWN_PRINTER_DRIVER;
5204 fill_printer_driver_info_2(info, driver, servername);
5206 free_a_printer(&printer,2);
5211 /********************************************************************
5212 * copy a strings array and convert to UNICODE
5214 * convert an array of ascii string to a UNICODE string
5215 ********************************************************************/
5217 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5224 DEBUG(6,("init_unistr_array\n"));
5235 v = ""; /* hack to handle null lists */
5238 /* hack to allow this to be used in places other than when generating
5239 the list of dependent files */
5242 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5246 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5248 /* add one extra unit16 for the second terminating NULL */
5250 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5251 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5258 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5263 /* special case for ""; we need to add both NULL's here */
5265 (*uni_array)[j++]=0x0000;
5266 (*uni_array)[j]=0x0000;
5269 DEBUGADD(6,("last one:done\n"));
5271 /* return size of array in uint16's */
5276 /********************************************************************
5277 * construct_printer_info_3
5278 * fill a printer_info_3 struct
5279 ********************************************************************/
5281 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5287 info->version=driver.info_3->cversion;
5289 init_unistr( &info->name, driver.info_3->name );
5290 init_unistr( &info->architecture, driver.info_3->environment );
5292 if (strlen(driver.info_3->driverpath)) {
5293 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5294 init_unistr( &info->driverpath, temp );
5296 init_unistr( &info->driverpath, "" );
5298 if (strlen(driver.info_3->datafile)) {
5299 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5300 init_unistr( &info->datafile, temp );
5302 init_unistr( &info->datafile, "" );
5304 if (strlen(driver.info_3->configfile)) {
5305 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5306 init_unistr( &info->configfile, temp );
5308 init_unistr( &info->configfile, "" );
5310 if (strlen(driver.info_3->helpfile)) {
5311 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5312 init_unistr( &info->helpfile, temp );
5314 init_unistr( &info->helpfile, "" );
5316 init_unistr( &info->monitorname, driver.info_3->monitorname );
5317 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5319 info->dependentfiles=NULL;
5320 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5323 /********************************************************************
5324 * construct_printer_info_3
5325 * fill a printer_info_3 struct
5326 ********************************************************************/
5328 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5330 NT_PRINTER_INFO_LEVEL *printer = NULL;
5331 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5333 ZERO_STRUCT(driver);
5335 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5336 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5337 if (!W_ERROR_IS_OK(status))
5338 return WERR_INVALID_PRINTER_NAME;
5340 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5341 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5346 * I put this code in during testing. Helpful when commenting out the
5347 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5348 * as win2k always queries the driver using an infor level of 6.
5349 * I've left it in (but ifdef'd out) because I'll probably
5350 * use it in experimentation again in the future. --jerry 22/01/2002
5353 if (!W_ERROR_IS_OK(status)) {
5355 * Is this a W2k client ?
5358 /* Yes - try again with a WinNT driver. */
5360 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5361 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5365 if (!W_ERROR_IS_OK(status)) {
5366 free_a_printer(&printer,2);
5367 return WERR_UNKNOWN_PRINTER_DRIVER;
5375 fill_printer_driver_info_3(info, driver, servername);
5377 free_a_printer(&printer,2);
5382 /********************************************************************
5383 * construct_printer_info_6
5384 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5385 ********************************************************************/
5387 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5393 memset(&nullstr, '\0', sizeof(fstring));
5395 info->version=driver.info_3->cversion;
5397 init_unistr( &info->name, driver.info_3->name );
5398 init_unistr( &info->architecture, driver.info_3->environment );
5400 if (strlen(driver.info_3->driverpath)) {
5401 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5402 init_unistr( &info->driverpath, temp );
5404 init_unistr( &info->driverpath, "" );
5406 if (strlen(driver.info_3->datafile)) {
5407 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5408 init_unistr( &info->datafile, temp );
5410 init_unistr( &info->datafile, "" );
5412 if (strlen(driver.info_3->configfile)) {
5413 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5414 init_unistr( &info->configfile, temp );
5416 init_unistr( &info->configfile, "" );
5418 if (strlen(driver.info_3->helpfile)) {
5419 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5420 init_unistr( &info->helpfile, temp );
5422 init_unistr( &info->helpfile, "" );
5424 init_unistr( &info->monitorname, driver.info_3->monitorname );
5425 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5427 info->dependentfiles = NULL;
5428 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5430 info->previousdrivernames=NULL;
5431 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5433 info->driver_date=0;
5436 info->driver_version_low=0;
5437 info->driver_version_high=0;
5439 init_unistr( &info->mfgname, "");
5440 init_unistr( &info->oem_url, "");
5441 init_unistr( &info->hardware_id, "");
5442 init_unistr( &info->provider, "");
5445 /********************************************************************
5446 * construct_printer_info_6
5447 * fill a printer_info_6 struct
5448 ********************************************************************/
5450 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5451 fstring servername, fstring architecture, uint32 version)
5453 NT_PRINTER_INFO_LEVEL *printer = NULL;
5454 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5457 ZERO_STRUCT(driver);
5459 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5461 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5463 if (!W_ERROR_IS_OK(status))
5464 return WERR_INVALID_PRINTER_NAME;
5466 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5468 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5470 if (!W_ERROR_IS_OK(status))
5473 * Is this a W2k client ?
5477 free_a_printer(&printer,2);
5478 return WERR_UNKNOWN_PRINTER_DRIVER;
5481 /* Yes - try again with a WinNT driver. */
5483 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5484 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5485 if (!W_ERROR_IS_OK(status)) {
5486 free_a_printer(&printer,2);
5487 return WERR_UNKNOWN_PRINTER_DRIVER;
5491 fill_printer_driver_info_6(info, driver, servername);
5493 free_a_printer(&printer,2);
5494 free_a_printer_driver(driver, 3);
5499 /****************************************************************************
5500 ****************************************************************************/
5502 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5504 SAFE_FREE(info->dependentfiles);
5507 /****************************************************************************
5508 ****************************************************************************/
5510 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5512 SAFE_FREE(info->dependentfiles);
5515 /****************************************************************************
5516 ****************************************************************************/
5518 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5520 DRIVER_INFO_1 *info=NULL;
5523 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5526 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5527 if (!W_ERROR_IS_OK(result))
5530 /* check the required size. */
5531 *needed += spoolss_size_printer_driver_info_1(info);
5533 if (*needed > offered) {
5534 result = WERR_INSUFFICIENT_BUFFER;
5538 if (!rpcbuf_alloc_size(buffer, *needed)) {
5539 result = WERR_NOMEM;
5543 /* fill the buffer with the structures */
5544 smb_io_printer_driver_info_1("", buffer, info, 0);
5553 /****************************************************************************
5554 ****************************************************************************/
5556 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5558 DRIVER_INFO_2 *info=NULL;
5561 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5564 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5565 if (!W_ERROR_IS_OK(result))
5568 /* check the required size. */
5569 *needed += spoolss_size_printer_driver_info_2(info);
5571 if (*needed > offered) {
5572 result = WERR_INSUFFICIENT_BUFFER;
5576 if (!rpcbuf_alloc_size(buffer, *needed)) {
5577 result = WERR_NOMEM;
5581 /* fill the buffer with the structures */
5582 smb_io_printer_driver_info_2("", buffer, info, 0);
5591 /****************************************************************************
5592 ****************************************************************************/
5594 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5601 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5602 if (!W_ERROR_IS_OK(result))
5605 /* check the required size. */
5606 *needed += spoolss_size_printer_driver_info_3(&info);
5608 if (*needed > offered) {
5609 result = WERR_INSUFFICIENT_BUFFER;
5613 if (!rpcbuf_alloc_size(buffer, *needed)) {
5614 result = WERR_NOMEM;
5618 /* fill the buffer with the structures */
5619 smb_io_printer_driver_info_3("", buffer, &info, 0);
5622 free_printer_driver_info_3(&info);
5627 /****************************************************************************
5628 ****************************************************************************/
5630 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5637 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5638 if (!W_ERROR_IS_OK(result))
5641 /* check the required size. */
5642 *needed += spoolss_size_printer_driver_info_6(&info);
5644 if (*needed > offered) {
5645 result = WERR_INSUFFICIENT_BUFFER;
5649 if (!rpcbuf_alloc_size(buffer, *needed)) {
5650 result = WERR_NOMEM;
5654 /* fill the buffer with the structures */
5655 smb_io_printer_driver_info_6("", buffer, &info, 0);
5658 free_printer_driver_info_6(&info);
5663 /****************************************************************************
5664 ****************************************************************************/
5666 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5668 POLICY_HND *handle = &q_u->handle;
5669 UNISTR2 *uni_arch = &q_u->architecture;
5670 uint32 level = q_u->level;
5671 uint32 clientmajorversion = q_u->clientmajorversion;
5672 RPC_BUFFER *buffer = NULL;
5673 uint32 offered = q_u->offered;
5674 uint32 *needed = &r_u->needed;
5675 uint32 *servermajorversion = &r_u->servermajorversion;
5676 uint32 *serverminorversion = &r_u->serverminorversion;
5677 Printer_entry *printer;
5680 fstring architecture;
5683 /* that's an [in out] buffer */
5685 if (!q_u->buffer && (offered!=0)) {
5686 return WERR_INVALID_PARAM;
5689 rpcbuf_move(q_u->buffer, &r_u->buffer);
5690 buffer = r_u->buffer;
5692 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5694 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5695 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5696 return WERR_INVALID_PRINTER_NAME;
5700 *servermajorversion = 0;
5701 *serverminorversion = 0;
5703 fstrcpy(servername, get_server_name( printer ));
5704 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5706 if (!get_printer_snum(p, handle, &snum, NULL))
5711 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5713 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5715 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5717 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5720 /* apparently this call is the equivalent of
5721 EnumPrinterDataEx() for the DsDriver key */
5726 return WERR_UNKNOWN_LEVEL;
5729 /****************************************************************************
5730 ****************************************************************************/
5732 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5734 POLICY_HND *handle = &q_u->handle;
5736 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5739 DEBUG(3,("Error in startpageprinter printer handle\n"));
5743 Printer->page_started=True;
5747 /****************************************************************************
5748 ****************************************************************************/
5750 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5752 POLICY_HND *handle = &q_u->handle;
5755 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5758 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5762 if (!get_printer_snum(p, handle, &snum, NULL))
5765 Printer->page_started=False;
5766 print_job_endpage(snum, Printer->jobid);
5771 /********************************************************************
5772 * api_spoolss_getprinter
5773 * called from the spoolss dispatcher
5775 ********************************************************************/
5777 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5779 POLICY_HND *handle = &q_u->handle;
5780 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5781 uint32 *jobid = &r_u->jobid;
5783 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5787 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5790 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5795 * a nice thing with NT is it doesn't listen to what you tell it.
5796 * when asked to send _only_ RAW datas, it tries to send datas
5799 * So I add checks like in NT Server ...
5802 if (info_1->p_datatype != 0) {
5803 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5804 if (strcmp(datatype, "RAW") != 0) {
5806 return WERR_INVALID_DATATYPE;
5810 /* get the share number of the printer */
5811 if (!get_printer_snum(p, handle, &snum, NULL)) {
5815 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5817 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5819 /* An error occured in print_job_start() so return an appropriate
5822 if (Printer->jobid == -1) {
5823 return map_werror_from_unix(errno);
5826 Printer->document_started=True;
5827 (*jobid) = Printer->jobid;
5832 /********************************************************************
5833 * api_spoolss_getprinter
5834 * called from the spoolss dispatcher
5836 ********************************************************************/
5838 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5840 POLICY_HND *handle = &q_u->handle;
5842 return _spoolss_enddocprinter_internal(p, handle);
5845 /****************************************************************************
5846 ****************************************************************************/
5848 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5850 POLICY_HND *handle = &q_u->handle;
5851 uint32 buffer_size = q_u->buffer_size;
5852 uint8 *buffer = q_u->buffer;
5853 uint32 *buffer_written = &q_u->buffer_size2;
5855 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5858 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5859 r_u->buffer_written = q_u->buffer_size2;
5863 if (!get_printer_snum(p, handle, &snum, NULL))
5866 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5867 (SMB_OFF_T)-1, (size_t)buffer_size);
5868 if (*buffer_written == (uint32)-1) {
5869 r_u->buffer_written = 0;
5870 if (errno == ENOSPC)
5871 return WERR_NO_SPOOL_SPACE;
5873 return WERR_ACCESS_DENIED;
5876 r_u->buffer_written = q_u->buffer_size2;
5881 /********************************************************************
5882 * api_spoolss_getprinter
5883 * called from the spoolss dispatcher
5885 ********************************************************************/
5887 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5891 WERROR errcode = WERR_BADFUNC;
5892 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5895 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5899 if (!get_printer_snum(p, handle, &snum, NULL))
5903 case PRINTER_CONTROL_PAUSE:
5904 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5908 case PRINTER_CONTROL_RESUME:
5909 case PRINTER_CONTROL_UNPAUSE:
5910 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5914 case PRINTER_CONTROL_PURGE:
5915 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5920 return WERR_UNKNOWN_LEVEL;
5926 /********************************************************************
5927 * api_spoolss_abortprinter
5928 * From MSDN: "Deletes printer's spool file if printer is configured
5930 ********************************************************************/
5932 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5934 POLICY_HND *handle = &q_u->handle;
5935 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5937 WERROR errcode = WERR_OK;
5940 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5944 if (!get_printer_snum(p, handle, &snum, NULL))
5947 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5952 /********************************************************************
5953 * called by spoolss_api_setprinter
5954 * when updating a printer description
5955 ********************************************************************/
5957 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5958 const SPOOL_PRINTER_INFO_LEVEL *info,
5959 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5961 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5965 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5967 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5968 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5969 OUR_HANDLE(handle)));
5971 result = WERR_BADFID;
5976 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5977 result = WERR_INVALID_PARAM;
5981 /* Check the user has permissions to change the security
5982 descriptor. By experimentation with two NT machines, the user
5983 requires Full Access to the printer to change security
5986 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5987 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5988 result = WERR_ACCESS_DENIED;
5992 /* NT seems to like setting the security descriptor even though
5993 nothing may have actually changed. */
5995 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5997 if (DEBUGLEVEL >= 10) {
6001 the_acl = old_secdesc_ctr->sd->dacl;
6002 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6003 PRINTERNAME(snum), the_acl->num_aces));
6005 for (i = 0; i < the_acl->num_aces; i++) {
6008 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6010 DEBUG(10, ("%s 0x%08x\n", sid_str,
6011 the_acl->aces[i].access_mask));
6014 the_acl = secdesc_ctr->sd->dacl;
6017 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6018 PRINTERNAME(snum), the_acl->num_aces));
6020 for (i = 0; i < the_acl->num_aces; i++) {
6023 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6025 DEBUG(10, ("%s 0x%08x\n", sid_str,
6026 the_acl->aces[i].access_mask));
6029 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6033 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6034 if (!new_secdesc_ctr) {
6035 result = WERR_NOMEM;
6039 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6044 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6051 /********************************************************************
6052 Canonicalize printer info from a client
6054 ATTN: It does not matter what we set the servername to hear
6055 since we do the necessary work in get_a_printer() to set it to
6056 the correct value based on what the client sent in the
6057 _spoolss_open_printer_ex().
6058 ********************************************************************/
6060 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6062 fstring printername;
6065 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6066 "portname=%s drivername=%s comment=%s location=%s\n",
6067 info->servername, info->printername, info->sharename,
6068 info->portname, info->drivername, info->comment, info->location));
6070 /* we force some elements to "correct" values */
6071 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6072 fstrcpy(info->sharename, lp_servicename(snum));
6074 /* check to see if we allow printername != sharename */
6076 if ( lp_force_printername(snum) ) {
6077 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6078 global_myname(), info->sharename );
6081 /* make sure printername is in \\server\printername format */
6083 fstrcpy( printername, info->printername );
6085 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6086 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6090 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6091 global_myname(), p );
6094 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6095 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6102 /****************************************************************************
6103 ****************************************************************************/
6105 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
6107 char *cmd = lp_addport_cmd();
6111 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6112 BOOL is_print_op = False;
6115 return WERR_ACCESS_DENIED;
6118 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
6121 is_print_op = user_has_privileges( token, &se_printop );
6123 DEBUG(10,("Running [%s]\n", command));
6125 /********* BEGIN SePrintOperatorPrivilege **********/
6130 ret = smbrun(command, &fd);
6135 /********* END SePrintOperatorPrivilege **********/
6137 DEBUGADD(10,("returned [%d]\n", ret));
6142 return WERR_ACCESS_DENIED;
6148 /****************************************************************************
6149 ****************************************************************************/
6151 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6153 char *cmd = lp_addprinter_cmd();
6159 fstring remote_machine = "%m";
6160 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6161 BOOL is_print_op = False;
6163 standard_sub_basic(current_user_info.smb_name,
6164 current_user_info.domain,
6165 remote_machine,sizeof(remote_machine));
6167 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6168 cmd, printer->info_2->printername, printer->info_2->sharename,
6169 printer->info_2->portname, printer->info_2->drivername,
6170 printer->info_2->location, printer->info_2->comment, remote_machine);
6173 is_print_op = user_has_privileges( token, &se_printop );
6175 DEBUG(10,("Running [%s]\n", command));
6177 /********* BEGIN SePrintOperatorPrivilege **********/
6182 if ( (ret = smbrun(command, &fd)) == 0 ) {
6183 /* Tell everyone we updated smb.conf. */
6184 message_send_all(smbd_messaging_context(),
6185 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6191 /********* END SePrintOperatorPrivilege **********/
6193 DEBUGADD(10,("returned [%d]\n", ret));
6201 /* reload our services immediately */
6202 reload_services( False );
6205 /* Get lines and convert them back to dos-codepage */
6206 qlines = fd_lines_load(fd, &numlines, 0);
6207 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6210 /* Set the portname to what the script says the portname should be. */
6211 /* but don't require anything to be return from the script exit a good error code */
6214 /* Set the portname to what the script says the portname should be. */
6215 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6216 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6219 file_lines_free(qlines);
6224 /********************************************************************
6225 * Called by spoolss_api_setprinter
6226 * when updating a printer description.
6227 ********************************************************************/
6229 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6230 const SPOOL_PRINTER_INFO_LEVEL *info,
6231 DEVICEMODE *devmode)
6234 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6235 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6240 DEBUG(8,("update_printer\n"));
6245 result = WERR_BADFID;
6249 if (!get_printer_snum(p, handle, &snum, NULL)) {
6250 result = WERR_BADFID;
6254 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6255 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6256 result = WERR_BADFID;
6260 DEBUGADD(8,("Converting info_2 struct\n"));
6263 * convert_printer_info converts the incoming
6264 * info from the client and overwrites the info
6265 * just read from the tdb in the pointer 'printer'.
6268 if (!convert_printer_info(info, printer, level)) {
6269 result = WERR_NOMEM;
6274 /* we have a valid devmode
6275 convert it and link it*/
6277 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6278 if (!convert_devicemode(printer->info_2->printername, devmode,
6279 &printer->info_2->devmode)) {
6280 result = WERR_NOMEM;
6285 /* Do sanity check on the requested changes for Samba */
6287 if (!check_printer_ok(printer->info_2, snum)) {
6288 result = WERR_INVALID_PARAM;
6292 /* FIXME!!! If the driver has changed we really should verify that
6293 it is installed before doing much else --jerry */
6295 /* Check calling user has permission to update printer description */
6297 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6298 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6299 result = WERR_ACCESS_DENIED;
6303 /* Call addprinter hook */
6304 /* Check changes to see if this is really needed */
6306 if ( *lp_addprinter_cmd()
6307 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6308 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6309 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6310 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6312 /* add_printer_hook() will call reload_services() */
6314 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6315 result = WERR_ACCESS_DENIED;
6321 * When a *new* driver is bound to a printer, the drivername is used to
6322 * lookup previously saved driver initialization info, which is then
6323 * bound to the printer, simulating what happens in the Windows arch.
6325 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6327 if (!set_driver_init(printer, 2))
6329 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6330 printer->info_2->drivername));
6333 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6334 printer->info_2->drivername));
6336 notify_printer_driver(snum, printer->info_2->drivername);
6340 * flag which changes actually occured. This is a small subset of
6341 * all the possible changes. We also have to update things in the
6345 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6346 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6347 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6348 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6350 notify_printer_comment(snum, printer->info_2->comment);
6353 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6354 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6355 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6356 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6358 notify_printer_sharename(snum, printer->info_2->sharename);
6361 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6364 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6367 pname = printer->info_2->printername;
6370 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6371 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6372 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6374 notify_printer_printername( snum, pname );
6377 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6378 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6379 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6380 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6382 notify_printer_port(snum, printer->info_2->portname);
6385 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6386 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6387 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6388 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6390 notify_printer_location(snum, printer->info_2->location);
6393 /* here we need to update some more DsSpooler keys */
6394 /* uNCName, serverName, shortServerName */
6396 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6397 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6398 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6399 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6400 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6402 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6403 global_myname(), printer->info_2->sharename );
6404 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6405 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6406 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6408 /* Update printer info */
6409 result = mod_a_printer(printer, 2);
6412 free_a_printer(&printer, 2);
6413 free_a_printer(&old_printer, 2);
6419 /****************************************************************************
6420 ****************************************************************************/
6421 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6422 const SPOOL_PRINTER_INFO_LEVEL *info)
6425 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6427 Printer_entry *Printer;
6429 if ( lp_security() != SEC_ADS ) {
6430 return WERR_UNKNOWN_LEVEL;
6433 Printer = find_printer_index_by_hnd(p, handle);
6435 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6440 if (!get_printer_snum(p, handle, &snum, NULL))
6443 nt_printer_publish(Printer, snum, info7->action);
6447 return WERR_UNKNOWN_LEVEL;
6450 /****************************************************************************
6451 ****************************************************************************/
6453 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6455 POLICY_HND *handle = &q_u->handle;
6456 uint32 level = q_u->level;
6457 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6458 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6459 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6460 uint32 command = q_u->command;
6463 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6466 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6470 /* check the level */
6473 return control_printer(handle, command, p);
6475 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6476 if (!W_ERROR_IS_OK(result))
6479 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6482 return update_printer_sec(handle, level, info, p,
6485 return publish_or_unpublish_printer(p, handle, info);
6487 return WERR_UNKNOWN_LEVEL;
6491 /****************************************************************************
6492 ****************************************************************************/
6494 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6496 POLICY_HND *handle = &q_u->handle;
6497 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6500 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6504 if (Printer->notify.client_connected==True) {
6507 if ( Printer->printer_type == SPLHND_SERVER)
6509 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6510 !get_printer_snum(p, handle, &snum, NULL) )
6513 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6516 Printer->notify.flags=0;
6517 Printer->notify.options=0;
6518 Printer->notify.localmachine[0]='\0';
6519 Printer->notify.printerlocal=0;
6520 if (Printer->notify.option)
6521 free_spool_notify_option(&Printer->notify.option);
6522 Printer->notify.client_connected=False;
6527 /****************************************************************************
6528 ****************************************************************************/
6530 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6532 /* that's an [in out] buffer */
6534 if (!q_u->buffer && (q_u->offered!=0)) {
6535 return WERR_INVALID_PARAM;
6538 rpcbuf_move(q_u->buffer, &r_u->buffer);
6541 return WERR_INVALID_PARAM; /* this is what a NT server
6542 returns for AddJob. AddJob
6543 must fail on non-local
6547 /****************************************************************************
6548 ****************************************************************************/
6550 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6551 int position, int snum,
6552 const NT_PRINTER_INFO_LEVEL *ntprinter)
6556 t=gmtime(&queue->time);
6558 job_info->jobid=queue->job;
6559 init_unistr(&job_info->printername, lp_servicename(snum));
6560 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6561 init_unistr(&job_info->username, queue->fs_user);
6562 init_unistr(&job_info->document, queue->fs_file);
6563 init_unistr(&job_info->datatype, "RAW");
6564 init_unistr(&job_info->text_status, "");
6565 job_info->status=nt_printj_status(queue->status);
6566 job_info->priority=queue->priority;
6567 job_info->position=position;
6568 job_info->totalpages=queue->page_count;
6569 job_info->pagesprinted=0;
6571 make_systemtime(&job_info->submitted, t);
6574 /****************************************************************************
6575 ****************************************************************************/
6577 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6578 int position, int snum,
6579 const NT_PRINTER_INFO_LEVEL *ntprinter,
6580 DEVICEMODE *devmode)
6584 t=gmtime(&queue->time);
6586 job_info->jobid=queue->job;
6588 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6590 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6591 init_unistr(&job_info->username, queue->fs_user);
6592 init_unistr(&job_info->document, queue->fs_file);
6593 init_unistr(&job_info->notifyname, queue->fs_user);
6594 init_unistr(&job_info->datatype, "RAW");
6595 init_unistr(&job_info->printprocessor, "winprint");
6596 init_unistr(&job_info->parameters, "");
6597 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6598 init_unistr(&job_info->text_status, "");
6600 /* and here the security descriptor */
6602 job_info->status=nt_printj_status(queue->status);
6603 job_info->priority=queue->priority;
6604 job_info->position=position;
6605 job_info->starttime=0;
6606 job_info->untiltime=0;
6607 job_info->totalpages=queue->page_count;
6608 job_info->size=queue->size;
6609 make_systemtime(&(job_info->submitted), t);
6610 job_info->timeelapsed=0;
6611 job_info->pagesprinted=0;
6613 job_info->devmode = devmode;
6618 /****************************************************************************
6619 Enumjobs at level 1.
6620 ****************************************************************************/
6622 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6623 const NT_PRINTER_INFO_LEVEL *ntprinter,
6624 RPC_BUFFER *buffer, uint32 offered,
6625 uint32 *needed, uint32 *returned)
6629 WERROR result = WERR_OK;
6631 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6637 for (i=0; i<*returned; i++)
6638 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6640 /* check the required size. */
6641 for (i=0; i<*returned; i++)
6642 (*needed) += spoolss_size_job_info_1(&info[i]);
6644 if (*needed > offered) {
6645 result = WERR_INSUFFICIENT_BUFFER;
6649 if (!rpcbuf_alloc_size(buffer, *needed)) {
6650 result = WERR_NOMEM;
6654 /* fill the buffer with the structures */
6655 for (i=0; i<*returned; i++)
6656 smb_io_job_info_1("", buffer, &info[i], 0);
6662 if ( !W_ERROR_IS_OK(result) )
6668 /****************************************************************************
6669 Enumjobs at level 2.
6670 ****************************************************************************/
6672 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6673 const NT_PRINTER_INFO_LEVEL *ntprinter,
6674 RPC_BUFFER *buffer, uint32 offered,
6675 uint32 *needed, uint32 *returned)
6677 JOB_INFO_2 *info = NULL;
6679 WERROR result = WERR_OK;
6680 DEVICEMODE *devmode = NULL;
6682 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6687 /* this should not be a failure condition if the devmode is NULL */
6689 devmode = construct_dev_mode(lp_const_servicename(snum));
6691 for (i=0; i<*returned; i++)
6692 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6694 /* check the required size. */
6695 for (i=0; i<*returned; i++)
6696 (*needed) += spoolss_size_job_info_2(&info[i]);
6698 if (*needed > offered) {
6699 result = WERR_INSUFFICIENT_BUFFER;
6703 if (!rpcbuf_alloc_size(buffer, *needed)) {
6704 result = WERR_NOMEM;
6708 /* fill the buffer with the structures */
6709 for (i=0; i<*returned; i++)
6710 smb_io_job_info_2("", buffer, &info[i], 0);
6713 free_devmode(devmode);
6716 if ( !W_ERROR_IS_OK(result) )
6723 /****************************************************************************
6725 ****************************************************************************/
6727 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6729 POLICY_HND *handle = &q_u->handle;
6730 uint32 level = q_u->level;
6731 RPC_BUFFER *buffer = NULL;
6732 uint32 offered = q_u->offered;
6733 uint32 *needed = &r_u->needed;
6734 uint32 *returned = &r_u->returned;
6736 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6738 print_status_struct prt_status;
6739 print_queue_struct *queue=NULL;
6741 /* that's an [in out] buffer */
6743 if (!q_u->buffer && (offered!=0)) {
6744 return WERR_INVALID_PARAM;
6747 rpcbuf_move(q_u->buffer, &r_u->buffer);
6748 buffer = r_u->buffer;
6750 DEBUG(4,("_spoolss_enumjobs\n"));
6755 /* lookup the printer snum and tdb entry */
6757 if (!get_printer_snum(p, handle, &snum, NULL))
6760 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6761 if ( !W_ERROR_IS_OK(wret) )
6764 *returned = print_queue_status(snum, &queue, &prt_status);
6765 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6767 if (*returned == 0) {
6769 free_a_printer(&ntprinter, 2);
6775 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6778 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6782 wret = WERR_UNKNOWN_LEVEL;
6787 free_a_printer( &ntprinter, 2 );
6791 /****************************************************************************
6792 ****************************************************************************/
6794 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6799 /****************************************************************************
6800 ****************************************************************************/
6802 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6804 POLICY_HND *handle = &q_u->handle;
6805 uint32 jobid = q_u->jobid;
6806 uint32 command = q_u->command;
6809 WERROR errcode = WERR_BADFUNC;
6811 if (!get_printer_snum(p, handle, &snum, NULL)) {
6815 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6816 return WERR_INVALID_PRINTER_NAME;
6820 case JOB_CONTROL_CANCEL:
6821 case JOB_CONTROL_DELETE:
6822 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6826 case JOB_CONTROL_PAUSE:
6827 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6831 case JOB_CONTROL_RESTART:
6832 case JOB_CONTROL_RESUME:
6833 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6838 return WERR_UNKNOWN_LEVEL;
6844 /****************************************************************************
6845 Enumerates all printer drivers at level 1.
6846 ****************************************************************************/
6848 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6853 fstring *list = NULL;
6854 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6855 DRIVER_INFO_1 *driver_info_1=NULL;
6856 WERROR result = WERR_OK;
6860 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6862 ndrivers=get_ntdrivers(&list, architecture, version);
6863 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6865 if(ndrivers == -1) {
6866 SAFE_FREE(driver_info_1);
6871 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6872 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6878 for (i=0; i<ndrivers; i++) {
6880 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6881 ZERO_STRUCT(driver);
6882 status = get_a_printer_driver(&driver, 3, list[i],
6883 architecture, version);
6884 if (!W_ERROR_IS_OK(status)) {
6886 SAFE_FREE(driver_info_1);
6889 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6890 free_a_printer_driver(driver, 3);
6893 *returned+=ndrivers;
6897 /* check the required size. */
6898 for (i=0; i<*returned; i++) {
6899 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6900 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6903 if (*needed > offered) {
6904 result = WERR_INSUFFICIENT_BUFFER;
6908 if (!rpcbuf_alloc_size(buffer, *needed)) {
6909 result = WERR_NOMEM;
6913 /* fill the buffer with the driver structures */
6914 for (i=0; i<*returned; i++) {
6915 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6916 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6920 SAFE_FREE(driver_info_1);
6922 if ( !W_ERROR_IS_OK(result) )
6928 /****************************************************************************
6929 Enumerates all printer drivers at level 2.
6930 ****************************************************************************/
6932 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6937 fstring *list = NULL;
6938 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6939 DRIVER_INFO_2 *driver_info_2=NULL;
6940 WERROR result = WERR_OK;
6944 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6946 ndrivers=get_ntdrivers(&list, architecture, version);
6947 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6949 if(ndrivers == -1) {
6950 SAFE_FREE(driver_info_2);
6955 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6956 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6962 for (i=0; i<ndrivers; i++) {
6965 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6966 ZERO_STRUCT(driver);
6967 status = get_a_printer_driver(&driver, 3, list[i],
6968 architecture, version);
6969 if (!W_ERROR_IS_OK(status)) {
6971 SAFE_FREE(driver_info_2);
6974 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6975 free_a_printer_driver(driver, 3);
6978 *returned+=ndrivers;
6982 /* check the required size. */
6983 for (i=0; i<*returned; i++) {
6984 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6985 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6988 if (*needed > offered) {
6989 result = WERR_INSUFFICIENT_BUFFER;
6993 if (!rpcbuf_alloc_size(buffer, *needed)) {
6994 result = WERR_NOMEM;
6998 /* fill the buffer with the form structures */
6999 for (i=0; i<*returned; i++) {
7000 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7001 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7005 SAFE_FREE(driver_info_2);
7007 if ( !W_ERROR_IS_OK(result) )
7013 /****************************************************************************
7014 Enumerates all printer drivers at level 3.
7015 ****************************************************************************/
7017 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7022 fstring *list = NULL;
7023 DRIVER_INFO_3 *driver_info_3=NULL;
7024 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7025 WERROR result = WERR_OK;
7029 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7031 ndrivers=get_ntdrivers(&list, architecture, version);
7032 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7034 if(ndrivers == -1) {
7035 SAFE_FREE(driver_info_3);
7040 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7041 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7047 for (i=0; i<ndrivers; i++) {
7050 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7051 ZERO_STRUCT(driver);
7052 status = get_a_printer_driver(&driver, 3, list[i],
7053 architecture, version);
7054 if (!W_ERROR_IS_OK(status)) {
7056 SAFE_FREE(driver_info_3);
7059 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7060 free_a_printer_driver(driver, 3);
7063 *returned+=ndrivers;
7067 /* check the required size. */
7068 for (i=0; i<*returned; i++) {
7069 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7070 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7073 if (*needed > offered) {
7074 result = WERR_INSUFFICIENT_BUFFER;
7078 if (!rpcbuf_alloc_size(buffer, *needed)) {
7079 result = WERR_NOMEM;
7083 /* fill the buffer with the driver structures */
7084 for (i=0; i<*returned; i++) {
7085 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7086 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7090 for (i=0; i<*returned; i++) {
7091 SAFE_FREE(driver_info_3[i].dependentfiles);
7094 SAFE_FREE(driver_info_3);
7096 if ( !W_ERROR_IS_OK(result) )
7102 /****************************************************************************
7103 Enumerates all printer drivers.
7104 ****************************************************************************/
7106 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7108 uint32 level = q_u->level;
7109 RPC_BUFFER *buffer = NULL;
7110 uint32 offered = q_u->offered;
7111 uint32 *needed = &r_u->needed;
7112 uint32 *returned = &r_u->returned;
7115 fstring architecture;
7117 /* that's an [in out] buffer */
7119 if (!q_u->buffer && (offered!=0)) {
7120 return WERR_INVALID_PARAM;
7123 rpcbuf_move(q_u->buffer, &r_u->buffer);
7124 buffer = r_u->buffer;
7126 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7131 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7132 unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7134 if ( !is_myname_or_ipaddr( servername ) )
7135 return WERR_UNKNOWN_PRINTER_DRIVER;
7139 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7141 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7143 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7145 return WERR_UNKNOWN_LEVEL;
7149 /****************************************************************************
7150 ****************************************************************************/
7152 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7154 form->flag=list->flag;
7155 init_unistr(&form->name, list->name);
7156 form->width=list->width;
7157 form->length=list->length;
7158 form->left=list->left;
7159 form->top=list->top;
7160 form->right=list->right;
7161 form->bottom=list->bottom;
7164 /****************************************************************************
7165 ****************************************************************************/
7167 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7169 uint32 level = q_u->level;
7170 RPC_BUFFER *buffer = NULL;
7171 uint32 offered = q_u->offered;
7172 uint32 *needed = &r_u->needed;
7173 uint32 *numofforms = &r_u->numofforms;
7174 uint32 numbuiltinforms;
7176 nt_forms_struct *list=NULL;
7177 nt_forms_struct *builtinlist=NULL;
7182 /* that's an [in out] buffer */
7184 if (!q_u->buffer && (offered!=0) ) {
7185 return WERR_INVALID_PARAM;
7188 rpcbuf_move(q_u->buffer, &r_u->buffer);
7189 buffer = r_u->buffer;
7191 DEBUG(4,("_spoolss_enumforms\n"));
7192 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7193 DEBUGADD(5,("Info level [%d]\n", level));
7195 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7196 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7197 *numofforms = get_ntforms(&list);
7198 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7199 *numofforms += numbuiltinforms;
7201 if (*numofforms == 0) {
7202 SAFE_FREE(builtinlist);
7204 return WERR_NO_MORE_ITEMS;
7209 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7210 SAFE_FREE(builtinlist);
7216 /* construct the list of form structures */
7217 for (i=0; i<numbuiltinforms; i++) {
7218 DEBUGADD(6,("Filling form number [%d]\n",i));
7219 fill_form_1(&forms_1[i], &builtinlist[i]);
7222 SAFE_FREE(builtinlist);
7224 for (; i<*numofforms; i++) {
7225 DEBUGADD(6,("Filling form number [%d]\n",i));
7226 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7231 /* check the required size. */
7232 for (i=0; i<numbuiltinforms; i++) {
7233 DEBUGADD(6,("adding form [%d]'s size\n",i));
7234 buffer_size += spoolss_size_form_1(&forms_1[i]);
7236 for (; i<*numofforms; i++) {
7237 DEBUGADD(6,("adding form [%d]'s size\n",i));
7238 buffer_size += spoolss_size_form_1(&forms_1[i]);
7241 *needed=buffer_size;
7243 if (*needed > offered) {
7246 return WERR_INSUFFICIENT_BUFFER;
7249 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7255 /* fill the buffer with the form structures */
7256 for (i=0; i<numbuiltinforms; i++) {
7257 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7258 smb_io_form_1("", buffer, &forms_1[i], 0);
7260 for (; i<*numofforms; i++) {
7261 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7262 smb_io_form_1("", buffer, &forms_1[i], 0);
7271 SAFE_FREE(builtinlist);
7272 return WERR_UNKNOWN_LEVEL;
7276 /****************************************************************************
7277 ****************************************************************************/
7279 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7281 uint32 level = q_u->level;
7282 UNISTR2 *uni_formname = &q_u->formname;
7283 RPC_BUFFER *buffer = NULL;
7284 uint32 offered = q_u->offered;
7285 uint32 *needed = &r_u->needed;
7287 nt_forms_struct *list=NULL;
7288 nt_forms_struct builtin_form;
7293 int numofforms=0, i=0;
7295 /* that's an [in out] buffer */
7297 if (!q_u->buffer && (offered!=0)) {
7298 return WERR_INVALID_PARAM;
7301 rpcbuf_move(q_u->buffer, &r_u->buffer);
7302 buffer = r_u->buffer;
7304 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
7306 DEBUG(4,("_spoolss_getform\n"));
7307 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7308 DEBUGADD(5,("Info level [%d]\n", level));
7310 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7311 if (!foundBuiltin) {
7312 numofforms = get_ntforms(&list);
7313 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7315 if (numofforms == 0)
7322 fill_form_1(&form_1, &builtin_form);
7325 /* Check if the requested name is in the list of form structures */
7326 for (i=0; i<numofforms; i++) {
7328 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7330 if (strequal(form_name, list[i].name)) {
7331 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7332 fill_form_1(&form_1, &list[i]);
7338 if (i == numofforms) {
7342 /* check the required size. */
7344 *needed=spoolss_size_form_1(&form_1);
7346 if (*needed > offered)
7347 return WERR_INSUFFICIENT_BUFFER;
7349 if (!rpcbuf_alloc_size(buffer, buffer_size))
7352 /* fill the buffer with the form structures */
7353 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7354 smb_io_form_1("", buffer, &form_1, 0);
7360 return WERR_UNKNOWN_LEVEL;
7364 /****************************************************************************
7365 ****************************************************************************/
7367 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7369 init_unistr(&port->port_name, name);
7372 /****************************************************************************
7373 TODO: This probably needs distinguish between TCP/IP and Local ports
7375 ****************************************************************************/
7377 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7379 init_unistr(&port->port_name, name);
7380 init_unistr(&port->monitor_name, "Local Monitor");
7381 init_unistr(&port->description, SPL_LOCAL_PORT );
7382 port->port_type=PORT_TYPE_WRITE;
7387 /****************************************************************************
7388 wrapper around the enumer ports command
7389 ****************************************************************************/
7391 WERROR enumports_hook( int *count, char ***lines )
7393 char *cmd = lp_enumports_cmd();
7403 /* if no hook then just fill in the default port */
7406 if (!(qlines = SMB_MALLOC_ARRAY( char*, 2 ))) {
7409 if (!(qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME ))) {
7417 /* we have a valid enumport command */
7419 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7421 DEBUG(10,("Running [%s]\n", command));
7422 ret = smbrun(command, &fd);
7423 DEBUG(10,("Returned [%d]\n", ret));
7428 return WERR_ACCESS_DENIED;
7432 qlines = fd_lines_load(fd, &numlines, 0);
7433 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7443 /****************************************************************************
7445 ****************************************************************************/
7447 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7449 PORT_INFO_1 *ports=NULL;
7451 WERROR result = WERR_OK;
7452 char **qlines = NULL;
7455 result = enumports_hook( &numlines, &qlines );
7456 if (!W_ERROR_IS_OK(result)) {
7457 file_lines_free(qlines);
7462 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7463 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7464 dos_errstr(WERR_NOMEM)));
7465 file_lines_free(qlines);
7469 for (i=0; i<numlines; i++) {
7470 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7471 fill_port_1(&ports[i], qlines[i]);
7474 file_lines_free(qlines);
7476 *returned = numlines;
7478 /* check the required size. */
7479 for (i=0; i<*returned; i++) {
7480 DEBUGADD(6,("adding port [%d]'s size\n", i));
7481 *needed += spoolss_size_port_info_1(&ports[i]);
7484 if (*needed > offered) {
7485 result = WERR_INSUFFICIENT_BUFFER;
7489 if (!rpcbuf_alloc_size(buffer, *needed)) {
7490 result = WERR_NOMEM;
7494 /* fill the buffer with the ports structures */
7495 for (i=0; i<*returned; i++) {
7496 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7497 smb_io_port_1("", buffer, &ports[i], 0);
7503 if ( !W_ERROR_IS_OK(result) )
7509 /****************************************************************************
7511 ****************************************************************************/
7513 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7515 PORT_INFO_2 *ports=NULL;
7517 WERROR result = WERR_OK;
7518 char **qlines = NULL;
7521 result = enumports_hook( &numlines, &qlines );
7522 if ( !W_ERROR_IS_OK(result)) {
7523 file_lines_free(qlines);
7528 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7529 file_lines_free(qlines);
7533 for (i=0; i<numlines; i++) {
7534 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7535 fill_port_2(&(ports[i]), qlines[i]);
7539 file_lines_free(qlines);
7541 *returned = numlines;
7543 /* check the required size. */
7544 for (i=0; i<*returned; i++) {
7545 DEBUGADD(6,("adding port [%d]'s size\n", i));
7546 *needed += spoolss_size_port_info_2(&ports[i]);
7549 if (*needed > offered) {
7550 result = WERR_INSUFFICIENT_BUFFER;
7554 if (!rpcbuf_alloc_size(buffer, *needed)) {
7555 result = WERR_NOMEM;
7559 /* fill the buffer with the ports structures */
7560 for (i=0; i<*returned; i++) {
7561 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7562 smb_io_port_2("", buffer, &ports[i], 0);
7568 if ( !W_ERROR_IS_OK(result) )
7574 /****************************************************************************
7576 ****************************************************************************/
7578 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7580 uint32 level = q_u->level;
7581 RPC_BUFFER *buffer = NULL;
7582 uint32 offered = q_u->offered;
7583 uint32 *needed = &r_u->needed;
7584 uint32 *returned = &r_u->returned;
7586 /* that's an [in out] buffer */
7588 if (!q_u->buffer && (offered!=0)) {
7589 return WERR_INVALID_PARAM;
7592 rpcbuf_move(q_u->buffer, &r_u->buffer);
7593 buffer = r_u->buffer;
7595 DEBUG(4,("_spoolss_enumports\n"));
7602 return enumports_level_1(buffer, offered, needed, returned);
7604 return enumports_level_2(buffer, offered, needed, returned);
7606 return WERR_UNKNOWN_LEVEL;
7610 /****************************************************************************
7611 ****************************************************************************/
7613 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7614 const SPOOL_PRINTER_INFO_LEVEL *info,
7615 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7616 uint32 user_switch, const SPOOL_USER_CTR *user,
7619 NT_PRINTER_INFO_LEVEL *printer = NULL;
7622 WERROR err = WERR_OK;
7624 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7625 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7629 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7630 if (!convert_printer_info(info, printer, 2)) {
7631 free_a_printer(&printer, 2);
7635 /* check to see if the printer already exists */
7637 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7638 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7639 printer->info_2->sharename));
7640 free_a_printer(&printer, 2);
7641 return WERR_PRINTER_ALREADY_EXISTS;
7644 /* FIXME!!! smbd should check to see if the driver is installed before
7645 trying to add a printer like this --jerry */
7647 if (*lp_addprinter_cmd() ) {
7648 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7649 free_a_printer(&printer,2);
7650 return WERR_ACCESS_DENIED;
7653 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7654 "smb.conf parameter \"addprinter command\" is defined. This"
7655 "parameter must exist for this call to succeed\n",
7656 printer->info_2->sharename ));
7659 /* use our primary netbios name since get_a_printer() will convert
7660 it to what the client expects on a case by case basis */
7662 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7663 printer->info_2->sharename);
7666 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7667 free_a_printer(&printer,2);
7668 return WERR_ACCESS_DENIED;
7671 /* you must be a printer admin to add a new printer */
7672 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7673 free_a_printer(&printer,2);
7674 return WERR_ACCESS_DENIED;
7678 * Do sanity check on the requested changes for Samba.
7681 if (!check_printer_ok(printer->info_2, snum)) {
7682 free_a_printer(&printer,2);
7683 return WERR_INVALID_PARAM;
7687 * When a printer is created, the drivername bound to the printer is used
7688 * to lookup previously saved driver initialization info, which is then
7689 * bound to the new printer, simulating what happens in the Windows arch.
7694 set_driver_init(printer, 2);
7698 /* A valid devmode was included, convert and link it
7700 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7702 if (!convert_devicemode(printer->info_2->printername, devmode,
7703 &printer->info_2->devmode))
7707 /* write the ASCII on disk */
7708 err = mod_a_printer(printer, 2);
7709 if (!W_ERROR_IS_OK(err)) {
7710 free_a_printer(&printer,2);
7714 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7715 /* Handle open failed - remove addition. */
7716 del_a_printer(printer->info_2->sharename);
7717 free_a_printer(&printer,2);
7718 return WERR_ACCESS_DENIED;
7721 update_c_setprinter(False);
7722 free_a_printer(&printer,2);
7727 /****************************************************************************
7728 ****************************************************************************/
7730 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7732 UNISTR2 *uni_srv_name = q_u->server_name;
7733 uint32 level = q_u->level;
7734 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7735 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7736 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7737 uint32 user_switch = q_u->user_switch;
7738 SPOOL_USER_CTR *user = &q_u->user_ctr;
7739 POLICY_HND *handle = &r_u->handle;
7743 /* we don't handle yet */
7744 /* but I know what to do ... */
7745 return WERR_UNKNOWN_LEVEL;
7747 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7749 user_switch, user, handle);
7751 return WERR_UNKNOWN_LEVEL;
7755 /****************************************************************************
7756 ****************************************************************************/
7758 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7760 uint32 level = q_u->level;
7761 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7762 WERROR err = WERR_OK;
7763 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7764 fstring driver_name;
7767 ZERO_STRUCT(driver);
7769 if (!convert_printer_driver_info(info, &driver, level)) {
7774 DEBUG(5,("Cleaning driver's information\n"));
7775 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7776 if (!W_ERROR_IS_OK(err))
7779 DEBUG(5,("Moving driver to final destination\n"));
7780 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7784 if (add_a_printer_driver(driver, level)!=0) {
7785 err = WERR_ACCESS_DENIED;
7790 * I think this is where he DrvUpgradePrinter() hook would be
7791 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7792 * server. Right now, we just need to send ourselves a message
7793 * to update each printer bound to this driver. --jerry
7796 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7797 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7802 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7803 * decide if the driver init data should be deleted. The rules are:
7804 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7805 * 2) delete init data only if there is no 2k/Xp driver
7806 * 3) always delete init data
7807 * The generalized rule is always use init data from the highest order driver.
7808 * It is necessary to follow the driver install by an initialization step to
7809 * finish off this process.
7812 version = driver.info_3->cversion;
7813 else if (level == 6)
7814 version = driver.info_6->version;
7819 * 9x printer driver - never delete init data
7822 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7827 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7828 * there is no 2k/Xp driver init data for this driver name.
7832 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7834 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7836 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7838 if (!del_driver_init(driver_name))
7839 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7842 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7844 free_a_printer_driver(driver1,3);
7845 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7852 * 2k or Xp printer driver - always delete init data
7855 if (!del_driver_init(driver_name))
7856 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7860 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7866 free_a_printer_driver(driver, level);
7870 /********************************************************************
7871 * spoolss_addprinterdriverex
7872 ********************************************************************/
7874 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7876 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7877 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7880 * we only support the semantics of AddPrinterDriver()
7881 * i.e. only copy files that are newer than existing ones
7884 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7885 return WERR_ACCESS_DENIED;
7887 ZERO_STRUCT(q_u_local);
7888 ZERO_STRUCT(r_u_local);
7890 /* just pass the information off to _spoolss_addprinterdriver() */
7891 q_u_local.server_name_ptr = q_u->server_name_ptr;
7892 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7893 q_u_local.level = q_u->level;
7894 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7896 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7899 /****************************************************************************
7900 ****************************************************************************/
7902 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7904 init_unistr(&info->name, name);
7907 /****************************************************************************
7908 ****************************************************************************/
7910 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7916 const char *short_archi;
7917 DRIVER_DIRECTORY_1 *info=NULL;
7918 WERROR result = WERR_OK;
7920 unistr2_to_ascii(servername, name, sizeof(servername));
7921 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi));
7923 /* check for beginning double '\'s and that the server
7926 pservername = servername;
7927 if ( *pservername == '\\' && strlen(servername)>2 ) {
7931 if ( !is_myname_or_ipaddr( pservername ) )
7932 return WERR_INVALID_PARAM;
7934 if (!(short_archi = get_short_archi(long_archi)))
7935 return WERR_INVALID_ENVIRONMENT;
7937 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7940 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7942 DEBUG(4,("printer driver directory: [%s]\n", path));
7944 fill_driverdir_1(info, path);
7946 *needed += spoolss_size_driverdir_info_1(info);
7948 if (*needed > offered) {
7949 result = WERR_INSUFFICIENT_BUFFER;
7953 if (!rpcbuf_alloc_size(buffer, *needed)) {
7954 result = WERR_NOMEM;
7958 smb_io_driverdir_1("", buffer, info, 0);
7966 /****************************************************************************
7967 ****************************************************************************/
7969 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7971 UNISTR2 *name = &q_u->name;
7972 UNISTR2 *uni_environment = &q_u->environment;
7973 uint32 level = q_u->level;
7974 RPC_BUFFER *buffer = NULL;
7975 uint32 offered = q_u->offered;
7976 uint32 *needed = &r_u->needed;
7978 /* that's an [in out] buffer */
7980 if (!q_u->buffer && (offered!=0)) {
7981 return WERR_INVALID_PARAM;
7984 rpcbuf_move(q_u->buffer, &r_u->buffer);
7985 buffer = r_u->buffer;
7987 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7993 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7995 return WERR_UNKNOWN_LEVEL;
7999 /****************************************************************************
8000 ****************************************************************************/
8002 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8004 POLICY_HND *handle = &q_u->handle;
8005 uint32 idx = q_u->index;
8006 uint32 in_value_len = q_u->valuesize;
8007 uint32 in_data_len = q_u->datasize;
8008 uint32 *out_max_value_len = &r_u->valuesize;
8009 uint16 **out_value = &r_u->value;
8010 uint32 *out_value_len = &r_u->realvaluesize;
8011 uint32 *out_type = &r_u->type;
8012 uint32 *out_max_data_len = &r_u->datasize;
8013 uint8 **data_out = &r_u->data;
8014 uint32 *out_data_len = &r_u->realdatasize;
8016 NT_PRINTER_INFO_LEVEL *printer = NULL;
8018 uint32 biggest_valuesize;
8019 uint32 biggest_datasize;
8021 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8024 REGISTRY_VALUE *val = NULL;
8025 NT_PRINTER_DATA *p_data;
8026 int i, key_index, num_values;
8031 *out_max_data_len = 0;
8035 DEBUG(5,("spoolss_enumprinterdata\n"));
8038 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8042 if (!get_printer_snum(p,handle, &snum, NULL))
8045 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8046 if (!W_ERROR_IS_OK(result))
8049 p_data = printer->info_2->data;
8050 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8055 * The NT machine wants to know the biggest size of value and data
8057 * cf: MSDN EnumPrinterData remark section
8060 if ( !in_value_len && !in_data_len && (key_index != -1) )
8062 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8064 biggest_valuesize = 0;
8065 biggest_datasize = 0;
8067 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8069 for ( i=0; i<num_values; i++ )
8071 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8073 name_length = strlen(val->valuename);
8074 if ( strlen(val->valuename) > biggest_valuesize )
8075 biggest_valuesize = name_length;
8077 if ( val->size > biggest_datasize )
8078 biggest_datasize = val->size;
8080 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8084 /* the value is an UNICODE string but real_value_size is the length
8085 in bytes including the trailing 0 */
8087 *out_value_len = 2 * (1+biggest_valuesize);
8088 *out_data_len = biggest_datasize;
8090 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8096 * the value len is wrong in NT sp3
8097 * that's the number of bytes not the number of unicode chars
8100 if ( key_index != -1 )
8101 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8106 /* out_value should default to "" or else NT4 has
8107 problems unmarshalling the response */
8109 *out_max_value_len=(in_value_len/sizeof(uint16));
8112 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8114 result = WERR_NOMEM;
8117 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8123 /* the data is counted in bytes */
8125 *out_max_data_len = in_data_len;
8126 *out_data_len = in_data_len;
8128 /* only allocate when given a non-zero data_len */
8130 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8132 result = WERR_NOMEM;
8136 result = WERR_NO_MORE_ITEMS;
8142 * - counted in bytes in the request
8143 * - counted in UNICODE chars in the max reply
8144 * - counted in bytes in the real size
8146 * take a pause *before* coding not *during* coding
8150 *out_max_value_len=(in_value_len/sizeof(uint16));
8152 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8154 result = WERR_NOMEM;
8158 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8166 *out_type = regval_type( val );
8168 /* data - counted in bytes */
8170 *out_max_data_len = in_data_len;
8171 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8173 result = WERR_NOMEM;
8176 data_len = regval_size(val);
8177 if ( *data_out && data_len )
8178 memcpy( *data_out, regval_data_p(val), data_len );
8179 *out_data_len = data_len;
8183 free_a_printer(&printer, 2);
8187 /****************************************************************************
8188 ****************************************************************************/
8190 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8192 POLICY_HND *handle = &q_u->handle;
8193 UNISTR2 *value = &q_u->value;
8194 uint32 type = q_u->type;
8195 uint8 *data = q_u->data;
8196 uint32 real_len = q_u->real_len;
8198 NT_PRINTER_INFO_LEVEL *printer = NULL;
8200 WERROR status = WERR_OK;
8201 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8204 DEBUG(5,("spoolss_setprinterdata\n"));
8207 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8211 if ( Printer->printer_type == SPLHND_SERVER ) {
8212 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8213 return WERR_INVALID_PARAM;
8216 if (!get_printer_snum(p,handle, &snum, NULL))
8220 * Access check : NT returns "access denied" if you make a
8221 * SetPrinterData call without the necessary privildge.
8222 * we were originally returning OK if nothing changed
8223 * which made Win2k issue **a lot** of SetPrinterData
8224 * when connecting to a printer --jerry
8227 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8229 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8230 status = WERR_ACCESS_DENIED;
8234 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8235 if (!W_ERROR_IS_OK(status))
8238 unistr2_to_ascii(valuename, value, sizeof(valuename));
8241 * When client side code sets a magic printer data key, detect it and save
8242 * the current printer data and the magic key's data (its the DEVMODE) for
8243 * future printer/driver initializations.
8245 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8247 /* Set devmode and printer initialization info */
8248 status = save_driver_init( printer, 2, data, real_len );
8250 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8254 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8255 type, data, real_len );
8256 if ( W_ERROR_IS_OK(status) )
8257 status = mod_a_printer(printer, 2);
8261 free_a_printer(&printer, 2);
8266 /****************************************************************************
8267 ****************************************************************************/
8269 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8271 POLICY_HND *handle = &q_u->handle;
8272 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8275 DEBUG(5,("_spoolss_resetprinter\n"));
8278 * All we do is to check to see if the handle and queue is valid.
8279 * This call really doesn't mean anything to us because we only
8280 * support RAW printing. --jerry
8284 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8288 if (!get_printer_snum(p,handle, &snum, NULL))
8292 /* blindly return success */
8297 /****************************************************************************
8298 ****************************************************************************/
8300 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8302 POLICY_HND *handle = &q_u->handle;
8303 UNISTR2 *value = &q_u->valuename;
8305 NT_PRINTER_INFO_LEVEL *printer = NULL;
8307 WERROR status = WERR_OK;
8308 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8311 DEBUG(5,("spoolss_deleteprinterdata\n"));
8314 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8318 if (!get_printer_snum(p, handle, &snum, NULL))
8321 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8322 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8323 return WERR_ACCESS_DENIED;
8326 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8327 if (!W_ERROR_IS_OK(status))
8330 unistr2_to_ascii(valuename, value, sizeof(valuename));
8332 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8334 if ( W_ERROR_IS_OK(status) )
8335 mod_a_printer( printer, 2 );
8337 free_a_printer(&printer, 2);
8342 /****************************************************************************
8343 ****************************************************************************/
8345 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8347 POLICY_HND *handle = &q_u->handle;
8348 FORM *form = &q_u->form;
8349 nt_forms_struct tmpForm;
8351 WERROR status = WERR_OK;
8352 NT_PRINTER_INFO_LEVEL *printer = NULL;
8355 nt_forms_struct *list=NULL;
8356 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8358 DEBUG(5,("spoolss_addform\n"));
8361 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8366 /* forms can be added on printer of on the print server handle */
8368 if ( Printer->printer_type == SPLHND_PRINTER )
8370 if (!get_printer_snum(p,handle, &snum, NULL))
8373 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8374 if (!W_ERROR_IS_OK(status))
8378 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8379 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8380 status = WERR_ACCESS_DENIED;
8384 /* can't add if builtin */
8386 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8387 status = WERR_ALREADY_EXISTS;
8391 count = get_ntforms(&list);
8393 if(!add_a_form(&list, form, &count)) {
8394 status = WERR_NOMEM;
8398 write_ntforms(&list, count);
8401 * ChangeID must always be set if this is a printer
8404 if ( Printer->printer_type == SPLHND_PRINTER )
8405 status = mod_a_printer(printer, 2);
8409 free_a_printer(&printer, 2);
8415 /****************************************************************************
8416 ****************************************************************************/
8418 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8420 POLICY_HND *handle = &q_u->handle;
8421 UNISTR2 *form_name = &q_u->name;
8422 nt_forms_struct tmpForm;
8424 nt_forms_struct *list=NULL;
8425 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8427 WERROR status = WERR_OK;
8428 NT_PRINTER_INFO_LEVEL *printer = NULL;
8430 DEBUG(5,("spoolss_deleteform\n"));
8433 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8437 /* forms can be deleted on printer of on the print server handle */
8439 if ( Printer->printer_type == SPLHND_PRINTER )
8441 if (!get_printer_snum(p,handle, &snum, NULL))
8444 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8445 if (!W_ERROR_IS_OK(status))
8449 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8450 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8451 status = WERR_ACCESS_DENIED;
8455 /* can't delete if builtin */
8457 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8458 status = WERR_INVALID_PARAM;
8462 count = get_ntforms(&list);
8464 if ( !delete_a_form(&list, form_name, &count, &status ))
8468 * ChangeID must always be set if this is a printer
8471 if ( Printer->printer_type == SPLHND_PRINTER )
8472 status = mod_a_printer(printer, 2);
8476 free_a_printer(&printer, 2);
8482 /****************************************************************************
8483 ****************************************************************************/
8485 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8487 POLICY_HND *handle = &q_u->handle;
8488 FORM *form = &q_u->form;
8489 nt_forms_struct tmpForm;
8491 WERROR status = WERR_OK;
8492 NT_PRINTER_INFO_LEVEL *printer = NULL;
8495 nt_forms_struct *list=NULL;
8496 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8498 DEBUG(5,("spoolss_setform\n"));
8501 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8505 /* forms can be modified on printer of on the print server handle */
8507 if ( Printer->printer_type == SPLHND_PRINTER )
8509 if (!get_printer_snum(p,handle, &snum, NULL))
8512 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8513 if (!W_ERROR_IS_OK(status))
8517 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8518 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8519 status = WERR_ACCESS_DENIED;
8523 /* can't set if builtin */
8524 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8525 status = WERR_INVALID_PARAM;
8529 count = get_ntforms(&list);
8530 update_a_form(&list, form, count);
8531 write_ntforms(&list, count);
8534 * ChangeID must always be set if this is a printer
8537 if ( Printer->printer_type == SPLHND_PRINTER )
8538 status = mod_a_printer(printer, 2);
8543 free_a_printer(&printer, 2);
8549 /****************************************************************************
8550 enumprintprocessors level 1.
8551 ****************************************************************************/
8553 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8555 PRINTPROCESSOR_1 *info_1=NULL;
8556 WERROR result = WERR_OK;
8558 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8563 init_unistr(&info_1->name, "winprint");
8565 *needed += spoolss_size_printprocessor_info_1(info_1);
8567 if (*needed > offered) {
8568 result = WERR_INSUFFICIENT_BUFFER;
8572 if (!rpcbuf_alloc_size(buffer, *needed)) {
8573 result = WERR_NOMEM;
8577 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8582 if ( !W_ERROR_IS_OK(result) )
8588 /****************************************************************************
8589 ****************************************************************************/
8591 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8593 uint32 level = q_u->level;
8594 RPC_BUFFER *buffer = NULL;
8595 uint32 offered = q_u->offered;
8596 uint32 *needed = &r_u->needed;
8597 uint32 *returned = &r_u->returned;
8599 /* that's an [in out] buffer */
8601 if (!q_u->buffer && (offered!=0)) {
8602 return WERR_INVALID_PARAM;
8605 rpcbuf_move(q_u->buffer, &r_u->buffer);
8606 buffer = r_u->buffer;
8608 DEBUG(5,("spoolss_enumprintprocessors\n"));
8611 * Enumerate the print processors ...
8613 * Just reply with "winprint", to keep NT happy
8614 * and I can use my nice printer checker.
8622 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8624 return WERR_UNKNOWN_LEVEL;
8628 /****************************************************************************
8629 enumprintprocdatatypes level 1.
8630 ****************************************************************************/
8632 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8634 PRINTPROCDATATYPE_1 *info_1=NULL;
8635 WERROR result = WERR_OK;
8637 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8642 init_unistr(&info_1->name, "RAW");
8644 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8646 if (*needed > offered) {
8647 result = WERR_INSUFFICIENT_BUFFER;
8651 if (!rpcbuf_alloc_size(buffer, *needed)) {
8652 result = WERR_NOMEM;
8656 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8661 if ( !W_ERROR_IS_OK(result) )
8667 /****************************************************************************
8668 ****************************************************************************/
8670 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8672 uint32 level = q_u->level;
8673 RPC_BUFFER *buffer = NULL;
8674 uint32 offered = q_u->offered;
8675 uint32 *needed = &r_u->needed;
8676 uint32 *returned = &r_u->returned;
8678 /* that's an [in out] buffer */
8680 if (!q_u->buffer && (offered!=0)) {
8681 return WERR_INVALID_PARAM;
8684 rpcbuf_move(q_u->buffer, &r_u->buffer);
8685 buffer = r_u->buffer;
8687 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8694 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8696 return WERR_UNKNOWN_LEVEL;
8700 /****************************************************************************
8701 enumprintmonitors level 1.
8702 ****************************************************************************/
8704 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8706 PRINTMONITOR_1 *info_1;
8707 WERROR result = WERR_OK;
8710 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8715 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8716 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8718 for ( i=0; i<*returned; i++ ) {
8719 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8722 if (*needed > offered) {
8723 result = WERR_INSUFFICIENT_BUFFER;
8727 if (!rpcbuf_alloc_size(buffer, *needed)) {
8728 result = WERR_NOMEM;
8732 for ( i=0; i<*returned; i++ ) {
8733 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8739 if ( !W_ERROR_IS_OK(result) )
8745 /****************************************************************************
8746 enumprintmonitors level 2.
8747 ****************************************************************************/
8749 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8751 PRINTMONITOR_2 *info_2;
8752 WERROR result = WERR_OK;
8755 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8760 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8761 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8762 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8764 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8765 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8766 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8768 for ( i=0; i<*returned; i++ ) {
8769 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8772 if (*needed > offered) {
8773 result = WERR_INSUFFICIENT_BUFFER;
8777 if (!rpcbuf_alloc_size(buffer, *needed)) {
8778 result = WERR_NOMEM;
8782 for ( i=0; i<*returned; i++ ) {
8783 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8789 if ( !W_ERROR_IS_OK(result) )
8795 /****************************************************************************
8796 ****************************************************************************/
8798 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8800 uint32 level = q_u->level;
8801 RPC_BUFFER *buffer = NULL;
8802 uint32 offered = q_u->offered;
8803 uint32 *needed = &r_u->needed;
8804 uint32 *returned = &r_u->returned;
8806 /* that's an [in out] buffer */
8808 if (!q_u->buffer && (offered!=0)) {
8809 return WERR_INVALID_PARAM;
8812 rpcbuf_move(q_u->buffer, &r_u->buffer);
8813 buffer = r_u->buffer;
8815 DEBUG(5,("spoolss_enumprintmonitors\n"));
8818 * Enumerate the print monitors ...
8820 * Just reply with "Local Port", to keep NT happy
8821 * and I can use my nice printer checker.
8829 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8831 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8833 return WERR_UNKNOWN_LEVEL;
8837 /****************************************************************************
8838 ****************************************************************************/
8840 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8841 NT_PRINTER_INFO_LEVEL *ntprinter,
8842 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8847 JOB_INFO_1 *info_1=NULL;
8848 WERROR result = WERR_OK;
8850 info_1=SMB_MALLOC_P(JOB_INFO_1);
8852 if (info_1 == NULL) {
8856 for (i=0; i<count && found==False; i++) {
8857 if ((*queue)[i].job==(int)jobid)
8863 /* NT treats not found as bad param... yet another bad choice */
8864 return WERR_INVALID_PARAM;
8867 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8869 *needed += spoolss_size_job_info_1(info_1);
8871 if (*needed > offered) {
8872 result = WERR_INSUFFICIENT_BUFFER;
8876 if (!rpcbuf_alloc_size(buffer, *needed)) {
8877 result = WERR_NOMEM;
8881 smb_io_job_info_1("", buffer, info_1, 0);
8889 /****************************************************************************
8890 ****************************************************************************/
8892 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8893 NT_PRINTER_INFO_LEVEL *ntprinter,
8894 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8901 DEVICEMODE *devmode = NULL;
8902 NT_DEVICEMODE *nt_devmode = NULL;
8904 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8907 ZERO_STRUCTP(info_2);
8909 for ( i=0; i<count && found==False; i++ )
8911 if ((*queue)[i].job == (int)jobid)
8916 /* NT treats not found as bad param... yet another bad
8918 result = WERR_INVALID_PARAM;
8923 * if the print job does not have a DEVMODE associated with it,
8924 * just use the one for the printer. A NULL devicemode is not
8925 * a failure condition
8928 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8929 devmode = construct_dev_mode(lp_const_servicename(snum));
8931 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8932 ZERO_STRUCTP( devmode );
8933 convert_nt_devicemode( devmode, nt_devmode );
8937 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8939 *needed += spoolss_size_job_info_2(info_2);
8941 if (*needed > offered) {
8942 result = WERR_INSUFFICIENT_BUFFER;
8946 if (!rpcbuf_alloc_size(buffer, *needed)) {
8947 result = WERR_NOMEM;
8951 smb_io_job_info_2("", buffer, info_2, 0);
8956 /* Cleanup allocated memory */
8958 free_job_info_2(info_2); /* Also frees devmode */
8964 /****************************************************************************
8965 ****************************************************************************/
8967 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8969 POLICY_HND *handle = &q_u->handle;
8970 uint32 jobid = q_u->jobid;
8971 uint32 level = q_u->level;
8972 RPC_BUFFER *buffer = NULL;
8973 uint32 offered = q_u->offered;
8974 uint32 *needed = &r_u->needed;
8975 WERROR wstatus = WERR_OK;
8976 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8979 print_queue_struct *queue = NULL;
8980 print_status_struct prt_status;
8982 /* that's an [in out] buffer */
8984 if (!q_u->buffer && (offered!=0)) {
8985 return WERR_INVALID_PARAM;
8988 rpcbuf_move(q_u->buffer, &r_u->buffer);
8989 buffer = r_u->buffer;
8991 DEBUG(5,("spoolss_getjob\n"));
8995 if (!get_printer_snum(p, handle, &snum, NULL))
8998 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8999 if ( !W_ERROR_IS_OK(wstatus) )
9002 count = print_queue_status(snum, &queue, &prt_status);
9004 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9005 count, prt_status.status, prt_status.message));
9009 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9010 buffer, offered, needed);
9013 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9014 buffer, offered, needed);
9017 wstatus = WERR_UNKNOWN_LEVEL;
9022 free_a_printer( &ntprinter, 2 );
9027 /********************************************************************
9028 spoolss_getprinterdataex
9030 From MSDN documentation of GetPrinterDataEx: pass request
9031 to GetPrinterData if key is "PrinterDriverData".
9032 ********************************************************************/
9034 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9036 POLICY_HND *handle = &q_u->handle;
9037 uint32 in_size = q_u->size;
9038 uint32 *type = &r_u->type;
9039 uint32 *out_size = &r_u->size;
9040 uint8 **data = &r_u->data;
9041 uint32 *needed = &r_u->needed;
9042 fstring keyname, valuename;
9044 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9046 NT_PRINTER_INFO_LEVEL *printer = NULL;
9048 WERROR status = WERR_OK;
9050 DEBUG(4,("_spoolss_getprinterdataex\n"));
9052 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname));
9053 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename));
9055 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9056 keyname, valuename));
9058 /* in case of problem, return some default values */
9062 *out_size = in_size;
9065 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9066 status = WERR_BADFID;
9070 /* Is the handle to a printer or to the server? */
9072 if (Printer->printer_type == SPLHND_SERVER) {
9073 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9074 status = WERR_INVALID_PARAM;
9078 if ( !get_printer_snum(p,handle, &snum, NULL) )
9081 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9082 if ( !W_ERROR_IS_OK(status) )
9085 /* check to see if the keyname is valid */
9086 if ( !strlen(keyname) ) {
9087 status = WERR_INVALID_PARAM;
9091 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9092 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9093 free_a_printer( &printer, 2 );
9094 status = WERR_BADFILE;
9098 /* When given a new keyname, we should just create it */
9100 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9102 if (*needed > *out_size)
9103 status = WERR_MORE_DATA;
9106 if ( !W_ERROR_IS_OK(status) )
9108 DEBUG(5, ("error: allocating %d\n", *out_size));
9110 /* reply this param doesn't exist */
9114 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9115 status = WERR_NOMEM;
9124 free_a_printer( &printer, 2 );
9129 /********************************************************************
9130 * spoolss_setprinterdataex
9131 ********************************************************************/
9133 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9135 POLICY_HND *handle = &q_u->handle;
9136 uint32 type = q_u->type;
9137 uint8 *data = q_u->data;
9138 uint32 real_len = q_u->real_len;
9140 NT_PRINTER_INFO_LEVEL *printer = NULL;
9142 WERROR status = WERR_OK;
9143 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9148 DEBUG(4,("_spoolss_setprinterdataex\n"));
9150 /* From MSDN documentation of SetPrinterDataEx: pass request to
9151 SetPrinterData if key is "PrinterDriverData" */
9154 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9158 if ( Printer->printer_type == SPLHND_SERVER ) {
9159 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9160 return WERR_INVALID_PARAM;
9163 if ( !get_printer_snum(p,handle, &snum, NULL) )
9167 * Access check : NT returns "access denied" if you make a
9168 * SetPrinterData call without the necessary privildge.
9169 * we were originally returning OK if nothing changed
9170 * which made Win2k issue **a lot** of SetPrinterData
9171 * when connecting to a printer --jerry
9174 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9176 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9177 return WERR_ACCESS_DENIED;
9180 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9181 if (!W_ERROR_IS_OK(status))
9184 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename));
9185 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname));
9187 /* check for OID in valuename */
9189 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9195 /* save the registry data */
9197 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9199 if ( W_ERROR_IS_OK(status) )
9201 /* save the OID if one was specified */
9203 fstrcat( keyname, "\\" );
9204 fstrcat( keyname, SPOOL_OID_KEY );
9207 * I'm not checking the status here on purpose. Don't know
9208 * if this is right, but I'm returning the status from the
9209 * previous set_printer_dataex() call. I have no idea if
9210 * this is right. --jerry
9213 set_printer_dataex( printer, keyname, valuename,
9214 REG_SZ, (uint8 *)oid_string,
9215 strlen(oid_string)+1 );
9218 status = mod_a_printer(printer, 2);
9221 free_a_printer(&printer, 2);
9227 /********************************************************************
9228 * spoolss_deleteprinterdataex
9229 ********************************************************************/
9231 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9233 POLICY_HND *handle = &q_u->handle;
9234 UNISTR2 *value = &q_u->valuename;
9235 UNISTR2 *key = &q_u->keyname;
9237 NT_PRINTER_INFO_LEVEL *printer = NULL;
9239 WERROR status = WERR_OK;
9240 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9241 pstring valuename, keyname;
9243 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9246 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9250 if (!get_printer_snum(p, handle, &snum, NULL))
9253 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9254 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9255 return WERR_ACCESS_DENIED;
9258 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9259 if (!W_ERROR_IS_OK(status))
9262 unistr2_to_ascii(valuename, value, sizeof(valuename));
9263 unistr2_to_ascii(keyname, key, sizeof(keyname));
9265 status = delete_printer_dataex( printer, keyname, valuename );
9267 if ( W_ERROR_IS_OK(status) )
9268 mod_a_printer( printer, 2 );
9270 free_a_printer(&printer, 2);
9275 /********************************************************************
9276 * spoolss_enumprinterkey
9277 ********************************************************************/
9280 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9283 fstring *keynames = NULL;
9284 uint16 *enumkeys = NULL;
9287 POLICY_HND *handle = &q_u->handle;
9288 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9289 NT_PRINTER_DATA *data;
9290 NT_PRINTER_INFO_LEVEL *printer = NULL;
9292 WERROR status = WERR_BADFILE;
9295 DEBUG(4,("_spoolss_enumprinterkey\n"));
9298 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9302 if ( !get_printer_snum(p,handle, &snum, NULL) )
9305 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9306 if (!W_ERROR_IS_OK(status))
9309 /* get the list of subkey names */
9311 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9312 data = printer->info_2->data;
9314 num_keys = get_printer_subkeys( data, key, &keynames );
9316 if ( num_keys == -1 ) {
9317 status = WERR_BADFILE;
9321 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9323 r_u->needed = printerkey_len*2;
9325 if ( q_u->size < r_u->needed ) {
9326 status = WERR_MORE_DATA;
9330 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9331 status = WERR_NOMEM;
9337 if ( q_u->size < r_u->needed )
9338 status = WERR_MORE_DATA;
9341 free_a_printer( &printer, 2 );
9342 SAFE_FREE( keynames );
9347 /********************************************************************
9348 * spoolss_deleteprinterkey
9349 ********************************************************************/
9351 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9353 POLICY_HND *handle = &q_u->handle;
9354 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9356 NT_PRINTER_INFO_LEVEL *printer = NULL;
9360 DEBUG(5,("spoolss_deleteprinterkey\n"));
9363 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9367 /* if keyname == NULL, return error */
9369 if ( !q_u->keyname.buffer )
9370 return WERR_INVALID_PARAM;
9372 if (!get_printer_snum(p, handle, &snum, NULL))
9375 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9376 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9377 return WERR_ACCESS_DENIED;
9380 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9381 if (!W_ERROR_IS_OK(status))
9384 /* delete the key and all subneys */
9386 unistr2_to_ascii(key, &q_u->keyname, sizeof(key));
9388 status = delete_all_printer_data( printer->info_2, key );
9390 if ( W_ERROR_IS_OK(status) )
9391 status = mod_a_printer(printer, 2);
9393 free_a_printer( &printer, 2 );
9399 /********************************************************************
9400 * spoolss_enumprinterdataex
9401 ********************************************************************/
9403 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9405 POLICY_HND *handle = &q_u->handle;
9406 uint32 in_size = q_u->size;
9409 NT_PRINTER_INFO_LEVEL *printer = NULL;
9410 PRINTER_ENUM_VALUES *enum_values = NULL;
9411 NT_PRINTER_DATA *p_data;
9413 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9418 REGISTRY_VALUE *val;
9423 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9426 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9431 * first check for a keyname of NULL or "". Win2k seems to send
9432 * this a lot and we should send back WERR_INVALID_PARAM
9433 * no need to spend time looking up the printer in this case.
9437 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9438 if ( !strlen(key) ) {
9439 result = WERR_INVALID_PARAM;
9443 /* get the printer off of disk */
9445 if (!get_printer_snum(p,handle, &snum, NULL))
9448 ZERO_STRUCT(printer);
9449 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9450 if (!W_ERROR_IS_OK(result))
9453 /* now look for a match on the key name */
9455 p_data = printer->info_2->data;
9457 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9458 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9460 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9461 result = WERR_INVALID_PARAM;
9468 /* allocate the memory for the array of pointers -- if necessary */
9470 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9473 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9475 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9476 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9477 result = WERR_NOMEM;
9481 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9485 * loop through all params and build the array to pass
9486 * back to the client
9489 for ( i=0; i<num_entries; i++ )
9491 /* lookup the registry value */
9493 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9494 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9498 value_name = regval_name( val );
9499 init_unistr( &enum_values[i].valuename, value_name );
9500 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9501 enum_values[i].type = regval_type( val );
9503 data_len = regval_size( val );
9505 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9507 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9509 result = WERR_NOMEM;
9513 enum_values[i].data_len = data_len;
9515 /* keep track of the size of the array in bytes */
9517 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9520 /* housekeeping information in the reply */
9522 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9523 * the hand marshalled container size is a multiple
9524 * of 4 bytes for RPC alignment.
9528 needed += 4-(needed % 4);
9531 r_u->needed = needed;
9532 r_u->returned = num_entries;
9534 if (needed > in_size) {
9535 result = WERR_MORE_DATA;
9539 /* copy data into the reply */
9541 r_u->ctr.size = r_u->needed;
9543 r_u->ctr.size_of_array = r_u->returned;
9544 r_u->ctr.values = enum_values;
9550 free_a_printer(&printer, 2);
9555 /****************************************************************************
9556 ****************************************************************************/
9558 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9560 init_unistr(&info->name, name);
9563 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9564 UNISTR2 *environment,
9571 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9572 WERROR result = WERR_OK;
9574 unistr2_to_ascii(long_archi, environment, sizeof(long_archi));
9576 if (!get_short_archi(long_archi))
9577 return WERR_INVALID_ENVIRONMENT;
9579 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9582 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9584 fill_printprocessordirectory_1(info, path);
9586 *needed += spoolss_size_printprocessordirectory_info_1(info);
9588 if (*needed > offered) {
9589 result = WERR_INSUFFICIENT_BUFFER;
9593 if (!rpcbuf_alloc_size(buffer, *needed)) {
9594 result = WERR_INSUFFICIENT_BUFFER;
9598 smb_io_printprocessordirectory_1("", buffer, info, 0);
9606 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9608 uint32 level = q_u->level;
9609 RPC_BUFFER *buffer = NULL;
9610 uint32 offered = q_u->offered;
9611 uint32 *needed = &r_u->needed;
9614 /* that's an [in out] buffer */
9616 if (!q_u->buffer && (offered!=0)) {
9617 return WERR_INVALID_PARAM;
9620 rpcbuf_move(q_u->buffer, &r_u->buffer);
9621 buffer = r_u->buffer;
9623 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9629 result = getprintprocessordirectory_level_1
9630 (&q_u->name, &q_u->environment, buffer, offered, needed);
9633 result = WERR_UNKNOWN_LEVEL;
9639 /*******************************************************************
9640 Streams the monitor UI DLL name in UNICODE
9641 *******************************************************************/
9643 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9644 RPC_BUFFER *out, uint32 *needed )
9646 const char *dllname = "tcpmonui.dll";
9648 *needed = (strlen(dllname)+1) * 2;
9650 if ( rpcbuf_get_size(out) < *needed ) {
9651 return WERR_INSUFFICIENT_BUFFER;
9654 if ( !make_monitorui_buf( out, dllname ) ) {
9661 /*******************************************************************
9662 Create a new TCP/IP port
9663 *******************************************************************/
9665 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9666 RPC_BUFFER *out, uint32 *needed )
9668 NT_PORT_DATA_1 port1;
9671 ZERO_STRUCT( port1 );
9673 /* convert to our internal port data structure */
9675 if ( !convert_port_data_1( &port1, in ) ) {
9679 /* create the device URI and call the add_port_hook() */
9681 switch ( port1.protocol ) {
9682 case PORT_PROTOCOL_DIRECT:
9683 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9686 case PORT_PROTOCOL_LPR:
9687 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9691 return WERR_UNKNOWN_PORT;
9694 return add_port_hook( token, port1.name, device_uri );
9697 /*******************************************************************
9698 *******************************************************************/
9700 struct xcv_api_table xcvtcp_cmds[] = {
9701 { "MonitorUI", xcvtcp_monitorui },
9702 { "AddPort", xcvtcp_addport},
9706 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9707 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9712 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9714 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9715 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9716 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9719 return WERR_BADFUNC;
9722 /*******************************************************************
9723 *******************************************************************/
9724 #if 0 /* don't support management using the "Local Port" monitor */
9726 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9727 RPC_BUFFER *out, uint32 *needed )
9729 const char *dllname = "localui.dll";
9731 *needed = (strlen(dllname)+1) * 2;
9733 if ( rpcbuf_get_size(out) < *needed ) {
9734 return WERR_INSUFFICIENT_BUFFER;
9737 if ( !make_monitorui_buf( out, dllname )) {
9744 /*******************************************************************
9745 *******************************************************************/
9747 struct xcv_api_table xcvlocal_cmds[] = {
9748 { "MonitorUI", xcvlocal_monitorui },
9752 struct xcv_api_table xcvlocal_cmds[] = {
9759 /*******************************************************************
9760 *******************************************************************/
9762 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9763 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9768 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9770 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9771 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9772 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9774 return WERR_BADFUNC;
9777 /*******************************************************************
9778 *******************************************************************/
9780 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9782 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9786 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9790 /* Has to be a handle to the TCP/IP port monitor */
9792 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9793 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9797 /* requires administrative access to the server */
9799 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9800 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9801 return WERR_ACCESS_DENIED;
9804 /* Get the command name. There's numerous commands supported by the
9805 TCPMON interface. */
9807 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9808 q_u->dataname.uni_str_len*2, 0);
9810 /* Allocate the outgoing buffer */
9812 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9814 switch ( Printer->printer_type ) {
9815 case SPLHND_PORTMON_TCP:
9816 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9817 &q_u->indata, &r_u->outdata, &r_u->needed );
9818 case SPLHND_PORTMON_LOCAL:
9819 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9820 &q_u->indata, &r_u->outdata, &r_u->needed );
9823 return WERR_INVALID_PRINT_MONITOR;