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")) {
2405 const char *hostname = get_mydnsfullname();
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 sockaddr_storage *client_ss, const char *remote_machine)
2534 struct cli_state *the_cli;
2535 struct sockaddr_storage rm_addr;
2537 if ( is_zero_addr(client_ss) ) {
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 (ismyaddr(&rm_addr)) {
2544 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2548 char addr[INET6_ADDRSTRLEN];
2549 rm_addr = *client_ss;
2550 print_sockaddr(addr, sizeof(addr), &rm_addr);
2551 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2555 /* setup the connection */
2557 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2558 &rm_addr, 0, "IPC$", "IPC",
2562 0, lp_client_signing(), NULL );
2564 if ( !NT_STATUS_IS_OK( ret ) ) {
2565 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2570 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2571 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2572 cli_shutdown(the_cli);
2577 * Ok - we have an anonymous connection to the IPC$ share.
2578 * Now start the NT Domain stuff :-).
2581 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2582 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2583 remote_machine, nt_errstr(ret)));
2584 cli_shutdown(the_cli);
2588 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2590 (*pp_pipe)->cli = the_cli;
2595 /***************************************************************************
2596 Connect to the client.
2597 ****************************************************************************/
2599 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2600 uint32 localprinter, uint32 type,
2601 POLICY_HND *handle, struct sockaddr_storage *client_ss)
2606 * If it's the first connection, contact the client
2607 * and connect to the IPC$ share anonymously
2609 if (smb_connections==0) {
2610 fstring unix_printer;
2612 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2614 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ss, unix_printer ))
2617 messaging_register(smbd_messaging_context(), NULL,
2618 MSG_PRINTER_NOTIFY2,
2619 receive_notify2_message_list);
2620 /* Tell the connections db we're now interested in printer
2621 * notify messages. */
2622 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2626 * Tell the specific printing tdb we want messages for this printer
2627 * by registering our PID.
2630 if (!print_notify_register_pid(snum))
2631 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2635 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2638 if (!W_ERROR_IS_OK(result))
2639 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2640 dos_errstr(result)));
2642 return (W_ERROR_IS_OK(result));
2645 /********************************************************************
2647 * ReplyFindFirstPrinterChangeNotifyEx
2649 * before replying OK: status=0 a rpc call is made to the workstation
2650 * asking ReplyOpenPrinter
2652 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2653 * called from api_spoolss_rffpcnex
2654 ********************************************************************/
2656 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2658 POLICY_HND *handle = &q_u->handle;
2659 uint32 flags = q_u->flags;
2660 uint32 options = q_u->options;
2661 UNISTR2 *localmachine = &q_u->localmachine;
2662 uint32 printerlocal = q_u->printerlocal;
2664 SPOOL_NOTIFY_OPTION *option = q_u->option;
2665 struct sockaddr_storage client_ss;
2667 /* store the notify value in the printer struct */
2669 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2672 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2676 Printer->notify.flags=flags;
2677 Printer->notify.options=options;
2678 Printer->notify.printerlocal=printerlocal;
2680 if (Printer->notify.option)
2681 free_spool_notify_option(&Printer->notify.option);
2683 Printer->notify.option=dup_spool_notify_option(option);
2685 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2686 sizeof(Printer->notify.localmachine));
2688 /* Connect to the client machine and send a ReplyOpenPrinter */
2690 if ( Printer->printer_type == SPLHND_SERVER)
2692 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2693 !get_printer_snum(p, handle, &snum, NULL) )
2696 if (!interpret_string_addr(&client_ss,
2697 p->conn->client_address,
2699 return WERR_SERVER_UNAVAILABLE;
2702 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2703 Printer->notify.printerlocal, 1,
2704 &Printer->notify.client_hnd, &client_ss))
2705 return WERR_SERVER_UNAVAILABLE;
2707 Printer->notify.client_connected=True;
2712 /*******************************************************************
2713 * fill a notify_info_data with the servername
2714 ********************************************************************/
2716 void spoolss_notify_server_name(int snum,
2717 SPOOL_NOTIFY_INFO_DATA *data,
2718 print_queue_struct *queue,
2719 NT_PRINTER_INFO_LEVEL *printer,
2720 TALLOC_CTX *mem_ctx)
2725 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2727 data->notify_data.data.length = len;
2729 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2730 if (!data->notify_data.data.string) {
2731 data->notify_data.data.length = 0;
2735 memcpy(data->notify_data.data.string, temp, len);
2737 data->notify_data.data.string = NULL;
2741 /*******************************************************************
2742 * fill a notify_info_data with the printername (not including the servername).
2743 ********************************************************************/
2745 void spoolss_notify_printer_name(int snum,
2746 SPOOL_NOTIFY_INFO_DATA *data,
2747 print_queue_struct *queue,
2748 NT_PRINTER_INFO_LEVEL *printer,
2749 TALLOC_CTX *mem_ctx)
2754 /* the notify name should not contain the \\server\ part */
2755 char *p = strrchr(printer->info_2->printername, '\\');
2758 p = printer->info_2->printername;
2763 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2765 data->notify_data.data.length = len;
2767 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2768 if (!data->notify_data.data.string) {
2769 data->notify_data.data.length = 0;
2772 memcpy(data->notify_data.data.string, temp, len);
2774 data->notify_data.data.string = NULL;
2778 /*******************************************************************
2779 * fill a notify_info_data with the servicename
2780 ********************************************************************/
2782 void spoolss_notify_share_name(int snum,
2783 SPOOL_NOTIFY_INFO_DATA *data,
2784 print_queue_struct *queue,
2785 NT_PRINTER_INFO_LEVEL *printer,
2786 TALLOC_CTX *mem_ctx)
2791 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2793 data->notify_data.data.length = len;
2795 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2796 if (!data->notify_data.data.string) {
2797 data->notify_data.data.length = 0;
2800 memcpy(data->notify_data.data.string, temp, len);
2802 data->notify_data.data.string = NULL;
2807 /*******************************************************************
2808 * fill a notify_info_data with the port name
2809 ********************************************************************/
2811 void spoolss_notify_port_name(int snum,
2812 SPOOL_NOTIFY_INFO_DATA *data,
2813 print_queue_struct *queue,
2814 NT_PRINTER_INFO_LEVEL *printer,
2815 TALLOC_CTX *mem_ctx)
2820 /* even if it's strange, that's consistant in all the code */
2822 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2824 data->notify_data.data.length = len;
2826 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2828 if (!data->notify_data.data.string) {
2829 data->notify_data.data.length = 0;
2833 memcpy(data->notify_data.data.string, temp, len);
2835 data->notify_data.data.string = NULL;
2839 /*******************************************************************
2840 * fill a notify_info_data with the printername
2841 * but it doesn't exist, have to see what to do
2842 ********************************************************************/
2844 void spoolss_notify_driver_name(int snum,
2845 SPOOL_NOTIFY_INFO_DATA *data,
2846 print_queue_struct *queue,
2847 NT_PRINTER_INFO_LEVEL *printer,
2848 TALLOC_CTX *mem_ctx)
2853 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2855 data->notify_data.data.length = len;
2857 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2859 if (!data->notify_data.data.string) {
2860 data->notify_data.data.length = 0;
2864 memcpy(data->notify_data.data.string, temp, len);
2866 data->notify_data.data.string = NULL;
2870 /*******************************************************************
2871 * fill a notify_info_data with the comment
2872 ********************************************************************/
2874 void spoolss_notify_comment(int snum,
2875 SPOOL_NOTIFY_INFO_DATA *data,
2876 print_queue_struct *queue,
2877 NT_PRINTER_INFO_LEVEL *printer,
2878 TALLOC_CTX *mem_ctx)
2883 if (*printer->info_2->comment == '\0')
2884 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2886 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2888 data->notify_data.data.length = len;
2890 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2892 if (!data->notify_data.data.string) {
2893 data->notify_data.data.length = 0;
2897 memcpy(data->notify_data.data.string, temp, len);
2899 data->notify_data.data.string = NULL;
2903 /*******************************************************************
2904 * fill a notify_info_data with the comment
2905 * location = "Room 1, floor 2, building 3"
2906 ********************************************************************/
2908 void spoolss_notify_location(int snum,
2909 SPOOL_NOTIFY_INFO_DATA *data,
2910 print_queue_struct *queue,
2911 NT_PRINTER_INFO_LEVEL *printer,
2912 TALLOC_CTX *mem_ctx)
2917 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2919 data->notify_data.data.length = len;
2921 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2923 if (!data->notify_data.data.string) {
2924 data->notify_data.data.length = 0;
2928 memcpy(data->notify_data.data.string, temp, len);
2930 data->notify_data.data.string = NULL;
2934 /*******************************************************************
2935 * fill a notify_info_data with the device mode
2936 * jfm:xxxx don't to it for know but that's a real problem !!!
2937 ********************************************************************/
2939 static void spoolss_notify_devmode(int snum,
2940 SPOOL_NOTIFY_INFO_DATA *data,
2941 print_queue_struct *queue,
2942 NT_PRINTER_INFO_LEVEL *printer,
2943 TALLOC_CTX *mem_ctx)
2945 /* for a dummy implementation we have to zero the fields */
2946 data->notify_data.data.length = 0;
2947 data->notify_data.data.string = NULL;
2950 /*******************************************************************
2951 * fill a notify_info_data with the separator file name
2952 ********************************************************************/
2954 void spoolss_notify_sepfile(int snum,
2955 SPOOL_NOTIFY_INFO_DATA *data,
2956 print_queue_struct *queue,
2957 NT_PRINTER_INFO_LEVEL *printer,
2958 TALLOC_CTX *mem_ctx)
2963 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2965 data->notify_data.data.length = len;
2967 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2969 if (!data->notify_data.data.string) {
2970 data->notify_data.data.length = 0;
2974 memcpy(data->notify_data.data.string, temp, len);
2976 data->notify_data.data.string = NULL;
2980 /*******************************************************************
2981 * fill a notify_info_data with the print processor
2982 * jfm:xxxx return always winprint to indicate we don't do anything to it
2983 ********************************************************************/
2985 void spoolss_notify_print_processor(int snum,
2986 SPOOL_NOTIFY_INFO_DATA *data,
2987 print_queue_struct *queue,
2988 NT_PRINTER_INFO_LEVEL *printer,
2989 TALLOC_CTX *mem_ctx)
2994 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2996 data->notify_data.data.length = len;
2998 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3000 if (!data->notify_data.data.string) {
3001 data->notify_data.data.length = 0;
3005 memcpy(data->notify_data.data.string, temp, len);
3007 data->notify_data.data.string = NULL;
3011 /*******************************************************************
3012 * fill a notify_info_data with the print processor options
3013 * jfm:xxxx send an empty string
3014 ********************************************************************/
3016 void spoolss_notify_parameters(int snum,
3017 SPOOL_NOTIFY_INFO_DATA *data,
3018 print_queue_struct *queue,
3019 NT_PRINTER_INFO_LEVEL *printer,
3020 TALLOC_CTX *mem_ctx)
3025 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3027 data->notify_data.data.length = len;
3029 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3031 if (!data->notify_data.data.string) {
3032 data->notify_data.data.length = 0;
3036 memcpy(data->notify_data.data.string, temp, len);
3038 data->notify_data.data.string = NULL;
3042 /*******************************************************************
3043 * fill a notify_info_data with the data type
3044 * jfm:xxxx always send RAW as data type
3045 ********************************************************************/
3047 void spoolss_notify_datatype(int snum,
3048 SPOOL_NOTIFY_INFO_DATA *data,
3049 print_queue_struct *queue,
3050 NT_PRINTER_INFO_LEVEL *printer,
3051 TALLOC_CTX *mem_ctx)
3056 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3058 data->notify_data.data.length = len;
3060 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3062 if (!data->notify_data.data.string) {
3063 data->notify_data.data.length = 0;
3067 memcpy(data->notify_data.data.string, temp, len);
3069 data->notify_data.data.string = NULL;
3073 /*******************************************************************
3074 * fill a notify_info_data with the security descriptor
3075 * jfm:xxxx send an null pointer to say no security desc
3076 * have to implement security before !
3077 ********************************************************************/
3079 static void spoolss_notify_security_desc(int snum,
3080 SPOOL_NOTIFY_INFO_DATA *data,
3081 print_queue_struct *queue,
3082 NT_PRINTER_INFO_LEVEL *printer,
3083 TALLOC_CTX *mem_ctx)
3085 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3086 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3089 /*******************************************************************
3090 * fill a notify_info_data with the attributes
3091 * jfm:xxxx a samba printer is always shared
3092 ********************************************************************/
3094 void spoolss_notify_attributes(int snum,
3095 SPOOL_NOTIFY_INFO_DATA *data,
3096 print_queue_struct *queue,
3097 NT_PRINTER_INFO_LEVEL *printer,
3098 TALLOC_CTX *mem_ctx)
3100 data->notify_data.value[0] = printer->info_2->attributes;
3101 data->notify_data.value[1] = 0;
3104 /*******************************************************************
3105 * fill a notify_info_data with the priority
3106 ********************************************************************/
3108 static void spoolss_notify_priority(int snum,
3109 SPOOL_NOTIFY_INFO_DATA *data,
3110 print_queue_struct *queue,
3111 NT_PRINTER_INFO_LEVEL *printer,
3112 TALLOC_CTX *mem_ctx)
3114 data->notify_data.value[0] = printer->info_2->priority;
3115 data->notify_data.value[1] = 0;
3118 /*******************************************************************
3119 * fill a notify_info_data with the default priority
3120 ********************************************************************/
3122 static void spoolss_notify_default_priority(int snum,
3123 SPOOL_NOTIFY_INFO_DATA *data,
3124 print_queue_struct *queue,
3125 NT_PRINTER_INFO_LEVEL *printer,
3126 TALLOC_CTX *mem_ctx)
3128 data->notify_data.value[0] = printer->info_2->default_priority;
3129 data->notify_data.value[1] = 0;
3132 /*******************************************************************
3133 * fill a notify_info_data with the start time
3134 ********************************************************************/
3136 static void spoolss_notify_start_time(int snum,
3137 SPOOL_NOTIFY_INFO_DATA *data,
3138 print_queue_struct *queue,
3139 NT_PRINTER_INFO_LEVEL *printer,
3140 TALLOC_CTX *mem_ctx)
3142 data->notify_data.value[0] = printer->info_2->starttime;
3143 data->notify_data.value[1] = 0;
3146 /*******************************************************************
3147 * fill a notify_info_data with the until time
3148 ********************************************************************/
3150 static void spoolss_notify_until_time(int snum,
3151 SPOOL_NOTIFY_INFO_DATA *data,
3152 print_queue_struct *queue,
3153 NT_PRINTER_INFO_LEVEL *printer,
3154 TALLOC_CTX *mem_ctx)
3156 data->notify_data.value[0] = printer->info_2->untiltime;
3157 data->notify_data.value[1] = 0;
3160 /*******************************************************************
3161 * fill a notify_info_data with the status
3162 ********************************************************************/
3164 static void spoolss_notify_status(int snum,
3165 SPOOL_NOTIFY_INFO_DATA *data,
3166 print_queue_struct *queue,
3167 NT_PRINTER_INFO_LEVEL *printer,
3168 TALLOC_CTX *mem_ctx)
3170 print_status_struct status;
3172 print_queue_length(snum, &status);
3173 data->notify_data.value[0]=(uint32) status.status;
3174 data->notify_data.value[1] = 0;
3177 /*******************************************************************
3178 * fill a notify_info_data with the number of jobs queued
3179 ********************************************************************/
3181 void spoolss_notify_cjobs(int snum,
3182 SPOOL_NOTIFY_INFO_DATA *data,
3183 print_queue_struct *queue,
3184 NT_PRINTER_INFO_LEVEL *printer,
3185 TALLOC_CTX *mem_ctx)
3187 data->notify_data.value[0] = print_queue_length(snum, NULL);
3188 data->notify_data.value[1] = 0;
3191 /*******************************************************************
3192 * fill a notify_info_data with the average ppm
3193 ********************************************************************/
3195 static void spoolss_notify_average_ppm(int snum,
3196 SPOOL_NOTIFY_INFO_DATA *data,
3197 print_queue_struct *queue,
3198 NT_PRINTER_INFO_LEVEL *printer,
3199 TALLOC_CTX *mem_ctx)
3201 /* always respond 8 pages per minutes */
3202 /* a little hard ! */
3203 data->notify_data.value[0] = printer->info_2->averageppm;
3204 data->notify_data.value[1] = 0;
3207 /*******************************************************************
3208 * fill a notify_info_data with username
3209 ********************************************************************/
3211 static void spoolss_notify_username(int snum,
3212 SPOOL_NOTIFY_INFO_DATA *data,
3213 print_queue_struct *queue,
3214 NT_PRINTER_INFO_LEVEL *printer,
3215 TALLOC_CTX *mem_ctx)
3220 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3222 data->notify_data.data.length = len;
3224 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3226 if (!data->notify_data.data.string) {
3227 data->notify_data.data.length = 0;
3231 memcpy(data->notify_data.data.string, temp, len);
3233 data->notify_data.data.string = NULL;
3237 /*******************************************************************
3238 * fill a notify_info_data with job status
3239 ********************************************************************/
3241 static void spoolss_notify_job_status(int snum,
3242 SPOOL_NOTIFY_INFO_DATA *data,
3243 print_queue_struct *queue,
3244 NT_PRINTER_INFO_LEVEL *printer,
3245 TALLOC_CTX *mem_ctx)
3247 data->notify_data.value[0]=nt_printj_status(queue->status);
3248 data->notify_data.value[1] = 0;
3251 /*******************************************************************
3252 * fill a notify_info_data with job name
3253 ********************************************************************/
3255 static void spoolss_notify_job_name(int snum,
3256 SPOOL_NOTIFY_INFO_DATA *data,
3257 print_queue_struct *queue,
3258 NT_PRINTER_INFO_LEVEL *printer,
3259 TALLOC_CTX *mem_ctx)
3264 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3266 data->notify_data.data.length = len;
3268 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3270 if (!data->notify_data.data.string) {
3271 data->notify_data.data.length = 0;
3275 memcpy(data->notify_data.data.string, temp, len);
3277 data->notify_data.data.string = NULL;
3281 /*******************************************************************
3282 * fill a notify_info_data with job status
3283 ********************************************************************/
3285 static void spoolss_notify_job_status_string(int snum,
3286 SPOOL_NOTIFY_INFO_DATA *data,
3287 print_queue_struct *queue,
3288 NT_PRINTER_INFO_LEVEL *printer,
3289 TALLOC_CTX *mem_ctx)
3292 * Now we're returning job status codes we just return a "" here. JRA.
3299 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3302 switch (queue->status) {
3307 p = ""; /* NT provides the paused string */
3316 #endif /* NO LONGER NEEDED. */
3318 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3320 data->notify_data.data.length = len;
3322 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3324 if (!data->notify_data.data.string) {
3325 data->notify_data.data.length = 0;
3329 memcpy(data->notify_data.data.string, temp, len);
3331 data->notify_data.data.string = NULL;
3335 /*******************************************************************
3336 * fill a notify_info_data with job time
3337 ********************************************************************/
3339 static void spoolss_notify_job_time(int snum,
3340 SPOOL_NOTIFY_INFO_DATA *data,
3341 print_queue_struct *queue,
3342 NT_PRINTER_INFO_LEVEL *printer,
3343 TALLOC_CTX *mem_ctx)
3345 data->notify_data.value[0]=0x0;
3346 data->notify_data.value[1]=0;
3349 /*******************************************************************
3350 * fill a notify_info_data with job size
3351 ********************************************************************/
3353 static void spoolss_notify_job_size(int snum,
3354 SPOOL_NOTIFY_INFO_DATA *data,
3355 print_queue_struct *queue,
3356 NT_PRINTER_INFO_LEVEL *printer,
3357 TALLOC_CTX *mem_ctx)
3359 data->notify_data.value[0]=queue->size;
3360 data->notify_data.value[1]=0;
3363 /*******************************************************************
3364 * fill a notify_info_data with page info
3365 ********************************************************************/
3366 static void spoolss_notify_total_pages(int snum,
3367 SPOOL_NOTIFY_INFO_DATA *data,
3368 print_queue_struct *queue,
3369 NT_PRINTER_INFO_LEVEL *printer,
3370 TALLOC_CTX *mem_ctx)
3372 data->notify_data.value[0]=queue->page_count;
3373 data->notify_data.value[1]=0;
3376 /*******************************************************************
3377 * fill a notify_info_data with pages printed info.
3378 ********************************************************************/
3379 static void spoolss_notify_pages_printed(int snum,
3380 SPOOL_NOTIFY_INFO_DATA *data,
3381 print_queue_struct *queue,
3382 NT_PRINTER_INFO_LEVEL *printer,
3383 TALLOC_CTX *mem_ctx)
3385 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3386 data->notify_data.value[1]=0;
3389 /*******************************************************************
3390 Fill a notify_info_data with job position.
3391 ********************************************************************/
3393 static void spoolss_notify_job_position(int snum,
3394 SPOOL_NOTIFY_INFO_DATA *data,
3395 print_queue_struct *queue,
3396 NT_PRINTER_INFO_LEVEL *printer,
3397 TALLOC_CTX *mem_ctx)
3399 data->notify_data.value[0]=queue->job;
3400 data->notify_data.value[1]=0;
3403 /*******************************************************************
3404 Fill a notify_info_data with submitted time.
3405 ********************************************************************/
3407 static void spoolss_notify_submitted_time(int snum,
3408 SPOOL_NOTIFY_INFO_DATA *data,
3409 print_queue_struct *queue,
3410 NT_PRINTER_INFO_LEVEL *printer,
3411 TALLOC_CTX *mem_ctx)
3418 t=gmtime(&queue->time);
3420 len = sizeof(SYSTEMTIME);
3422 data->notify_data.data.length = len;
3423 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3425 if (!data->notify_data.data.string) {
3426 data->notify_data.data.length = 0;
3430 make_systemtime(&st, t);
3433 * Systemtime must be linearized as a set of UINT16's.
3434 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3437 p = (char *)data->notify_data.data.string;
3438 SSVAL(p, 0, st.year);
3439 SSVAL(p, 2, st.month);
3440 SSVAL(p, 4, st.dayofweek);
3441 SSVAL(p, 6, st.day);
3442 SSVAL(p, 8, st.hour);
3443 SSVAL(p, 10, st.minute);
3444 SSVAL(p, 12, st.second);
3445 SSVAL(p, 14, st.milliseconds);
3448 struct s_notify_info_data_table
3454 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3455 print_queue_struct *queue,
3456 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3459 /* A table describing the various print notification constants and
3460 whether the notification data is a pointer to a variable sized
3461 buffer, a one value uint32 or a two value uint32. */
3463 static const struct s_notify_info_data_table notify_info_data_table[] =
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3485 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3486 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3487 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3488 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3489 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3490 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3508 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3509 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3510 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3511 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3512 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3513 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3514 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3517 /*******************************************************************
3518 Return the size of info_data structure.
3519 ********************************************************************/
3521 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3525 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3526 if ( (notify_info_data_table[i].type == type)
3527 && (notify_info_data_table[i].field == field) ) {
3528 switch(notify_info_data_table[i].size) {
3529 case NOTIFY_ONE_VALUE:
3530 case NOTIFY_TWO_VALUE:
3535 /* The only pointer notify data I have seen on
3536 the wire is the submitted time and this has
3537 the notify size set to 4. -tpot */
3539 case NOTIFY_POINTER:
3542 case NOTIFY_SECDESC:
3548 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3553 /*******************************************************************
3554 Return the type of notify_info_data.
3555 ********************************************************************/
3557 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3561 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3562 if (notify_info_data_table[i].type == type &&
3563 notify_info_data_table[i].field == field)
3564 return notify_info_data_table[i].size;
3570 /****************************************************************************
3571 ****************************************************************************/
3573 static bool search_notify(uint16 type, uint16 field, int *value)
3577 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3578 if (notify_info_data_table[i].type == type &&
3579 notify_info_data_table[i].field == field &&
3580 notify_info_data_table[i].fn != NULL) {
3589 /****************************************************************************
3590 ****************************************************************************/
3592 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3594 info_data->type = type;
3595 info_data->field = field;
3596 info_data->reserved = 0;
3598 info_data->size = size_of_notify_info_data(type, field);
3599 info_data->enc_type = type_of_notify_info_data(type, field);
3604 /*******************************************************************
3606 * fill a notify_info struct with info asked
3608 ********************************************************************/
3610 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3611 snum, SPOOL_NOTIFY_OPTION_TYPE
3612 *option_type, uint32 id,
3613 TALLOC_CTX *mem_ctx)
3619 SPOOL_NOTIFY_INFO_DATA *current_data;
3620 NT_PRINTER_INFO_LEVEL *printer = NULL;
3621 print_queue_struct *queue=NULL;
3623 type=option_type->type;
3625 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3626 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3627 option_type->count, lp_servicename(snum)));
3629 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3632 for(field_num=0; field_num<option_type->count; field_num++) {
3633 field = option_type->fields[field_num];
3635 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3637 if (!search_notify(type, field, &j) )
3640 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3641 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3642 free_a_printer(&printer, 2);
3646 current_data = &info->data[info->count];
3648 construct_info_data(current_data, type, field, id);
3650 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3651 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3653 notify_info_data_table[j].fn(snum, current_data, queue,
3659 free_a_printer(&printer, 2);
3663 /*******************************************************************
3665 * fill a notify_info struct with info asked
3667 ********************************************************************/
3669 static bool construct_notify_jobs_info(print_queue_struct *queue,
3670 SPOOL_NOTIFY_INFO *info,
3671 NT_PRINTER_INFO_LEVEL *printer,
3672 int snum, SPOOL_NOTIFY_OPTION_TYPE
3673 *option_type, uint32 id,
3674 TALLOC_CTX *mem_ctx)
3680 SPOOL_NOTIFY_INFO_DATA *current_data;
3682 DEBUG(4,("construct_notify_jobs_info\n"));
3684 type = option_type->type;
3686 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3687 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3688 option_type->count));
3690 for(field_num=0; field_num<option_type->count; field_num++) {
3691 field = option_type->fields[field_num];
3693 if (!search_notify(type, field, &j) )
3696 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3697 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3701 current_data=&(info->data[info->count]);
3703 construct_info_data(current_data, type, field, id);
3704 notify_info_data_table[j].fn(snum, current_data, queue,
3713 * JFM: The enumeration is not that simple, it's even non obvious.
3715 * let's take an example: I want to monitor the PRINTER SERVER for
3716 * the printer's name and the number of jobs currently queued.
3717 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3718 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3720 * I have 3 printers on the back of my server.
3722 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3725 * 1 printer 1 name 1
3726 * 2 printer 1 cjob 1
3727 * 3 printer 2 name 2
3728 * 4 printer 2 cjob 2
3729 * 5 printer 3 name 3
3730 * 6 printer 3 name 3
3732 * that's the print server case, the printer case is even worse.
3735 /*******************************************************************
3737 * enumerate all printers on the printserver
3738 * fill a notify_info struct with info asked
3740 ********************************************************************/
3742 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3743 SPOOL_NOTIFY_INFO *info,
3744 TALLOC_CTX *mem_ctx)
3747 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3748 int n_services=lp_numservices();
3750 SPOOL_NOTIFY_OPTION *option;
3751 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3753 DEBUG(4,("printserver_notify_info\n"));
3758 option=Printer->notify.option;
3763 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3764 sending a ffpcn() request first */
3769 for (i=0; i<option->count; i++) {
3770 option_type=&(option->ctr.type[i]);
3772 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3775 for (snum=0; snum<n_services; snum++)
3777 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3778 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3784 * Debugging information, don't delete.
3787 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3788 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3789 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3791 for (i=0; i<info->count; i++) {
3792 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3793 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3794 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3801 /*******************************************************************
3803 * fill a notify_info struct with info asked
3805 ********************************************************************/
3807 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3808 TALLOC_CTX *mem_ctx)
3811 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3814 SPOOL_NOTIFY_OPTION *option;
3815 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3817 print_queue_struct *queue=NULL;
3818 print_status_struct status;
3820 DEBUG(4,("printer_notify_info\n"));
3825 option=Printer->notify.option;
3831 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3832 sending a ffpcn() request first */
3837 get_printer_snum(p, hnd, &snum, NULL);
3839 for (i=0; i<option->count; i++) {
3840 option_type=&option->ctr.type[i];
3842 switch ( option_type->type ) {
3843 case PRINTER_NOTIFY_TYPE:
3844 if(construct_notify_printer_info(Printer, info, snum,
3850 case JOB_NOTIFY_TYPE: {
3851 NT_PRINTER_INFO_LEVEL *printer = NULL;
3853 count = print_queue_status(snum, &queue, &status);
3855 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3858 for (j=0; j<count; j++) {
3859 construct_notify_jobs_info(&queue[j], info,
3866 free_a_printer(&printer, 2);
3876 * Debugging information, don't delete.
3879 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3880 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3881 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3883 for (i=0; i<info->count; i++) {
3884 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3885 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3886 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3892 /********************************************************************
3894 ********************************************************************/
3896 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3898 POLICY_HND *handle = &q_u->handle;
3899 SPOOL_NOTIFY_INFO *info = &r_u->info;
3901 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3902 WERROR result = WERR_BADFID;
3904 /* we always have a NOTIFY_INFO struct */
3908 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3909 OUR_HANDLE(handle)));
3913 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3916 * We are now using the change value, and
3917 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3918 * I don't have a global notification system, I'm sending back all the
3919 * informations even when _NOTHING_ has changed.
3922 /* We need to keep track of the change value to send back in
3923 RRPCN replies otherwise our updates are ignored. */
3925 Printer->notify.fnpcn = True;
3927 if (Printer->notify.client_connected) {
3928 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3929 Printer->notify.change = q_u->change;
3932 /* just ignore the SPOOL_NOTIFY_OPTION */
3934 switch (Printer->printer_type) {
3936 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3939 case SPLHND_PRINTER:
3940 result = printer_notify_info(p, handle, info, p->mem_ctx);
3944 Printer->notify.fnpcn = False;
3950 /********************************************************************
3951 * construct_printer_info_0
3952 * fill a printer_info_0 struct
3953 ********************************************************************/
3955 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3959 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3960 counter_printer_0 *session_counter;
3961 uint32 global_counter;
3964 print_status_struct status;
3966 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3969 count = print_queue_length(snum, &status);
3971 /* check if we already have a counter for this printer */
3972 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3973 if (session_counter->snum == snum)
3977 /* it's the first time, add it to the list */
3978 if (session_counter==NULL) {
3979 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3980 free_a_printer(&ntprinter, 2);
3983 ZERO_STRUCTP(session_counter);
3984 session_counter->snum=snum;
3985 session_counter->counter=0;
3986 DLIST_ADD(counter_list, session_counter);
3990 session_counter->counter++;
3993 * the global_counter should be stored in a TDB as it's common to all the clients
3994 * and should be zeroed on samba startup
3996 global_counter=session_counter->counter;
3998 pstrcpy(chaine,ntprinter->info_2->printername);
4000 init_unistr(&printer->printername, chaine);
4002 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
4003 init_unistr(&printer->servername, chaine);
4005 printer->cjobs = count;
4006 printer->total_jobs = 0;
4007 printer->total_bytes = 0;
4009 setuptime = (time_t)ntprinter->info_2->setuptime;
4010 t=gmtime(&setuptime);
4012 printer->year = t->tm_year+1900;
4013 printer->month = t->tm_mon+1;
4014 printer->dayofweek = t->tm_wday;
4015 printer->day = t->tm_mday;
4016 printer->hour = t->tm_hour;
4017 printer->minute = t->tm_min;
4018 printer->second = t->tm_sec;
4019 printer->milliseconds = 0;
4021 printer->global_counter = global_counter;
4022 printer->total_pages = 0;
4024 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4025 printer->major_version = 0x0005; /* NT 5 */
4026 printer->build_version = 0x0893; /* build 2195 */
4028 printer->unknown7 = 0x1;
4029 printer->unknown8 = 0x0;
4030 printer->unknown9 = 0x0;
4031 printer->session_counter = session_counter->counter;
4032 printer->unknown11 = 0x0;
4033 printer->printer_errors = 0x0; /* number of print failure */
4034 printer->unknown13 = 0x0;
4035 printer->unknown14 = 0x1;
4036 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4037 printer->unknown16 = 0x0;
4038 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4039 printer->unknown18 = 0x0;
4040 printer->status = nt_printq_status(status.status);
4041 printer->unknown20 = 0x0;
4042 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4043 printer->unknown22 = 0x0;
4044 printer->unknown23 = 0x6; /* 6 ???*/
4045 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4046 printer->unknown25 = 0;
4047 printer->unknown26 = 0;
4048 printer->unknown27 = 0;
4049 printer->unknown28 = 0;
4050 printer->unknown29 = 0;
4052 free_a_printer(&ntprinter,2);
4056 /********************************************************************
4057 * construct_printer_info_1
4058 * fill a printer_info_1 struct
4059 ********************************************************************/
4060 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4064 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4066 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4069 printer->flags=flags;
4071 if (*ntprinter->info_2->comment == '\0') {
4072 init_unistr(&printer->comment, lp_comment(snum));
4073 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4074 ntprinter->info_2->drivername, lp_comment(snum));
4077 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4078 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4079 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4082 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4084 init_unistr(&printer->description, chaine);
4085 init_unistr(&printer->name, chaine2);
4087 free_a_printer(&ntprinter,2);
4092 /****************************************************************************
4093 Free a DEVMODE struct.
4094 ****************************************************************************/
4096 static void free_dev_mode(DEVICEMODE *dev)
4101 SAFE_FREE(dev->dev_private);
4106 /****************************************************************************
4107 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4108 should be valid upon entry
4109 ****************************************************************************/
4111 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4113 if ( !devmode || !ntdevmode )
4116 init_unistr(&devmode->devicename, ntdevmode->devicename);
4118 init_unistr(&devmode->formname, ntdevmode->formname);
4120 devmode->specversion = ntdevmode->specversion;
4121 devmode->driverversion = ntdevmode->driverversion;
4122 devmode->size = ntdevmode->size;
4123 devmode->driverextra = ntdevmode->driverextra;
4124 devmode->fields = ntdevmode->fields;
4126 devmode->orientation = ntdevmode->orientation;
4127 devmode->papersize = ntdevmode->papersize;
4128 devmode->paperlength = ntdevmode->paperlength;
4129 devmode->paperwidth = ntdevmode->paperwidth;
4130 devmode->scale = ntdevmode->scale;
4131 devmode->copies = ntdevmode->copies;
4132 devmode->defaultsource = ntdevmode->defaultsource;
4133 devmode->printquality = ntdevmode->printquality;
4134 devmode->color = ntdevmode->color;
4135 devmode->duplex = ntdevmode->duplex;
4136 devmode->yresolution = ntdevmode->yresolution;
4137 devmode->ttoption = ntdevmode->ttoption;
4138 devmode->collate = ntdevmode->collate;
4139 devmode->icmmethod = ntdevmode->icmmethod;
4140 devmode->icmintent = ntdevmode->icmintent;
4141 devmode->mediatype = ntdevmode->mediatype;
4142 devmode->dithertype = ntdevmode->dithertype;
4144 if (ntdevmode->nt_dev_private != NULL) {
4145 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4152 /****************************************************************************
4153 Create a DEVMODE struct. Returns malloced memory.
4154 ****************************************************************************/
4156 DEVICEMODE *construct_dev_mode(const char *servicename)
4158 NT_PRINTER_INFO_LEVEL *printer = NULL;
4159 DEVICEMODE *devmode = NULL;
4161 DEBUG(7,("construct_dev_mode\n"));
4163 DEBUGADD(8,("getting printer characteristics\n"));
4165 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4168 if ( !printer->info_2->devmode ) {
4169 DEBUG(5, ("BONG! There was no device mode!\n"));
4173 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4174 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4178 ZERO_STRUCTP(devmode);
4180 DEBUGADD(8,("loading DEVICEMODE\n"));
4182 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4183 free_dev_mode( devmode );
4188 free_a_printer(&printer,2);
4193 /********************************************************************
4194 * construct_printer_info_2
4195 * fill a printer_info_2 struct
4196 ********************************************************************/
4198 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4201 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4203 print_status_struct status;
4205 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4208 count = print_queue_length(snum, &status);
4210 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4211 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4212 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4213 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4214 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4216 if (*ntprinter->info_2->comment == '\0')
4217 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4219 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4221 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4222 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4223 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4224 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4225 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4227 printer->attributes = ntprinter->info_2->attributes;
4229 printer->priority = ntprinter->info_2->priority; /* priority */
4230 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4231 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4232 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4233 printer->status = nt_printq_status(status.status); /* status */
4234 printer->cjobs = count; /* jobs */
4235 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4237 if ( !(printer->devmode = construct_dev_mode(
4238 lp_const_servicename(snum))) )
4239 DEBUG(8, ("Returning NULL Devicemode!\n"));
4241 printer->secdesc = NULL;
4243 if ( ntprinter->info_2->secdesc_buf
4244 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4246 /* don't use talloc_steal() here unless you do a deep steal of all
4247 the SEC_DESC members */
4249 printer->secdesc = dup_sec_desc( talloc_tos(),
4250 ntprinter->info_2->secdesc_buf->sd );
4253 free_a_printer(&ntprinter, 2);
4258 /********************************************************************
4259 * construct_printer_info_3
4260 * fill a printer_info_3 struct
4261 ********************************************************************/
4263 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4265 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4266 PRINTER_INFO_3 *printer = NULL;
4268 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4272 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4273 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4274 free_a_printer(&ntprinter, 2);
4278 ZERO_STRUCTP(printer);
4280 /* These are the components of the SD we are returning. */
4282 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4283 /* don't use talloc_steal() here unless you do a deep steal of all
4284 the SEC_DESC members */
4286 printer->secdesc = dup_sec_desc( talloc_tos(),
4287 ntprinter->info_2->secdesc_buf->sd );
4290 free_a_printer(&ntprinter, 2);
4292 *pp_printer = printer;
4296 /********************************************************************
4297 * construct_printer_info_4
4298 * fill a printer_info_4 struct
4299 ********************************************************************/
4301 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4303 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4305 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4308 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4309 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4310 printer->attributes = ntprinter->info_2->attributes;
4312 free_a_printer(&ntprinter, 2);
4316 /********************************************************************
4317 * construct_printer_info_5
4318 * fill a printer_info_5 struct
4319 ********************************************************************/
4321 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4323 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4325 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4328 init_unistr(&printer->printername, ntprinter->info_2->printername);
4329 init_unistr(&printer->portname, ntprinter->info_2->portname);
4330 printer->attributes = ntprinter->info_2->attributes;
4332 /* these two are not used by NT+ according to MSDN */
4334 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4335 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4337 free_a_printer(&ntprinter, 2);
4342 /********************************************************************
4343 * construct_printer_info_6
4344 * fill a printer_info_6 struct
4345 ********************************************************************/
4347 static bool construct_printer_info_6(Printer_entry *print_hnd,
4348 PRINTER_INFO_6 *printer,
4351 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4353 print_status_struct status;
4355 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4356 lp_const_servicename(snum))))
4359 count = print_queue_length(snum, &status);
4361 printer->status = nt_printq_status(status.status);
4363 free_a_printer(&ntprinter, 2);
4368 /********************************************************************
4369 * construct_printer_info_7
4370 * fill a printer_info_7 struct
4371 ********************************************************************/
4373 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4375 char *guid_str = NULL;
4378 if (is_printer_published(print_hnd, snum, &guid)) {
4379 asprintf(&guid_str, "{%s}",
4380 smb_uuid_string(talloc_tos(), guid));
4381 strupper_m(guid_str);
4382 init_unistr(&printer->guid, guid_str);
4383 printer->action = SPOOL_DS_PUBLISH;
4385 init_unistr(&printer->guid, "");
4386 printer->action = SPOOL_DS_UNPUBLISH;
4392 /********************************************************************
4393 Spoolss_enumprinters.
4394 ********************************************************************/
4396 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4400 int n_services=lp_numservices();
4401 PRINTER_INFO_1 *printers=NULL;
4402 PRINTER_INFO_1 current_prt;
4403 WERROR result = WERR_OK;
4405 DEBUG(4,("enum_all_printers_info_1\n"));
4407 for (snum=0; snum<n_services; snum++) {
4408 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4409 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4411 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4412 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4413 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4417 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4419 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4425 /* check the required size. */
4426 for (i=0; i<*returned; i++)
4427 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4429 if (*needed > offered) {
4430 result = WERR_INSUFFICIENT_BUFFER;
4434 if (!rpcbuf_alloc_size(buffer, *needed)) {
4435 result = WERR_NOMEM;
4439 /* fill the buffer with the structures */
4440 for (i=0; i<*returned; i++)
4441 smb_io_printer_info_1("", buffer, &printers[i], 0);
4446 SAFE_FREE(printers);
4448 if ( !W_ERROR_IS_OK(result) )
4454 /********************************************************************
4455 enum_all_printers_info_1_local.
4456 *********************************************************************/
4458 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4460 DEBUG(4,("enum_all_printers_info_1_local\n"));
4462 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4465 /********************************************************************
4466 enum_all_printers_info_1_name.
4467 *********************************************************************/
4469 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4473 DEBUG(4,("enum_all_printers_info_1_name\n"));
4475 if ((name[0] == '\\') && (name[1] == '\\'))
4478 if (is_myname_or_ipaddr(s)) {
4479 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4482 return WERR_INVALID_NAME;
4485 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4486 /********************************************************************
4487 enum_all_printers_info_1_remote.
4488 *********************************************************************/
4490 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4492 PRINTER_INFO_1 *printer;
4493 fstring printername;
4496 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4497 WERROR result = WERR_OK;
4499 /* JFM: currently it's more a place holder than anything else.
4500 * In the spooler world there is a notion of server registration.
4501 * the print servers are registered on the PDC (in the same domain)
4503 * We should have a TDB here. The registration is done thru an
4504 * undocumented RPC call.
4507 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4512 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4513 slprintf(desc, sizeof(desc)-1,"%s", name);
4514 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4516 init_unistr(&printer->description, desc);
4517 init_unistr(&printer->name, printername);
4518 init_unistr(&printer->comment, comment);
4519 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4521 /* check the required size. */
4522 *needed += spoolss_size_printer_info_1(printer);
4524 if (*needed > offered) {
4525 result = WERR_INSUFFICIENT_BUFFER;
4529 if (!rpcbuf_alloc_size(buffer, *needed)) {
4530 result = WERR_NOMEM;
4534 /* fill the buffer with the structures */
4535 smb_io_printer_info_1("", buffer, printer, 0);
4541 if ( !W_ERROR_IS_OK(result) )
4549 /********************************************************************
4550 enum_all_printers_info_1_network.
4551 *********************************************************************/
4553 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4557 DEBUG(4,("enum_all_printers_info_1_network\n"));
4559 /* If we respond to a enum_printers level 1 on our name with flags
4560 set to PRINTER_ENUM_REMOTE with a list of printers then these
4561 printers incorrectly appear in the APW browse list.
4562 Specifically the printers for the server appear at the workgroup
4563 level where all the other servers in the domain are
4564 listed. Windows responds to this call with a
4565 WERR_CAN_NOT_COMPLETE so we should do the same. */
4567 if (name[0] == '\\' && name[1] == '\\')
4570 if (is_myname_or_ipaddr(s))
4571 return WERR_CAN_NOT_COMPLETE;
4573 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4576 /********************************************************************
4577 * api_spoolss_enumprinters
4579 * called from api_spoolss_enumprinters (see this to understand)
4580 ********************************************************************/
4582 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4586 int n_services=lp_numservices();
4587 PRINTER_INFO_2 *printers=NULL;
4588 PRINTER_INFO_2 current_prt;
4589 WERROR result = WERR_OK;
4593 for (snum=0; snum<n_services; snum++) {
4594 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4595 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4597 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4598 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4599 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4604 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4606 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4613 /* check the required size. */
4614 for (i=0; i<*returned; i++)
4615 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4617 if (*needed > offered) {
4618 result = WERR_INSUFFICIENT_BUFFER;
4622 if (!rpcbuf_alloc_size(buffer, *needed)) {
4623 result = WERR_NOMEM;
4627 /* fill the buffer with the structures */
4628 for (i=0; i<*returned; i++)
4629 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4634 for (i=0; i<*returned; i++)
4635 free_devmode(printers[i].devmode);
4637 SAFE_FREE(printers);
4639 if ( !W_ERROR_IS_OK(result) )
4645 /********************************************************************
4646 * handle enumeration of printers at level 1
4647 ********************************************************************/
4649 static WERROR enumprinters_level1( uint32 flags, fstring name,
4650 RPC_BUFFER *buffer, uint32 offered,
4651 uint32 *needed, uint32 *returned)
4653 /* Not all the flags are equals */
4655 if (flags & PRINTER_ENUM_LOCAL)
4656 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4658 if (flags & PRINTER_ENUM_NAME)
4659 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4661 #if 0 /* JERRY - disabled for now */
4662 if (flags & PRINTER_ENUM_REMOTE)
4663 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4666 if (flags & PRINTER_ENUM_NETWORK)
4667 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4669 return WERR_OK; /* NT4sp5 does that */
4672 /********************************************************************
4673 * handle enumeration of printers at level 2
4674 ********************************************************************/
4676 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4677 RPC_BUFFER *buffer, uint32 offered,
4678 uint32 *needed, uint32 *returned)
4680 char *s = servername;
4682 if (flags & PRINTER_ENUM_LOCAL) {
4683 return enum_all_printers_info_2(buffer, offered, needed, returned);
4686 if (flags & PRINTER_ENUM_NAME) {
4687 if ((servername[0] == '\\') && (servername[1] == '\\'))
4689 if (is_myname_or_ipaddr(s))
4690 return enum_all_printers_info_2(buffer, offered, needed, returned);
4692 return WERR_INVALID_NAME;
4695 if (flags & PRINTER_ENUM_REMOTE)
4696 return WERR_UNKNOWN_LEVEL;
4701 /********************************************************************
4702 * handle enumeration of printers at level 5
4703 ********************************************************************/
4705 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4706 RPC_BUFFER *buffer, uint32 offered,
4707 uint32 *needed, uint32 *returned)
4709 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4713 /********************************************************************
4714 * api_spoolss_enumprinters
4716 * called from api_spoolss_enumprinters (see this to understand)
4717 ********************************************************************/
4719 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4721 uint32 flags = q_u->flags;
4722 UNISTR2 *servername = &q_u->servername;
4723 uint32 level = q_u->level;
4724 RPC_BUFFER *buffer = NULL;
4725 uint32 offered = q_u->offered;
4726 uint32 *needed = &r_u->needed;
4727 uint32 *returned = &r_u->returned;
4731 /* that's an [in out] buffer */
4733 if (!q_u->buffer && (offered!=0)) {
4734 return WERR_INVALID_PARAM;
4737 rpcbuf_move(q_u->buffer, &r_u->buffer);
4738 buffer = r_u->buffer;
4740 DEBUG(4,("_spoolss_enumprinters\n"));
4747 * flags==PRINTER_ENUM_NAME
4748 * if name=="" then enumerates all printers
4749 * if name!="" then enumerate the printer
4750 * flags==PRINTER_ENUM_REMOTE
4751 * name is NULL, enumerate printers
4752 * Level 2: name!="" enumerates printers, name can't be NULL
4753 * Level 3: doesn't exist
4754 * Level 4: does a local registry lookup
4755 * Level 5: same as Level 2
4758 unistr2_to_ascii(name, servername, sizeof(name));
4763 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4765 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4767 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4772 return WERR_UNKNOWN_LEVEL;
4775 /****************************************************************************
4776 ****************************************************************************/
4778 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4780 PRINTER_INFO_0 *printer=NULL;
4781 WERROR result = WERR_OK;
4783 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4786 construct_printer_info_0(print_hnd, printer, snum);
4788 /* check the required size. */
4789 *needed += spoolss_size_printer_info_0(printer);
4791 if (*needed > offered) {
4792 result = WERR_INSUFFICIENT_BUFFER;
4796 if (!rpcbuf_alloc_size(buffer, *needed)) {
4797 result = WERR_NOMEM;
4801 /* fill the buffer with the structures */
4802 smb_io_printer_info_0("", buffer, printer, 0);
4812 /****************************************************************************
4813 ****************************************************************************/
4815 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4817 PRINTER_INFO_1 *printer=NULL;
4818 WERROR result = WERR_OK;
4820 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4823 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4825 /* check the required size. */
4826 *needed += spoolss_size_printer_info_1(printer);
4828 if (*needed > offered) {
4829 result = WERR_INSUFFICIENT_BUFFER;
4833 if (!rpcbuf_alloc_size(buffer, *needed)) {
4834 result = WERR_NOMEM;
4838 /* fill the buffer with the structures */
4839 smb_io_printer_info_1("", buffer, printer, 0);
4848 /****************************************************************************
4849 ****************************************************************************/
4851 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4853 PRINTER_INFO_2 *printer=NULL;
4854 WERROR result = WERR_OK;
4856 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4859 construct_printer_info_2(print_hnd, printer, snum);
4861 /* check the required size. */
4862 *needed += spoolss_size_printer_info_2(printer);
4864 if (*needed > offered) {
4865 result = WERR_INSUFFICIENT_BUFFER;
4869 if (!rpcbuf_alloc_size(buffer, *needed)) {
4870 result = WERR_NOMEM;
4874 /* fill the buffer with the structures */
4875 if (!smb_io_printer_info_2("", buffer, printer, 0))
4876 result = WERR_NOMEM;
4880 free_printer_info_2(printer);
4885 /****************************************************************************
4886 ****************************************************************************/
4888 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4890 PRINTER_INFO_3 *printer=NULL;
4891 WERROR result = WERR_OK;
4893 if (!construct_printer_info_3(print_hnd, &printer, snum))
4896 /* check the required size. */
4897 *needed += spoolss_size_printer_info_3(printer);
4899 if (*needed > offered) {
4900 result = WERR_INSUFFICIENT_BUFFER;
4904 if (!rpcbuf_alloc_size(buffer, *needed)) {
4905 result = WERR_NOMEM;
4909 /* fill the buffer with the structures */
4910 smb_io_printer_info_3("", buffer, printer, 0);
4914 free_printer_info_3(printer);
4919 /****************************************************************************
4920 ****************************************************************************/
4922 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4924 PRINTER_INFO_4 *printer=NULL;
4925 WERROR result = WERR_OK;
4927 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4930 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4935 /* check the required size. */
4936 *needed += spoolss_size_printer_info_4(printer);
4938 if (*needed > offered) {
4939 result = WERR_INSUFFICIENT_BUFFER;
4943 if (!rpcbuf_alloc_size(buffer, *needed)) {
4944 result = WERR_NOMEM;
4948 /* fill the buffer with the structures */
4949 smb_io_printer_info_4("", buffer, printer, 0);
4953 free_printer_info_4(printer);
4958 /****************************************************************************
4959 ****************************************************************************/
4961 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4963 PRINTER_INFO_5 *printer=NULL;
4964 WERROR result = WERR_OK;
4966 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4969 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4970 free_printer_info_5(printer);
4974 /* check the required size. */
4975 *needed += spoolss_size_printer_info_5(printer);
4977 if (*needed > offered) {
4978 result = WERR_INSUFFICIENT_BUFFER;
4982 if (!rpcbuf_alloc_size(buffer, *needed)) {
4983 result = WERR_NOMEM;
4987 /* fill the buffer with the structures */
4988 smb_io_printer_info_5("", buffer, printer, 0);
4992 free_printer_info_5(printer);
4997 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4999 RPC_BUFFER *buffer, uint32 offered,
5002 PRINTER_INFO_6 *printer;
5003 WERROR result = WERR_OK;
5005 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5009 if (!construct_printer_info_6(print_hnd, printer, snum)) {
5010 free_printer_info_6(printer);
5014 /* check the required size. */
5015 *needed += spoolss_size_printer_info_6(printer);
5017 if (*needed > offered) {
5018 result = WERR_INSUFFICIENT_BUFFER;
5022 if (!rpcbuf_alloc_size(buffer, *needed)) {
5023 result = WERR_NOMEM;
5027 /* fill the buffer with the structures */
5028 smb_io_printer_info_6("", buffer, printer, 0);
5032 free_printer_info_6(printer);
5037 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5039 PRINTER_INFO_7 *printer=NULL;
5040 WERROR result = WERR_OK;
5042 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5045 if (!construct_printer_info_7(print_hnd, printer, snum))
5048 /* check the required size. */
5049 *needed += spoolss_size_printer_info_7(printer);
5051 if (*needed > offered) {
5052 result = WERR_INSUFFICIENT_BUFFER;
5056 if (!rpcbuf_alloc_size(buffer, *needed)) {
5057 result = WERR_NOMEM;
5062 /* fill the buffer with the structures */
5063 smb_io_printer_info_7("", buffer, printer, 0);
5067 free_printer_info_7(printer);
5072 /****************************************************************************
5073 ****************************************************************************/
5075 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5077 POLICY_HND *handle = &q_u->handle;
5078 uint32 level = q_u->level;
5079 RPC_BUFFER *buffer = NULL;
5080 uint32 offered = q_u->offered;
5081 uint32 *needed = &r_u->needed;
5082 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5086 /* that's an [in out] buffer */
5088 if (!q_u->buffer && (offered!=0)) {
5089 return WERR_INVALID_PARAM;
5092 rpcbuf_move(q_u->buffer, &r_u->buffer);
5093 buffer = r_u->buffer;
5097 if (!get_printer_snum(p, handle, &snum, NULL))
5102 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5104 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5106 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5108 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5110 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5112 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5114 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5116 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5118 return WERR_UNKNOWN_LEVEL;
5121 /********************************************************************
5122 * fill a DRIVER_INFO_1 struct
5123 ********************************************************************/
5125 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5127 init_unistr( &info->name, driver.info_3->name);
5130 /********************************************************************
5131 * construct_printer_driver_info_1
5132 ********************************************************************/
5134 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5136 NT_PRINTER_INFO_LEVEL *printer = NULL;
5137 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5139 ZERO_STRUCT(driver);
5141 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5142 return WERR_INVALID_PRINTER_NAME;
5144 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5145 free_a_printer(&printer, 2);
5146 return WERR_UNKNOWN_PRINTER_DRIVER;
5149 fill_printer_driver_info_1(info, driver, servername, architecture);
5151 free_a_printer(&printer,2);
5156 /********************************************************************
5157 * construct_printer_driver_info_2
5158 * fill a printer_info_2 struct
5159 ********************************************************************/
5161 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5165 info->version=driver.info_3->cversion;
5167 init_unistr( &info->name, driver.info_3->name );
5168 init_unistr( &info->architecture, driver.info_3->environment );
5171 if (strlen(driver.info_3->driverpath)) {
5172 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5173 init_unistr( &info->driverpath, temp );
5175 init_unistr( &info->driverpath, "" );
5177 if (strlen(driver.info_3->datafile)) {
5178 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5179 init_unistr( &info->datafile, temp );
5181 init_unistr( &info->datafile, "" );
5183 if (strlen(driver.info_3->configfile)) {
5184 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5185 init_unistr( &info->configfile, temp );
5187 init_unistr( &info->configfile, "" );
5190 /********************************************************************
5191 * construct_printer_driver_info_2
5192 * fill a printer_info_2 struct
5193 ********************************************************************/
5195 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5197 NT_PRINTER_INFO_LEVEL *printer = NULL;
5198 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5200 ZERO_STRUCT(printer);
5201 ZERO_STRUCT(driver);
5203 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5204 return WERR_INVALID_PRINTER_NAME;
5206 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5207 free_a_printer(&printer, 2);
5208 return WERR_UNKNOWN_PRINTER_DRIVER;
5211 fill_printer_driver_info_2(info, driver, servername);
5213 free_a_printer(&printer,2);
5218 /********************************************************************
5219 * copy a strings array and convert to UNICODE
5221 * convert an array of ascii string to a UNICODE string
5222 ********************************************************************/
5224 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5231 DEBUG(6,("init_unistr_array\n"));
5242 v = ""; /* hack to handle null lists */
5245 /* hack to allow this to be used in places other than when generating
5246 the list of dependent files */
5249 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5253 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5255 /* add one extra unit16 for the second terminating NULL */
5257 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5258 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5265 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5270 /* special case for ""; we need to add both NULL's here */
5272 (*uni_array)[j++]=0x0000;
5273 (*uni_array)[j]=0x0000;
5276 DEBUGADD(6,("last one:done\n"));
5278 /* return size of array in uint16's */
5283 /********************************************************************
5284 * construct_printer_info_3
5285 * fill a printer_info_3 struct
5286 ********************************************************************/
5288 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5294 info->version=driver.info_3->cversion;
5296 init_unistr( &info->name, driver.info_3->name );
5297 init_unistr( &info->architecture, driver.info_3->environment );
5299 if (strlen(driver.info_3->driverpath)) {
5300 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5301 init_unistr( &info->driverpath, temp );
5303 init_unistr( &info->driverpath, "" );
5305 if (strlen(driver.info_3->datafile)) {
5306 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5307 init_unistr( &info->datafile, temp );
5309 init_unistr( &info->datafile, "" );
5311 if (strlen(driver.info_3->configfile)) {
5312 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5313 init_unistr( &info->configfile, temp );
5315 init_unistr( &info->configfile, "" );
5317 if (strlen(driver.info_3->helpfile)) {
5318 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5319 init_unistr( &info->helpfile, temp );
5321 init_unistr( &info->helpfile, "" );
5323 init_unistr( &info->monitorname, driver.info_3->monitorname );
5324 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5326 info->dependentfiles=NULL;
5327 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5330 /********************************************************************
5331 * construct_printer_info_3
5332 * fill a printer_info_3 struct
5333 ********************************************************************/
5335 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5337 NT_PRINTER_INFO_LEVEL *printer = NULL;
5338 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5340 ZERO_STRUCT(driver);
5342 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5343 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5344 if (!W_ERROR_IS_OK(status))
5345 return WERR_INVALID_PRINTER_NAME;
5347 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5348 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5353 * I put this code in during testing. Helpful when commenting out the
5354 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5355 * as win2k always queries the driver using an infor level of 6.
5356 * I've left it in (but ifdef'd out) because I'll probably
5357 * use it in experimentation again in the future. --jerry 22/01/2002
5360 if (!W_ERROR_IS_OK(status)) {
5362 * Is this a W2k client ?
5365 /* Yes - try again with a WinNT driver. */
5367 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5368 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5372 if (!W_ERROR_IS_OK(status)) {
5373 free_a_printer(&printer,2);
5374 return WERR_UNKNOWN_PRINTER_DRIVER;
5382 fill_printer_driver_info_3(info, driver, servername);
5384 free_a_printer(&printer,2);
5389 /********************************************************************
5390 * construct_printer_info_6
5391 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5392 ********************************************************************/
5394 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5400 memset(&nullstr, '\0', sizeof(fstring));
5402 info->version=driver.info_3->cversion;
5404 init_unistr( &info->name, driver.info_3->name );
5405 init_unistr( &info->architecture, driver.info_3->environment );
5407 if (strlen(driver.info_3->driverpath)) {
5408 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5409 init_unistr( &info->driverpath, temp );
5411 init_unistr( &info->driverpath, "" );
5413 if (strlen(driver.info_3->datafile)) {
5414 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5415 init_unistr( &info->datafile, temp );
5417 init_unistr( &info->datafile, "" );
5419 if (strlen(driver.info_3->configfile)) {
5420 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5421 init_unistr( &info->configfile, temp );
5423 init_unistr( &info->configfile, "" );
5425 if (strlen(driver.info_3->helpfile)) {
5426 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5427 init_unistr( &info->helpfile, temp );
5429 init_unistr( &info->helpfile, "" );
5431 init_unistr( &info->monitorname, driver.info_3->monitorname );
5432 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5434 info->dependentfiles = NULL;
5435 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5437 info->previousdrivernames=NULL;
5438 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5440 info->driver_date=0;
5443 info->driver_version_low=0;
5444 info->driver_version_high=0;
5446 init_unistr( &info->mfgname, "");
5447 init_unistr( &info->oem_url, "");
5448 init_unistr( &info->hardware_id, "");
5449 init_unistr( &info->provider, "");
5452 /********************************************************************
5453 * construct_printer_info_6
5454 * fill a printer_info_6 struct
5455 ********************************************************************/
5457 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5458 fstring servername, fstring architecture, uint32 version)
5460 NT_PRINTER_INFO_LEVEL *printer = NULL;
5461 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5464 ZERO_STRUCT(driver);
5466 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5468 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5470 if (!W_ERROR_IS_OK(status))
5471 return WERR_INVALID_PRINTER_NAME;
5473 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5475 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5477 if (!W_ERROR_IS_OK(status))
5480 * Is this a W2k client ?
5484 free_a_printer(&printer,2);
5485 return WERR_UNKNOWN_PRINTER_DRIVER;
5488 /* Yes - try again with a WinNT driver. */
5490 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5491 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5492 if (!W_ERROR_IS_OK(status)) {
5493 free_a_printer(&printer,2);
5494 return WERR_UNKNOWN_PRINTER_DRIVER;
5498 fill_printer_driver_info_6(info, driver, servername);
5500 free_a_printer(&printer,2);
5501 free_a_printer_driver(driver, 3);
5506 /****************************************************************************
5507 ****************************************************************************/
5509 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5511 SAFE_FREE(info->dependentfiles);
5514 /****************************************************************************
5515 ****************************************************************************/
5517 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5519 SAFE_FREE(info->dependentfiles);
5522 /****************************************************************************
5523 ****************************************************************************/
5525 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5527 DRIVER_INFO_1 *info=NULL;
5530 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5533 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5534 if (!W_ERROR_IS_OK(result))
5537 /* check the required size. */
5538 *needed += spoolss_size_printer_driver_info_1(info);
5540 if (*needed > offered) {
5541 result = WERR_INSUFFICIENT_BUFFER;
5545 if (!rpcbuf_alloc_size(buffer, *needed)) {
5546 result = WERR_NOMEM;
5550 /* fill the buffer with the structures */
5551 smb_io_printer_driver_info_1("", buffer, info, 0);
5560 /****************************************************************************
5561 ****************************************************************************/
5563 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5565 DRIVER_INFO_2 *info=NULL;
5568 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5571 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5572 if (!W_ERROR_IS_OK(result))
5575 /* check the required size. */
5576 *needed += spoolss_size_printer_driver_info_2(info);
5578 if (*needed > offered) {
5579 result = WERR_INSUFFICIENT_BUFFER;
5583 if (!rpcbuf_alloc_size(buffer, *needed)) {
5584 result = WERR_NOMEM;
5588 /* fill the buffer with the structures */
5589 smb_io_printer_driver_info_2("", buffer, info, 0);
5598 /****************************************************************************
5599 ****************************************************************************/
5601 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5608 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5609 if (!W_ERROR_IS_OK(result))
5612 /* check the required size. */
5613 *needed += spoolss_size_printer_driver_info_3(&info);
5615 if (*needed > offered) {
5616 result = WERR_INSUFFICIENT_BUFFER;
5620 if (!rpcbuf_alloc_size(buffer, *needed)) {
5621 result = WERR_NOMEM;
5625 /* fill the buffer with the structures */
5626 smb_io_printer_driver_info_3("", buffer, &info, 0);
5629 free_printer_driver_info_3(&info);
5634 /****************************************************************************
5635 ****************************************************************************/
5637 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5644 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5645 if (!W_ERROR_IS_OK(result))
5648 /* check the required size. */
5649 *needed += spoolss_size_printer_driver_info_6(&info);
5651 if (*needed > offered) {
5652 result = WERR_INSUFFICIENT_BUFFER;
5656 if (!rpcbuf_alloc_size(buffer, *needed)) {
5657 result = WERR_NOMEM;
5661 /* fill the buffer with the structures */
5662 smb_io_printer_driver_info_6("", buffer, &info, 0);
5665 free_printer_driver_info_6(&info);
5670 /****************************************************************************
5671 ****************************************************************************/
5673 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5675 POLICY_HND *handle = &q_u->handle;
5676 UNISTR2 *uni_arch = &q_u->architecture;
5677 uint32 level = q_u->level;
5678 uint32 clientmajorversion = q_u->clientmajorversion;
5679 RPC_BUFFER *buffer = NULL;
5680 uint32 offered = q_u->offered;
5681 uint32 *needed = &r_u->needed;
5682 uint32 *servermajorversion = &r_u->servermajorversion;
5683 uint32 *serverminorversion = &r_u->serverminorversion;
5684 Printer_entry *printer;
5687 fstring architecture;
5690 /* that's an [in out] buffer */
5692 if (!q_u->buffer && (offered!=0)) {
5693 return WERR_INVALID_PARAM;
5696 rpcbuf_move(q_u->buffer, &r_u->buffer);
5697 buffer = r_u->buffer;
5699 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5701 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5702 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5703 return WERR_INVALID_PRINTER_NAME;
5707 *servermajorversion = 0;
5708 *serverminorversion = 0;
5710 fstrcpy(servername, get_server_name( printer ));
5711 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5713 if (!get_printer_snum(p, handle, &snum, NULL))
5718 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5720 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5722 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5724 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5727 /* apparently this call is the equivalent of
5728 EnumPrinterDataEx() for the DsDriver key */
5733 return WERR_UNKNOWN_LEVEL;
5736 /****************************************************************************
5737 ****************************************************************************/
5739 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5741 POLICY_HND *handle = &q_u->handle;
5743 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5746 DEBUG(3,("Error in startpageprinter printer handle\n"));
5750 Printer->page_started=True;
5754 /****************************************************************************
5755 ****************************************************************************/
5757 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5759 POLICY_HND *handle = &q_u->handle;
5762 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5765 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5769 if (!get_printer_snum(p, handle, &snum, NULL))
5772 Printer->page_started=False;
5773 print_job_endpage(snum, Printer->jobid);
5778 /********************************************************************
5779 * api_spoolss_getprinter
5780 * called from the spoolss dispatcher
5782 ********************************************************************/
5784 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5786 POLICY_HND *handle = &q_u->handle;
5787 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5788 uint32 *jobid = &r_u->jobid;
5790 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5794 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5797 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5802 * a nice thing with NT is it doesn't listen to what you tell it.
5803 * when asked to send _only_ RAW datas, it tries to send datas
5806 * So I add checks like in NT Server ...
5809 if (info_1->p_datatype != 0) {
5810 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5811 if (strcmp(datatype, "RAW") != 0) {
5813 return WERR_INVALID_DATATYPE;
5817 /* get the share number of the printer */
5818 if (!get_printer_snum(p, handle, &snum, NULL)) {
5822 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5824 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5826 /* An error occured in print_job_start() so return an appropriate
5829 if (Printer->jobid == -1) {
5830 return map_werror_from_unix(errno);
5833 Printer->document_started=True;
5834 (*jobid) = Printer->jobid;
5839 /********************************************************************
5840 * api_spoolss_getprinter
5841 * called from the spoolss dispatcher
5843 ********************************************************************/
5845 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5847 POLICY_HND *handle = &q_u->handle;
5849 return _spoolss_enddocprinter_internal(p, handle);
5852 /****************************************************************************
5853 ****************************************************************************/
5855 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5857 POLICY_HND *handle = &q_u->handle;
5858 uint32 buffer_size = q_u->buffer_size;
5859 uint8 *buffer = q_u->buffer;
5860 uint32 *buffer_written = &q_u->buffer_size2;
5862 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5865 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5866 r_u->buffer_written = q_u->buffer_size2;
5870 if (!get_printer_snum(p, handle, &snum, NULL))
5873 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5874 (SMB_OFF_T)-1, (size_t)buffer_size);
5875 if (*buffer_written == (uint32)-1) {
5876 r_u->buffer_written = 0;
5877 if (errno == ENOSPC)
5878 return WERR_NO_SPOOL_SPACE;
5880 return WERR_ACCESS_DENIED;
5883 r_u->buffer_written = q_u->buffer_size2;
5888 /********************************************************************
5889 * api_spoolss_getprinter
5890 * called from the spoolss dispatcher
5892 ********************************************************************/
5894 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5898 WERROR errcode = WERR_BADFUNC;
5899 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5902 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5906 if (!get_printer_snum(p, handle, &snum, NULL))
5910 case PRINTER_CONTROL_PAUSE:
5911 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5915 case PRINTER_CONTROL_RESUME:
5916 case PRINTER_CONTROL_UNPAUSE:
5917 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5921 case PRINTER_CONTROL_PURGE:
5922 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5927 return WERR_UNKNOWN_LEVEL;
5933 /********************************************************************
5934 * api_spoolss_abortprinter
5935 * From MSDN: "Deletes printer's spool file if printer is configured
5937 ********************************************************************/
5939 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5941 POLICY_HND *handle = &q_u->handle;
5942 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5944 WERROR errcode = WERR_OK;
5947 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5951 if (!get_printer_snum(p, handle, &snum, NULL))
5954 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5959 /********************************************************************
5960 * called by spoolss_api_setprinter
5961 * when updating a printer description
5962 ********************************************************************/
5964 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5965 const SPOOL_PRINTER_INFO_LEVEL *info,
5966 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5968 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5972 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5974 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5975 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5976 OUR_HANDLE(handle)));
5978 result = WERR_BADFID;
5983 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5984 result = WERR_INVALID_PARAM;
5988 /* Check the user has permissions to change the security
5989 descriptor. By experimentation with two NT machines, the user
5990 requires Full Access to the printer to change security
5993 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5994 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5995 result = WERR_ACCESS_DENIED;
5999 /* NT seems to like setting the security descriptor even though
6000 nothing may have actually changed. */
6002 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
6004 if (DEBUGLEVEL >= 10) {
6008 the_acl = old_secdesc_ctr->sd->dacl;
6009 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6010 PRINTERNAME(snum), the_acl->num_aces));
6012 for (i = 0; i < the_acl->num_aces; i++) {
6015 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6017 DEBUG(10, ("%s 0x%08x\n", sid_str,
6018 the_acl->aces[i].access_mask));
6021 the_acl = secdesc_ctr->sd->dacl;
6024 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6025 PRINTERNAME(snum), the_acl->num_aces));
6027 for (i = 0; i < the_acl->num_aces; i++) {
6030 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6032 DEBUG(10, ("%s 0x%08x\n", sid_str,
6033 the_acl->aces[i].access_mask));
6036 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6040 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6041 if (!new_secdesc_ctr) {
6042 result = WERR_NOMEM;
6046 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6051 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6058 /********************************************************************
6059 Canonicalize printer info from a client
6061 ATTN: It does not matter what we set the servername to hear
6062 since we do the necessary work in get_a_printer() to set it to
6063 the correct value based on what the client sent in the
6064 _spoolss_open_printer_ex().
6065 ********************************************************************/
6067 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6069 fstring printername;
6072 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6073 "portname=%s drivername=%s comment=%s location=%s\n",
6074 info->servername, info->printername, info->sharename,
6075 info->portname, info->drivername, info->comment, info->location));
6077 /* we force some elements to "correct" values */
6078 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6079 fstrcpy(info->sharename, lp_servicename(snum));
6081 /* check to see if we allow printername != sharename */
6083 if ( lp_force_printername(snum) ) {
6084 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6085 global_myname(), info->sharename );
6088 /* make sure printername is in \\server\printername format */
6090 fstrcpy( printername, info->printername );
6092 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6093 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6097 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6098 global_myname(), p );
6101 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6102 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6109 /****************************************************************************
6110 ****************************************************************************/
6112 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
6114 char *cmd = lp_addport_cmd();
6118 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6119 bool is_print_op = False;
6122 return WERR_ACCESS_DENIED;
6125 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
6128 is_print_op = user_has_privileges( token, &se_printop );
6130 DEBUG(10,("Running [%s]\n", command));
6132 /********* BEGIN SePrintOperatorPrivilege **********/
6137 ret = smbrun(command, &fd);
6142 /********* END SePrintOperatorPrivilege **********/
6144 DEBUGADD(10,("returned [%d]\n", ret));
6149 return WERR_ACCESS_DENIED;
6155 /****************************************************************************
6156 ****************************************************************************/
6158 bool add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6160 char *cmd = lp_addprinter_cmd();
6166 fstring remote_machine = "%m";
6167 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6168 bool is_print_op = False;
6170 standard_sub_basic(current_user_info.smb_name,
6171 current_user_info.domain,
6172 remote_machine,sizeof(remote_machine));
6174 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6175 cmd, printer->info_2->printername, printer->info_2->sharename,
6176 printer->info_2->portname, printer->info_2->drivername,
6177 printer->info_2->location, printer->info_2->comment, remote_machine);
6180 is_print_op = user_has_privileges( token, &se_printop );
6182 DEBUG(10,("Running [%s]\n", command));
6184 /********* BEGIN SePrintOperatorPrivilege **********/
6189 if ( (ret = smbrun(command, &fd)) == 0 ) {
6190 /* Tell everyone we updated smb.conf. */
6191 message_send_all(smbd_messaging_context(),
6192 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6198 /********* END SePrintOperatorPrivilege **********/
6200 DEBUGADD(10,("returned [%d]\n", ret));
6208 /* reload our services immediately */
6209 reload_services( False );
6212 /* Get lines and convert them back to dos-codepage */
6213 qlines = fd_lines_load(fd, &numlines, 0);
6214 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6217 /* Set the portname to what the script says the portname should be. */
6218 /* but don't require anything to be return from the script exit a good error code */
6221 /* Set the portname to what the script says the portname should be. */
6222 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6223 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6226 file_lines_free(qlines);
6231 /********************************************************************
6232 * Called by spoolss_api_setprinter
6233 * when updating a printer description.
6234 ********************************************************************/
6236 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6237 const SPOOL_PRINTER_INFO_LEVEL *info,
6238 DEVICEMODE *devmode)
6241 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6242 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6247 DEBUG(8,("update_printer\n"));
6252 result = WERR_BADFID;
6256 if (!get_printer_snum(p, handle, &snum, NULL)) {
6257 result = WERR_BADFID;
6261 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6262 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6263 result = WERR_BADFID;
6267 DEBUGADD(8,("Converting info_2 struct\n"));
6270 * convert_printer_info converts the incoming
6271 * info from the client and overwrites the info
6272 * just read from the tdb in the pointer 'printer'.
6275 if (!convert_printer_info(info, printer, level)) {
6276 result = WERR_NOMEM;
6281 /* we have a valid devmode
6282 convert it and link it*/
6284 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6285 if (!convert_devicemode(printer->info_2->printername, devmode,
6286 &printer->info_2->devmode)) {
6287 result = WERR_NOMEM;
6292 /* Do sanity check on the requested changes for Samba */
6294 if (!check_printer_ok(printer->info_2, snum)) {
6295 result = WERR_INVALID_PARAM;
6299 /* FIXME!!! If the driver has changed we really should verify that
6300 it is installed before doing much else --jerry */
6302 /* Check calling user has permission to update printer description */
6304 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6305 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6306 result = WERR_ACCESS_DENIED;
6310 /* Call addprinter hook */
6311 /* Check changes to see if this is really needed */
6313 if ( *lp_addprinter_cmd()
6314 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6315 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6316 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6317 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6319 /* add_printer_hook() will call reload_services() */
6321 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6322 result = WERR_ACCESS_DENIED;
6328 * When a *new* driver is bound to a printer, the drivername is used to
6329 * lookup previously saved driver initialization info, which is then
6330 * bound to the printer, simulating what happens in the Windows arch.
6332 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6334 if (!set_driver_init(printer, 2))
6336 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6337 printer->info_2->drivername));
6340 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6341 printer->info_2->drivername));
6343 notify_printer_driver(snum, printer->info_2->drivername);
6347 * flag which changes actually occured. This is a small subset of
6348 * all the possible changes. We also have to update things in the
6352 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6353 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6354 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6355 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6357 notify_printer_comment(snum, printer->info_2->comment);
6360 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6361 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6362 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6363 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6365 notify_printer_sharename(snum, printer->info_2->sharename);
6368 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6371 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6374 pname = printer->info_2->printername;
6377 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6378 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6379 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6381 notify_printer_printername( snum, pname );
6384 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6385 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6386 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6387 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6389 notify_printer_port(snum, printer->info_2->portname);
6392 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6393 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6394 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6395 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6397 notify_printer_location(snum, printer->info_2->location);
6400 /* here we need to update some more DsSpooler keys */
6401 /* uNCName, serverName, shortServerName */
6403 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6404 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6405 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6406 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6407 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6409 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6410 global_myname(), printer->info_2->sharename );
6411 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6412 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6413 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6415 /* Update printer info */
6416 result = mod_a_printer(printer, 2);
6419 free_a_printer(&printer, 2);
6420 free_a_printer(&old_printer, 2);
6426 /****************************************************************************
6427 ****************************************************************************/
6428 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6429 const SPOOL_PRINTER_INFO_LEVEL *info)
6432 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6434 Printer_entry *Printer;
6436 if ( lp_security() != SEC_ADS ) {
6437 return WERR_UNKNOWN_LEVEL;
6440 Printer = find_printer_index_by_hnd(p, handle);
6442 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6447 if (!get_printer_snum(p, handle, &snum, NULL))
6450 nt_printer_publish(Printer, snum, info7->action);
6454 return WERR_UNKNOWN_LEVEL;
6457 /****************************************************************************
6458 ****************************************************************************/
6460 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6462 POLICY_HND *handle = &q_u->handle;
6463 uint32 level = q_u->level;
6464 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6465 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6466 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6467 uint32 command = q_u->command;
6470 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6473 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6477 /* check the level */
6480 return control_printer(handle, command, p);
6482 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6483 if (!W_ERROR_IS_OK(result))
6486 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6489 return update_printer_sec(handle, level, info, p,
6492 return publish_or_unpublish_printer(p, handle, info);
6494 return WERR_UNKNOWN_LEVEL;
6498 /****************************************************************************
6499 ****************************************************************************/
6501 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6503 POLICY_HND *handle = &q_u->handle;
6504 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6507 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6511 if (Printer->notify.client_connected==True) {
6514 if ( Printer->printer_type == SPLHND_SERVER)
6516 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6517 !get_printer_snum(p, handle, &snum, NULL) )
6520 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6523 Printer->notify.flags=0;
6524 Printer->notify.options=0;
6525 Printer->notify.localmachine[0]='\0';
6526 Printer->notify.printerlocal=0;
6527 if (Printer->notify.option)
6528 free_spool_notify_option(&Printer->notify.option);
6529 Printer->notify.client_connected=False;
6534 /****************************************************************************
6535 ****************************************************************************/
6537 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6539 /* that's an [in out] buffer */
6541 if (!q_u->buffer && (q_u->offered!=0)) {
6542 return WERR_INVALID_PARAM;
6545 rpcbuf_move(q_u->buffer, &r_u->buffer);
6548 return WERR_INVALID_PARAM; /* this is what a NT server
6549 returns for AddJob. AddJob
6550 must fail on non-local
6554 /****************************************************************************
6555 ****************************************************************************/
6557 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6558 int position, int snum,
6559 const NT_PRINTER_INFO_LEVEL *ntprinter)
6563 t=gmtime(&queue->time);
6565 job_info->jobid=queue->job;
6566 init_unistr(&job_info->printername, lp_servicename(snum));
6567 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6568 init_unistr(&job_info->username, queue->fs_user);
6569 init_unistr(&job_info->document, queue->fs_file);
6570 init_unistr(&job_info->datatype, "RAW");
6571 init_unistr(&job_info->text_status, "");
6572 job_info->status=nt_printj_status(queue->status);
6573 job_info->priority=queue->priority;
6574 job_info->position=position;
6575 job_info->totalpages=queue->page_count;
6576 job_info->pagesprinted=0;
6578 make_systemtime(&job_info->submitted, t);
6581 /****************************************************************************
6582 ****************************************************************************/
6584 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6585 int position, int snum,
6586 const NT_PRINTER_INFO_LEVEL *ntprinter,
6587 DEVICEMODE *devmode)
6591 t=gmtime(&queue->time);
6593 job_info->jobid=queue->job;
6595 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6597 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6598 init_unistr(&job_info->username, queue->fs_user);
6599 init_unistr(&job_info->document, queue->fs_file);
6600 init_unistr(&job_info->notifyname, queue->fs_user);
6601 init_unistr(&job_info->datatype, "RAW");
6602 init_unistr(&job_info->printprocessor, "winprint");
6603 init_unistr(&job_info->parameters, "");
6604 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6605 init_unistr(&job_info->text_status, "");
6607 /* and here the security descriptor */
6609 job_info->status=nt_printj_status(queue->status);
6610 job_info->priority=queue->priority;
6611 job_info->position=position;
6612 job_info->starttime=0;
6613 job_info->untiltime=0;
6614 job_info->totalpages=queue->page_count;
6615 job_info->size=queue->size;
6616 make_systemtime(&(job_info->submitted), t);
6617 job_info->timeelapsed=0;
6618 job_info->pagesprinted=0;
6620 job_info->devmode = devmode;
6625 /****************************************************************************
6626 Enumjobs at level 1.
6627 ****************************************************************************/
6629 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6630 const NT_PRINTER_INFO_LEVEL *ntprinter,
6631 RPC_BUFFER *buffer, uint32 offered,
6632 uint32 *needed, uint32 *returned)
6636 WERROR result = WERR_OK;
6638 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6644 for (i=0; i<*returned; i++)
6645 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6647 /* check the required size. */
6648 for (i=0; i<*returned; i++)
6649 (*needed) += spoolss_size_job_info_1(&info[i]);
6651 if (*needed > offered) {
6652 result = WERR_INSUFFICIENT_BUFFER;
6656 if (!rpcbuf_alloc_size(buffer, *needed)) {
6657 result = WERR_NOMEM;
6661 /* fill the buffer with the structures */
6662 for (i=0; i<*returned; i++)
6663 smb_io_job_info_1("", buffer, &info[i], 0);
6669 if ( !W_ERROR_IS_OK(result) )
6675 /****************************************************************************
6676 Enumjobs at level 2.
6677 ****************************************************************************/
6679 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6680 const NT_PRINTER_INFO_LEVEL *ntprinter,
6681 RPC_BUFFER *buffer, uint32 offered,
6682 uint32 *needed, uint32 *returned)
6684 JOB_INFO_2 *info = NULL;
6686 WERROR result = WERR_OK;
6687 DEVICEMODE *devmode = NULL;
6689 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6694 /* this should not be a failure condition if the devmode is NULL */
6696 devmode = construct_dev_mode(lp_const_servicename(snum));
6698 for (i=0; i<*returned; i++)
6699 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6701 /* check the required size. */
6702 for (i=0; i<*returned; i++)
6703 (*needed) += spoolss_size_job_info_2(&info[i]);
6705 if (*needed > offered) {
6706 result = WERR_INSUFFICIENT_BUFFER;
6710 if (!rpcbuf_alloc_size(buffer, *needed)) {
6711 result = WERR_NOMEM;
6715 /* fill the buffer with the structures */
6716 for (i=0; i<*returned; i++)
6717 smb_io_job_info_2("", buffer, &info[i], 0);
6720 free_devmode(devmode);
6723 if ( !W_ERROR_IS_OK(result) )
6730 /****************************************************************************
6732 ****************************************************************************/
6734 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6736 POLICY_HND *handle = &q_u->handle;
6737 uint32 level = q_u->level;
6738 RPC_BUFFER *buffer = NULL;
6739 uint32 offered = q_u->offered;
6740 uint32 *needed = &r_u->needed;
6741 uint32 *returned = &r_u->returned;
6743 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6745 print_status_struct prt_status;
6746 print_queue_struct *queue=NULL;
6748 /* that's an [in out] buffer */
6750 if (!q_u->buffer && (offered!=0)) {
6751 return WERR_INVALID_PARAM;
6754 rpcbuf_move(q_u->buffer, &r_u->buffer);
6755 buffer = r_u->buffer;
6757 DEBUG(4,("_spoolss_enumjobs\n"));
6762 /* lookup the printer snum and tdb entry */
6764 if (!get_printer_snum(p, handle, &snum, NULL))
6767 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6768 if ( !W_ERROR_IS_OK(wret) )
6771 *returned = print_queue_status(snum, &queue, &prt_status);
6772 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6774 if (*returned == 0) {
6776 free_a_printer(&ntprinter, 2);
6782 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6785 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6789 wret = WERR_UNKNOWN_LEVEL;
6794 free_a_printer( &ntprinter, 2 );
6798 /****************************************************************************
6799 ****************************************************************************/
6801 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6806 /****************************************************************************
6807 ****************************************************************************/
6809 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6811 POLICY_HND *handle = &q_u->handle;
6812 uint32 jobid = q_u->jobid;
6813 uint32 command = q_u->command;
6816 WERROR errcode = WERR_BADFUNC;
6818 if (!get_printer_snum(p, handle, &snum, NULL)) {
6822 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6823 return WERR_INVALID_PRINTER_NAME;
6827 case JOB_CONTROL_CANCEL:
6828 case JOB_CONTROL_DELETE:
6829 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6833 case JOB_CONTROL_PAUSE:
6834 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6838 case JOB_CONTROL_RESTART:
6839 case JOB_CONTROL_RESUME:
6840 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6845 return WERR_UNKNOWN_LEVEL;
6851 /****************************************************************************
6852 Enumerates all printer drivers at level 1.
6853 ****************************************************************************/
6855 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6860 fstring *list = NULL;
6861 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6862 DRIVER_INFO_1 *driver_info_1=NULL;
6863 WERROR result = WERR_OK;
6867 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6869 ndrivers=get_ntdrivers(&list, architecture, version);
6870 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6872 if(ndrivers == -1) {
6873 SAFE_FREE(driver_info_1);
6878 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6879 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6885 for (i=0; i<ndrivers; i++) {
6887 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6888 ZERO_STRUCT(driver);
6889 status = get_a_printer_driver(&driver, 3, list[i],
6890 architecture, version);
6891 if (!W_ERROR_IS_OK(status)) {
6893 SAFE_FREE(driver_info_1);
6896 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6897 free_a_printer_driver(driver, 3);
6900 *returned+=ndrivers;
6904 /* check the required size. */
6905 for (i=0; i<*returned; i++) {
6906 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6907 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6910 if (*needed > offered) {
6911 result = WERR_INSUFFICIENT_BUFFER;
6915 if (!rpcbuf_alloc_size(buffer, *needed)) {
6916 result = WERR_NOMEM;
6920 /* fill the buffer with the driver structures */
6921 for (i=0; i<*returned; i++) {
6922 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6923 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6927 SAFE_FREE(driver_info_1);
6929 if ( !W_ERROR_IS_OK(result) )
6935 /****************************************************************************
6936 Enumerates all printer drivers at level 2.
6937 ****************************************************************************/
6939 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6944 fstring *list = NULL;
6945 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6946 DRIVER_INFO_2 *driver_info_2=NULL;
6947 WERROR result = WERR_OK;
6951 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6953 ndrivers=get_ntdrivers(&list, architecture, version);
6954 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6956 if(ndrivers == -1) {
6957 SAFE_FREE(driver_info_2);
6962 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6963 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6969 for (i=0; i<ndrivers; i++) {
6972 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6973 ZERO_STRUCT(driver);
6974 status = get_a_printer_driver(&driver, 3, list[i],
6975 architecture, version);
6976 if (!W_ERROR_IS_OK(status)) {
6978 SAFE_FREE(driver_info_2);
6981 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6982 free_a_printer_driver(driver, 3);
6985 *returned+=ndrivers;
6989 /* check the required size. */
6990 for (i=0; i<*returned; i++) {
6991 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6992 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6995 if (*needed > offered) {
6996 result = WERR_INSUFFICIENT_BUFFER;
7000 if (!rpcbuf_alloc_size(buffer, *needed)) {
7001 result = WERR_NOMEM;
7005 /* fill the buffer with the form structures */
7006 for (i=0; i<*returned; i++) {
7007 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7008 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7012 SAFE_FREE(driver_info_2);
7014 if ( !W_ERROR_IS_OK(result) )
7020 /****************************************************************************
7021 Enumerates all printer drivers at level 3.
7022 ****************************************************************************/
7024 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7029 fstring *list = NULL;
7030 DRIVER_INFO_3 *driver_info_3=NULL;
7031 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7032 WERROR result = WERR_OK;
7036 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7038 ndrivers=get_ntdrivers(&list, architecture, version);
7039 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7041 if(ndrivers == -1) {
7042 SAFE_FREE(driver_info_3);
7047 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7048 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7054 for (i=0; i<ndrivers; i++) {
7057 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7058 ZERO_STRUCT(driver);
7059 status = get_a_printer_driver(&driver, 3, list[i],
7060 architecture, version);
7061 if (!W_ERROR_IS_OK(status)) {
7063 SAFE_FREE(driver_info_3);
7066 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7067 free_a_printer_driver(driver, 3);
7070 *returned+=ndrivers;
7074 /* check the required size. */
7075 for (i=0; i<*returned; i++) {
7076 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7077 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7080 if (*needed > offered) {
7081 result = WERR_INSUFFICIENT_BUFFER;
7085 if (!rpcbuf_alloc_size(buffer, *needed)) {
7086 result = WERR_NOMEM;
7090 /* fill the buffer with the driver structures */
7091 for (i=0; i<*returned; i++) {
7092 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7093 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7097 for (i=0; i<*returned; i++) {
7098 SAFE_FREE(driver_info_3[i].dependentfiles);
7101 SAFE_FREE(driver_info_3);
7103 if ( !W_ERROR_IS_OK(result) )
7109 /****************************************************************************
7110 Enumerates all printer drivers.
7111 ****************************************************************************/
7113 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7115 uint32 level = q_u->level;
7116 RPC_BUFFER *buffer = NULL;
7117 uint32 offered = q_u->offered;
7118 uint32 *needed = &r_u->needed;
7119 uint32 *returned = &r_u->returned;
7122 fstring architecture;
7124 /* that's an [in out] buffer */
7126 if (!q_u->buffer && (offered!=0)) {
7127 return WERR_INVALID_PARAM;
7130 rpcbuf_move(q_u->buffer, &r_u->buffer);
7131 buffer = r_u->buffer;
7133 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7138 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7139 unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7141 if ( !is_myname_or_ipaddr( servername ) )
7142 return WERR_UNKNOWN_PRINTER_DRIVER;
7146 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7148 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7150 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7152 return WERR_UNKNOWN_LEVEL;
7156 /****************************************************************************
7157 ****************************************************************************/
7159 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7161 form->flag=list->flag;
7162 init_unistr(&form->name, list->name);
7163 form->width=list->width;
7164 form->length=list->length;
7165 form->left=list->left;
7166 form->top=list->top;
7167 form->right=list->right;
7168 form->bottom=list->bottom;
7171 /****************************************************************************
7172 ****************************************************************************/
7174 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7176 uint32 level = q_u->level;
7177 RPC_BUFFER *buffer = NULL;
7178 uint32 offered = q_u->offered;
7179 uint32 *needed = &r_u->needed;
7180 uint32 *numofforms = &r_u->numofforms;
7181 uint32 numbuiltinforms;
7183 nt_forms_struct *list=NULL;
7184 nt_forms_struct *builtinlist=NULL;
7189 /* that's an [in out] buffer */
7191 if (!q_u->buffer && (offered!=0) ) {
7192 return WERR_INVALID_PARAM;
7195 rpcbuf_move(q_u->buffer, &r_u->buffer);
7196 buffer = r_u->buffer;
7198 DEBUG(4,("_spoolss_enumforms\n"));
7199 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7200 DEBUGADD(5,("Info level [%d]\n", level));
7202 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7203 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7204 *numofforms = get_ntforms(&list);
7205 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7206 *numofforms += numbuiltinforms;
7208 if (*numofforms == 0) {
7209 SAFE_FREE(builtinlist);
7211 return WERR_NO_MORE_ITEMS;
7216 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7217 SAFE_FREE(builtinlist);
7223 /* construct the list of form structures */
7224 for (i=0; i<numbuiltinforms; i++) {
7225 DEBUGADD(6,("Filling form number [%d]\n",i));
7226 fill_form_1(&forms_1[i], &builtinlist[i]);
7229 SAFE_FREE(builtinlist);
7231 for (; i<*numofforms; i++) {
7232 DEBUGADD(6,("Filling form number [%d]\n",i));
7233 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7238 /* check the required size. */
7239 for (i=0; i<numbuiltinforms; i++) {
7240 DEBUGADD(6,("adding form [%d]'s size\n",i));
7241 buffer_size += spoolss_size_form_1(&forms_1[i]);
7243 for (; i<*numofforms; i++) {
7244 DEBUGADD(6,("adding form [%d]'s size\n",i));
7245 buffer_size += spoolss_size_form_1(&forms_1[i]);
7248 *needed=buffer_size;
7250 if (*needed > offered) {
7253 return WERR_INSUFFICIENT_BUFFER;
7256 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7262 /* fill the buffer with the form structures */
7263 for (i=0; i<numbuiltinforms; i++) {
7264 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7265 smb_io_form_1("", buffer, &forms_1[i], 0);
7267 for (; i<*numofforms; i++) {
7268 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7269 smb_io_form_1("", buffer, &forms_1[i], 0);
7278 SAFE_FREE(builtinlist);
7279 return WERR_UNKNOWN_LEVEL;
7283 /****************************************************************************
7284 ****************************************************************************/
7286 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7288 uint32 level = q_u->level;
7289 UNISTR2 *uni_formname = &q_u->formname;
7290 RPC_BUFFER *buffer = NULL;
7291 uint32 offered = q_u->offered;
7292 uint32 *needed = &r_u->needed;
7294 nt_forms_struct *list=NULL;
7295 nt_forms_struct builtin_form;
7300 int numofforms=0, i=0;
7302 /* that's an [in out] buffer */
7304 if (!q_u->buffer && (offered!=0)) {
7305 return WERR_INVALID_PARAM;
7308 rpcbuf_move(q_u->buffer, &r_u->buffer);
7309 buffer = r_u->buffer;
7311 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
7313 DEBUG(4,("_spoolss_getform\n"));
7314 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7315 DEBUGADD(5,("Info level [%d]\n", level));
7317 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7318 if (!foundBuiltin) {
7319 numofforms = get_ntforms(&list);
7320 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7322 if (numofforms == 0)
7329 fill_form_1(&form_1, &builtin_form);
7332 /* Check if the requested name is in the list of form structures */
7333 for (i=0; i<numofforms; i++) {
7335 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7337 if (strequal(form_name, list[i].name)) {
7338 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7339 fill_form_1(&form_1, &list[i]);
7345 if (i == numofforms) {
7349 /* check the required size. */
7351 *needed=spoolss_size_form_1(&form_1);
7353 if (*needed > offered)
7354 return WERR_INSUFFICIENT_BUFFER;
7356 if (!rpcbuf_alloc_size(buffer, buffer_size))
7359 /* fill the buffer with the form structures */
7360 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7361 smb_io_form_1("", buffer, &form_1, 0);
7367 return WERR_UNKNOWN_LEVEL;
7371 /****************************************************************************
7372 ****************************************************************************/
7374 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7376 init_unistr(&port->port_name, name);
7379 /****************************************************************************
7380 TODO: This probably needs distinguish between TCP/IP and Local ports
7382 ****************************************************************************/
7384 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7386 init_unistr(&port->port_name, name);
7387 init_unistr(&port->monitor_name, "Local Monitor");
7388 init_unistr(&port->description, SPL_LOCAL_PORT );
7389 port->port_type=PORT_TYPE_WRITE;
7394 /****************************************************************************
7395 wrapper around the enumer ports command
7396 ****************************************************************************/
7398 WERROR enumports_hook( int *count, char ***lines )
7400 char *cmd = lp_enumports_cmd();
7410 /* if no hook then just fill in the default port */
7413 if (!(qlines = SMB_MALLOC_ARRAY( char*, 2 ))) {
7416 if (!(qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME ))) {
7424 /* we have a valid enumport command */
7426 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7428 DEBUG(10,("Running [%s]\n", command));
7429 ret = smbrun(command, &fd);
7430 DEBUG(10,("Returned [%d]\n", ret));
7435 return WERR_ACCESS_DENIED;
7439 qlines = fd_lines_load(fd, &numlines, 0);
7440 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7450 /****************************************************************************
7452 ****************************************************************************/
7454 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7456 PORT_INFO_1 *ports=NULL;
7458 WERROR result = WERR_OK;
7459 char **qlines = NULL;
7462 result = enumports_hook( &numlines, &qlines );
7463 if (!W_ERROR_IS_OK(result)) {
7464 file_lines_free(qlines);
7469 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7470 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7471 dos_errstr(WERR_NOMEM)));
7472 file_lines_free(qlines);
7476 for (i=0; i<numlines; i++) {
7477 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7478 fill_port_1(&ports[i], qlines[i]);
7481 file_lines_free(qlines);
7483 *returned = numlines;
7485 /* check the required size. */
7486 for (i=0; i<*returned; i++) {
7487 DEBUGADD(6,("adding port [%d]'s size\n", i));
7488 *needed += spoolss_size_port_info_1(&ports[i]);
7491 if (*needed > offered) {
7492 result = WERR_INSUFFICIENT_BUFFER;
7496 if (!rpcbuf_alloc_size(buffer, *needed)) {
7497 result = WERR_NOMEM;
7501 /* fill the buffer with the ports structures */
7502 for (i=0; i<*returned; i++) {
7503 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7504 smb_io_port_1("", buffer, &ports[i], 0);
7510 if ( !W_ERROR_IS_OK(result) )
7516 /****************************************************************************
7518 ****************************************************************************/
7520 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7522 PORT_INFO_2 *ports=NULL;
7524 WERROR result = WERR_OK;
7525 char **qlines = NULL;
7528 result = enumports_hook( &numlines, &qlines );
7529 if ( !W_ERROR_IS_OK(result)) {
7530 file_lines_free(qlines);
7535 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7536 file_lines_free(qlines);
7540 for (i=0; i<numlines; i++) {
7541 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7542 fill_port_2(&(ports[i]), qlines[i]);
7546 file_lines_free(qlines);
7548 *returned = numlines;
7550 /* check the required size. */
7551 for (i=0; i<*returned; i++) {
7552 DEBUGADD(6,("adding port [%d]'s size\n", i));
7553 *needed += spoolss_size_port_info_2(&ports[i]);
7556 if (*needed > offered) {
7557 result = WERR_INSUFFICIENT_BUFFER;
7561 if (!rpcbuf_alloc_size(buffer, *needed)) {
7562 result = WERR_NOMEM;
7566 /* fill the buffer with the ports structures */
7567 for (i=0; i<*returned; i++) {
7568 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7569 smb_io_port_2("", buffer, &ports[i], 0);
7575 if ( !W_ERROR_IS_OK(result) )
7581 /****************************************************************************
7583 ****************************************************************************/
7585 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7587 uint32 level = q_u->level;
7588 RPC_BUFFER *buffer = NULL;
7589 uint32 offered = q_u->offered;
7590 uint32 *needed = &r_u->needed;
7591 uint32 *returned = &r_u->returned;
7593 /* that's an [in out] buffer */
7595 if (!q_u->buffer && (offered!=0)) {
7596 return WERR_INVALID_PARAM;
7599 rpcbuf_move(q_u->buffer, &r_u->buffer);
7600 buffer = r_u->buffer;
7602 DEBUG(4,("_spoolss_enumports\n"));
7609 return enumports_level_1(buffer, offered, needed, returned);
7611 return enumports_level_2(buffer, offered, needed, returned);
7613 return WERR_UNKNOWN_LEVEL;
7617 /****************************************************************************
7618 ****************************************************************************/
7620 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7621 const SPOOL_PRINTER_INFO_LEVEL *info,
7622 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7623 uint32 user_switch, const SPOOL_USER_CTR *user,
7626 NT_PRINTER_INFO_LEVEL *printer = NULL;
7629 WERROR err = WERR_OK;
7631 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7632 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7636 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7637 if (!convert_printer_info(info, printer, 2)) {
7638 free_a_printer(&printer, 2);
7642 /* check to see if the printer already exists */
7644 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7645 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7646 printer->info_2->sharename));
7647 free_a_printer(&printer, 2);
7648 return WERR_PRINTER_ALREADY_EXISTS;
7651 /* FIXME!!! smbd should check to see if the driver is installed before
7652 trying to add a printer like this --jerry */
7654 if (*lp_addprinter_cmd() ) {
7655 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7656 free_a_printer(&printer,2);
7657 return WERR_ACCESS_DENIED;
7660 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7661 "smb.conf parameter \"addprinter command\" is defined. This"
7662 "parameter must exist for this call to succeed\n",
7663 printer->info_2->sharename ));
7666 /* use our primary netbios name since get_a_printer() will convert
7667 it to what the client expects on a case by case basis */
7669 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7670 printer->info_2->sharename);
7673 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7674 free_a_printer(&printer,2);
7675 return WERR_ACCESS_DENIED;
7678 /* you must be a printer admin to add a new printer */
7679 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7680 free_a_printer(&printer,2);
7681 return WERR_ACCESS_DENIED;
7685 * Do sanity check on the requested changes for Samba.
7688 if (!check_printer_ok(printer->info_2, snum)) {
7689 free_a_printer(&printer,2);
7690 return WERR_INVALID_PARAM;
7694 * When a printer is created, the drivername bound to the printer is used
7695 * to lookup previously saved driver initialization info, which is then
7696 * bound to the new printer, simulating what happens in the Windows arch.
7701 set_driver_init(printer, 2);
7705 /* A valid devmode was included, convert and link it
7707 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7709 if (!convert_devicemode(printer->info_2->printername, devmode,
7710 &printer->info_2->devmode))
7714 /* write the ASCII on disk */
7715 err = mod_a_printer(printer, 2);
7716 if (!W_ERROR_IS_OK(err)) {
7717 free_a_printer(&printer,2);
7721 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7722 /* Handle open failed - remove addition. */
7723 del_a_printer(printer->info_2->sharename);
7724 free_a_printer(&printer,2);
7725 return WERR_ACCESS_DENIED;
7728 update_c_setprinter(False);
7729 free_a_printer(&printer,2);
7734 /****************************************************************************
7735 ****************************************************************************/
7737 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7739 UNISTR2 *uni_srv_name = q_u->server_name;
7740 uint32 level = q_u->level;
7741 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7742 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7743 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7744 uint32 user_switch = q_u->user_switch;
7745 SPOOL_USER_CTR *user = &q_u->user_ctr;
7746 POLICY_HND *handle = &r_u->handle;
7750 /* we don't handle yet */
7751 /* but I know what to do ... */
7752 return WERR_UNKNOWN_LEVEL;
7754 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7756 user_switch, user, handle);
7758 return WERR_UNKNOWN_LEVEL;
7762 /****************************************************************************
7763 ****************************************************************************/
7765 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7767 uint32 level = q_u->level;
7768 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7769 WERROR err = WERR_OK;
7770 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7771 fstring driver_name;
7774 ZERO_STRUCT(driver);
7776 if (!convert_printer_driver_info(info, &driver, level)) {
7781 DEBUG(5,("Cleaning driver's information\n"));
7782 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7783 if (!W_ERROR_IS_OK(err))
7786 DEBUG(5,("Moving driver to final destination\n"));
7787 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7791 if (add_a_printer_driver(driver, level)!=0) {
7792 err = WERR_ACCESS_DENIED;
7797 * I think this is where he DrvUpgradePrinter() hook would be
7798 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7799 * server. Right now, we just need to send ourselves a message
7800 * to update each printer bound to this driver. --jerry
7803 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7804 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7809 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7810 * decide if the driver init data should be deleted. The rules are:
7811 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7812 * 2) delete init data only if there is no 2k/Xp driver
7813 * 3) always delete init data
7814 * The generalized rule is always use init data from the highest order driver.
7815 * It is necessary to follow the driver install by an initialization step to
7816 * finish off this process.
7819 version = driver.info_3->cversion;
7820 else if (level == 6)
7821 version = driver.info_6->version;
7826 * 9x printer driver - never delete init data
7829 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7834 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7835 * there is no 2k/Xp driver init data for this driver name.
7839 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7841 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7843 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7845 if (!del_driver_init(driver_name))
7846 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7849 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7851 free_a_printer_driver(driver1,3);
7852 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7859 * 2k or Xp printer driver - always delete init data
7862 if (!del_driver_init(driver_name))
7863 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7867 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7873 free_a_printer_driver(driver, level);
7877 /********************************************************************
7878 * spoolss_addprinterdriverex
7879 ********************************************************************/
7881 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7883 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7884 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7887 * we only support the semantics of AddPrinterDriver()
7888 * i.e. only copy files that are newer than existing ones
7891 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7892 return WERR_ACCESS_DENIED;
7894 ZERO_STRUCT(q_u_local);
7895 ZERO_STRUCT(r_u_local);
7897 /* just pass the information off to _spoolss_addprinterdriver() */
7898 q_u_local.server_name_ptr = q_u->server_name_ptr;
7899 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7900 q_u_local.level = q_u->level;
7901 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7903 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7906 /****************************************************************************
7907 ****************************************************************************/
7909 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7911 init_unistr(&info->name, name);
7914 /****************************************************************************
7915 ****************************************************************************/
7917 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7923 const char *short_archi;
7924 DRIVER_DIRECTORY_1 *info=NULL;
7925 WERROR result = WERR_OK;
7927 unistr2_to_ascii(servername, name, sizeof(servername));
7928 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi));
7930 /* check for beginning double '\'s and that the server
7933 pservername = servername;
7934 if ( *pservername == '\\' && strlen(servername)>2 ) {
7938 if ( !is_myname_or_ipaddr( pservername ) )
7939 return WERR_INVALID_PARAM;
7941 if (!(short_archi = get_short_archi(long_archi)))
7942 return WERR_INVALID_ENVIRONMENT;
7944 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7947 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7949 DEBUG(4,("printer driver directory: [%s]\n", path));
7951 fill_driverdir_1(info, path);
7953 *needed += spoolss_size_driverdir_info_1(info);
7955 if (*needed > offered) {
7956 result = WERR_INSUFFICIENT_BUFFER;
7960 if (!rpcbuf_alloc_size(buffer, *needed)) {
7961 result = WERR_NOMEM;
7965 smb_io_driverdir_1("", buffer, info, 0);
7973 /****************************************************************************
7974 ****************************************************************************/
7976 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7978 UNISTR2 *name = &q_u->name;
7979 UNISTR2 *uni_environment = &q_u->environment;
7980 uint32 level = q_u->level;
7981 RPC_BUFFER *buffer = NULL;
7982 uint32 offered = q_u->offered;
7983 uint32 *needed = &r_u->needed;
7985 /* that's an [in out] buffer */
7987 if (!q_u->buffer && (offered!=0)) {
7988 return WERR_INVALID_PARAM;
7991 rpcbuf_move(q_u->buffer, &r_u->buffer);
7992 buffer = r_u->buffer;
7994 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8000 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8002 return WERR_UNKNOWN_LEVEL;
8006 /****************************************************************************
8007 ****************************************************************************/
8009 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8011 POLICY_HND *handle = &q_u->handle;
8012 uint32 idx = q_u->index;
8013 uint32 in_value_len = q_u->valuesize;
8014 uint32 in_data_len = q_u->datasize;
8015 uint32 *out_max_value_len = &r_u->valuesize;
8016 uint16 **out_value = &r_u->value;
8017 uint32 *out_value_len = &r_u->realvaluesize;
8018 uint32 *out_type = &r_u->type;
8019 uint32 *out_max_data_len = &r_u->datasize;
8020 uint8 **data_out = &r_u->data;
8021 uint32 *out_data_len = &r_u->realdatasize;
8023 NT_PRINTER_INFO_LEVEL *printer = NULL;
8025 uint32 biggest_valuesize;
8026 uint32 biggest_datasize;
8028 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8031 REGISTRY_VALUE *val = NULL;
8032 NT_PRINTER_DATA *p_data;
8033 int i, key_index, num_values;
8038 *out_max_data_len = 0;
8042 DEBUG(5,("spoolss_enumprinterdata\n"));
8045 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8049 if (!get_printer_snum(p,handle, &snum, NULL))
8052 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8053 if (!W_ERROR_IS_OK(result))
8056 p_data = printer->info_2->data;
8057 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8062 * The NT machine wants to know the biggest size of value and data
8064 * cf: MSDN EnumPrinterData remark section
8067 if ( !in_value_len && !in_data_len && (key_index != -1) )
8069 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8071 biggest_valuesize = 0;
8072 biggest_datasize = 0;
8074 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8076 for ( i=0; i<num_values; i++ )
8078 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8080 name_length = strlen(val->valuename);
8081 if ( strlen(val->valuename) > biggest_valuesize )
8082 biggest_valuesize = name_length;
8084 if ( val->size > biggest_datasize )
8085 biggest_datasize = val->size;
8087 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8091 /* the value is an UNICODE string but real_value_size is the length
8092 in bytes including the trailing 0 */
8094 *out_value_len = 2 * (1+biggest_valuesize);
8095 *out_data_len = biggest_datasize;
8097 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8103 * the value len is wrong in NT sp3
8104 * that's the number of bytes not the number of unicode chars
8107 if ( key_index != -1 )
8108 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8113 /* out_value should default to "" or else NT4 has
8114 problems unmarshalling the response */
8116 *out_max_value_len=(in_value_len/sizeof(uint16));
8119 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8121 result = WERR_NOMEM;
8124 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8130 /* the data is counted in bytes */
8132 *out_max_data_len = in_data_len;
8133 *out_data_len = in_data_len;
8135 /* only allocate when given a non-zero data_len */
8137 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8139 result = WERR_NOMEM;
8143 result = WERR_NO_MORE_ITEMS;
8149 * - counted in bytes in the request
8150 * - counted in UNICODE chars in the max reply
8151 * - counted in bytes in the real size
8153 * take a pause *before* coding not *during* coding
8157 *out_max_value_len=(in_value_len/sizeof(uint16));
8159 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8161 result = WERR_NOMEM;
8165 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8173 *out_type = regval_type( val );
8175 /* data - counted in bytes */
8177 *out_max_data_len = in_data_len;
8178 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8180 result = WERR_NOMEM;
8183 data_len = regval_size(val);
8184 if ( *data_out && data_len )
8185 memcpy( *data_out, regval_data_p(val), data_len );
8186 *out_data_len = data_len;
8190 free_a_printer(&printer, 2);
8194 /****************************************************************************
8195 ****************************************************************************/
8197 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8199 POLICY_HND *handle = &q_u->handle;
8200 UNISTR2 *value = &q_u->value;
8201 uint32 type = q_u->type;
8202 uint8 *data = q_u->data;
8203 uint32 real_len = q_u->real_len;
8205 NT_PRINTER_INFO_LEVEL *printer = NULL;
8207 WERROR status = WERR_OK;
8208 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8211 DEBUG(5,("spoolss_setprinterdata\n"));
8214 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8218 if ( Printer->printer_type == SPLHND_SERVER ) {
8219 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8220 return WERR_INVALID_PARAM;
8223 if (!get_printer_snum(p,handle, &snum, NULL))
8227 * Access check : NT returns "access denied" if you make a
8228 * SetPrinterData call without the necessary privildge.
8229 * we were originally returning OK if nothing changed
8230 * which made Win2k issue **a lot** of SetPrinterData
8231 * when connecting to a printer --jerry
8234 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8236 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8237 status = WERR_ACCESS_DENIED;
8241 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8242 if (!W_ERROR_IS_OK(status))
8245 unistr2_to_ascii(valuename, value, sizeof(valuename));
8248 * When client side code sets a magic printer data key, detect it and save
8249 * the current printer data and the magic key's data (its the DEVMODE) for
8250 * future printer/driver initializations.
8252 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8254 /* Set devmode and printer initialization info */
8255 status = save_driver_init( printer, 2, data, real_len );
8257 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8261 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8262 type, data, real_len );
8263 if ( W_ERROR_IS_OK(status) )
8264 status = mod_a_printer(printer, 2);
8268 free_a_printer(&printer, 2);
8273 /****************************************************************************
8274 ****************************************************************************/
8276 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8278 POLICY_HND *handle = &q_u->handle;
8279 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8282 DEBUG(5,("_spoolss_resetprinter\n"));
8285 * All we do is to check to see if the handle and queue is valid.
8286 * This call really doesn't mean anything to us because we only
8287 * support RAW printing. --jerry
8291 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8295 if (!get_printer_snum(p,handle, &snum, NULL))
8299 /* blindly return success */
8304 /****************************************************************************
8305 ****************************************************************************/
8307 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8309 POLICY_HND *handle = &q_u->handle;
8310 UNISTR2 *value = &q_u->valuename;
8312 NT_PRINTER_INFO_LEVEL *printer = NULL;
8314 WERROR status = WERR_OK;
8315 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8318 DEBUG(5,("spoolss_deleteprinterdata\n"));
8321 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8325 if (!get_printer_snum(p, handle, &snum, NULL))
8328 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8329 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8330 return WERR_ACCESS_DENIED;
8333 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8334 if (!W_ERROR_IS_OK(status))
8337 unistr2_to_ascii(valuename, value, sizeof(valuename));
8339 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8341 if ( W_ERROR_IS_OK(status) )
8342 mod_a_printer( printer, 2 );
8344 free_a_printer(&printer, 2);
8349 /****************************************************************************
8350 ****************************************************************************/
8352 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8354 POLICY_HND *handle = &q_u->handle;
8355 FORM *form = &q_u->form;
8356 nt_forms_struct tmpForm;
8358 WERROR status = WERR_OK;
8359 NT_PRINTER_INFO_LEVEL *printer = NULL;
8362 nt_forms_struct *list=NULL;
8363 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8365 DEBUG(5,("spoolss_addform\n"));
8368 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8373 /* forms can be added on printer of on the print server handle */
8375 if ( Printer->printer_type == SPLHND_PRINTER )
8377 if (!get_printer_snum(p,handle, &snum, NULL))
8380 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8381 if (!W_ERROR_IS_OK(status))
8385 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8386 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8387 status = WERR_ACCESS_DENIED;
8391 /* can't add if builtin */
8393 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8394 status = WERR_ALREADY_EXISTS;
8398 count = get_ntforms(&list);
8400 if(!add_a_form(&list, form, &count)) {
8401 status = WERR_NOMEM;
8405 write_ntforms(&list, count);
8408 * ChangeID must always be set if this is a printer
8411 if ( Printer->printer_type == SPLHND_PRINTER )
8412 status = mod_a_printer(printer, 2);
8416 free_a_printer(&printer, 2);
8422 /****************************************************************************
8423 ****************************************************************************/
8425 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8427 POLICY_HND *handle = &q_u->handle;
8428 UNISTR2 *form_name = &q_u->name;
8429 nt_forms_struct tmpForm;
8431 nt_forms_struct *list=NULL;
8432 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8434 WERROR status = WERR_OK;
8435 NT_PRINTER_INFO_LEVEL *printer = NULL;
8437 DEBUG(5,("spoolss_deleteform\n"));
8440 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8444 /* forms can be deleted on printer of on the print server handle */
8446 if ( Printer->printer_type == SPLHND_PRINTER )
8448 if (!get_printer_snum(p,handle, &snum, NULL))
8451 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8452 if (!W_ERROR_IS_OK(status))
8456 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8457 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8458 status = WERR_ACCESS_DENIED;
8462 /* can't delete if builtin */
8464 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8465 status = WERR_INVALID_PARAM;
8469 count = get_ntforms(&list);
8471 if ( !delete_a_form(&list, form_name, &count, &status ))
8475 * ChangeID must always be set if this is a printer
8478 if ( Printer->printer_type == SPLHND_PRINTER )
8479 status = mod_a_printer(printer, 2);
8483 free_a_printer(&printer, 2);
8489 /****************************************************************************
8490 ****************************************************************************/
8492 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8494 POLICY_HND *handle = &q_u->handle;
8495 FORM *form = &q_u->form;
8496 nt_forms_struct tmpForm;
8498 WERROR status = WERR_OK;
8499 NT_PRINTER_INFO_LEVEL *printer = NULL;
8502 nt_forms_struct *list=NULL;
8503 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8505 DEBUG(5,("spoolss_setform\n"));
8508 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8512 /* forms can be modified on printer of on the print server handle */
8514 if ( Printer->printer_type == SPLHND_PRINTER )
8516 if (!get_printer_snum(p,handle, &snum, NULL))
8519 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8520 if (!W_ERROR_IS_OK(status))
8524 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8525 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8526 status = WERR_ACCESS_DENIED;
8530 /* can't set if builtin */
8531 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8532 status = WERR_INVALID_PARAM;
8536 count = get_ntforms(&list);
8537 update_a_form(&list, form, count);
8538 write_ntforms(&list, count);
8541 * ChangeID must always be set if this is a printer
8544 if ( Printer->printer_type == SPLHND_PRINTER )
8545 status = mod_a_printer(printer, 2);
8550 free_a_printer(&printer, 2);
8556 /****************************************************************************
8557 enumprintprocessors level 1.
8558 ****************************************************************************/
8560 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8562 PRINTPROCESSOR_1 *info_1=NULL;
8563 WERROR result = WERR_OK;
8565 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8570 init_unistr(&info_1->name, "winprint");
8572 *needed += spoolss_size_printprocessor_info_1(info_1);
8574 if (*needed > offered) {
8575 result = WERR_INSUFFICIENT_BUFFER;
8579 if (!rpcbuf_alloc_size(buffer, *needed)) {
8580 result = WERR_NOMEM;
8584 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8589 if ( !W_ERROR_IS_OK(result) )
8595 /****************************************************************************
8596 ****************************************************************************/
8598 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8600 uint32 level = q_u->level;
8601 RPC_BUFFER *buffer = NULL;
8602 uint32 offered = q_u->offered;
8603 uint32 *needed = &r_u->needed;
8604 uint32 *returned = &r_u->returned;
8606 /* that's an [in out] buffer */
8608 if (!q_u->buffer && (offered!=0)) {
8609 return WERR_INVALID_PARAM;
8612 rpcbuf_move(q_u->buffer, &r_u->buffer);
8613 buffer = r_u->buffer;
8615 DEBUG(5,("spoolss_enumprintprocessors\n"));
8618 * Enumerate the print processors ...
8620 * Just reply with "winprint", to keep NT happy
8621 * and I can use my nice printer checker.
8629 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8631 return WERR_UNKNOWN_LEVEL;
8635 /****************************************************************************
8636 enumprintprocdatatypes level 1.
8637 ****************************************************************************/
8639 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8641 PRINTPROCDATATYPE_1 *info_1=NULL;
8642 WERROR result = WERR_OK;
8644 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8649 init_unistr(&info_1->name, "RAW");
8651 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8653 if (*needed > offered) {
8654 result = WERR_INSUFFICIENT_BUFFER;
8658 if (!rpcbuf_alloc_size(buffer, *needed)) {
8659 result = WERR_NOMEM;
8663 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8668 if ( !W_ERROR_IS_OK(result) )
8674 /****************************************************************************
8675 ****************************************************************************/
8677 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8679 uint32 level = q_u->level;
8680 RPC_BUFFER *buffer = NULL;
8681 uint32 offered = q_u->offered;
8682 uint32 *needed = &r_u->needed;
8683 uint32 *returned = &r_u->returned;
8685 /* that's an [in out] buffer */
8687 if (!q_u->buffer && (offered!=0)) {
8688 return WERR_INVALID_PARAM;
8691 rpcbuf_move(q_u->buffer, &r_u->buffer);
8692 buffer = r_u->buffer;
8694 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8701 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8703 return WERR_UNKNOWN_LEVEL;
8707 /****************************************************************************
8708 enumprintmonitors level 1.
8709 ****************************************************************************/
8711 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8713 PRINTMONITOR_1 *info_1;
8714 WERROR result = WERR_OK;
8717 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8722 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8723 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8725 for ( i=0; i<*returned; i++ ) {
8726 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8729 if (*needed > offered) {
8730 result = WERR_INSUFFICIENT_BUFFER;
8734 if (!rpcbuf_alloc_size(buffer, *needed)) {
8735 result = WERR_NOMEM;
8739 for ( i=0; i<*returned; i++ ) {
8740 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8746 if ( !W_ERROR_IS_OK(result) )
8752 /****************************************************************************
8753 enumprintmonitors level 2.
8754 ****************************************************************************/
8756 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8758 PRINTMONITOR_2 *info_2;
8759 WERROR result = WERR_OK;
8762 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8767 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8768 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8769 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8771 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8772 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8773 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8775 for ( i=0; i<*returned; i++ ) {
8776 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8779 if (*needed > offered) {
8780 result = WERR_INSUFFICIENT_BUFFER;
8784 if (!rpcbuf_alloc_size(buffer, *needed)) {
8785 result = WERR_NOMEM;
8789 for ( i=0; i<*returned; i++ ) {
8790 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8796 if ( !W_ERROR_IS_OK(result) )
8802 /****************************************************************************
8803 ****************************************************************************/
8805 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8807 uint32 level = q_u->level;
8808 RPC_BUFFER *buffer = NULL;
8809 uint32 offered = q_u->offered;
8810 uint32 *needed = &r_u->needed;
8811 uint32 *returned = &r_u->returned;
8813 /* that's an [in out] buffer */
8815 if (!q_u->buffer && (offered!=0)) {
8816 return WERR_INVALID_PARAM;
8819 rpcbuf_move(q_u->buffer, &r_u->buffer);
8820 buffer = r_u->buffer;
8822 DEBUG(5,("spoolss_enumprintmonitors\n"));
8825 * Enumerate the print monitors ...
8827 * Just reply with "Local Port", to keep NT happy
8828 * and I can use my nice printer checker.
8836 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8838 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8840 return WERR_UNKNOWN_LEVEL;
8844 /****************************************************************************
8845 ****************************************************************************/
8847 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8848 NT_PRINTER_INFO_LEVEL *ntprinter,
8849 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8854 JOB_INFO_1 *info_1=NULL;
8855 WERROR result = WERR_OK;
8857 info_1=SMB_MALLOC_P(JOB_INFO_1);
8859 if (info_1 == NULL) {
8863 for (i=0; i<count && found==False; i++) {
8864 if ((*queue)[i].job==(int)jobid)
8870 /* NT treats not found as bad param... yet another bad choice */
8871 return WERR_INVALID_PARAM;
8874 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8876 *needed += spoolss_size_job_info_1(info_1);
8878 if (*needed > offered) {
8879 result = WERR_INSUFFICIENT_BUFFER;
8883 if (!rpcbuf_alloc_size(buffer, *needed)) {
8884 result = WERR_NOMEM;
8888 smb_io_job_info_1("", buffer, info_1, 0);
8896 /****************************************************************************
8897 ****************************************************************************/
8899 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8900 NT_PRINTER_INFO_LEVEL *ntprinter,
8901 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8908 DEVICEMODE *devmode = NULL;
8909 NT_DEVICEMODE *nt_devmode = NULL;
8911 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8914 ZERO_STRUCTP(info_2);
8916 for ( i=0; i<count && found==False; i++ )
8918 if ((*queue)[i].job == (int)jobid)
8923 /* NT treats not found as bad param... yet another bad
8925 result = WERR_INVALID_PARAM;
8930 * if the print job does not have a DEVMODE associated with it,
8931 * just use the one for the printer. A NULL devicemode is not
8932 * a failure condition
8935 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8936 devmode = construct_dev_mode(lp_const_servicename(snum));
8938 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8939 ZERO_STRUCTP( devmode );
8940 convert_nt_devicemode( devmode, nt_devmode );
8944 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8946 *needed += spoolss_size_job_info_2(info_2);
8948 if (*needed > offered) {
8949 result = WERR_INSUFFICIENT_BUFFER;
8953 if (!rpcbuf_alloc_size(buffer, *needed)) {
8954 result = WERR_NOMEM;
8958 smb_io_job_info_2("", buffer, info_2, 0);
8963 /* Cleanup allocated memory */
8965 free_job_info_2(info_2); /* Also frees devmode */
8971 /****************************************************************************
8972 ****************************************************************************/
8974 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8976 POLICY_HND *handle = &q_u->handle;
8977 uint32 jobid = q_u->jobid;
8978 uint32 level = q_u->level;
8979 RPC_BUFFER *buffer = NULL;
8980 uint32 offered = q_u->offered;
8981 uint32 *needed = &r_u->needed;
8982 WERROR wstatus = WERR_OK;
8983 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8986 print_queue_struct *queue = NULL;
8987 print_status_struct prt_status;
8989 /* that's an [in out] buffer */
8991 if (!q_u->buffer && (offered!=0)) {
8992 return WERR_INVALID_PARAM;
8995 rpcbuf_move(q_u->buffer, &r_u->buffer);
8996 buffer = r_u->buffer;
8998 DEBUG(5,("spoolss_getjob\n"));
9002 if (!get_printer_snum(p, handle, &snum, NULL))
9005 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9006 if ( !W_ERROR_IS_OK(wstatus) )
9009 count = print_queue_status(snum, &queue, &prt_status);
9011 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9012 count, prt_status.status, prt_status.message));
9016 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9017 buffer, offered, needed);
9020 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9021 buffer, offered, needed);
9024 wstatus = WERR_UNKNOWN_LEVEL;
9029 free_a_printer( &ntprinter, 2 );
9034 /********************************************************************
9035 spoolss_getprinterdataex
9037 From MSDN documentation of GetPrinterDataEx: pass request
9038 to GetPrinterData if key is "PrinterDriverData".
9039 ********************************************************************/
9041 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9043 POLICY_HND *handle = &q_u->handle;
9044 uint32 in_size = q_u->size;
9045 uint32 *type = &r_u->type;
9046 uint32 *out_size = &r_u->size;
9047 uint8 **data = &r_u->data;
9048 uint32 *needed = &r_u->needed;
9049 fstring keyname, valuename;
9051 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9053 NT_PRINTER_INFO_LEVEL *printer = NULL;
9055 WERROR status = WERR_OK;
9057 DEBUG(4,("_spoolss_getprinterdataex\n"));
9059 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname));
9060 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename));
9062 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9063 keyname, valuename));
9065 /* in case of problem, return some default values */
9069 *out_size = in_size;
9072 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9073 status = WERR_BADFID;
9077 /* Is the handle to a printer or to the server? */
9079 if (Printer->printer_type == SPLHND_SERVER) {
9080 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9081 status = WERR_INVALID_PARAM;
9085 if ( !get_printer_snum(p,handle, &snum, NULL) )
9088 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9089 if ( !W_ERROR_IS_OK(status) )
9092 /* check to see if the keyname is valid */
9093 if ( !strlen(keyname) ) {
9094 status = WERR_INVALID_PARAM;
9098 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9099 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9100 free_a_printer( &printer, 2 );
9101 status = WERR_BADFILE;
9105 /* When given a new keyname, we should just create it */
9107 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9109 if (*needed > *out_size)
9110 status = WERR_MORE_DATA;
9113 if ( !W_ERROR_IS_OK(status) )
9115 DEBUG(5, ("error: allocating %d\n", *out_size));
9117 /* reply this param doesn't exist */
9121 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9122 status = WERR_NOMEM;
9131 free_a_printer( &printer, 2 );
9136 /********************************************************************
9137 * spoolss_setprinterdataex
9138 ********************************************************************/
9140 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9142 POLICY_HND *handle = &q_u->handle;
9143 uint32 type = q_u->type;
9144 uint8 *data = q_u->data;
9145 uint32 real_len = q_u->real_len;
9147 NT_PRINTER_INFO_LEVEL *printer = NULL;
9149 WERROR status = WERR_OK;
9150 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9155 DEBUG(4,("_spoolss_setprinterdataex\n"));
9157 /* From MSDN documentation of SetPrinterDataEx: pass request to
9158 SetPrinterData if key is "PrinterDriverData" */
9161 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9165 if ( Printer->printer_type == SPLHND_SERVER ) {
9166 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9167 return WERR_INVALID_PARAM;
9170 if ( !get_printer_snum(p,handle, &snum, NULL) )
9174 * Access check : NT returns "access denied" if you make a
9175 * SetPrinterData call without the necessary privildge.
9176 * we were originally returning OK if nothing changed
9177 * which made Win2k issue **a lot** of SetPrinterData
9178 * when connecting to a printer --jerry
9181 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9183 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9184 return WERR_ACCESS_DENIED;
9187 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9188 if (!W_ERROR_IS_OK(status))
9191 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename));
9192 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname));
9194 /* check for OID in valuename */
9196 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9202 /* save the registry data */
9204 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9206 if ( W_ERROR_IS_OK(status) )
9208 /* save the OID if one was specified */
9210 fstrcat( keyname, "\\" );
9211 fstrcat( keyname, SPOOL_OID_KEY );
9214 * I'm not checking the status here on purpose. Don't know
9215 * if this is right, but I'm returning the status from the
9216 * previous set_printer_dataex() call. I have no idea if
9217 * this is right. --jerry
9220 set_printer_dataex( printer, keyname, valuename,
9221 REG_SZ, (uint8 *)oid_string,
9222 strlen(oid_string)+1 );
9225 status = mod_a_printer(printer, 2);
9228 free_a_printer(&printer, 2);
9234 /********************************************************************
9235 * spoolss_deleteprinterdataex
9236 ********************************************************************/
9238 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9240 POLICY_HND *handle = &q_u->handle;
9241 UNISTR2 *value = &q_u->valuename;
9242 UNISTR2 *key = &q_u->keyname;
9244 NT_PRINTER_INFO_LEVEL *printer = NULL;
9246 WERROR status = WERR_OK;
9247 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9248 pstring valuename, keyname;
9250 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9253 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9257 if (!get_printer_snum(p, handle, &snum, NULL))
9260 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9261 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9262 return WERR_ACCESS_DENIED;
9265 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9266 if (!W_ERROR_IS_OK(status))
9269 unistr2_to_ascii(valuename, value, sizeof(valuename));
9270 unistr2_to_ascii(keyname, key, sizeof(keyname));
9272 status = delete_printer_dataex( printer, keyname, valuename );
9274 if ( W_ERROR_IS_OK(status) )
9275 mod_a_printer( printer, 2 );
9277 free_a_printer(&printer, 2);
9282 /********************************************************************
9283 * spoolss_enumprinterkey
9284 ********************************************************************/
9287 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9290 fstring *keynames = NULL;
9291 uint16 *enumkeys = NULL;
9294 POLICY_HND *handle = &q_u->handle;
9295 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9296 NT_PRINTER_DATA *data;
9297 NT_PRINTER_INFO_LEVEL *printer = NULL;
9299 WERROR status = WERR_BADFILE;
9302 DEBUG(4,("_spoolss_enumprinterkey\n"));
9305 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9309 if ( !get_printer_snum(p,handle, &snum, NULL) )
9312 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9313 if (!W_ERROR_IS_OK(status))
9316 /* get the list of subkey names */
9318 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9319 data = printer->info_2->data;
9321 num_keys = get_printer_subkeys( data, key, &keynames );
9323 if ( num_keys == -1 ) {
9324 status = WERR_BADFILE;
9328 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9330 r_u->needed = printerkey_len*2;
9332 if ( q_u->size < r_u->needed ) {
9333 status = WERR_MORE_DATA;
9337 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9338 status = WERR_NOMEM;
9344 if ( q_u->size < r_u->needed )
9345 status = WERR_MORE_DATA;
9348 free_a_printer( &printer, 2 );
9349 SAFE_FREE( keynames );
9354 /********************************************************************
9355 * spoolss_deleteprinterkey
9356 ********************************************************************/
9358 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9360 POLICY_HND *handle = &q_u->handle;
9361 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9363 NT_PRINTER_INFO_LEVEL *printer = NULL;
9367 DEBUG(5,("spoolss_deleteprinterkey\n"));
9370 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9374 /* if keyname == NULL, return error */
9376 if ( !q_u->keyname.buffer )
9377 return WERR_INVALID_PARAM;
9379 if (!get_printer_snum(p, handle, &snum, NULL))
9382 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9383 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9384 return WERR_ACCESS_DENIED;
9387 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9388 if (!W_ERROR_IS_OK(status))
9391 /* delete the key and all subneys */
9393 unistr2_to_ascii(key, &q_u->keyname, sizeof(key));
9395 status = delete_all_printer_data( printer->info_2, key );
9397 if ( W_ERROR_IS_OK(status) )
9398 status = mod_a_printer(printer, 2);
9400 free_a_printer( &printer, 2 );
9406 /********************************************************************
9407 * spoolss_enumprinterdataex
9408 ********************************************************************/
9410 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9412 POLICY_HND *handle = &q_u->handle;
9413 uint32 in_size = q_u->size;
9416 NT_PRINTER_INFO_LEVEL *printer = NULL;
9417 PRINTER_ENUM_VALUES *enum_values = NULL;
9418 NT_PRINTER_DATA *p_data;
9420 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9425 REGISTRY_VALUE *val;
9430 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9433 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9438 * first check for a keyname of NULL or "". Win2k seems to send
9439 * this a lot and we should send back WERR_INVALID_PARAM
9440 * no need to spend time looking up the printer in this case.
9444 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9445 if ( !strlen(key) ) {
9446 result = WERR_INVALID_PARAM;
9450 /* get the printer off of disk */
9452 if (!get_printer_snum(p,handle, &snum, NULL))
9455 ZERO_STRUCT(printer);
9456 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9457 if (!W_ERROR_IS_OK(result))
9460 /* now look for a match on the key name */
9462 p_data = printer->info_2->data;
9464 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9465 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9467 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9468 result = WERR_INVALID_PARAM;
9475 /* allocate the memory for the array of pointers -- if necessary */
9477 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9480 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9482 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9483 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9484 result = WERR_NOMEM;
9488 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9492 * loop through all params and build the array to pass
9493 * back to the client
9496 for ( i=0; i<num_entries; i++ )
9498 /* lookup the registry value */
9500 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9501 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9505 value_name = regval_name( val );
9506 init_unistr( &enum_values[i].valuename, value_name );
9507 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9508 enum_values[i].type = regval_type( val );
9510 data_len = regval_size( val );
9512 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9514 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9516 result = WERR_NOMEM;
9520 enum_values[i].data_len = data_len;
9522 /* keep track of the size of the array in bytes */
9524 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9527 /* housekeeping information in the reply */
9529 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9530 * the hand marshalled container size is a multiple
9531 * of 4 bytes for RPC alignment.
9535 needed += 4-(needed % 4);
9538 r_u->needed = needed;
9539 r_u->returned = num_entries;
9541 if (needed > in_size) {
9542 result = WERR_MORE_DATA;
9546 /* copy data into the reply */
9548 r_u->ctr.size = r_u->needed;
9550 r_u->ctr.size_of_array = r_u->returned;
9551 r_u->ctr.values = enum_values;
9557 free_a_printer(&printer, 2);
9562 /****************************************************************************
9563 ****************************************************************************/
9565 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9567 init_unistr(&info->name, name);
9570 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9571 UNISTR2 *environment,
9578 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9579 WERROR result = WERR_OK;
9581 unistr2_to_ascii(long_archi, environment, sizeof(long_archi));
9583 if (!get_short_archi(long_archi))
9584 return WERR_INVALID_ENVIRONMENT;
9586 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9589 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9591 fill_printprocessordirectory_1(info, path);
9593 *needed += spoolss_size_printprocessordirectory_info_1(info);
9595 if (*needed > offered) {
9596 result = WERR_INSUFFICIENT_BUFFER;
9600 if (!rpcbuf_alloc_size(buffer, *needed)) {
9601 result = WERR_INSUFFICIENT_BUFFER;
9605 smb_io_printprocessordirectory_1("", buffer, info, 0);
9613 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9615 uint32 level = q_u->level;
9616 RPC_BUFFER *buffer = NULL;
9617 uint32 offered = q_u->offered;
9618 uint32 *needed = &r_u->needed;
9621 /* that's an [in out] buffer */
9623 if (!q_u->buffer && (offered!=0)) {
9624 return WERR_INVALID_PARAM;
9627 rpcbuf_move(q_u->buffer, &r_u->buffer);
9628 buffer = r_u->buffer;
9630 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9636 result = getprintprocessordirectory_level_1
9637 (&q_u->name, &q_u->environment, buffer, offered, needed);
9640 result = WERR_UNKNOWN_LEVEL;
9646 /*******************************************************************
9647 Streams the monitor UI DLL name in UNICODE
9648 *******************************************************************/
9650 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9651 RPC_BUFFER *out, uint32 *needed )
9653 const char *dllname = "tcpmonui.dll";
9655 *needed = (strlen(dllname)+1) * 2;
9657 if ( rpcbuf_get_size(out) < *needed ) {
9658 return WERR_INSUFFICIENT_BUFFER;
9661 if ( !make_monitorui_buf( out, dllname ) ) {
9668 /*******************************************************************
9669 Create a new TCP/IP port
9670 *******************************************************************/
9672 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9673 RPC_BUFFER *out, uint32 *needed )
9675 NT_PORT_DATA_1 port1;
9678 ZERO_STRUCT( port1 );
9680 /* convert to our internal port data structure */
9682 if ( !convert_port_data_1( &port1, in ) ) {
9686 /* create the device URI and call the add_port_hook() */
9688 switch ( port1.protocol ) {
9689 case PORT_PROTOCOL_DIRECT:
9690 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9693 case PORT_PROTOCOL_LPR:
9694 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9698 return WERR_UNKNOWN_PORT;
9701 return add_port_hook( token, port1.name, device_uri );
9704 /*******************************************************************
9705 *******************************************************************/
9707 struct xcv_api_table xcvtcp_cmds[] = {
9708 { "MonitorUI", xcvtcp_monitorui },
9709 { "AddPort", xcvtcp_addport},
9713 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9714 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9719 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9721 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9722 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9723 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9726 return WERR_BADFUNC;
9729 /*******************************************************************
9730 *******************************************************************/
9731 #if 0 /* don't support management using the "Local Port" monitor */
9733 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9734 RPC_BUFFER *out, uint32 *needed )
9736 const char *dllname = "localui.dll";
9738 *needed = (strlen(dllname)+1) * 2;
9740 if ( rpcbuf_get_size(out) < *needed ) {
9741 return WERR_INSUFFICIENT_BUFFER;
9744 if ( !make_monitorui_buf( out, dllname )) {
9751 /*******************************************************************
9752 *******************************************************************/
9754 struct xcv_api_table xcvlocal_cmds[] = {
9755 { "MonitorUI", xcvlocal_monitorui },
9759 struct xcv_api_table xcvlocal_cmds[] = {
9766 /*******************************************************************
9767 *******************************************************************/
9769 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9770 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9775 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9777 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9778 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9779 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9781 return WERR_BADFUNC;
9784 /*******************************************************************
9785 *******************************************************************/
9787 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9789 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9793 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9797 /* Has to be a handle to the TCP/IP port monitor */
9799 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9800 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9804 /* requires administrative access to the server */
9806 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9807 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9808 return WERR_ACCESS_DENIED;
9811 /* Get the command name. There's numerous commands supported by the
9812 TCPMON interface. */
9814 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9815 q_u->dataname.uni_str_len*2, 0);
9817 /* Allocate the outgoing buffer */
9819 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9821 switch ( Printer->printer_type ) {
9822 case SPLHND_PORTMON_TCP:
9823 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9824 &q_u->indata, &r_u->outdata, &r_u->needed );
9825 case SPLHND_PORTMON_LOCAL:
9826 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9827 &q_u->indata, &r_u->outdata, &r_u->needed );
9830 return WERR_INVALID_PRINT_MONITOR;