2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 extern userdom_struct current_user_info;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 const char *long_archi;
45 const char *short_archi;
49 static Printer_entry *printers_list;
51 typedef struct _counter_printer_0 {
52 struct _counter_printer_0 *next;
53 struct _counter_printer_0 *prev;
59 static counter_printer_0 *counter_list;
61 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
62 static uint32 smb_connections=0;
65 /* in printing/nt_printing.c */
67 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
69 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
70 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
73 /* API table for Xcv Monitor functions */
75 struct xcv_api_table {
77 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
81 /* translate between internal status numbers and NT status numbers */
82 static int nt_printj_status(int v)
88 return JOB_STATUS_PAUSED;
90 return JOB_STATUS_SPOOLING;
92 return JOB_STATUS_PRINTING;
94 return JOB_STATUS_ERROR;
96 return JOB_STATUS_DELETING;
98 return JOB_STATUS_OFFLINE;
100 return JOB_STATUS_PAPEROUT;
102 return JOB_STATUS_PRINTED;
104 return JOB_STATUS_DELETED;
106 return JOB_STATUS_BLOCKED;
107 case LPQ_USER_INTERVENTION:
108 return JOB_STATUS_USER_INTERVENTION;
113 static int nt_printq_status(int v)
117 return PRINTER_STATUS_PAUSED;
126 /****************************************************************************
127 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
128 ****************************************************************************/
130 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
135 SAFE_FREE((*pp)->ctr.type);
139 /***************************************************************************
140 Disconnect from the client
141 ****************************************************************************/
143 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
148 * Tell the specific printing tdb we no longer want messages for this printer
149 * by deregistering our PID.
152 if (!print_notify_deregister_pid(snum))
153 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
155 /* weird if the test succeds !!! */
156 if (smb_connections==0) {
157 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
161 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
163 if (!W_ERROR_IS_OK(result))
164 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
165 dos_errstr(result)));
167 /* if it's the last connection, deconnect the IPC$ share */
168 if (smb_connections==1) {
170 cli_shutdown( notify_cli_pipe->cli );
171 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
173 message_deregister(MSG_PRINTER_NOTIFY2);
175 /* Tell the connections db we're no longer interested in
176 * printer notify messages. */
178 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
184 /****************************************************************************
185 Functions to free a printer entry datastruct.
186 ****************************************************************************/
188 static void free_printer_entry(void *ptr)
190 Printer_entry *Printer = (Printer_entry *)ptr;
192 if (Printer->notify.client_connected==True) {
195 if ( Printer->printer_type == SPLHND_SERVER) {
197 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
198 } else if (Printer->printer_type == SPLHND_PRINTER) {
199 snum = print_queue_snum(Printer->sharename);
201 srv_spoolss_replycloseprinter(snum,
202 &Printer->notify.client_hnd);
206 Printer->notify.flags=0;
207 Printer->notify.options=0;
208 Printer->notify.localmachine[0]='\0';
209 Printer->notify.printerlocal=0;
210 free_spool_notify_option(&Printer->notify.option);
211 Printer->notify.option=NULL;
212 Printer->notify.client_connected=False;
214 free_nt_devicemode( &Printer->nt_devmode );
215 free_a_printer( &Printer->printer_info, 2 );
217 talloc_destroy( Printer->ctx );
219 /* Remove from the internal list. */
220 DLIST_REMOVE(printers_list, Printer);
225 /****************************************************************************
226 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
227 ****************************************************************************/
229 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
231 SPOOL_NOTIFY_OPTION *new_sp = NULL;
236 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
243 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
245 if (!new_sp->ctr.type) {
254 /****************************************************************************
255 find printer index by handle
256 ****************************************************************************/
258 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
260 Printer_entry *find_printer = NULL;
262 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
263 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
270 /****************************************************************************
271 Close printer index by handle.
272 ****************************************************************************/
274 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
276 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
279 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
283 close_policy_hnd(p, hnd);
288 /****************************************************************************
289 Delete a printer given a handle.
290 ****************************************************************************/
291 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
293 char *cmd = lp_deleteprinter_cmd();
296 SE_PRIV se_printop = SE_PRINT_OPERATOR;
297 BOOL is_print_op = False;
299 /* can't fail if we don't try */
304 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
307 is_print_op = user_has_privileges( token, &se_printop );
309 DEBUG(10,("Running [%s]\n", command));
311 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
316 if ( (ret = smbrun(command, NULL)) == 0 ) {
317 /* Tell everyone we updated smb.conf. */
318 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
324 /********** END SePrintOperatorPrivlege BLOCK **********/
326 DEBUGADD(10,("returned [%d]\n", ret));
329 return WERR_BADFID; /* What to return here? */
331 /* go ahead and re-read the services immediately */
332 reload_services( False );
334 if ( lp_servicenumber( sharename ) < 0 )
335 return WERR_ACCESS_DENIED;
340 /****************************************************************************
341 Delete a printer given a handle.
342 ****************************************************************************/
344 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
346 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
349 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
354 * It turns out that Windows allows delete printer on a handle
355 * opened by an admin user, then used on a pipe handle created
356 * by an anonymous user..... but they're working on security.... riiight !
360 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
361 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
362 return WERR_ACCESS_DENIED;
365 /* this does not need a become root since the access check has been
366 done on the handle already */
368 if (del_a_printer( Printer->sharename ) != 0) {
369 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
373 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
376 /****************************************************************************
377 Return the snum of a printer corresponding to an handle.
378 ****************************************************************************/
380 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
382 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
385 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
389 switch (Printer->printer_type) {
391 DEBUG(4,("short name:%s\n", Printer->sharename));
392 *number = print_queue_snum(Printer->sharename);
393 return (*number != -1);
401 /****************************************************************************
402 Set printer handle type.
403 Check if it's \\server or \\server\printer
404 ****************************************************************************/
406 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
408 DEBUG(3,("Setting printer type=%s\n", handlename));
410 if ( strlen(handlename) < 3 ) {
411 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
415 /* it's a print server */
416 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
417 DEBUGADD(4,("Printer is a print server\n"));
418 Printer->printer_type = SPLHND_SERVER;
420 /* it's a printer (set_printer_hnd_name() will handle port monitors */
422 DEBUGADD(4,("Printer is a printer\n"));
423 Printer->printer_type = SPLHND_PRINTER;
429 /****************************************************************************
430 Set printer handle name.. Accept names like \\server, \\server\printer,
431 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
432 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
433 XcvDataPort() interface.
434 ****************************************************************************/
436 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
439 int n_services=lp_numservices();
440 char *aprinter, *printername;
441 const char *servername;
444 NT_PRINTER_INFO_LEVEL *printer;
447 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
449 aprinter = handlename;
450 if ( *handlename == '\\' ) {
451 servername = handlename + 2;
452 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
461 /* save the servername to fill in replies on this handle */
463 if ( !is_myname_or_ipaddr( servername ) )
466 fstrcpy( Printer->servername, servername );
468 if ( Printer->printer_type == SPLHND_SERVER )
471 if ( Printer->printer_type != SPLHND_PRINTER )
474 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
476 /* check for the Port Monitor Interface */
478 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
479 Printer->printer_type = SPLHND_PORTMON_TCP;
480 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
483 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
484 Printer->printer_type = SPLHND_PORTMON_LOCAL;
485 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
489 /* Search all sharenames first as this is easier than pulling
490 the printer_info_2 off of disk. Don't use find_service() since
491 that calls out to map_username() */
493 /* do another loop to look for printernames */
495 for (snum=0; !found && snum<n_services; snum++) {
497 /* no point going on if this is not a printer */
499 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
502 fstrcpy(sname, lp_servicename(snum));
503 if ( strequal( aprinter, sname ) ) {
508 /* no point looking up the printer object if
509 we aren't allowing printername != sharename */
511 if ( lp_force_printername(snum) )
514 fstrcpy(sname, lp_servicename(snum));
517 result = get_a_printer( NULL, &printer, 2, sname );
518 if ( !W_ERROR_IS_OK(result) ) {
519 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
520 sname, dos_errstr(result)));
524 /* printername is always returned as \\server\printername */
525 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
526 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
527 printer->info_2->printername));
528 free_a_printer( &printer, 2);
534 if ( strequal(printername, aprinter) ) {
539 DEBUGADD(10, ("printername: %s\n", printername));
541 free_a_printer( &printer, 2);
545 DEBUGADD(4,("Printer not found\n"));
549 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
551 fstrcpy(Printer->sharename, sname);
556 /****************************************************************************
557 Find first available printer slot. creates a printer handle for you.
558 ****************************************************************************/
560 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
562 Printer_entry *new_printer;
564 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
566 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
569 ZERO_STRUCTP(new_printer);
571 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
572 SAFE_FREE(new_printer);
576 /* Add to the internal list. */
577 DLIST_ADD(printers_list, new_printer);
579 new_printer->notify.option=NULL;
581 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
582 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
583 close_printer_handle(p, hnd);
587 if (!set_printer_hnd_printertype(new_printer, name)) {
588 close_printer_handle(p, hnd);
592 if (!set_printer_hnd_name(new_printer, name)) {
593 close_printer_handle(p, hnd);
597 new_printer->access_granted = access_granted;
599 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
604 /***************************************************************************
605 check to see if the client motify handle is monitoring the notification
606 given by (notify_type, notify_field).
607 **************************************************************************/
609 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
615 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
618 SPOOL_NOTIFY_OPTION *option = p->notify.option;
622 * Flags should always be zero when the change notify
623 * is registered by the client's spooler. A user Win32 app
624 * might use the flags though instead of the NOTIFY_OPTION_INFO
633 return is_monitoring_event_flags(
634 p->notify.flags, notify_type, notify_field);
636 for (i = 0; i < option->count; i++) {
638 /* Check match for notify_type */
640 if (option->ctr.type[i].type != notify_type)
643 /* Check match for field */
645 for (j = 0; j < option->ctr.type[i].count; j++) {
646 if (option->ctr.type[i].fields[j] == notify_field) {
652 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
653 p->servername, p->sharename, notify_type, notify_field));
658 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
660 static void notify_one_value(struct spoolss_notify_msg *msg,
661 SPOOL_NOTIFY_INFO_DATA *data,
664 data->notify_data.value[0] = msg->notify.value[0];
665 data->notify_data.value[1] = 0;
668 static void notify_string(struct spoolss_notify_msg *msg,
669 SPOOL_NOTIFY_INFO_DATA *data,
674 /* The length of the message includes the trailing \0 */
676 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
678 data->notify_data.data.length = msg->len * 2;
679 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
681 if (!data->notify_data.data.string) {
682 data->notify_data.data.length = 0;
686 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
689 static void notify_system_time(struct spoolss_notify_msg *msg,
690 SPOOL_NOTIFY_INFO_DATA *data,
696 if (msg->len != sizeof(time_t)) {
697 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
702 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
703 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
707 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
708 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
713 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
718 data->notify_data.data.length = prs_offset(&ps);
719 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
720 if (!data->notify_data.data.string) {
725 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
730 struct notify2_message_table {
732 void (*fn)(struct spoolss_notify_msg *msg,
733 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
736 static struct notify2_message_table printer_notify_table[] = {
737 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
738 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
739 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
740 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
741 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
742 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
743 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
744 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
745 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
746 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
747 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
748 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
749 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
750 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
751 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
752 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
753 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
754 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
755 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
758 static struct notify2_message_table job_notify_table[] = {
759 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
760 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
761 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
762 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
763 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
764 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
765 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
766 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
767 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
768 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
769 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
770 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
771 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
772 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
773 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
774 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
775 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
776 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
777 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
778 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
779 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
780 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
781 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
782 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
786 /***********************************************************************
787 Allocate talloc context for container object
788 **********************************************************************/
790 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
795 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
800 /***********************************************************************
801 release all allocated memory and zero out structure
802 **********************************************************************/
804 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
810 talloc_destroy(ctr->ctx);
817 /***********************************************************************
818 **********************************************************************/
820 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
828 /***********************************************************************
829 **********************************************************************/
831 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
833 if ( !ctr || !ctr->msg_groups )
836 if ( idx >= ctr->num_groups )
839 return &ctr->msg_groups[idx];
843 /***********************************************************************
844 How many groups of change messages do we have ?
845 **********************************************************************/
847 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
852 return ctr->num_groups;
855 /***********************************************************************
856 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
857 **********************************************************************/
859 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
861 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
862 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
863 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
869 /* loop over all groups looking for a matching printer name */
871 for ( i=0; i<ctr->num_groups; i++ ) {
872 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
876 /* add a new group? */
878 if ( i == ctr->num_groups ) {
881 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
882 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
885 ctr->msg_groups = groups;
887 /* clear the new entry and set the printer name */
889 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
890 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
893 /* add the change messages; 'i' is the correct index now regardless */
895 msg_grp = &ctr->msg_groups[i];
899 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
900 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
903 msg_grp->msgs = msg_list;
905 new_slot = msg_grp->num_msgs-1;
906 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
908 /* need to allocate own copy of data */
911 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
913 return ctr->num_groups;
916 /***********************************************************************
917 Send a change notication message on all handles which have a call
919 **********************************************************************/
921 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
924 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
925 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
926 SPOOLSS_NOTIFY_MSG *messages;
927 int sending_msg_count;
930 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
934 messages = msg_group->msgs;
937 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
941 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
943 /* loop over all printers */
945 for (p = printers_list; p; p = p->next) {
946 SPOOL_NOTIFY_INFO_DATA *data;
951 /* Is there notification on this handle? */
953 if ( !p->notify.client_connected )
956 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
958 /* For this printer? Print servers always receive
961 if ( ( p->printer_type == SPLHND_PRINTER ) &&
962 ( !strequal(msg_group->printername, p->sharename) ) )
965 DEBUG(10,("Our printer\n"));
967 /* allocate the max entries possible */
969 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
976 /* build the array of change notifications */
978 sending_msg_count = 0;
980 for ( i=0; i<msg_group->num_msgs; i++ ) {
981 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
983 /* Are we monitoring this event? */
985 if (!is_monitoring_event(p, msg->type, msg->field))
991 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
992 msg->type, msg->field, p->sharename));
995 * if the is a printer notification handle and not a job notification
996 * type, then set the id to 0. Other wise just use what was specified
999 * When registering change notification on a print server handle
1000 * we always need to send back the id (snum) matching the printer
1001 * for which the change took place. For change notify registered
1002 * on a printer handle, this does not matter and the id should be 0.
1007 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1013 /* Convert unix jobid to smb jobid */
1015 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1016 id = sysjob_to_jobid(msg->id);
1019 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1024 construct_info_data( &data[data_len], msg->type, msg->field, id );
1027 case PRINTER_NOTIFY_TYPE:
1028 if ( printer_notify_table[msg->field].fn )
1029 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1032 case JOB_NOTIFY_TYPE:
1033 if ( job_notify_table[msg->field].fn )
1034 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1038 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1045 if ( sending_msg_count ) {
1046 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1047 data_len, data, p->notify.change, 0 );
1052 DEBUG(8,("send_notify2_changes: Exit...\n"));
1056 /***********************************************************************
1057 **********************************************************************/
1059 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1062 uint32 tv_sec, tv_usec;
1065 /* Unpack message */
1067 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1070 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1072 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1075 tdb_unpack((char *)buf + offset, len - offset, "dd",
1076 &msg->notify.value[0], &msg->notify.value[1]);
1078 tdb_unpack((char *)buf + offset, len - offset, "B",
1079 &msg->len, &msg->notify.data);
1081 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1082 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1084 tv->tv_sec = tv_sec;
1085 tv->tv_usec = tv_usec;
1088 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1089 msg->notify.value[1]));
1091 dump_data(3, msg->notify.data, msg->len);
1096 /********************************************************************
1097 Receive a notify2 message list
1098 ********************************************************************/
1100 static void receive_notify2_message_list(int msg_type, struct process_id src,
1101 void *msg, size_t len)
1103 size_t msg_count, i;
1104 char *buf = (char *)msg;
1107 SPOOLSS_NOTIFY_MSG notify;
1108 SPOOLSS_NOTIFY_MSG_CTR messages;
1112 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1116 msg_count = IVAL(buf, 0);
1119 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1121 if (msg_count == 0) {
1122 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1126 /* initialize the container */
1128 ZERO_STRUCT( messages );
1129 notify_msg_ctr_init( &messages );
1132 * build message groups for each printer identified
1133 * in a change_notify msg. Remember that a PCN message
1134 * includes the handle returned for the srv_spoolss_replyopenprinter()
1135 * call. Therefore messages are grouped according to printer handle.
1138 for ( i=0; i<msg_count; i++ ) {
1139 struct timeval msg_tv;
1141 if (msg_ptr + 4 - buf > len) {
1142 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1146 msg_len = IVAL(msg_ptr,0);
1149 if (msg_ptr + msg_len - buf > len) {
1150 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1154 /* unpack messages */
1156 ZERO_STRUCT( notify );
1157 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1160 /* add to correct list in container */
1162 notify_msg_ctr_addmsg( &messages, ¬ify );
1164 /* free memory that might have been allocated by notify2_unpack_msg() */
1166 if ( notify.len != 0 )
1167 SAFE_FREE( notify.notify.data );
1170 /* process each group of messages */
1172 num_groups = notify_msg_ctr_numgroups( &messages );
1173 for ( i=0; i<num_groups; i++ )
1174 send_notify2_changes( &messages, i );
1179 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1181 notify_msg_ctr_destroy( &messages );
1186 /********************************************************************
1187 Send a message to ourself about new driver being installed
1188 so we can upgrade the information for each printer bound to this
1190 ********************************************************************/
1192 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1194 int len = strlen(drivername);
1199 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1202 message_send_pid(pid_to_procid(sys_getpid()),
1203 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1208 /**********************************************************************
1209 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1210 over all printers, upgrading ones as necessary
1211 **********************************************************************/
1213 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1217 int n_services = lp_numservices();
1219 len = MIN(len,sizeof(drivername)-1);
1220 strncpy(drivername, buf, len);
1222 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1224 /* Iterate the printer list */
1226 for (snum=0; snum<n_services; snum++)
1228 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1231 NT_PRINTER_INFO_LEVEL *printer = NULL;
1233 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1234 if (!W_ERROR_IS_OK(result))
1237 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1239 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1241 /* all we care about currently is the change_id */
1243 result = mod_a_printer(printer, 2);
1244 if (!W_ERROR_IS_OK(result)) {
1245 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1246 dos_errstr(result)));
1250 free_a_printer(&printer, 2);
1257 /********************************************************************
1258 Update the cache for all printq's with a registered client
1260 ********************************************************************/
1262 void update_monitored_printq_cache( void )
1264 Printer_entry *printer = printers_list;
1267 /* loop through all printers and update the cache where
1268 client_connected == True */
1271 if ( (printer->printer_type == SPLHND_PRINTER)
1272 && printer->notify.client_connected )
1274 snum = print_queue_snum(printer->sharename);
1275 print_queue_status( snum, NULL, NULL );
1278 printer = printer->next;
1283 /********************************************************************
1284 Send a message to ourself about new driver being installed
1285 so we can upgrade the information for each printer bound to this
1287 ********************************************************************/
1289 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1291 int len = strlen(drivername);
1296 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1299 message_send_pid(pid_to_procid(sys_getpid()),
1300 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1305 /**********************************************************************
1306 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1307 over all printers, resetting printer data as neessary
1308 **********************************************************************/
1310 void reset_all_printerdata(int msg_type, struct process_id src,
1311 void *buf, size_t len)
1315 int n_services = lp_numservices();
1317 len = MIN( len, sizeof(drivername)-1 );
1318 strncpy( drivername, buf, len );
1320 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1322 /* Iterate the printer list */
1324 for ( snum=0; snum<n_services; snum++ )
1326 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1329 NT_PRINTER_INFO_LEVEL *printer = NULL;
1331 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1332 if ( !W_ERROR_IS_OK(result) )
1336 * if the printer is bound to the driver,
1337 * then reset to the new driver initdata
1340 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1342 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1344 if ( !set_driver_init(printer, 2) ) {
1345 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1346 printer->info_2->printername, printer->info_2->drivername));
1349 result = mod_a_printer( printer, 2 );
1350 if ( !W_ERROR_IS_OK(result) ) {
1351 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1352 get_dos_error_msg(result)));
1356 free_a_printer( &printer, 2 );
1365 /********************************************************************
1366 Copy routines used by convert_to_openprinterex()
1367 *******************************************************************/
1369 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1377 DEBUG (8,("dup_devmode\n"));
1379 /* bulk copy first */
1381 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1385 /* dup the pointer members separately */
1387 len = unistrlen(devmode->devicename.buffer);
1389 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1390 if (!d->devicename.buffer) {
1393 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1398 len = unistrlen(devmode->formname.buffer);
1400 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1401 if (!d->devicename.buffer) {
1404 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1408 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1409 if (!d->dev_private) {
1415 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1417 if (!new_ctr || !ctr)
1420 DEBUG(8,("copy_devmode_ctr\n"));
1422 new_ctr->size = ctr->size;
1423 new_ctr->devmode_ptr = ctr->devmode_ptr;
1425 if(ctr->devmode_ptr)
1426 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1429 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1431 if (!new_def || !def)
1434 DEBUG(8,("copy_printer_defaults\n"));
1436 new_def->datatype_ptr = def->datatype_ptr;
1438 if (def->datatype_ptr)
1439 copy_unistr2(&new_def->datatype, &def->datatype);
1441 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1443 new_def->access_required = def->access_required;
1446 /********************************************************************
1447 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1448 * SPOOL_Q_OPEN_PRINTER_EX structure
1449 ********************************************************************/
1451 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1453 if (!q_u_ex || !q_u)
1456 DEBUG(8,("convert_to_openprinterex\n"));
1458 if ( q_u->printername ) {
1459 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1460 if (q_u_ex->printername == NULL)
1462 copy_unistr2(q_u_ex->printername, q_u->printername);
1465 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1470 /********************************************************************
1471 * spoolss_open_printer
1473 * called from the spoolss dispatcher
1474 ********************************************************************/
1476 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1478 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1479 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1484 ZERO_STRUCT(q_u_ex);
1485 ZERO_STRUCT(r_u_ex);
1487 /* convert the OpenPrinter() call to OpenPrinterEx() */
1489 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1490 if (!W_ERROR_IS_OK(r_u_ex.status))
1491 return r_u_ex.status;
1493 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1495 /* convert back to OpenPrinter() */
1497 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1502 /********************************************************************
1503 ********************************************************************/
1505 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1507 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1508 POLICY_HND *handle = &r_u->handle;
1512 struct current_user user;
1513 Printer_entry *Printer=NULL;
1515 if ( !q_u->printername )
1516 return WERR_INVALID_PRINTER_NAME;
1518 /* some sanity check because you can open a printer or a print server */
1519 /* aka: \\server\printer or \\server */
1521 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1523 DEBUGADD(3,("checking name: %s\n",name));
1525 if (!open_printer_hnd(p, handle, name, 0))
1526 return WERR_INVALID_PRINTER_NAME;
1528 Printer=find_printer_index_by_hnd(p, handle);
1530 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1531 "handle we created for printer %s\n", name ));
1532 close_printer_handle(p,handle);
1533 return WERR_INVALID_PRINTER_NAME;
1536 get_current_user(&user, p);
1539 * First case: the user is opening the print server:
1541 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1542 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1544 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1545 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1546 * or if the user is listed in the smb.conf printer admin parameter.
1548 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1549 * client view printer folder, but does not show the MSAPW.
1551 * Note: this test needs code to check access rights here too. Jeremy
1552 * could you look at this?
1554 * Second case: the user is opening a printer:
1555 * NT doesn't let us connect to a printer if the connecting user
1556 * doesn't have print permission.
1558 * Third case: user is opening a Port Monitor
1559 * access checks same as opening a handle to the print server.
1562 switch (Printer->printer_type )
1565 case SPLHND_PORTMON_TCP:
1566 case SPLHND_PORTMON_LOCAL:
1567 /* Printserver handles use global struct... */
1571 /* Map standard access rights to object specific access rights */
1573 se_map_standard(&printer_default->access_required,
1574 &printserver_std_mapping);
1576 /* Deny any object specific bits that don't apply to print
1577 servers (i.e printer and job specific bits) */
1579 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1581 if (printer_default->access_required &
1582 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1583 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1584 close_printer_handle(p, handle);
1585 return WERR_ACCESS_DENIED;
1588 /* Allow admin access */
1590 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1592 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1594 if (!lp_ms_add_printer_wizard()) {
1595 close_printer_handle(p, handle);
1596 return WERR_ACCESS_DENIED;
1599 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1600 and not a printer admin, then fail */
1602 if ((user.ut.uid != 0) &&
1603 !user_has_privileges(user.nt_user_token,
1605 !token_contains_name_in_list(
1606 uidtoname(user.ut.uid), NULL,
1608 lp_printer_admin(snum))) {
1609 close_printer_handle(p, handle);
1610 return WERR_ACCESS_DENIED;
1613 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1617 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1620 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1621 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1623 /* We fall through to return WERR_OK */
1626 case SPLHND_PRINTER:
1627 /* NT doesn't let us connect to a printer if the connecting user
1628 doesn't have print permission. */
1630 if (!get_printer_snum(p, handle, &snum)) {
1631 close_printer_handle(p, handle);
1635 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1637 /* map an empty access mask to the minimum access mask */
1638 if (printer_default->access_required == 0x0)
1639 printer_default->access_required = PRINTER_ACCESS_USE;
1642 * If we are not serving the printer driver for this printer,
1643 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1644 * will keep NT clients happy --jerry
1647 if (lp_use_client_driver(snum)
1648 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1650 printer_default->access_required = PRINTER_ACCESS_USE;
1653 /* check smb.conf parameters and the the sec_desc */
1655 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1656 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1657 return WERR_ACCESS_DENIED;
1660 if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
1662 !print_access_check(&user, snum,
1663 printer_default->access_required)) {
1664 DEBUG(3, ("access DENIED for printer open\n"));
1665 close_printer_handle(p, handle);
1666 return WERR_ACCESS_DENIED;
1669 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1670 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1671 close_printer_handle(p, handle);
1672 return WERR_ACCESS_DENIED;
1675 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1676 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1678 printer_default->access_required = PRINTER_ACCESS_USE;
1680 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1681 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1686 /* sanity check to prevent programmer error */
1690 Printer->access_granted = printer_default->access_required;
1693 * If the client sent a devmode in the OpenPrinter() call, then
1694 * save it here in case we get a job submission on this handle
1697 if ( (Printer->printer_type != SPLHND_SERVER)
1698 && q_u->printer_default.devmode_cont.devmode_ptr )
1700 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1701 &Printer->nt_devmode );
1704 #if 0 /* JERRY -- I'm doubtful this is really effective */
1705 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1706 optimization in Windows 2000 clients --jerry */
1708 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1709 && (RA_WIN2K == get_remote_arch()) )
1711 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1712 sys_usleep( 500000 );
1719 /****************************************************************************
1720 ****************************************************************************/
1722 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1723 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1729 /* allocate memory if needed. Messy because
1730 convert_printer_info is used to update an existing
1731 printer or build a new one */
1733 if ( !printer->info_2 ) {
1734 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1735 if ( !printer->info_2 ) {
1736 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1741 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1742 printer->info_2->setuptime = time(NULL);
1750 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1751 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1757 printer->info_3=NULL;
1758 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1762 printer->info_6=NULL;
1763 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1773 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1774 NT_DEVICEMODE **pp_nt_devmode)
1776 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1779 * Ensure nt_devmode is a valid pointer
1780 * as we will be overwriting it.
1783 if (nt_devmode == NULL) {
1784 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1785 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1789 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1790 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1792 nt_devmode->specversion=devmode->specversion;
1793 nt_devmode->driverversion=devmode->driverversion;
1794 nt_devmode->size=devmode->size;
1795 nt_devmode->fields=devmode->fields;
1796 nt_devmode->orientation=devmode->orientation;
1797 nt_devmode->papersize=devmode->papersize;
1798 nt_devmode->paperlength=devmode->paperlength;
1799 nt_devmode->paperwidth=devmode->paperwidth;
1800 nt_devmode->scale=devmode->scale;
1801 nt_devmode->copies=devmode->copies;
1802 nt_devmode->defaultsource=devmode->defaultsource;
1803 nt_devmode->printquality=devmode->printquality;
1804 nt_devmode->color=devmode->color;
1805 nt_devmode->duplex=devmode->duplex;
1806 nt_devmode->yresolution=devmode->yresolution;
1807 nt_devmode->ttoption=devmode->ttoption;
1808 nt_devmode->collate=devmode->collate;
1810 nt_devmode->logpixels=devmode->logpixels;
1811 nt_devmode->bitsperpel=devmode->bitsperpel;
1812 nt_devmode->pelswidth=devmode->pelswidth;
1813 nt_devmode->pelsheight=devmode->pelsheight;
1814 nt_devmode->displayflags=devmode->displayflags;
1815 nt_devmode->displayfrequency=devmode->displayfrequency;
1816 nt_devmode->icmmethod=devmode->icmmethod;
1817 nt_devmode->icmintent=devmode->icmintent;
1818 nt_devmode->mediatype=devmode->mediatype;
1819 nt_devmode->dithertype=devmode->dithertype;
1820 nt_devmode->reserved1=devmode->reserved1;
1821 nt_devmode->reserved2=devmode->reserved2;
1822 nt_devmode->panningwidth=devmode->panningwidth;
1823 nt_devmode->panningheight=devmode->panningheight;
1826 * Only change private and driverextra if the incoming devmode
1827 * has a new one. JRA.
1830 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1831 SAFE_FREE(nt_devmode->nt_dev_private);
1832 nt_devmode->driverextra=devmode->driverextra;
1833 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1835 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1838 *pp_nt_devmode = nt_devmode;
1843 /********************************************************************
1844 * _spoolss_enddocprinter_internal.
1845 ********************************************************************/
1847 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1849 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1853 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1857 if (!get_printer_snum(p, handle, &snum))
1860 Printer->document_started=False;
1861 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1862 /* error codes unhandled so far ... */
1867 /********************************************************************
1868 * api_spoolss_closeprinter
1869 ********************************************************************/
1871 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1873 POLICY_HND *handle = &q_u->handle;
1875 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1877 if (Printer && Printer->document_started)
1878 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1880 if (!close_printer_handle(p, handle))
1883 /* clear the returned printer handle. Observed behavior
1884 from Win2k server. Don't think this really matters.
1885 Previous code just copied the value of the closed
1888 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1893 /********************************************************************
1894 * api_spoolss_deleteprinter
1896 ********************************************************************/
1898 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1900 POLICY_HND *handle = &q_u->handle;
1901 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1904 if (Printer && Printer->document_started)
1905 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1907 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1909 result = delete_printer_handle(p, handle);
1911 update_c_setprinter(False);
1916 /*******************************************************************
1917 * static function to lookup the version id corresponding to an
1918 * long architecture string
1919 ******************************************************************/
1921 static int get_version_id (char * arch)
1924 struct table_node archi_table[]= {
1926 {"Windows 4.0", "WIN40", 0 },
1927 {"Windows NT x86", "W32X86", 2 },
1928 {"Windows NT R4000", "W32MIPS", 2 },
1929 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1930 {"Windows NT PowerPC", "W32PPC", 2 },
1931 {"Windows IA64", "IA64", 3 },
1932 {"Windows x64", "x64", 3 },
1936 for (i=0; archi_table[i].long_archi != NULL; i++)
1938 if (strcmp(arch, archi_table[i].long_archi) == 0)
1939 return (archi_table[i].version);
1945 /********************************************************************
1946 * _spoolss_deleteprinterdriver
1947 ********************************************************************/
1949 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1953 NT_PRINTER_DRIVER_INFO_LEVEL info;
1954 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1956 struct current_user user;
1958 WERROR status_win2k = WERR_ACCESS_DENIED;
1959 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1961 get_current_user(&user, p);
1963 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1964 and not a printer admin, then fail */
1966 if ( (user.ut.uid != 0)
1967 && !user_has_privileges(user.nt_user_token, &se_printop )
1968 && !token_contains_name_in_list( uidtoname(user.ut.uid),
1969 NULL, user.nt_user_token, lp_printer_admin(-1)) )
1971 return WERR_ACCESS_DENIED;
1974 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1975 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1977 /* check that we have a valid driver name first */
1979 if ((version=get_version_id(arch)) == -1)
1980 return WERR_INVALID_ENVIRONMENT;
1983 ZERO_STRUCT(info_win2k);
1985 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1987 /* try for Win2k driver if "Windows NT x86" */
1989 if ( version == 2 ) {
1991 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1992 status = WERR_UNKNOWN_PRINTER_DRIVER;
1996 /* otherwise it was a failure */
1998 status = WERR_UNKNOWN_PRINTER_DRIVER;
2004 if (printer_driver_in_use(info.info_3)) {
2005 status = WERR_PRINTER_DRIVER_IN_USE;
2011 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2013 /* if we get to here, we now have 2 driver info structures to remove */
2014 /* remove the Win2k driver first*/
2016 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2017 free_a_printer_driver( info_win2k, 3 );
2019 /* this should not have failed---if it did, report to client */
2020 if ( !W_ERROR_IS_OK(status_win2k) )
2022 status = status_win2k;
2028 status = delete_printer_driver(info.info_3, &user, version, False);
2030 /* if at least one of the deletes succeeded return OK */
2032 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2036 free_a_printer_driver( info, 3 );
2041 /********************************************************************
2042 * spoolss_deleteprinterdriverex
2043 ********************************************************************/
2045 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2049 NT_PRINTER_DRIVER_INFO_LEVEL info;
2050 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2052 uint32 flags = q_u->delete_flags;
2054 struct current_user user;
2056 WERROR status_win2k = WERR_ACCESS_DENIED;
2057 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2059 get_current_user(&user, p);
2061 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2062 and not a printer admin, then fail */
2064 if ( (user.ut.uid != 0)
2065 && !user_has_privileges(user.nt_user_token, &se_printop )
2066 && !token_contains_name_in_list( uidtoname(user.ut.uid),
2067 NULL, user.nt_user_token, lp_printer_admin(-1)) )
2069 return WERR_ACCESS_DENIED;
2072 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2073 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2075 /* check that we have a valid driver name first */
2076 if ((version=get_version_id(arch)) == -1) {
2077 /* this is what NT returns */
2078 return WERR_INVALID_ENVIRONMENT;
2081 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2082 version = q_u->version;
2085 ZERO_STRUCT(info_win2k);
2087 status = get_a_printer_driver(&info, 3, driver, arch, version);
2089 if ( !W_ERROR_IS_OK(status) )
2092 * if the client asked for a specific version,
2093 * or this is something other than Windows NT x86,
2097 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2100 /* try for Win2k driver if "Windows NT x86" */
2103 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2104 status = WERR_UNKNOWN_PRINTER_DRIVER;
2109 if ( printer_driver_in_use(info.info_3) ) {
2110 status = WERR_PRINTER_DRIVER_IN_USE;
2115 * we have a couple of cases to consider.
2116 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2117 * then the delete should fail if **any** files overlap with
2119 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2120 * non-overlapping files
2121 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2122 * is set, the do not delete any files
2123 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2126 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2128 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2130 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2131 /* no idea of the correct error here */
2132 status = WERR_ACCESS_DENIED;
2137 /* also check for W32X86/3 if necessary; maybe we already have? */
2139 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2140 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2143 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2144 /* no idea of the correct error here */
2145 free_a_printer_driver( info_win2k, 3 );
2146 status = WERR_ACCESS_DENIED;
2150 /* if we get to here, we now have 2 driver info structures to remove */
2151 /* remove the Win2k driver first*/
2153 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2154 free_a_printer_driver( info_win2k, 3 );
2156 /* this should not have failed---if it did, report to client */
2158 if ( !W_ERROR_IS_OK(status_win2k) )
2163 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2165 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2168 free_a_printer_driver( info, 3 );
2174 /****************************************************************************
2175 Internal routine for retreiving printerdata
2176 ***************************************************************************/
2178 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2179 const char *key, const char *value, uint32 *type, uint8 **data,
2180 uint32 *needed, uint32 in_size )
2182 REGISTRY_VALUE *val;
2186 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2187 return WERR_BADFILE;
2189 *type = regval_type( val );
2191 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2193 size = regval_size( val );
2195 /* copy the min(in_size, len) */
2198 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2200 /* special case for 0 length values */
2202 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2206 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2215 DEBUG(5,("get_printer_dataex: copy done\n"));
2220 /****************************************************************************
2221 Internal routine for removing printerdata
2222 ***************************************************************************/
2224 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2226 return delete_printer_data( printer->info_2, key, value );
2229 /****************************************************************************
2230 Internal routine for storing printerdata
2231 ***************************************************************************/
2233 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2234 uint32 type, uint8 *data, int real_len )
2236 /* the registry objects enforce uniqueness based on value name */
2238 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2241 /********************************************************************
2242 GetPrinterData on a printer server Handle.
2243 ********************************************************************/
2245 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2249 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2251 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2253 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2259 if (!StrCaseCmp(value, "BeepEnabled")) {
2261 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2263 SIVAL(*data, 0, 0x00);
2268 if (!StrCaseCmp(value, "EventLog")) {
2270 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2272 /* formally was 0x1b */
2273 SIVAL(*data, 0, 0x0);
2278 if (!StrCaseCmp(value, "NetPopup")) {
2280 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2282 SIVAL(*data, 0, 0x00);
2287 if (!StrCaseCmp(value, "MajorVersion")) {
2289 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2292 /* Windows NT 4.0 seems to not allow uploading of drivers
2293 to a server that reports 0x3 as the MajorVersion.
2294 need to investigate more how Win2k gets around this .
2297 if ( RA_WINNT == get_remote_arch() )
2306 if (!StrCaseCmp(value, "MinorVersion")) {
2308 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2316 * uint32 size = 0x114
2318 * uint32 minor = [0|1]
2319 * uint32 build = [2195|2600]
2320 * extra unicode string = e.g. "Service Pack 3"
2322 if (!StrCaseCmp(value, "OSVersion")) {
2326 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2329 SIVAL(*data, 0, *needed); /* size */
2330 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2332 SIVAL(*data, 12, 2195); /* build */
2334 /* leave extra string empty */
2340 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2341 const char *string="C:\\PRINTERS";
2343 *needed = 2*(strlen(string)+1);
2344 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2346 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2348 /* it's done by hand ready to go on the wire */
2349 for (i=0; i<strlen(string); i++) {
2350 (*data)[2*i]=string[i];
2351 (*data)[2*i+1]='\0';
2356 if (!StrCaseCmp(value, "Architecture")) {
2357 const char *string="Windows NT x86";
2359 *needed = 2*(strlen(string)+1);
2360 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2362 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2363 for (i=0; i<strlen(string); i++) {
2364 (*data)[2*i]=string[i];
2365 (*data)[2*i+1]='\0';
2370 if (!StrCaseCmp(value, "DsPresent")) {
2372 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2375 /* only show the publish check box if we are a
2376 memeber of a AD domain */
2378 if ( lp_security() == SEC_ADS )
2379 SIVAL(*data, 0, 0x01);
2381 SIVAL(*data, 0, 0x00);
2387 if (!StrCaseCmp(value, "DNSMachineName")) {
2390 if (!get_mydnsfullname(hostname))
2391 return WERR_BADFILE;
2393 *needed = 2*(strlen(hostname)+1);
2394 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2396 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2397 for (i=0; i<strlen(hostname); i++) {
2398 (*data)[2*i]=hostname[i];
2399 (*data)[2*i+1]='\0';
2405 return WERR_BADFILE;
2408 /********************************************************************
2409 * spoolss_getprinterdata
2410 ********************************************************************/
2412 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2414 POLICY_HND *handle = &q_u->handle;
2415 UNISTR2 *valuename = &q_u->valuename;
2416 uint32 in_size = q_u->size;
2417 uint32 *type = &r_u->type;
2418 uint32 *out_size = &r_u->size;
2419 uint8 **data = &r_u->data;
2420 uint32 *needed = &r_u->needed;
2423 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2424 NT_PRINTER_INFO_LEVEL *printer = NULL;
2428 * Reminder: when it's a string, the length is in BYTES
2429 * even if UNICODE is negociated.
2434 *out_size = in_size;
2436 /* in case of problem, return some default values */
2441 DEBUG(4,("_spoolss_getprinterdata\n"));
2444 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2445 status = WERR_BADFID;
2449 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2451 if ( Printer->printer_type == SPLHND_SERVER )
2452 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2455 if ( !get_printer_snum(p,handle, &snum) ) {
2456 status = WERR_BADFID;
2460 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2461 if ( !W_ERROR_IS_OK(status) )
2464 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2466 if ( strequal(value, "ChangeId") ) {
2468 *needed = sizeof(uint32);
2469 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2470 status = WERR_NOMEM;
2473 SIVAL( *data, 0, printer->info_2->changeid );
2477 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2480 if (*needed > *out_size)
2481 status = WERR_MORE_DATA;
2484 if ( !W_ERROR_IS_OK(status) )
2486 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2488 /* reply this param doesn't exist */
2491 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2493 free_a_printer( &printer, 2 );
2502 /* cleanup & exit */
2505 free_a_printer( &printer, 2 );
2510 /*********************************************************
2511 Connect to the client machine.
2512 **********************************************************/
2514 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2515 struct in_addr *client_ip, const char *remote_machine)
2518 struct cli_state *the_cli;
2519 struct in_addr rm_addr;
2521 if ( is_zero_ip(*client_ip) ) {
2522 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2523 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2527 if ( ismyip( rm_addr )) {
2528 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2532 rm_addr.s_addr = client_ip->s_addr;
2533 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2534 inet_ntoa(*client_ip) ));
2537 /* setup the connection */
2539 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2540 &rm_addr, 0, "IPC$", "IPC",
2544 0, lp_client_signing(), NULL );
2546 if ( !NT_STATUS_IS_OK( ret ) ) {
2547 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2552 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2553 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2554 cli_shutdown(the_cli);
2559 * Ok - we have an anonymous connection to the IPC$ share.
2560 * Now start the NT Domain stuff :-).
2563 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2564 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2565 remote_machine, nt_errstr(ret)));
2566 cli_shutdown(the_cli);
2570 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2572 (*pp_pipe)->cli = the_cli;
2577 /***************************************************************************
2578 Connect to the client.
2579 ****************************************************************************/
2581 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2582 uint32 localprinter, uint32 type,
2583 POLICY_HND *handle, struct in_addr *client_ip)
2588 * If it's the first connection, contact the client
2589 * and connect to the IPC$ share anonymously
2591 if (smb_connections==0) {
2592 fstring unix_printer;
2594 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2596 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2599 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2600 /* Tell the connections db we're now interested in printer
2601 * notify messages. */
2602 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2606 * Tell the specific printing tdb we want messages for this printer
2607 * by registering our PID.
2610 if (!print_notify_register_pid(snum))
2611 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2615 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2618 if (!W_ERROR_IS_OK(result))
2619 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2620 dos_errstr(result)));
2622 return (W_ERROR_IS_OK(result));
2625 /********************************************************************
2627 * ReplyFindFirstPrinterChangeNotifyEx
2629 * before replying OK: status=0 a rpc call is made to the workstation
2630 * asking ReplyOpenPrinter
2632 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2633 * called from api_spoolss_rffpcnex
2634 ********************************************************************/
2636 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2638 POLICY_HND *handle = &q_u->handle;
2639 uint32 flags = q_u->flags;
2640 uint32 options = q_u->options;
2641 UNISTR2 *localmachine = &q_u->localmachine;
2642 uint32 printerlocal = q_u->printerlocal;
2644 SPOOL_NOTIFY_OPTION *option = q_u->option;
2645 struct in_addr client_ip;
2647 /* store the notify value in the printer struct */
2649 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2652 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2656 Printer->notify.flags=flags;
2657 Printer->notify.options=options;
2658 Printer->notify.printerlocal=printerlocal;
2660 if (Printer->notify.option)
2661 free_spool_notify_option(&Printer->notify.option);
2663 Printer->notify.option=dup_spool_notify_option(option);
2665 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2666 sizeof(Printer->notify.localmachine)-1);
2668 /* Connect to the client machine and send a ReplyOpenPrinter */
2670 if ( Printer->printer_type == SPLHND_SERVER)
2672 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2673 !get_printer_snum(p, handle, &snum) )
2676 client_ip.s_addr = inet_addr(p->conn->client_address);
2678 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2679 Printer->notify.printerlocal, 1,
2680 &Printer->notify.client_hnd, &client_ip))
2681 return WERR_SERVER_UNAVAILABLE;
2683 Printer->notify.client_connected=True;
2688 /*******************************************************************
2689 * fill a notify_info_data with the servername
2690 ********************************************************************/
2692 void spoolss_notify_server_name(int snum,
2693 SPOOL_NOTIFY_INFO_DATA *data,
2694 print_queue_struct *queue,
2695 NT_PRINTER_INFO_LEVEL *printer,
2696 TALLOC_CTX *mem_ctx)
2701 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2703 data->notify_data.data.length = len;
2704 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2706 if (!data->notify_data.data.string) {
2707 data->notify_data.data.length = 0;
2711 memcpy(data->notify_data.data.string, temp, len);
2714 /*******************************************************************
2715 * fill a notify_info_data with the printername (not including the servername).
2716 ********************************************************************/
2718 void spoolss_notify_printer_name(int snum,
2719 SPOOL_NOTIFY_INFO_DATA *data,
2720 print_queue_struct *queue,
2721 NT_PRINTER_INFO_LEVEL *printer,
2722 TALLOC_CTX *mem_ctx)
2727 /* the notify name should not contain the \\server\ part */
2728 char *p = strrchr(printer->info_2->printername, '\\');
2731 p = printer->info_2->printername;
2736 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2738 data->notify_data.data.length = len;
2739 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2741 if (!data->notify_data.data.string) {
2742 data->notify_data.data.length = 0;
2746 memcpy(data->notify_data.data.string, temp, len);
2749 /*******************************************************************
2750 * fill a notify_info_data with the servicename
2751 ********************************************************************/
2753 void spoolss_notify_share_name(int snum,
2754 SPOOL_NOTIFY_INFO_DATA *data,
2755 print_queue_struct *queue,
2756 NT_PRINTER_INFO_LEVEL *printer,
2757 TALLOC_CTX *mem_ctx)
2762 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2764 data->notify_data.data.length = len;
2765 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2767 if (!data->notify_data.data.string) {
2768 data->notify_data.data.length = 0;
2772 memcpy(data->notify_data.data.string, temp, len);
2775 /*******************************************************************
2776 * fill a notify_info_data with the port name
2777 ********************************************************************/
2779 void spoolss_notify_port_name(int snum,
2780 SPOOL_NOTIFY_INFO_DATA *data,
2781 print_queue_struct *queue,
2782 NT_PRINTER_INFO_LEVEL *printer,
2783 TALLOC_CTX *mem_ctx)
2788 /* even if it's strange, that's consistant in all the code */
2790 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2792 data->notify_data.data.length = len;
2793 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2795 if (!data->notify_data.data.string) {
2796 data->notify_data.data.length = 0;
2800 memcpy(data->notify_data.data.string, temp, len);
2803 /*******************************************************************
2804 * fill a notify_info_data with the printername
2805 * but it doesn't exist, have to see what to do
2806 ********************************************************************/
2808 void spoolss_notify_driver_name(int snum,
2809 SPOOL_NOTIFY_INFO_DATA *data,
2810 print_queue_struct *queue,
2811 NT_PRINTER_INFO_LEVEL *printer,
2812 TALLOC_CTX *mem_ctx)
2817 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2819 data->notify_data.data.length = len;
2820 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2822 if (!data->notify_data.data.string) {
2823 data->notify_data.data.length = 0;
2827 memcpy(data->notify_data.data.string, temp, len);
2830 /*******************************************************************
2831 * fill a notify_info_data with the comment
2832 ********************************************************************/
2834 void spoolss_notify_comment(int snum,
2835 SPOOL_NOTIFY_INFO_DATA *data,
2836 print_queue_struct *queue,
2837 NT_PRINTER_INFO_LEVEL *printer,
2838 TALLOC_CTX *mem_ctx)
2843 if (*printer->info_2->comment == '\0')
2844 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2846 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2848 data->notify_data.data.length = len;
2849 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2851 if (!data->notify_data.data.string) {
2852 data->notify_data.data.length = 0;
2856 memcpy(data->notify_data.data.string, temp, len);
2859 /*******************************************************************
2860 * fill a notify_info_data with the comment
2861 * location = "Room 1, floor 2, building 3"
2862 ********************************************************************/
2864 void spoolss_notify_location(int snum,
2865 SPOOL_NOTIFY_INFO_DATA *data,
2866 print_queue_struct *queue,
2867 NT_PRINTER_INFO_LEVEL *printer,
2868 TALLOC_CTX *mem_ctx)
2873 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2875 data->notify_data.data.length = len;
2876 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2878 if (!data->notify_data.data.string) {
2879 data->notify_data.data.length = 0;
2883 memcpy(data->notify_data.data.string, temp, len);
2886 /*******************************************************************
2887 * fill a notify_info_data with the device mode
2888 * jfm:xxxx don't to it for know but that's a real problem !!!
2889 ********************************************************************/
2891 static void spoolss_notify_devmode(int snum,
2892 SPOOL_NOTIFY_INFO_DATA *data,
2893 print_queue_struct *queue,
2894 NT_PRINTER_INFO_LEVEL *printer,
2895 TALLOC_CTX *mem_ctx)
2899 /*******************************************************************
2900 * fill a notify_info_data with the separator file name
2901 ********************************************************************/
2903 void spoolss_notify_sepfile(int snum,
2904 SPOOL_NOTIFY_INFO_DATA *data,
2905 print_queue_struct *queue,
2906 NT_PRINTER_INFO_LEVEL *printer,
2907 TALLOC_CTX *mem_ctx)
2912 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2914 data->notify_data.data.length = len;
2915 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2917 if (!data->notify_data.data.string) {
2918 data->notify_data.data.length = 0;
2922 memcpy(data->notify_data.data.string, temp, len);
2925 /*******************************************************************
2926 * fill a notify_info_data with the print processor
2927 * jfm:xxxx return always winprint to indicate we don't do anything to it
2928 ********************************************************************/
2930 void spoolss_notify_print_processor(int snum,
2931 SPOOL_NOTIFY_INFO_DATA *data,
2932 print_queue_struct *queue,
2933 NT_PRINTER_INFO_LEVEL *printer,
2934 TALLOC_CTX *mem_ctx)
2939 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2941 data->notify_data.data.length = len;
2942 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2944 if (!data->notify_data.data.string) {
2945 data->notify_data.data.length = 0;
2949 memcpy(data->notify_data.data.string, temp, len);
2952 /*******************************************************************
2953 * fill a notify_info_data with the print processor options
2954 * jfm:xxxx send an empty string
2955 ********************************************************************/
2957 void spoolss_notify_parameters(int snum,
2958 SPOOL_NOTIFY_INFO_DATA *data,
2959 print_queue_struct *queue,
2960 NT_PRINTER_INFO_LEVEL *printer,
2961 TALLOC_CTX *mem_ctx)
2966 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2968 data->notify_data.data.length = len;
2969 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2971 if (!data->notify_data.data.string) {
2972 data->notify_data.data.length = 0;
2976 memcpy(data->notify_data.data.string, temp, len);
2979 /*******************************************************************
2980 * fill a notify_info_data with the data type
2981 * jfm:xxxx always send RAW as data type
2982 ********************************************************************/
2984 void spoolss_notify_datatype(int snum,
2985 SPOOL_NOTIFY_INFO_DATA *data,
2986 print_queue_struct *queue,
2987 NT_PRINTER_INFO_LEVEL *printer,
2988 TALLOC_CTX *mem_ctx)
2993 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2995 data->notify_data.data.length = len;
2996 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2998 if (!data->notify_data.data.string) {
2999 data->notify_data.data.length = 0;
3003 memcpy(data->notify_data.data.string, temp, len);
3006 /*******************************************************************
3007 * fill a notify_info_data with the security descriptor
3008 * jfm:xxxx send an null pointer to say no security desc
3009 * have to implement security before !
3010 ********************************************************************/
3012 static void spoolss_notify_security_desc(int snum,
3013 SPOOL_NOTIFY_INFO_DATA *data,
3014 print_queue_struct *queue,
3015 NT_PRINTER_INFO_LEVEL *printer,
3016 TALLOC_CTX *mem_ctx)
3018 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3019 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3022 /*******************************************************************
3023 * fill a notify_info_data with the attributes
3024 * jfm:xxxx a samba printer is always shared
3025 ********************************************************************/
3027 void spoolss_notify_attributes(int snum,
3028 SPOOL_NOTIFY_INFO_DATA *data,
3029 print_queue_struct *queue,
3030 NT_PRINTER_INFO_LEVEL *printer,
3031 TALLOC_CTX *mem_ctx)
3033 data->notify_data.value[0] = printer->info_2->attributes;
3034 data->notify_data.value[1] = 0;
3037 /*******************************************************************
3038 * fill a notify_info_data with the priority
3039 ********************************************************************/
3041 static void spoolss_notify_priority(int snum,
3042 SPOOL_NOTIFY_INFO_DATA *data,
3043 print_queue_struct *queue,
3044 NT_PRINTER_INFO_LEVEL *printer,
3045 TALLOC_CTX *mem_ctx)
3047 data->notify_data.value[0] = printer->info_2->priority;
3048 data->notify_data.value[1] = 0;
3051 /*******************************************************************
3052 * fill a notify_info_data with the default priority
3053 ********************************************************************/
3055 static void spoolss_notify_default_priority(int snum,
3056 SPOOL_NOTIFY_INFO_DATA *data,
3057 print_queue_struct *queue,
3058 NT_PRINTER_INFO_LEVEL *printer,
3059 TALLOC_CTX *mem_ctx)
3061 data->notify_data.value[0] = printer->info_2->default_priority;
3062 data->notify_data.value[1] = 0;
3065 /*******************************************************************
3066 * fill a notify_info_data with the start time
3067 ********************************************************************/
3069 static void spoolss_notify_start_time(int snum,
3070 SPOOL_NOTIFY_INFO_DATA *data,
3071 print_queue_struct *queue,
3072 NT_PRINTER_INFO_LEVEL *printer,
3073 TALLOC_CTX *mem_ctx)
3075 data->notify_data.value[0] = printer->info_2->starttime;
3076 data->notify_data.value[1] = 0;
3079 /*******************************************************************
3080 * fill a notify_info_data with the until time
3081 ********************************************************************/
3083 static void spoolss_notify_until_time(int snum,
3084 SPOOL_NOTIFY_INFO_DATA *data,
3085 print_queue_struct *queue,
3086 NT_PRINTER_INFO_LEVEL *printer,
3087 TALLOC_CTX *mem_ctx)
3089 data->notify_data.value[0] = printer->info_2->untiltime;
3090 data->notify_data.value[1] = 0;
3093 /*******************************************************************
3094 * fill a notify_info_data with the status
3095 ********************************************************************/
3097 static void spoolss_notify_status(int snum,
3098 SPOOL_NOTIFY_INFO_DATA *data,
3099 print_queue_struct *queue,
3100 NT_PRINTER_INFO_LEVEL *printer,
3101 TALLOC_CTX *mem_ctx)
3103 print_status_struct status;
3105 print_queue_length(snum, &status);
3106 data->notify_data.value[0]=(uint32) status.status;
3107 data->notify_data.value[1] = 0;
3110 /*******************************************************************
3111 * fill a notify_info_data with the number of jobs queued
3112 ********************************************************************/
3114 void spoolss_notify_cjobs(int snum,
3115 SPOOL_NOTIFY_INFO_DATA *data,
3116 print_queue_struct *queue,
3117 NT_PRINTER_INFO_LEVEL *printer,
3118 TALLOC_CTX *mem_ctx)
3120 data->notify_data.value[0] = print_queue_length(snum, NULL);
3121 data->notify_data.value[1] = 0;
3124 /*******************************************************************
3125 * fill a notify_info_data with the average ppm
3126 ********************************************************************/
3128 static void spoolss_notify_average_ppm(int snum,
3129 SPOOL_NOTIFY_INFO_DATA *data,
3130 print_queue_struct *queue,
3131 NT_PRINTER_INFO_LEVEL *printer,
3132 TALLOC_CTX *mem_ctx)
3134 /* always respond 8 pages per minutes */
3135 /* a little hard ! */
3136 data->notify_data.value[0] = printer->info_2->averageppm;
3137 data->notify_data.value[1] = 0;
3140 /*******************************************************************
3141 * fill a notify_info_data with username
3142 ********************************************************************/
3144 static void spoolss_notify_username(int snum,
3145 SPOOL_NOTIFY_INFO_DATA *data,
3146 print_queue_struct *queue,
3147 NT_PRINTER_INFO_LEVEL *printer,
3148 TALLOC_CTX *mem_ctx)
3153 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3155 data->notify_data.data.length = len;
3156 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3158 if (!data->notify_data.data.string) {
3159 data->notify_data.data.length = 0;
3163 memcpy(data->notify_data.data.string, temp, len);
3166 /*******************************************************************
3167 * fill a notify_info_data with job status
3168 ********************************************************************/
3170 static void spoolss_notify_job_status(int snum,
3171 SPOOL_NOTIFY_INFO_DATA *data,
3172 print_queue_struct *queue,
3173 NT_PRINTER_INFO_LEVEL *printer,
3174 TALLOC_CTX *mem_ctx)
3176 data->notify_data.value[0]=nt_printj_status(queue->status);
3177 data->notify_data.value[1] = 0;
3180 /*******************************************************************
3181 * fill a notify_info_data with job name
3182 ********************************************************************/
3184 static void spoolss_notify_job_name(int snum,
3185 SPOOL_NOTIFY_INFO_DATA *data,
3186 print_queue_struct *queue,
3187 NT_PRINTER_INFO_LEVEL *printer,
3188 TALLOC_CTX *mem_ctx)
3193 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3195 data->notify_data.data.length = len;
3196 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3198 if (!data->notify_data.data.string) {
3199 data->notify_data.data.length = 0;
3203 memcpy(data->notify_data.data.string, temp, len);
3206 /*******************************************************************
3207 * fill a notify_info_data with job status
3208 ********************************************************************/
3210 static void spoolss_notify_job_status_string(int snum,
3211 SPOOL_NOTIFY_INFO_DATA *data,
3212 print_queue_struct *queue,
3213 NT_PRINTER_INFO_LEVEL *printer,
3214 TALLOC_CTX *mem_ctx)
3217 * Now we're returning job status codes we just return a "" here. JRA.
3224 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3227 switch (queue->status) {
3232 p = ""; /* NT provides the paused string */
3241 #endif /* NO LONGER NEEDED. */
3243 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3245 data->notify_data.data.length = len;
3246 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3248 if (!data->notify_data.data.string) {
3249 data->notify_data.data.length = 0;
3253 memcpy(data->notify_data.data.string, temp, len);
3256 /*******************************************************************
3257 * fill a notify_info_data with job time
3258 ********************************************************************/
3260 static void spoolss_notify_job_time(int snum,
3261 SPOOL_NOTIFY_INFO_DATA *data,
3262 print_queue_struct *queue,
3263 NT_PRINTER_INFO_LEVEL *printer,
3264 TALLOC_CTX *mem_ctx)
3266 data->notify_data.value[0]=0x0;
3267 data->notify_data.value[1]=0;
3270 /*******************************************************************
3271 * fill a notify_info_data with job size
3272 ********************************************************************/
3274 static void spoolss_notify_job_size(int snum,
3275 SPOOL_NOTIFY_INFO_DATA *data,
3276 print_queue_struct *queue,
3277 NT_PRINTER_INFO_LEVEL *printer,
3278 TALLOC_CTX *mem_ctx)
3280 data->notify_data.value[0]=queue->size;
3281 data->notify_data.value[1]=0;
3284 /*******************************************************************
3285 * fill a notify_info_data with page info
3286 ********************************************************************/
3287 static void spoolss_notify_total_pages(int snum,
3288 SPOOL_NOTIFY_INFO_DATA *data,
3289 print_queue_struct *queue,
3290 NT_PRINTER_INFO_LEVEL *printer,
3291 TALLOC_CTX *mem_ctx)
3293 data->notify_data.value[0]=queue->page_count;
3294 data->notify_data.value[1]=0;
3297 /*******************************************************************
3298 * fill a notify_info_data with pages printed info.
3299 ********************************************************************/
3300 static void spoolss_notify_pages_printed(int snum,
3301 SPOOL_NOTIFY_INFO_DATA *data,
3302 print_queue_struct *queue,
3303 NT_PRINTER_INFO_LEVEL *printer,
3304 TALLOC_CTX *mem_ctx)
3306 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3307 data->notify_data.value[1]=0;
3310 /*******************************************************************
3311 Fill a notify_info_data with job position.
3312 ********************************************************************/
3314 static void spoolss_notify_job_position(int snum,
3315 SPOOL_NOTIFY_INFO_DATA *data,
3316 print_queue_struct *queue,
3317 NT_PRINTER_INFO_LEVEL *printer,
3318 TALLOC_CTX *mem_ctx)
3320 data->notify_data.value[0]=queue->job;
3321 data->notify_data.value[1]=0;
3324 /*******************************************************************
3325 Fill a notify_info_data with submitted time.
3326 ********************************************************************/
3328 static void spoolss_notify_submitted_time(int snum,
3329 SPOOL_NOTIFY_INFO_DATA *data,
3330 print_queue_struct *queue,
3331 NT_PRINTER_INFO_LEVEL *printer,
3332 TALLOC_CTX *mem_ctx)
3339 t=gmtime(&queue->time);
3341 len = sizeof(SYSTEMTIME);
3343 data->notify_data.data.length = len;
3344 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3346 if (!data->notify_data.data.string) {
3347 data->notify_data.data.length = 0;
3351 make_systemtime(&st, t);
3354 * Systemtime must be linearized as a set of UINT16's.
3355 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3358 p = (char *)data->notify_data.data.string;
3359 SSVAL(p, 0, st.year);
3360 SSVAL(p, 2, st.month);
3361 SSVAL(p, 4, st.dayofweek);
3362 SSVAL(p, 6, st.day);
3363 SSVAL(p, 8, st.hour);
3364 SSVAL(p, 10, st.minute);
3365 SSVAL(p, 12, st.second);
3366 SSVAL(p, 14, st.milliseconds);
3369 struct s_notify_info_data_table
3375 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3376 print_queue_struct *queue,
3377 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3380 /* A table describing the various print notification constants and
3381 whether the notification data is a pointer to a variable sized
3382 buffer, a one value uint32 or a two value uint32. */
3384 static const struct s_notify_info_data_table notify_info_data_table[] =
3386 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3387 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3388 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3389 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3412 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3413 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3414 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3415 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3435 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3438 /*******************************************************************
3439 Return the size of info_data structure.
3440 ********************************************************************/
3442 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3446 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3447 if ( (notify_info_data_table[i].type == type)
3448 && (notify_info_data_table[i].field == field) ) {
3449 switch(notify_info_data_table[i].size) {
3450 case NOTIFY_ONE_VALUE:
3451 case NOTIFY_TWO_VALUE:
3456 /* The only pointer notify data I have seen on
3457 the wire is the submitted time and this has
3458 the notify size set to 4. -tpot */
3460 case NOTIFY_POINTER:
3463 case NOTIFY_SECDESC:
3469 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3474 /*******************************************************************
3475 Return the type of notify_info_data.
3476 ********************************************************************/
3478 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3482 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3483 if (notify_info_data_table[i].type == type &&
3484 notify_info_data_table[i].field == field)
3485 return notify_info_data_table[i].size;
3491 /****************************************************************************
3492 ****************************************************************************/
3494 static BOOL search_notify(uint16 type, uint16 field, int *value)
3498 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3499 if (notify_info_data_table[i].type == type &&
3500 notify_info_data_table[i].field == field &&
3501 notify_info_data_table[i].fn != NULL) {
3510 /****************************************************************************
3511 ****************************************************************************/
3513 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3515 info_data->type = type;
3516 info_data->field = field;
3517 info_data->reserved = 0;
3519 info_data->size = size_of_notify_info_data(type, field);
3520 info_data->enc_type = type_of_notify_info_data(type, field);
3525 /*******************************************************************
3527 * fill a notify_info struct with info asked
3529 ********************************************************************/
3531 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3532 snum, SPOOL_NOTIFY_OPTION_TYPE
3533 *option_type, uint32 id,
3534 TALLOC_CTX *mem_ctx)
3540 SPOOL_NOTIFY_INFO_DATA *current_data;
3541 NT_PRINTER_INFO_LEVEL *printer = NULL;
3542 print_queue_struct *queue=NULL;
3544 type=option_type->type;
3546 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3547 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3548 option_type->count, lp_servicename(snum)));
3550 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3553 for(field_num=0; field_num<option_type->count; field_num++) {
3554 field = option_type->fields[field_num];
3556 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3558 if (!search_notify(type, field, &j) )
3561 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3562 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3566 current_data = &info->data[info->count];
3568 construct_info_data(current_data, type, field, id);
3570 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3571 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3573 notify_info_data_table[j].fn(snum, current_data, queue,
3579 free_a_printer(&printer, 2);
3583 /*******************************************************************
3585 * fill a notify_info struct with info asked
3587 ********************************************************************/
3589 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3590 SPOOL_NOTIFY_INFO *info,
3591 NT_PRINTER_INFO_LEVEL *printer,
3592 int snum, SPOOL_NOTIFY_OPTION_TYPE
3593 *option_type, uint32 id,
3594 TALLOC_CTX *mem_ctx)
3600 SPOOL_NOTIFY_INFO_DATA *current_data;
3602 DEBUG(4,("construct_notify_jobs_info\n"));
3604 type = option_type->type;
3606 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3607 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3608 option_type->count));
3610 for(field_num=0; field_num<option_type->count; field_num++) {
3611 field = option_type->fields[field_num];
3613 if (!search_notify(type, field, &j) )
3616 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3617 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3621 current_data=&(info->data[info->count]);
3623 construct_info_data(current_data, type, field, id);
3624 notify_info_data_table[j].fn(snum, current_data, queue,
3633 * JFM: The enumeration is not that simple, it's even non obvious.
3635 * let's take an example: I want to monitor the PRINTER SERVER for
3636 * the printer's name and the number of jobs currently queued.
3637 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3638 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3640 * I have 3 printers on the back of my server.
3642 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3645 * 1 printer 1 name 1
3646 * 2 printer 1 cjob 1
3647 * 3 printer 2 name 2
3648 * 4 printer 2 cjob 2
3649 * 5 printer 3 name 3
3650 * 6 printer 3 name 3
3652 * that's the print server case, the printer case is even worse.
3655 /*******************************************************************
3657 * enumerate all printers on the printserver
3658 * fill a notify_info struct with info asked
3660 ********************************************************************/
3662 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3663 SPOOL_NOTIFY_INFO *info,
3664 TALLOC_CTX *mem_ctx)
3667 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3668 int n_services=lp_numservices();
3670 SPOOL_NOTIFY_OPTION *option;
3671 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3673 DEBUG(4,("printserver_notify_info\n"));
3678 option=Printer->notify.option;
3683 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3684 sending a ffpcn() request first */
3689 for (i=0; i<option->count; i++) {
3690 option_type=&(option->ctr.type[i]);
3692 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3695 for (snum=0; snum<n_services; snum++)
3697 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3698 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3704 * Debugging information, don't delete.
3707 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3708 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3709 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3711 for (i=0; i<info->count; i++) {
3712 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3713 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3714 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3721 /*******************************************************************
3723 * fill a notify_info struct with info asked
3725 ********************************************************************/
3727 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3728 TALLOC_CTX *mem_ctx)
3731 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3734 SPOOL_NOTIFY_OPTION *option;
3735 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3737 print_queue_struct *queue=NULL;
3738 print_status_struct status;
3740 DEBUG(4,("printer_notify_info\n"));
3745 option=Printer->notify.option;
3751 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3752 sending a ffpcn() request first */
3757 get_printer_snum(p, hnd, &snum);
3759 for (i=0; i<option->count; i++) {
3760 option_type=&option->ctr.type[i];
3762 switch ( option_type->type ) {
3763 case PRINTER_NOTIFY_TYPE:
3764 if(construct_notify_printer_info(Printer, info, snum,
3770 case JOB_NOTIFY_TYPE: {
3771 NT_PRINTER_INFO_LEVEL *printer = NULL;
3773 count = print_queue_status(snum, &queue, &status);
3775 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3778 for (j=0; j<count; j++) {
3779 construct_notify_jobs_info(&queue[j], info,
3786 free_a_printer(&printer, 2);
3796 * Debugging information, don't delete.
3799 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3800 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3801 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3803 for (i=0; i<info->count; i++) {
3804 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3805 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3806 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3812 /********************************************************************
3814 ********************************************************************/
3816 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3818 POLICY_HND *handle = &q_u->handle;
3819 SPOOL_NOTIFY_INFO *info = &r_u->info;
3821 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3822 WERROR result = WERR_BADFID;
3824 /* we always have a NOTIFY_INFO struct */
3828 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3829 OUR_HANDLE(handle)));
3833 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3836 * We are now using the change value, and
3837 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3838 * I don't have a global notification system, I'm sending back all the
3839 * informations even when _NOTHING_ has changed.
3842 /* We need to keep track of the change value to send back in
3843 RRPCN replies otherwise our updates are ignored. */
3845 Printer->notify.fnpcn = True;
3847 if (Printer->notify.client_connected) {
3848 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3849 Printer->notify.change = q_u->change;
3852 /* just ignore the SPOOL_NOTIFY_OPTION */
3854 switch (Printer->printer_type) {
3856 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3859 case SPLHND_PRINTER:
3860 result = printer_notify_info(p, handle, info, p->mem_ctx);
3864 Printer->notify.fnpcn = False;
3870 /********************************************************************
3871 * construct_printer_info_0
3872 * fill a printer_info_0 struct
3873 ********************************************************************/
3875 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3879 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3880 counter_printer_0 *session_counter;
3881 uint32 global_counter;
3884 print_status_struct status;
3886 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3889 count = print_queue_length(snum, &status);
3891 /* check if we already have a counter for this printer */
3892 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3893 if (session_counter->snum == snum)
3897 /* it's the first time, add it to the list */
3898 if (session_counter==NULL) {
3899 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3900 free_a_printer(&ntprinter, 2);
3903 ZERO_STRUCTP(session_counter);
3904 session_counter->snum=snum;
3905 session_counter->counter=0;
3906 DLIST_ADD(counter_list, session_counter);
3910 session_counter->counter++;
3913 * the global_counter should be stored in a TDB as it's common to all the clients
3914 * and should be zeroed on samba startup
3916 global_counter=session_counter->counter;
3918 pstrcpy(chaine,ntprinter->info_2->printername);
3920 init_unistr(&printer->printername, chaine);
3922 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3923 init_unistr(&printer->servername, chaine);
3925 printer->cjobs = count;
3926 printer->total_jobs = 0;
3927 printer->total_bytes = 0;
3929 setuptime = (time_t)ntprinter->info_2->setuptime;
3930 t=gmtime(&setuptime);
3932 printer->year = t->tm_year+1900;
3933 printer->month = t->tm_mon+1;
3934 printer->dayofweek = t->tm_wday;
3935 printer->day = t->tm_mday;
3936 printer->hour = t->tm_hour;
3937 printer->minute = t->tm_min;
3938 printer->second = t->tm_sec;
3939 printer->milliseconds = 0;
3941 printer->global_counter = global_counter;
3942 printer->total_pages = 0;
3944 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3945 printer->major_version = 0x0005; /* NT 5 */
3946 printer->build_version = 0x0893; /* build 2195 */
3948 printer->unknown7 = 0x1;
3949 printer->unknown8 = 0x0;
3950 printer->unknown9 = 0x0;
3951 printer->session_counter = session_counter->counter;
3952 printer->unknown11 = 0x0;
3953 printer->printer_errors = 0x0; /* number of print failure */
3954 printer->unknown13 = 0x0;
3955 printer->unknown14 = 0x1;
3956 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3957 printer->unknown16 = 0x0;
3958 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3959 printer->unknown18 = 0x0;
3960 printer->status = nt_printq_status(status.status);
3961 printer->unknown20 = 0x0;
3962 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3963 printer->unknown22 = 0x0;
3964 printer->unknown23 = 0x6; /* 6 ???*/
3965 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3966 printer->unknown25 = 0;
3967 printer->unknown26 = 0;
3968 printer->unknown27 = 0;
3969 printer->unknown28 = 0;
3970 printer->unknown29 = 0;
3972 free_a_printer(&ntprinter,2);
3976 /********************************************************************
3977 * construct_printer_info_1
3978 * fill a printer_info_1 struct
3979 ********************************************************************/
3980 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3984 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3986 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3989 printer->flags=flags;
3991 if (*ntprinter->info_2->comment == '\0') {
3992 init_unistr(&printer->comment, lp_comment(snum));
3993 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3994 ntprinter->info_2->drivername, lp_comment(snum));
3997 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3998 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3999 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4002 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4004 init_unistr(&printer->description, chaine);
4005 init_unistr(&printer->name, chaine2);
4007 free_a_printer(&ntprinter,2);
4012 /****************************************************************************
4013 Free a DEVMODE struct.
4014 ****************************************************************************/
4016 static void free_dev_mode(DEVICEMODE *dev)
4021 SAFE_FREE(dev->dev_private);
4026 /****************************************************************************
4027 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4028 should be valid upon entry
4029 ****************************************************************************/
4031 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4033 if ( !devmode || !ntdevmode )
4036 init_unistr(&devmode->devicename, ntdevmode->devicename);
4038 init_unistr(&devmode->formname, ntdevmode->formname);
4040 devmode->specversion = ntdevmode->specversion;
4041 devmode->driverversion = ntdevmode->driverversion;
4042 devmode->size = ntdevmode->size;
4043 devmode->driverextra = ntdevmode->driverextra;
4044 devmode->fields = ntdevmode->fields;
4046 devmode->orientation = ntdevmode->orientation;
4047 devmode->papersize = ntdevmode->papersize;
4048 devmode->paperlength = ntdevmode->paperlength;
4049 devmode->paperwidth = ntdevmode->paperwidth;
4050 devmode->scale = ntdevmode->scale;
4051 devmode->copies = ntdevmode->copies;
4052 devmode->defaultsource = ntdevmode->defaultsource;
4053 devmode->printquality = ntdevmode->printquality;
4054 devmode->color = ntdevmode->color;
4055 devmode->duplex = ntdevmode->duplex;
4056 devmode->yresolution = ntdevmode->yresolution;
4057 devmode->ttoption = ntdevmode->ttoption;
4058 devmode->collate = ntdevmode->collate;
4059 devmode->icmmethod = ntdevmode->icmmethod;
4060 devmode->icmintent = ntdevmode->icmintent;
4061 devmode->mediatype = ntdevmode->mediatype;
4062 devmode->dithertype = ntdevmode->dithertype;
4064 if (ntdevmode->nt_dev_private != NULL) {
4065 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4072 /****************************************************************************
4073 Create a DEVMODE struct. Returns malloced memory.
4074 ****************************************************************************/
4076 DEVICEMODE *construct_dev_mode(int snum)
4078 NT_PRINTER_INFO_LEVEL *printer = NULL;
4079 DEVICEMODE *devmode = NULL;
4081 DEBUG(7,("construct_dev_mode\n"));
4083 DEBUGADD(8,("getting printer characteristics\n"));
4085 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4088 if ( !printer->info_2->devmode ) {
4089 DEBUG(5, ("BONG! There was no device mode!\n"));
4093 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4094 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4098 ZERO_STRUCTP(devmode);
4100 DEBUGADD(8,("loading DEVICEMODE\n"));
4102 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4103 free_dev_mode( devmode );
4108 free_a_printer(&printer,2);
4113 /********************************************************************
4114 * construct_printer_info_2
4115 * fill a printer_info_2 struct
4116 ********************************************************************/
4118 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4121 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4123 print_status_struct status;
4125 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4128 count = print_queue_length(snum, &status);
4130 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4131 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4132 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4133 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4134 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4136 if (*ntprinter->info_2->comment == '\0')
4137 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4139 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4141 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4142 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4143 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4144 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4145 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4147 printer->attributes = ntprinter->info_2->attributes;
4149 printer->priority = ntprinter->info_2->priority; /* priority */
4150 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4151 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4152 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4153 printer->status = nt_printq_status(status.status); /* status */
4154 printer->cjobs = count; /* jobs */
4155 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4157 if ( !(printer->devmode = construct_dev_mode(snum)) )
4158 DEBUG(8, ("Returning NULL Devicemode!\n"));
4160 printer->secdesc = NULL;
4162 if ( ntprinter->info_2->secdesc_buf
4163 && ntprinter->info_2->secdesc_buf->len != 0 )
4165 /* don't use talloc_steal() here unless you do a deep steal of all
4166 the SEC_DESC members */
4168 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4169 ntprinter->info_2->secdesc_buf->sec );
4172 free_a_printer(&ntprinter, 2);
4177 /********************************************************************
4178 * construct_printer_info_3
4179 * fill a printer_info_3 struct
4180 ********************************************************************/
4182 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4184 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4185 PRINTER_INFO_3 *printer = NULL;
4187 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4191 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4192 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4196 ZERO_STRUCTP(printer);
4198 /* These are the components of the SD we are returning. */
4200 printer->flags = 0x4;
4202 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4203 /* don't use talloc_steal() here unless you do a deep steal of all
4204 the SEC_DESC members */
4206 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4207 ntprinter->info_2->secdesc_buf->sec );
4210 free_a_printer(&ntprinter, 2);
4212 *pp_printer = printer;
4216 /********************************************************************
4217 * construct_printer_info_4
4218 * fill a printer_info_4 struct
4219 ********************************************************************/
4221 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4223 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4225 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4228 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4229 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4230 printer->attributes = ntprinter->info_2->attributes;
4232 free_a_printer(&ntprinter, 2);
4236 /********************************************************************
4237 * construct_printer_info_5
4238 * fill a printer_info_5 struct
4239 ********************************************************************/
4241 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4243 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4245 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4248 init_unistr(&printer->printername, ntprinter->info_2->printername);
4249 init_unistr(&printer->portname, ntprinter->info_2->portname);
4250 printer->attributes = ntprinter->info_2->attributes;
4252 /* these two are not used by NT+ according to MSDN */
4254 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4255 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4257 free_a_printer(&ntprinter, 2);
4262 /********************************************************************
4263 * construct_printer_info_7
4264 * fill a printer_info_7 struct
4265 ********************************************************************/
4267 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4269 char *guid_str = NULL;
4272 if (is_printer_published(print_hnd, snum, &guid)) {
4273 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4274 strupper_m(guid_str);
4275 init_unistr(&printer->guid, guid_str);
4276 printer->action = SPOOL_DS_PUBLISH;
4278 init_unistr(&printer->guid, "");
4279 printer->action = SPOOL_DS_UNPUBLISH;
4285 /********************************************************************
4286 Spoolss_enumprinters.
4287 ********************************************************************/
4289 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4293 int n_services=lp_numservices();
4294 PRINTER_INFO_1 *printers=NULL;
4295 PRINTER_INFO_1 current_prt;
4296 WERROR result = WERR_OK;
4298 DEBUG(4,("enum_all_printers_info_1\n"));
4300 for (snum=0; snum<n_services; snum++) {
4301 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4302 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4304 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4305 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4306 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4310 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4312 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4318 /* check the required size. */
4319 for (i=0; i<*returned; i++)
4320 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4322 if (*needed > offered) {
4323 result = WERR_INSUFFICIENT_BUFFER;
4327 if (!rpcbuf_alloc_size(buffer, *needed)) {
4328 result = WERR_NOMEM;
4332 /* fill the buffer with the structures */
4333 for (i=0; i<*returned; i++)
4334 smb_io_printer_info_1("", buffer, &printers[i], 0);
4339 SAFE_FREE(printers);
4341 if ( !W_ERROR_IS_OK(result) )
4347 /********************************************************************
4348 enum_all_printers_info_1_local.
4349 *********************************************************************/
4351 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4353 DEBUG(4,("enum_all_printers_info_1_local\n"));
4355 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4358 /********************************************************************
4359 enum_all_printers_info_1_name.
4360 *********************************************************************/
4362 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4366 DEBUG(4,("enum_all_printers_info_1_name\n"));
4368 if ((name[0] == '\\') && (name[1] == '\\'))
4371 if (is_myname_or_ipaddr(s)) {
4372 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4375 return WERR_INVALID_NAME;
4378 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4379 /********************************************************************
4380 enum_all_printers_info_1_remote.
4381 *********************************************************************/
4383 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4385 PRINTER_INFO_1 *printer;
4386 fstring printername;
4389 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4390 WERROR result = WERR_OK;
4392 /* JFM: currently it's more a place holder than anything else.
4393 * In the spooler world there is a notion of server registration.
4394 * the print servers are registered on the PDC (in the same domain)
4396 * We should have a TDB here. The registration is done thru an
4397 * undocumented RPC call.
4400 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4405 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4406 slprintf(desc, sizeof(desc)-1,"%s", name);
4407 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4409 init_unistr(&printer->description, desc);
4410 init_unistr(&printer->name, printername);
4411 init_unistr(&printer->comment, comment);
4412 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4414 /* check the required size. */
4415 *needed += spoolss_size_printer_info_1(printer);
4417 if (*needed > offered) {
4418 result = WERR_INSUFFICIENT_BUFFER;
4422 if (!rpcbuf_alloc_size(buffer, *needed)) {
4423 result = WERR_NOMEM;
4427 /* fill the buffer with the structures */
4428 smb_io_printer_info_1("", buffer, printer, 0);
4434 if ( !W_ERROR_IS_OK(result) )
4442 /********************************************************************
4443 enum_all_printers_info_1_network.
4444 *********************************************************************/
4446 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4450 DEBUG(4,("enum_all_printers_info_1_network\n"));
4452 /* If we respond to a enum_printers level 1 on our name with flags
4453 set to PRINTER_ENUM_REMOTE with a list of printers then these
4454 printers incorrectly appear in the APW browse list.
4455 Specifically the printers for the server appear at the workgroup
4456 level where all the other servers in the domain are
4457 listed. Windows responds to this call with a
4458 WERR_CAN_NOT_COMPLETE so we should do the same. */
4460 if (name[0] == '\\' && name[1] == '\\')
4463 if (is_myname_or_ipaddr(s))
4464 return WERR_CAN_NOT_COMPLETE;
4466 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4469 /********************************************************************
4470 * api_spoolss_enumprinters
4472 * called from api_spoolss_enumprinters (see this to understand)
4473 ********************************************************************/
4475 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4479 int n_services=lp_numservices();
4480 PRINTER_INFO_2 *printers=NULL;
4481 PRINTER_INFO_2 current_prt;
4482 WERROR result = WERR_OK;
4486 for (snum=0; snum<n_services; snum++) {
4487 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4488 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4490 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4491 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4492 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4497 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4499 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4506 /* check the required size. */
4507 for (i=0; i<*returned; i++)
4508 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4510 if (*needed > offered) {
4511 result = WERR_INSUFFICIENT_BUFFER;
4515 if (!rpcbuf_alloc_size(buffer, *needed)) {
4516 result = WERR_NOMEM;
4520 /* fill the buffer with the structures */
4521 for (i=0; i<*returned; i++)
4522 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4527 for (i=0; i<*returned; i++)
4528 free_devmode(printers[i].devmode);
4530 SAFE_FREE(printers);
4532 if ( !W_ERROR_IS_OK(result) )
4538 /********************************************************************
4539 * handle enumeration of printers at level 1
4540 ********************************************************************/
4542 static WERROR enumprinters_level1( uint32 flags, fstring name,
4543 RPC_BUFFER *buffer, uint32 offered,
4544 uint32 *needed, uint32 *returned)
4546 /* Not all the flags are equals */
4548 if (flags & PRINTER_ENUM_LOCAL)
4549 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4551 if (flags & PRINTER_ENUM_NAME)
4552 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4554 #if 0 /* JERRY - disabled for now */
4555 if (flags & PRINTER_ENUM_REMOTE)
4556 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4559 if (flags & PRINTER_ENUM_NETWORK)
4560 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4562 return WERR_OK; /* NT4sp5 does that */
4565 /********************************************************************
4566 * handle enumeration of printers at level 2
4567 ********************************************************************/
4569 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4570 RPC_BUFFER *buffer, uint32 offered,
4571 uint32 *needed, uint32 *returned)
4573 char *s = servername;
4575 if (flags & PRINTER_ENUM_LOCAL) {
4576 return enum_all_printers_info_2(buffer, offered, needed, returned);
4579 if (flags & PRINTER_ENUM_NAME) {
4580 if ((servername[0] == '\\') && (servername[1] == '\\'))
4582 if (is_myname_or_ipaddr(s))
4583 return enum_all_printers_info_2(buffer, offered, needed, returned);
4585 return WERR_INVALID_NAME;
4588 if (flags & PRINTER_ENUM_REMOTE)
4589 return WERR_UNKNOWN_LEVEL;
4594 /********************************************************************
4595 * handle enumeration of printers at level 5
4596 ********************************************************************/
4598 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4599 RPC_BUFFER *buffer, uint32 offered,
4600 uint32 *needed, uint32 *returned)
4602 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4606 /********************************************************************
4607 * api_spoolss_enumprinters
4609 * called from api_spoolss_enumprinters (see this to understand)
4610 ********************************************************************/
4612 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4614 uint32 flags = q_u->flags;
4615 UNISTR2 *servername = &q_u->servername;
4616 uint32 level = q_u->level;
4617 RPC_BUFFER *buffer = NULL;
4618 uint32 offered = q_u->offered;
4619 uint32 *needed = &r_u->needed;
4620 uint32 *returned = &r_u->returned;
4624 /* that's an [in out] buffer */
4626 if (!q_u->buffer && (offered!=0)) {
4627 return WERR_INVALID_PARAM;
4630 rpcbuf_move(q_u->buffer, &r_u->buffer);
4631 buffer = r_u->buffer;
4633 DEBUG(4,("_spoolss_enumprinters\n"));
4640 * flags==PRINTER_ENUM_NAME
4641 * if name=="" then enumerates all printers
4642 * if name!="" then enumerate the printer
4643 * flags==PRINTER_ENUM_REMOTE
4644 * name is NULL, enumerate printers
4645 * Level 2: name!="" enumerates printers, name can't be NULL
4646 * Level 3: doesn't exist
4647 * Level 4: does a local registry lookup
4648 * Level 5: same as Level 2
4651 unistr2_to_ascii(name, servername, sizeof(name)-1);
4656 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4658 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4660 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4665 return WERR_UNKNOWN_LEVEL;
4668 /****************************************************************************
4669 ****************************************************************************/
4671 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4673 PRINTER_INFO_0 *printer=NULL;
4674 WERROR result = WERR_OK;
4676 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4679 construct_printer_info_0(print_hnd, printer, snum);
4681 /* check the required size. */
4682 *needed += spoolss_size_printer_info_0(printer);
4684 if (*needed > offered) {
4685 result = WERR_INSUFFICIENT_BUFFER;
4689 if (!rpcbuf_alloc_size(buffer, *needed)) {
4690 result = WERR_NOMEM;
4694 /* fill the buffer with the structures */
4695 smb_io_printer_info_0("", buffer, printer, 0);
4705 /****************************************************************************
4706 ****************************************************************************/
4708 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4710 PRINTER_INFO_1 *printer=NULL;
4711 WERROR result = WERR_OK;
4713 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4716 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4718 /* check the required size. */
4719 *needed += spoolss_size_printer_info_1(printer);
4721 if (*needed > offered) {
4722 result = WERR_INSUFFICIENT_BUFFER;
4726 if (!rpcbuf_alloc_size(buffer, *needed)) {
4727 result = WERR_NOMEM;
4731 /* fill the buffer with the structures */
4732 smb_io_printer_info_1("", buffer, printer, 0);
4741 /****************************************************************************
4742 ****************************************************************************/
4744 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4746 PRINTER_INFO_2 *printer=NULL;
4747 WERROR result = WERR_OK;
4749 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4752 construct_printer_info_2(print_hnd, printer, snum);
4754 /* check the required size. */
4755 *needed += spoolss_size_printer_info_2(printer);
4757 if (*needed > offered) {
4758 result = WERR_INSUFFICIENT_BUFFER;
4762 if (!rpcbuf_alloc_size(buffer, *needed)) {
4763 result = WERR_NOMEM;
4767 /* fill the buffer with the structures */
4768 if (!smb_io_printer_info_2("", buffer, printer, 0))
4769 result = WERR_NOMEM;
4773 free_printer_info_2(printer);
4778 /****************************************************************************
4779 ****************************************************************************/
4781 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4783 PRINTER_INFO_3 *printer=NULL;
4784 WERROR result = WERR_OK;
4786 if (!construct_printer_info_3(print_hnd, &printer, snum))
4789 /* check the required size. */
4790 *needed += spoolss_size_printer_info_3(printer);
4792 if (*needed > offered) {
4793 result = WERR_INSUFFICIENT_BUFFER;
4797 if (!rpcbuf_alloc_size(buffer, *needed)) {
4798 result = WERR_NOMEM;
4802 /* fill the buffer with the structures */
4803 smb_io_printer_info_3("", buffer, printer, 0);
4807 free_printer_info_3(printer);
4812 /****************************************************************************
4813 ****************************************************************************/
4815 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4817 PRINTER_INFO_4 *printer=NULL;
4818 WERROR result = WERR_OK;
4820 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4823 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4828 /* check the required size. */
4829 *needed += spoolss_size_printer_info_4(printer);
4831 if (*needed > offered) {
4832 result = WERR_INSUFFICIENT_BUFFER;
4836 if (!rpcbuf_alloc_size(buffer, *needed)) {
4837 result = WERR_NOMEM;
4841 /* fill the buffer with the structures */
4842 smb_io_printer_info_4("", buffer, printer, 0);
4846 free_printer_info_4(printer);
4851 /****************************************************************************
4852 ****************************************************************************/
4854 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4856 PRINTER_INFO_5 *printer=NULL;
4857 WERROR result = WERR_OK;
4859 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4862 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4863 free_printer_info_5(printer);
4867 /* check the required size. */
4868 *needed += spoolss_size_printer_info_5(printer);
4870 if (*needed > offered) {
4871 result = WERR_INSUFFICIENT_BUFFER;
4875 if (!rpcbuf_alloc_size(buffer, *needed)) {
4876 result = WERR_NOMEM;
4880 /* fill the buffer with the structures */
4881 smb_io_printer_info_5("", buffer, printer, 0);
4885 free_printer_info_5(printer);
4890 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4892 PRINTER_INFO_7 *printer=NULL;
4893 WERROR result = WERR_OK;
4895 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4898 if (!construct_printer_info_7(print_hnd, printer, snum))
4901 /* check the required size. */
4902 *needed += spoolss_size_printer_info_7(printer);
4904 if (*needed > offered) {
4905 result = WERR_INSUFFICIENT_BUFFER;
4909 if (!rpcbuf_alloc_size(buffer, *needed)) {
4910 result = WERR_NOMEM;
4915 /* fill the buffer with the structures */
4916 smb_io_printer_info_7("", buffer, printer, 0);
4920 free_printer_info_7(printer);
4925 /****************************************************************************
4926 ****************************************************************************/
4928 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4930 POLICY_HND *handle = &q_u->handle;
4931 uint32 level = q_u->level;
4932 RPC_BUFFER *buffer = NULL;
4933 uint32 offered = q_u->offered;
4934 uint32 *needed = &r_u->needed;
4935 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4939 /* that's an [in out] buffer */
4941 if (!q_u->buffer && (offered!=0)) {
4942 return WERR_INVALID_PARAM;
4945 rpcbuf_move(q_u->buffer, &r_u->buffer);
4946 buffer = r_u->buffer;
4950 if (!get_printer_snum(p, handle, &snum))
4955 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4957 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4959 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4961 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4963 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4965 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4967 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4969 return WERR_UNKNOWN_LEVEL;
4972 /********************************************************************
4973 * fill a DRIVER_INFO_1 struct
4974 ********************************************************************/
4976 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4978 init_unistr( &info->name, driver.info_3->name);
4981 /********************************************************************
4982 * construct_printer_driver_info_1
4983 ********************************************************************/
4985 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4987 NT_PRINTER_INFO_LEVEL *printer = NULL;
4988 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4990 ZERO_STRUCT(driver);
4992 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4993 return WERR_INVALID_PRINTER_NAME;
4995 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4996 return WERR_UNKNOWN_PRINTER_DRIVER;
4998 fill_printer_driver_info_1(info, driver, servername, architecture);
5000 free_a_printer(&printer,2);
5005 /********************************************************************
5006 * construct_printer_driver_info_2
5007 * fill a printer_info_2 struct
5008 ********************************************************************/
5010 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5014 info->version=driver.info_3->cversion;
5016 init_unistr( &info->name, driver.info_3->name );
5017 init_unistr( &info->architecture, driver.info_3->environment );
5020 if (strlen(driver.info_3->driverpath)) {
5021 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5022 init_unistr( &info->driverpath, temp );
5024 init_unistr( &info->driverpath, "" );
5026 if (strlen(driver.info_3->datafile)) {
5027 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5028 init_unistr( &info->datafile, temp );
5030 init_unistr( &info->datafile, "" );
5032 if (strlen(driver.info_3->configfile)) {
5033 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5034 init_unistr( &info->configfile, temp );
5036 init_unistr( &info->configfile, "" );
5039 /********************************************************************
5040 * construct_printer_driver_info_2
5041 * fill a printer_info_2 struct
5042 ********************************************************************/
5044 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5046 NT_PRINTER_INFO_LEVEL *printer = NULL;
5047 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5049 ZERO_STRUCT(printer);
5050 ZERO_STRUCT(driver);
5052 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5053 return WERR_INVALID_PRINTER_NAME;
5055 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5056 return WERR_UNKNOWN_PRINTER_DRIVER;
5058 fill_printer_driver_info_2(info, driver, servername);
5060 free_a_printer(&printer,2);
5065 /********************************************************************
5066 * copy a strings array and convert to UNICODE
5068 * convert an array of ascii string to a UNICODE string
5069 ********************************************************************/
5071 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5078 DEBUG(6,("init_unistr_array\n"));
5089 v = ""; /* hack to handle null lists */
5092 /* hack to allow this to be used in places other than when generating
5093 the list of dependent files */
5096 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5100 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5102 /* add one extra unit16 for the second terminating NULL */
5104 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5105 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5112 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5117 /* special case for ""; we need to add both NULL's here */
5119 (*uni_array)[j++]=0x0000;
5120 (*uni_array)[j]=0x0000;
5123 DEBUGADD(6,("last one:done\n"));
5125 /* return size of array in uint16's */
5130 /********************************************************************
5131 * construct_printer_info_3
5132 * fill a printer_info_3 struct
5133 ********************************************************************/
5135 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5141 info->version=driver.info_3->cversion;
5143 init_unistr( &info->name, driver.info_3->name );
5144 init_unistr( &info->architecture, driver.info_3->environment );
5146 if (strlen(driver.info_3->driverpath)) {
5147 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5148 init_unistr( &info->driverpath, temp );
5150 init_unistr( &info->driverpath, "" );
5152 if (strlen(driver.info_3->datafile)) {
5153 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5154 init_unistr( &info->datafile, temp );
5156 init_unistr( &info->datafile, "" );
5158 if (strlen(driver.info_3->configfile)) {
5159 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5160 init_unistr( &info->configfile, temp );
5162 init_unistr( &info->configfile, "" );
5164 if (strlen(driver.info_3->helpfile)) {
5165 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5166 init_unistr( &info->helpfile, temp );
5168 init_unistr( &info->helpfile, "" );
5170 init_unistr( &info->monitorname, driver.info_3->monitorname );
5171 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5173 info->dependentfiles=NULL;
5174 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5177 /********************************************************************
5178 * construct_printer_info_3
5179 * fill a printer_info_3 struct
5180 ********************************************************************/
5182 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5184 NT_PRINTER_INFO_LEVEL *printer = NULL;
5185 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5187 ZERO_STRUCT(driver);
5189 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5190 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5191 if (!W_ERROR_IS_OK(status))
5192 return WERR_INVALID_PRINTER_NAME;
5194 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5195 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5200 * I put this code in during testing. Helpful when commenting out the
5201 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5202 * as win2k always queries the driver using an infor level of 6.
5203 * I've left it in (but ifdef'd out) because I'll probably
5204 * use it in experimentation again in the future. --jerry 22/01/2002
5207 if (!W_ERROR_IS_OK(status)) {
5209 * Is this a W2k client ?
5212 /* Yes - try again with a WinNT driver. */
5214 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5215 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5219 if (!W_ERROR_IS_OK(status)) {
5220 free_a_printer(&printer,2);
5221 return WERR_UNKNOWN_PRINTER_DRIVER;
5229 fill_printer_driver_info_3(info, driver, servername);
5231 free_a_printer(&printer,2);
5236 /********************************************************************
5237 * construct_printer_info_6
5238 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5239 ********************************************************************/
5241 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5247 memset(&nullstr, '\0', sizeof(fstring));
5249 info->version=driver.info_3->cversion;
5251 init_unistr( &info->name, driver.info_3->name );
5252 init_unistr( &info->architecture, driver.info_3->environment );
5254 if (strlen(driver.info_3->driverpath)) {
5255 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5256 init_unistr( &info->driverpath, temp );
5258 init_unistr( &info->driverpath, "" );
5260 if (strlen(driver.info_3->datafile)) {
5261 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5262 init_unistr( &info->datafile, temp );
5264 init_unistr( &info->datafile, "" );
5266 if (strlen(driver.info_3->configfile)) {
5267 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5268 init_unistr( &info->configfile, temp );
5270 init_unistr( &info->configfile, "" );
5272 if (strlen(driver.info_3->helpfile)) {
5273 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5274 init_unistr( &info->helpfile, temp );
5276 init_unistr( &info->helpfile, "" );
5278 init_unistr( &info->monitorname, driver.info_3->monitorname );
5279 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5281 info->dependentfiles = NULL;
5282 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5284 info->previousdrivernames=NULL;
5285 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5287 info->driver_date.low=0;
5288 info->driver_date.high=0;
5291 info->driver_version_low=0;
5292 info->driver_version_high=0;
5294 init_unistr( &info->mfgname, "");
5295 init_unistr( &info->oem_url, "");
5296 init_unistr( &info->hardware_id, "");
5297 init_unistr( &info->provider, "");
5300 /********************************************************************
5301 * construct_printer_info_6
5302 * fill a printer_info_6 struct
5303 ********************************************************************/
5305 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5306 fstring servername, fstring architecture, uint32 version)
5308 NT_PRINTER_INFO_LEVEL *printer = NULL;
5309 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5312 ZERO_STRUCT(driver);
5314 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5316 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5318 if (!W_ERROR_IS_OK(status))
5319 return WERR_INVALID_PRINTER_NAME;
5321 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5323 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5325 if (!W_ERROR_IS_OK(status))
5328 * Is this a W2k client ?
5332 free_a_printer(&printer,2);
5333 return WERR_UNKNOWN_PRINTER_DRIVER;
5336 /* Yes - try again with a WinNT driver. */
5338 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5339 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5340 if (!W_ERROR_IS_OK(status)) {
5341 free_a_printer(&printer,2);
5342 return WERR_UNKNOWN_PRINTER_DRIVER;
5346 fill_printer_driver_info_6(info, driver, servername);
5348 free_a_printer(&printer,2);
5349 free_a_printer_driver(driver, 3);
5354 /****************************************************************************
5355 ****************************************************************************/
5357 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5359 SAFE_FREE(info->dependentfiles);
5362 /****************************************************************************
5363 ****************************************************************************/
5365 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5367 SAFE_FREE(info->dependentfiles);
5370 /****************************************************************************
5371 ****************************************************************************/
5373 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5375 DRIVER_INFO_1 *info=NULL;
5378 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5381 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5382 if (!W_ERROR_IS_OK(result))
5385 /* check the required size. */
5386 *needed += spoolss_size_printer_driver_info_1(info);
5388 if (*needed > offered) {
5389 result = WERR_INSUFFICIENT_BUFFER;
5393 if (!rpcbuf_alloc_size(buffer, *needed)) {
5394 result = WERR_NOMEM;
5398 /* fill the buffer with the structures */
5399 smb_io_printer_driver_info_1("", buffer, info, 0);
5408 /****************************************************************************
5409 ****************************************************************************/
5411 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5413 DRIVER_INFO_2 *info=NULL;
5416 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5419 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5420 if (!W_ERROR_IS_OK(result))
5423 /* check the required size. */
5424 *needed += spoolss_size_printer_driver_info_2(info);
5426 if (*needed > offered) {
5427 result = WERR_INSUFFICIENT_BUFFER;
5431 if (!rpcbuf_alloc_size(buffer, *needed)) {
5432 result = WERR_NOMEM;
5436 /* fill the buffer with the structures */
5437 smb_io_printer_driver_info_2("", buffer, info, 0);
5446 /****************************************************************************
5447 ****************************************************************************/
5449 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5456 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5457 if (!W_ERROR_IS_OK(result))
5460 /* check the required size. */
5461 *needed += spoolss_size_printer_driver_info_3(&info);
5463 if (*needed > offered) {
5464 result = WERR_INSUFFICIENT_BUFFER;
5468 if (!rpcbuf_alloc_size(buffer, *needed)) {
5469 result = WERR_NOMEM;
5473 /* fill the buffer with the structures */
5474 smb_io_printer_driver_info_3("", buffer, &info, 0);
5477 free_printer_driver_info_3(&info);
5482 /****************************************************************************
5483 ****************************************************************************/
5485 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5492 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5493 if (!W_ERROR_IS_OK(result))
5496 /* check the required size. */
5497 *needed += spoolss_size_printer_driver_info_6(&info);
5499 if (*needed > offered) {
5500 result = WERR_INSUFFICIENT_BUFFER;
5504 if (!rpcbuf_alloc_size(buffer, *needed)) {
5505 result = WERR_NOMEM;
5509 /* fill the buffer with the structures */
5510 smb_io_printer_driver_info_6("", buffer, &info, 0);
5513 free_printer_driver_info_6(&info);
5518 /****************************************************************************
5519 ****************************************************************************/
5521 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5523 POLICY_HND *handle = &q_u->handle;
5524 UNISTR2 *uni_arch = &q_u->architecture;
5525 uint32 level = q_u->level;
5526 uint32 clientmajorversion = q_u->clientmajorversion;
5527 RPC_BUFFER *buffer = NULL;
5528 uint32 offered = q_u->offered;
5529 uint32 *needed = &r_u->needed;
5530 uint32 *servermajorversion = &r_u->servermajorversion;
5531 uint32 *serverminorversion = &r_u->serverminorversion;
5532 Printer_entry *printer;
5535 fstring architecture;
5538 /* that's an [in out] buffer */
5540 if (!q_u->buffer && (offered!=0)) {
5541 return WERR_INVALID_PARAM;
5544 rpcbuf_move(q_u->buffer, &r_u->buffer);
5545 buffer = r_u->buffer;
5547 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5549 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5550 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5551 return WERR_INVALID_PRINTER_NAME;
5555 *servermajorversion = 0;
5556 *serverminorversion = 0;
5558 fstrcpy(servername, get_server_name( printer ));
5559 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5561 if (!get_printer_snum(p, handle, &snum))
5566 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5568 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5570 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5572 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5575 /* apparently this call is the equivalent of
5576 EnumPrinterDataEx() for the DsDriver key */
5581 return WERR_UNKNOWN_LEVEL;
5584 /****************************************************************************
5585 ****************************************************************************/
5587 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5589 POLICY_HND *handle = &q_u->handle;
5591 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5594 DEBUG(3,("Error in startpageprinter printer handle\n"));
5598 Printer->page_started=True;
5602 /****************************************************************************
5603 ****************************************************************************/
5605 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5607 POLICY_HND *handle = &q_u->handle;
5610 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5613 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5617 if (!get_printer_snum(p, handle, &snum))
5620 Printer->page_started=False;
5621 print_job_endpage(snum, Printer->jobid);
5626 /********************************************************************
5627 * api_spoolss_getprinter
5628 * called from the spoolss dispatcher
5630 ********************************************************************/
5632 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5634 POLICY_HND *handle = &q_u->handle;
5635 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5636 uint32 *jobid = &r_u->jobid;
5638 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5642 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5643 struct current_user user;
5646 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5650 get_current_user(&user, p);
5653 * a nice thing with NT is it doesn't listen to what you tell it.
5654 * when asked to send _only_ RAW datas, it tries to send datas
5657 * So I add checks like in NT Server ...
5660 if (info_1->p_datatype != 0) {
5661 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5662 if (strcmp(datatype, "RAW") != 0) {
5664 return WERR_INVALID_DATATYPE;
5668 /* get the share number of the printer */
5669 if (!get_printer_snum(p, handle, &snum)) {
5673 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5675 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5677 /* An error occured in print_job_start() so return an appropriate
5680 if (Printer->jobid == -1) {
5681 return map_werror_from_unix(errno);
5684 Printer->document_started=True;
5685 (*jobid) = Printer->jobid;
5690 /********************************************************************
5691 * api_spoolss_getprinter
5692 * called from the spoolss dispatcher
5694 ********************************************************************/
5696 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5698 POLICY_HND *handle = &q_u->handle;
5700 return _spoolss_enddocprinter_internal(p, handle);
5703 /****************************************************************************
5704 ****************************************************************************/
5706 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5708 POLICY_HND *handle = &q_u->handle;
5709 uint32 buffer_size = q_u->buffer_size;
5710 uint8 *buffer = q_u->buffer;
5711 uint32 *buffer_written = &q_u->buffer_size2;
5713 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5716 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5717 r_u->buffer_written = q_u->buffer_size2;
5721 if (!get_printer_snum(p, handle, &snum))
5724 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5725 (SMB_OFF_T)-1, (size_t)buffer_size);
5726 if (*buffer_written == (uint32)-1) {
5727 r_u->buffer_written = 0;
5728 if (errno == ENOSPC)
5729 return WERR_NO_SPOOL_SPACE;
5731 return WERR_ACCESS_DENIED;
5734 r_u->buffer_written = q_u->buffer_size2;
5739 /********************************************************************
5740 * api_spoolss_getprinter
5741 * called from the spoolss dispatcher
5743 ********************************************************************/
5745 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5748 struct current_user user;
5750 WERROR errcode = WERR_BADFUNC;
5751 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5753 get_current_user(&user, p);
5756 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5760 if (!get_printer_snum(p, handle, &snum))
5764 case PRINTER_CONTROL_PAUSE:
5765 if (print_queue_pause(&user, snum, &errcode)) {
5769 case PRINTER_CONTROL_RESUME:
5770 case PRINTER_CONTROL_UNPAUSE:
5771 if (print_queue_resume(&user, snum, &errcode)) {
5775 case PRINTER_CONTROL_PURGE:
5776 if (print_queue_purge(&user, snum, &errcode)) {
5781 return WERR_UNKNOWN_LEVEL;
5787 /********************************************************************
5788 * api_spoolss_abortprinter
5789 * From MSDN: "Deletes printer's spool file if printer is configured
5791 ********************************************************************/
5793 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5795 POLICY_HND *handle = &q_u->handle;
5796 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5798 struct current_user user;
5799 WERROR errcode = WERR_OK;
5802 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5806 if (!get_printer_snum(p, handle, &snum))
5809 get_current_user( &user, p );
5811 print_job_delete( &user, snum, Printer->jobid, &errcode );
5816 /********************************************************************
5817 * called by spoolss_api_setprinter
5818 * when updating a printer description
5819 ********************************************************************/
5821 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5822 const SPOOL_PRINTER_INFO_LEVEL *info,
5823 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5825 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5829 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5831 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5832 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5833 OUR_HANDLE(handle)));
5835 result = WERR_BADFID;
5839 /* Check the user has permissions to change the security
5840 descriptor. By experimentation with two NT machines, the user
5841 requires Full Access to the printer to change security
5844 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5845 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5846 result = WERR_ACCESS_DENIED;
5850 /* NT seems to like setting the security descriptor even though
5851 nothing may have actually changed. */
5853 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5855 if (DEBUGLEVEL >= 10) {
5859 the_acl = old_secdesc_ctr->sec->dacl;
5860 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5861 PRINTERNAME(snum), the_acl->num_aces));
5863 for (i = 0; i < the_acl->num_aces; i++) {
5866 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5868 DEBUG(10, ("%s 0x%08x\n", sid_str,
5869 the_acl->ace[i].info.mask));
5872 the_acl = secdesc_ctr->sec->dacl;
5875 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5876 PRINTERNAME(snum), the_acl->num_aces));
5878 for (i = 0; i < the_acl->num_aces; i++) {
5881 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5883 DEBUG(10, ("%s 0x%08x\n", sid_str,
5884 the_acl->ace[i].info.mask));
5887 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5891 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5892 if (!new_secdesc_ctr) {
5893 result = WERR_NOMEM;
5897 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5902 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5909 /********************************************************************
5910 Canonicalize printer info from a client
5912 ATTN: It does not matter what we set the servername to hear
5913 since we do the necessary work in get_a_printer() to set it to
5914 the correct value based on what the client sent in the
5915 _spoolss_open_printer_ex().
5916 ********************************************************************/
5918 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5920 fstring printername;
5923 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5924 "portname=%s drivername=%s comment=%s location=%s\n",
5925 info->servername, info->printername, info->sharename,
5926 info->portname, info->drivername, info->comment, info->location));
5928 /* we force some elements to "correct" values */
5929 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5930 fstrcpy(info->sharename, lp_servicename(snum));
5932 /* check to see if we allow printername != sharename */
5934 if ( lp_force_printername(snum) ) {
5935 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5936 global_myname(), info->sharename );
5939 /* make sure printername is in \\server\printername format */
5941 fstrcpy( printername, info->printername );
5943 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5944 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5948 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5949 global_myname(), p );
5952 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5953 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5960 /****************************************************************************
5961 ****************************************************************************/
5963 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
5965 char *cmd = lp_addport_cmd();
5969 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5970 BOOL is_print_op = False;
5973 return WERR_ACCESS_DENIED;
5976 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
5979 is_print_op = user_has_privileges( token, &se_printop );
5981 DEBUG(10,("Running [%s]\n", command));
5983 /********* BEGIN SePrintOperatorPrivilege **********/
5988 ret = smbrun(command, &fd);
5993 /********* END SePrintOperatorPrivilege **********/
5995 DEBUGADD(10,("returned [%d]\n", ret));
6000 return WERR_ACCESS_DENIED;
6006 /****************************************************************************
6007 ****************************************************************************/
6009 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6011 char *cmd = lp_addprinter_cmd();
6017 fstring remote_machine = "%m";
6018 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6019 BOOL is_print_op = False;
6021 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6023 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6024 cmd, printer->info_2->printername, printer->info_2->sharename,
6025 printer->info_2->portname, printer->info_2->drivername,
6026 printer->info_2->location, printer->info_2->comment, remote_machine);
6029 is_print_op = user_has_privileges( token, &se_printop );
6031 DEBUG(10,("Running [%s]\n", command));
6033 /********* BEGIN SePrintOperatorPrivilege **********/
6038 if ( (ret = smbrun(command, &fd)) == 0 ) {
6039 /* Tell everyone we updated smb.conf. */
6040 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6046 /********* END SePrintOperatorPrivilege **********/
6048 DEBUGADD(10,("returned [%d]\n", ret));
6056 /* reload our services immediately */
6057 reload_services( False );
6060 /* Get lines and convert them back to dos-codepage */
6061 qlines = fd_lines_load(fd, &numlines, 0);
6062 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6065 /* Set the portname to what the script says the portname should be. */
6066 /* but don't require anything to be return from the script exit a good error code */
6069 /* Set the portname to what the script says the portname should be. */
6070 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6071 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6074 file_lines_free(qlines);
6079 /********************************************************************
6080 * Called by spoolss_api_setprinter
6081 * when updating a printer description.
6082 ********************************************************************/
6084 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6085 const SPOOL_PRINTER_INFO_LEVEL *info,
6086 DEVICEMODE *devmode)
6089 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6090 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6095 DEBUG(8,("update_printer\n"));
6100 result = WERR_BADFID;
6104 if (!get_printer_snum(p, handle, &snum)) {
6105 result = WERR_BADFID;
6109 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6110 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6111 result = WERR_BADFID;
6115 DEBUGADD(8,("Converting info_2 struct\n"));
6118 * convert_printer_info converts the incoming
6119 * info from the client and overwrites the info
6120 * just read from the tdb in the pointer 'printer'.
6123 if (!convert_printer_info(info, printer, level)) {
6124 result = WERR_NOMEM;
6129 /* we have a valid devmode
6130 convert it and link it*/
6132 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6133 if (!convert_devicemode(printer->info_2->printername, devmode,
6134 &printer->info_2->devmode)) {
6135 result = WERR_NOMEM;
6140 /* Do sanity check on the requested changes for Samba */
6142 if (!check_printer_ok(printer->info_2, snum)) {
6143 result = WERR_INVALID_PARAM;
6147 /* FIXME!!! If the driver has changed we really should verify that
6148 it is installed before doing much else --jerry */
6150 /* Check calling user has permission to update printer description */
6152 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6153 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6154 result = WERR_ACCESS_DENIED;
6158 /* Call addprinter hook */
6159 /* Check changes to see if this is really needed */
6161 if ( *lp_addprinter_cmd()
6162 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6163 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6164 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6165 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6167 /* add_printer_hook() will call reload_services() */
6169 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6170 result = WERR_ACCESS_DENIED;
6176 * When a *new* driver is bound to a printer, the drivername is used to
6177 * lookup previously saved driver initialization info, which is then
6178 * bound to the printer, simulating what happens in the Windows arch.
6180 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6182 if (!set_driver_init(printer, 2))
6184 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6185 printer->info_2->drivername));
6188 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6189 printer->info_2->drivername));
6191 notify_printer_driver(snum, printer->info_2->drivername);
6195 * flag which changes actually occured. This is a small subset of
6196 * all the possible changes. We also have to update things in the
6200 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6201 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6202 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6203 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6205 notify_printer_comment(snum, printer->info_2->comment);
6208 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6209 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6210 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6211 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6213 notify_printer_sharename(snum, printer->info_2->sharename);
6216 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6219 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6222 pname = printer->info_2->printername;
6225 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6226 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6227 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6229 notify_printer_printername( snum, pname );
6232 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6233 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6234 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6235 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6237 notify_printer_port(snum, printer->info_2->portname);
6240 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6241 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6242 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6243 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6245 notify_printer_location(snum, printer->info_2->location);
6248 /* here we need to update some more DsSpooler keys */
6249 /* uNCName, serverName, shortServerName */
6251 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6252 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6253 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6254 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6255 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6257 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6258 global_myname(), printer->info_2->sharename );
6259 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6260 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6261 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6263 /* Update printer info */
6264 result = mod_a_printer(printer, 2);
6267 free_a_printer(&printer, 2);
6268 free_a_printer(&old_printer, 2);
6274 /****************************************************************************
6275 ****************************************************************************/
6276 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6277 const SPOOL_PRINTER_INFO_LEVEL *info)
6280 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6282 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6284 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6289 if (!get_printer_snum(p, handle, &snum))
6292 nt_printer_publish(Printer, snum, info7->action);
6296 return WERR_UNKNOWN_LEVEL;
6299 /****************************************************************************
6300 ****************************************************************************/
6302 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6304 POLICY_HND *handle = &q_u->handle;
6305 uint32 level = q_u->level;
6306 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6307 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6308 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6309 uint32 command = q_u->command;
6312 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6315 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6319 /* check the level */
6322 return control_printer(handle, command, p);
6324 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6325 if (!W_ERROR_IS_OK(result))
6328 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6331 return update_printer_sec(handle, level, info, p,
6334 return publish_or_unpublish_printer(p, handle, info);
6336 return WERR_UNKNOWN_LEVEL;
6340 /****************************************************************************
6341 ****************************************************************************/
6343 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6345 POLICY_HND *handle = &q_u->handle;
6346 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6349 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6353 if (Printer->notify.client_connected==True) {
6356 if ( Printer->printer_type == SPLHND_SERVER)
6358 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6359 !get_printer_snum(p, handle, &snum) )
6362 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6365 Printer->notify.flags=0;
6366 Printer->notify.options=0;
6367 Printer->notify.localmachine[0]='\0';
6368 Printer->notify.printerlocal=0;
6369 if (Printer->notify.option)
6370 free_spool_notify_option(&Printer->notify.option);
6371 Printer->notify.client_connected=False;
6376 /****************************************************************************
6377 ****************************************************************************/
6379 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6381 /* that's an [in out] buffer */
6383 if (!q_u->buffer && (q_u->offered!=0)) {
6384 return WERR_INVALID_PARAM;
6387 rpcbuf_move(q_u->buffer, &r_u->buffer);
6390 return WERR_INVALID_PARAM; /* this is what a NT server
6391 returns for AddJob. AddJob
6392 must fail on non-local
6396 /****************************************************************************
6397 ****************************************************************************/
6399 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6400 int position, int snum,
6401 NT_PRINTER_INFO_LEVEL *ntprinter)
6405 t=gmtime(&queue->time);
6407 job_info->jobid=queue->job;
6408 init_unistr(&job_info->printername, lp_servicename(snum));
6409 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6410 init_unistr(&job_info->username, queue->fs_user);
6411 init_unistr(&job_info->document, queue->fs_file);
6412 init_unistr(&job_info->datatype, "RAW");
6413 init_unistr(&job_info->text_status, "");
6414 job_info->status=nt_printj_status(queue->status);
6415 job_info->priority=queue->priority;
6416 job_info->position=position;
6417 job_info->totalpages=queue->page_count;
6418 job_info->pagesprinted=0;
6420 make_systemtime(&job_info->submitted, t);
6423 /****************************************************************************
6424 ****************************************************************************/
6426 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6427 int position, int snum,
6428 NT_PRINTER_INFO_LEVEL *ntprinter,
6429 DEVICEMODE *devmode)
6433 t=gmtime(&queue->time);
6435 job_info->jobid=queue->job;
6437 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6439 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6440 init_unistr(&job_info->username, queue->fs_user);
6441 init_unistr(&job_info->document, queue->fs_file);
6442 init_unistr(&job_info->notifyname, queue->fs_user);
6443 init_unistr(&job_info->datatype, "RAW");
6444 init_unistr(&job_info->printprocessor, "winprint");
6445 init_unistr(&job_info->parameters, "");
6446 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6447 init_unistr(&job_info->text_status, "");
6449 /* and here the security descriptor */
6451 job_info->status=nt_printj_status(queue->status);
6452 job_info->priority=queue->priority;
6453 job_info->position=position;
6454 job_info->starttime=0;
6455 job_info->untiltime=0;
6456 job_info->totalpages=queue->page_count;
6457 job_info->size=queue->size;
6458 make_systemtime(&(job_info->submitted), t);
6459 job_info->timeelapsed=0;
6460 job_info->pagesprinted=0;
6462 job_info->devmode = devmode;
6467 /****************************************************************************
6468 Enumjobs at level 1.
6469 ****************************************************************************/
6471 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6472 NT_PRINTER_INFO_LEVEL *ntprinter,
6473 RPC_BUFFER *buffer, uint32 offered,
6474 uint32 *needed, uint32 *returned)
6478 WERROR result = WERR_OK;
6480 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6487 for (i=0; i<*returned; i++)
6488 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6492 /* check the required size. */
6493 for (i=0; i<*returned; i++)
6494 (*needed) += spoolss_size_job_info_1(&info[i]);
6496 if (*needed > offered) {
6497 result = WERR_INSUFFICIENT_BUFFER;
6501 if (!rpcbuf_alloc_size(buffer, *needed)) {
6502 result = WERR_NOMEM;
6506 /* fill the buffer with the structures */
6507 for (i=0; i<*returned; i++)
6508 smb_io_job_info_1("", buffer, &info[i], 0);
6514 if ( !W_ERROR_IS_OK(result) )
6520 /****************************************************************************
6521 Enumjobs at level 2.
6522 ****************************************************************************/
6524 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6525 NT_PRINTER_INFO_LEVEL *ntprinter,
6526 RPC_BUFFER *buffer, uint32 offered,
6527 uint32 *needed, uint32 *returned)
6529 JOB_INFO_2 *info = NULL;
6531 WERROR result = WERR_OK;
6532 DEVICEMODE *devmode = NULL;
6534 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6539 /* this should not be a failure condition if the devmode is NULL */
6541 devmode = construct_dev_mode(snum);
6543 for (i=0; i<*returned; i++)
6544 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6546 free_a_printer(&ntprinter, 2);
6549 /* check the required size. */
6550 for (i=0; i<*returned; i++)
6551 (*needed) += spoolss_size_job_info_2(&info[i]);
6553 if (*needed > offered) {
6554 result = WERR_INSUFFICIENT_BUFFER;
6558 if (!rpcbuf_alloc_size(buffer, *needed)) {
6559 result = WERR_NOMEM;
6563 /* fill the buffer with the structures */
6564 for (i=0; i<*returned; i++)
6565 smb_io_job_info_2("", buffer, &info[i], 0);
6568 free_devmode(devmode);
6571 if ( !W_ERROR_IS_OK(result) )
6578 /****************************************************************************
6580 ****************************************************************************/
6582 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6584 POLICY_HND *handle = &q_u->handle;
6585 uint32 level = q_u->level;
6586 RPC_BUFFER *buffer = NULL;
6587 uint32 offered = q_u->offered;
6588 uint32 *needed = &r_u->needed;
6589 uint32 *returned = &r_u->returned;
6591 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6593 print_status_struct prt_status;
6594 print_queue_struct *queue=NULL;
6596 /* that's an [in out] buffer */
6598 if (!q_u->buffer && (offered!=0)) {
6599 return WERR_INVALID_PARAM;
6602 rpcbuf_move(q_u->buffer, &r_u->buffer);
6603 buffer = r_u->buffer;
6605 DEBUG(4,("_spoolss_enumjobs\n"));
6610 /* lookup the printer snum and tdb entry */
6612 if (!get_printer_snum(p, handle, &snum))
6615 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6616 if ( !W_ERROR_IS_OK(wret) )
6619 *returned = print_queue_status(snum, &queue, &prt_status);
6620 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6622 if (*returned == 0) {
6629 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6632 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6637 wret = WERR_UNKNOWN_LEVEL;
6640 free_a_printer( &ntprinter, 2 );
6644 /****************************************************************************
6645 ****************************************************************************/
6647 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6652 /****************************************************************************
6653 ****************************************************************************/
6655 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6657 POLICY_HND *handle = &q_u->handle;
6658 uint32 jobid = q_u->jobid;
6659 uint32 command = q_u->command;
6661 struct current_user user;
6663 WERROR errcode = WERR_BADFUNC;
6665 if (!get_printer_snum(p, handle, &snum)) {
6669 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6670 return WERR_INVALID_PRINTER_NAME;
6673 get_current_user(&user, p);
6676 case JOB_CONTROL_CANCEL:
6677 case JOB_CONTROL_DELETE:
6678 if (print_job_delete(&user, snum, jobid, &errcode)) {
6682 case JOB_CONTROL_PAUSE:
6683 if (print_job_pause(&user, snum, jobid, &errcode)) {
6687 case JOB_CONTROL_RESTART:
6688 case JOB_CONTROL_RESUME:
6689 if (print_job_resume(&user, snum, jobid, &errcode)) {
6694 return WERR_UNKNOWN_LEVEL;
6700 /****************************************************************************
6701 Enumerates all printer drivers at level 1.
6702 ****************************************************************************/
6704 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6709 fstring *list = NULL;
6710 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6711 DRIVER_INFO_1 *driver_info_1=NULL;
6712 WERROR result = WERR_OK;
6716 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6718 ndrivers=get_ntdrivers(&list, architecture, version);
6719 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6721 if(ndrivers == -1) {
6722 SAFE_FREE(driver_info_1);
6727 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6728 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6734 for (i=0; i<ndrivers; i++) {
6736 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6737 ZERO_STRUCT(driver);
6738 status = get_a_printer_driver(&driver, 3, list[i],
6739 architecture, version);
6740 if (!W_ERROR_IS_OK(status)) {
6742 SAFE_FREE(driver_info_1);
6745 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6746 free_a_printer_driver(driver, 3);
6749 *returned+=ndrivers;
6753 /* check the required size. */
6754 for (i=0; i<*returned; i++) {
6755 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6756 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6759 if (*needed > offered) {
6760 result = WERR_INSUFFICIENT_BUFFER;
6764 if (!rpcbuf_alloc_size(buffer, *needed)) {
6765 result = WERR_NOMEM;
6769 /* fill the buffer with the driver structures */
6770 for (i=0; i<*returned; i++) {
6771 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6772 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6776 SAFE_FREE(driver_info_1);
6778 if ( !W_ERROR_IS_OK(result) )
6784 /****************************************************************************
6785 Enumerates all printer drivers at level 2.
6786 ****************************************************************************/
6788 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6793 fstring *list = NULL;
6794 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6795 DRIVER_INFO_2 *driver_info_2=NULL;
6796 WERROR result = WERR_OK;
6800 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6802 ndrivers=get_ntdrivers(&list, architecture, version);
6803 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6805 if(ndrivers == -1) {
6806 SAFE_FREE(driver_info_2);
6811 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6812 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6818 for (i=0; i<ndrivers; i++) {
6821 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6822 ZERO_STRUCT(driver);
6823 status = get_a_printer_driver(&driver, 3, list[i],
6824 architecture, version);
6825 if (!W_ERROR_IS_OK(status)) {
6827 SAFE_FREE(driver_info_2);
6830 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6831 free_a_printer_driver(driver, 3);
6834 *returned+=ndrivers;
6838 /* check the required size. */
6839 for (i=0; i<*returned; i++) {
6840 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6841 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6844 if (*needed > offered) {
6845 result = WERR_INSUFFICIENT_BUFFER;
6849 if (!rpcbuf_alloc_size(buffer, *needed)) {
6850 result = WERR_NOMEM;
6854 /* fill the buffer with the form structures */
6855 for (i=0; i<*returned; i++) {
6856 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6857 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6861 SAFE_FREE(driver_info_2);
6863 if ( !W_ERROR_IS_OK(result) )
6869 /****************************************************************************
6870 Enumerates all printer drivers at level 3.
6871 ****************************************************************************/
6873 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6878 fstring *list = NULL;
6879 DRIVER_INFO_3 *driver_info_3=NULL;
6880 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6881 WERROR result = WERR_OK;
6885 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6887 ndrivers=get_ntdrivers(&list, architecture, version);
6888 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6890 if(ndrivers == -1) {
6891 SAFE_FREE(driver_info_3);
6896 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6897 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6903 for (i=0; i<ndrivers; i++) {
6906 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6907 ZERO_STRUCT(driver);
6908 status = get_a_printer_driver(&driver, 3, list[i],
6909 architecture, version);
6910 if (!W_ERROR_IS_OK(status)) {
6912 SAFE_FREE(driver_info_3);
6915 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6916 free_a_printer_driver(driver, 3);
6919 *returned+=ndrivers;
6923 /* check the required size. */
6924 for (i=0; i<*returned; i++) {
6925 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6926 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6929 if (*needed > offered) {
6930 result = WERR_INSUFFICIENT_BUFFER;
6934 if (!rpcbuf_alloc_size(buffer, *needed)) {
6935 result = WERR_NOMEM;
6939 /* fill the buffer with the driver structures */
6940 for (i=0; i<*returned; i++) {
6941 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6942 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6946 for (i=0; i<*returned; i++) {
6947 SAFE_FREE(driver_info_3[i].dependentfiles);
6950 SAFE_FREE(driver_info_3);
6952 if ( !W_ERROR_IS_OK(result) )
6958 /****************************************************************************
6959 Enumerates all printer drivers.
6960 ****************************************************************************/
6962 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6964 uint32 level = q_u->level;
6965 RPC_BUFFER *buffer = NULL;
6966 uint32 offered = q_u->offered;
6967 uint32 *needed = &r_u->needed;
6968 uint32 *returned = &r_u->returned;
6971 fstring architecture;
6973 /* that's an [in out] buffer */
6975 if (!q_u->buffer && (offered!=0)) {
6976 return WERR_INVALID_PARAM;
6979 rpcbuf_move(q_u->buffer, &r_u->buffer);
6980 buffer = r_u->buffer;
6982 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6987 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6988 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6990 if ( !is_myname_or_ipaddr( servername ) )
6991 return WERR_UNKNOWN_PRINTER_DRIVER;
6995 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6997 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6999 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7001 return WERR_UNKNOWN_LEVEL;
7005 /****************************************************************************
7006 ****************************************************************************/
7008 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7010 form->flag=list->flag;
7011 init_unistr(&form->name, list->name);
7012 form->width=list->width;
7013 form->length=list->length;
7014 form->left=list->left;
7015 form->top=list->top;
7016 form->right=list->right;
7017 form->bottom=list->bottom;
7020 /****************************************************************************
7021 ****************************************************************************/
7023 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7025 uint32 level = q_u->level;
7026 RPC_BUFFER *buffer = NULL;
7027 uint32 offered = q_u->offered;
7028 uint32 *needed = &r_u->needed;
7029 uint32 *numofforms = &r_u->numofforms;
7030 uint32 numbuiltinforms;
7032 nt_forms_struct *list=NULL;
7033 nt_forms_struct *builtinlist=NULL;
7038 /* that's an [in out] buffer */
7040 if (!q_u->buffer && (offered!=0) ) {
7041 return WERR_INVALID_PARAM;
7044 rpcbuf_move(q_u->buffer, &r_u->buffer);
7045 buffer = r_u->buffer;
7047 DEBUG(4,("_spoolss_enumforms\n"));
7048 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7049 DEBUGADD(5,("Info level [%d]\n", level));
7051 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7052 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7053 *numofforms = get_ntforms(&list);
7054 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7055 *numofforms += numbuiltinforms;
7057 if (*numofforms == 0) {
7058 SAFE_FREE(builtinlist);
7060 return WERR_NO_MORE_ITEMS;
7065 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7066 SAFE_FREE(builtinlist);
7072 /* construct the list of form structures */
7073 for (i=0; i<numbuiltinforms; i++) {
7074 DEBUGADD(6,("Filling form number [%d]\n",i));
7075 fill_form_1(&forms_1[i], &builtinlist[i]);
7078 SAFE_FREE(builtinlist);
7080 for (; i<*numofforms; i++) {
7081 DEBUGADD(6,("Filling form number [%d]\n",i));
7082 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7087 /* check the required size. */
7088 for (i=0; i<numbuiltinforms; i++) {
7089 DEBUGADD(6,("adding form [%d]'s size\n",i));
7090 buffer_size += spoolss_size_form_1(&forms_1[i]);
7092 for (; i<*numofforms; i++) {
7093 DEBUGADD(6,("adding form [%d]'s size\n",i));
7094 buffer_size += spoolss_size_form_1(&forms_1[i]);
7097 *needed=buffer_size;
7099 if (*needed > offered) {
7102 return WERR_INSUFFICIENT_BUFFER;
7105 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7111 /* fill the buffer with the form structures */
7112 for (i=0; i<numbuiltinforms; i++) {
7113 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7114 smb_io_form_1("", buffer, &forms_1[i], 0);
7116 for (; i<*numofforms; i++) {
7117 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7118 smb_io_form_1("", buffer, &forms_1[i], 0);
7127 SAFE_FREE(builtinlist);
7128 return WERR_UNKNOWN_LEVEL;
7132 /****************************************************************************
7133 ****************************************************************************/
7135 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7137 uint32 level = q_u->level;
7138 UNISTR2 *uni_formname = &q_u->formname;
7139 RPC_BUFFER *buffer = NULL;
7140 uint32 offered = q_u->offered;
7141 uint32 *needed = &r_u->needed;
7143 nt_forms_struct *list=NULL;
7144 nt_forms_struct builtin_form;
7149 int numofforms=0, i=0;
7151 /* that's an [in out] buffer */
7153 if (!q_u->buffer && (offered!=0)) {
7154 return WERR_INVALID_PARAM;
7157 rpcbuf_move(q_u->buffer, &r_u->buffer);
7158 buffer = r_u->buffer;
7160 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7162 DEBUG(4,("_spoolss_getform\n"));
7163 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7164 DEBUGADD(5,("Info level [%d]\n", level));
7166 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7167 if (!foundBuiltin) {
7168 numofforms = get_ntforms(&list);
7169 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7171 if (numofforms == 0)
7178 fill_form_1(&form_1, &builtin_form);
7181 /* Check if the requested name is in the list of form structures */
7182 for (i=0; i<numofforms; i++) {
7184 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7186 if (strequal(form_name, list[i].name)) {
7187 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7188 fill_form_1(&form_1, &list[i]);
7194 if (i == numofforms) {
7198 /* check the required size. */
7200 *needed=spoolss_size_form_1(&form_1);
7202 if (*needed > offered)
7203 return WERR_INSUFFICIENT_BUFFER;
7205 if (!rpcbuf_alloc_size(buffer, buffer_size))
7208 /* fill the buffer with the form structures */
7209 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7210 smb_io_form_1("", buffer, &form_1, 0);
7216 return WERR_UNKNOWN_LEVEL;
7220 /****************************************************************************
7221 ****************************************************************************/
7223 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7225 init_unistr(&port->port_name, name);
7228 /****************************************************************************
7229 TODO: This probably needs distinguish between TCP/IP and Local ports
7231 ****************************************************************************/
7233 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7235 init_unistr(&port->port_name, name);
7236 init_unistr(&port->monitor_name, "Local Monitor");
7237 init_unistr(&port->description, SPL_LOCAL_PORT );
7238 port->port_type=PORT_TYPE_WRITE;
7243 /****************************************************************************
7244 wrapper around the enumer ports command
7245 ****************************************************************************/
7247 WERROR enumports_hook( int *count, char ***lines )
7249 char *cmd = lp_enumports_cmd();
7259 /* if no hook then just fill in the default port */
7262 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7263 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7268 /* we have a valid enumport command */
7270 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7272 DEBUG(10,("Running [%s]\n", command));
7273 ret = smbrun(command, &fd);
7274 DEBUG(10,("Returned [%d]\n", ret));
7279 return WERR_ACCESS_DENIED;
7283 qlines = fd_lines_load(fd, &numlines, 0);
7284 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7294 /****************************************************************************
7296 ****************************************************************************/
7298 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7300 PORT_INFO_1 *ports=NULL;
7302 WERROR result = WERR_OK;
7303 char **qlines = NULL;
7306 result = enumports_hook( &numlines, &qlines );
7307 if (!W_ERROR_IS_OK(result)) {
7308 file_lines_free(qlines);
7313 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7314 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7315 dos_errstr(WERR_NOMEM)));
7316 file_lines_free(qlines);
7320 for (i=0; i<numlines; i++) {
7321 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7322 fill_port_1(&ports[i], qlines[i]);
7325 file_lines_free(qlines);
7327 *returned = numlines;
7329 /* check the required size. */
7330 for (i=0; i<*returned; i++) {
7331 DEBUGADD(6,("adding port [%d]'s size\n", i));
7332 *needed += spoolss_size_port_info_1(&ports[i]);
7335 if (*needed > offered) {
7336 result = WERR_INSUFFICIENT_BUFFER;
7340 if (!rpcbuf_alloc_size(buffer, *needed)) {
7341 result = WERR_NOMEM;
7345 /* fill the buffer with the ports structures */
7346 for (i=0; i<*returned; i++) {
7347 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7348 smb_io_port_1("", buffer, &ports[i], 0);
7354 if ( !W_ERROR_IS_OK(result) )
7360 /****************************************************************************
7362 ****************************************************************************/
7364 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7366 PORT_INFO_2 *ports=NULL;
7368 WERROR result = WERR_OK;
7369 char **qlines = NULL;
7372 result = enumports_hook( &numlines, &qlines );
7373 if ( !W_ERROR_IS_OK(result)) {
7374 file_lines_free(qlines);
7379 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7380 file_lines_free(qlines);
7384 for (i=0; i<numlines; i++) {
7385 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7386 fill_port_2(&(ports[i]), qlines[i]);
7390 file_lines_free(qlines);
7392 *returned = numlines;
7394 /* check the required size. */
7395 for (i=0; i<*returned; i++) {
7396 DEBUGADD(6,("adding port [%d]'s size\n", i));
7397 *needed += spoolss_size_port_info_2(&ports[i]);
7400 if (*needed > offered) {
7401 result = WERR_INSUFFICIENT_BUFFER;
7405 if (!rpcbuf_alloc_size(buffer, *needed)) {
7406 result = WERR_NOMEM;
7410 /* fill the buffer with the ports structures */
7411 for (i=0; i<*returned; i++) {
7412 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7413 smb_io_port_2("", buffer, &ports[i], 0);
7419 if ( !W_ERROR_IS_OK(result) )
7425 /****************************************************************************
7427 ****************************************************************************/
7429 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7431 uint32 level = q_u->level;
7432 RPC_BUFFER *buffer = NULL;
7433 uint32 offered = q_u->offered;
7434 uint32 *needed = &r_u->needed;
7435 uint32 *returned = &r_u->returned;
7437 /* that's an [in out] buffer */
7439 if (!q_u->buffer && (offered!=0)) {
7440 return WERR_INVALID_PARAM;
7443 rpcbuf_move(q_u->buffer, &r_u->buffer);
7444 buffer = r_u->buffer;
7446 DEBUG(4,("_spoolss_enumports\n"));
7453 return enumports_level_1(buffer, offered, needed, returned);
7455 return enumports_level_2(buffer, offered, needed, returned);
7457 return WERR_UNKNOWN_LEVEL;
7461 /****************************************************************************
7462 ****************************************************************************/
7464 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7465 const SPOOL_PRINTER_INFO_LEVEL *info,
7466 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7467 uint32 user_switch, const SPOOL_USER_CTR *user,
7470 NT_PRINTER_INFO_LEVEL *printer = NULL;
7473 WERROR err = WERR_OK;
7475 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7476 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7480 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7481 if (!convert_printer_info(info, printer, 2)) {
7482 free_a_printer(&printer, 2);
7486 /* check to see if the printer already exists */
7488 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7489 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7490 printer->info_2->sharename));
7491 free_a_printer(&printer, 2);
7492 return WERR_PRINTER_ALREADY_EXISTS;
7495 /* FIXME!!! smbd should check to see if the driver is installed before
7496 trying to add a printer like this --jerry */
7498 if (*lp_addprinter_cmd() ) {
7499 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7500 free_a_printer(&printer,2);
7501 return WERR_ACCESS_DENIED;
7504 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7505 "smb.conf parameter \"addprinter command\" is defined. This"
7506 "parameter must exist for this call to succeed\n",
7507 printer->info_2->sharename ));
7510 /* use our primary netbios name since get_a_printer() will convert
7511 it to what the client expects on a case by case basis */
7513 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7514 printer->info_2->sharename);
7517 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7518 free_a_printer(&printer,2);
7519 return WERR_ACCESS_DENIED;
7522 /* you must be a printer admin to add a new printer */
7523 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7524 free_a_printer(&printer,2);
7525 return WERR_ACCESS_DENIED;
7529 * Do sanity check on the requested changes for Samba.
7532 if (!check_printer_ok(printer->info_2, snum)) {
7533 free_a_printer(&printer,2);
7534 return WERR_INVALID_PARAM;
7538 * When a printer is created, the drivername bound to the printer is used
7539 * to lookup previously saved driver initialization info, which is then
7540 * bound to the new printer, simulating what happens in the Windows arch.
7545 set_driver_init(printer, 2);
7549 /* A valid devmode was included, convert and link it
7551 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7553 if (!convert_devicemode(printer->info_2->printername, devmode,
7554 &printer->info_2->devmode))
7558 /* write the ASCII on disk */
7559 err = mod_a_printer(printer, 2);
7560 if (!W_ERROR_IS_OK(err)) {
7561 free_a_printer(&printer,2);
7565 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7566 /* Handle open failed - remove addition. */
7567 del_a_printer(printer->info_2->sharename);
7568 free_a_printer(&printer,2);
7569 return WERR_ACCESS_DENIED;
7572 update_c_setprinter(False);
7573 free_a_printer(&printer,2);
7578 /****************************************************************************
7579 ****************************************************************************/
7581 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7583 UNISTR2 *uni_srv_name = q_u->server_name;
7584 uint32 level = q_u->level;
7585 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7586 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7587 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7588 uint32 user_switch = q_u->user_switch;
7589 SPOOL_USER_CTR *user = &q_u->user_ctr;
7590 POLICY_HND *handle = &r_u->handle;
7594 /* we don't handle yet */
7595 /* but I know what to do ... */
7596 return WERR_UNKNOWN_LEVEL;
7598 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7600 user_switch, user, handle);
7602 return WERR_UNKNOWN_LEVEL;
7606 /****************************************************************************
7607 ****************************************************************************/
7609 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7611 uint32 level = q_u->level;
7612 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7613 WERROR err = WERR_OK;
7614 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7615 struct current_user user;
7616 fstring driver_name;
7619 ZERO_STRUCT(driver);
7621 get_current_user(&user, p);
7623 if (!convert_printer_driver_info(info, &driver, level)) {
7628 DEBUG(5,("Cleaning driver's information\n"));
7629 err = clean_up_driver_struct(driver, level, &user);
7630 if (!W_ERROR_IS_OK(err))
7633 DEBUG(5,("Moving driver to final destination\n"));
7634 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7638 if (add_a_printer_driver(driver, level)!=0) {
7639 err = WERR_ACCESS_DENIED;
7644 * I think this is where he DrvUpgradePrinter() hook would be
7645 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7646 * server. Right now, we just need to send ourselves a message
7647 * to update each printer bound to this driver. --jerry
7650 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7651 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7656 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7657 * decide if the driver init data should be deleted. The rules are:
7658 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7659 * 2) delete init data only if there is no 2k/Xp driver
7660 * 3) always delete init data
7661 * The generalized rule is always use init data from the highest order driver.
7662 * It is necessary to follow the driver install by an initialization step to
7663 * finish off this process.
7666 version = driver.info_3->cversion;
7667 else if (level == 6)
7668 version = driver.info_6->version;
7673 * 9x printer driver - never delete init data
7676 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7681 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7682 * there is no 2k/Xp driver init data for this driver name.
7686 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7688 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7690 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7692 if (!del_driver_init(driver_name))
7693 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7696 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7698 free_a_printer_driver(driver1,3);
7699 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7706 * 2k or Xp printer driver - always delete init data
7709 if (!del_driver_init(driver_name))
7710 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7714 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7720 free_a_printer_driver(driver, level);
7724 /********************************************************************
7725 * spoolss_addprinterdriverex
7726 ********************************************************************/
7728 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7730 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7731 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7734 * we only support the semantics of AddPrinterDriver()
7735 * i.e. only copy files that are newer than existing ones
7738 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7739 return WERR_ACCESS_DENIED;
7741 ZERO_STRUCT(q_u_local);
7742 ZERO_STRUCT(r_u_local);
7744 /* just pass the information off to _spoolss_addprinterdriver() */
7745 q_u_local.server_name_ptr = q_u->server_name_ptr;
7746 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7747 q_u_local.level = q_u->level;
7748 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7750 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7753 /****************************************************************************
7754 ****************************************************************************/
7756 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7758 init_unistr(&info->name, name);
7761 /****************************************************************************
7762 ****************************************************************************/
7764 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7770 const char *short_archi;
7771 DRIVER_DIRECTORY_1 *info=NULL;
7772 WERROR result = WERR_OK;
7774 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7775 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7777 /* check for beginning double '\'s and that the server
7780 pservername = servername;
7781 if ( *pservername == '\\' && strlen(servername)>2 ) {
7785 if ( !is_myname_or_ipaddr( pservername ) )
7786 return WERR_INVALID_PARAM;
7788 if (!(short_archi = get_short_archi(long_archi)))
7789 return WERR_INVALID_ENVIRONMENT;
7791 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7794 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7796 DEBUG(4,("printer driver directory: [%s]\n", path));
7798 fill_driverdir_1(info, path);
7800 *needed += spoolss_size_driverdir_info_1(info);
7802 if (*needed > offered) {
7803 result = WERR_INSUFFICIENT_BUFFER;
7807 if (!rpcbuf_alloc_size(buffer, *needed)) {
7808 result = WERR_NOMEM;
7812 smb_io_driverdir_1("", buffer, info, 0);
7820 /****************************************************************************
7821 ****************************************************************************/
7823 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7825 UNISTR2 *name = &q_u->name;
7826 UNISTR2 *uni_environment = &q_u->environment;
7827 uint32 level = q_u->level;
7828 RPC_BUFFER *buffer = NULL;
7829 uint32 offered = q_u->offered;
7830 uint32 *needed = &r_u->needed;
7832 /* that's an [in out] buffer */
7834 if (!q_u->buffer && (offered!=0)) {
7835 return WERR_INVALID_PARAM;
7838 rpcbuf_move(q_u->buffer, &r_u->buffer);
7839 buffer = r_u->buffer;
7841 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7847 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7849 return WERR_UNKNOWN_LEVEL;
7853 /****************************************************************************
7854 ****************************************************************************/
7856 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7858 POLICY_HND *handle = &q_u->handle;
7859 uint32 idx = q_u->index;
7860 uint32 in_value_len = q_u->valuesize;
7861 uint32 in_data_len = q_u->datasize;
7862 uint32 *out_max_value_len = &r_u->valuesize;
7863 uint16 **out_value = &r_u->value;
7864 uint32 *out_value_len = &r_u->realvaluesize;
7865 uint32 *out_type = &r_u->type;
7866 uint32 *out_max_data_len = &r_u->datasize;
7867 uint8 **data_out = &r_u->data;
7868 uint32 *out_data_len = &r_u->realdatasize;
7870 NT_PRINTER_INFO_LEVEL *printer = NULL;
7872 uint32 biggest_valuesize;
7873 uint32 biggest_datasize;
7875 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7878 REGISTRY_VALUE *val = NULL;
7879 NT_PRINTER_DATA *p_data;
7880 int i, key_index, num_values;
7885 *out_max_data_len = 0;
7889 DEBUG(5,("spoolss_enumprinterdata\n"));
7892 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7896 if (!get_printer_snum(p,handle, &snum))
7899 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7900 if (!W_ERROR_IS_OK(result))
7903 p_data = printer->info_2->data;
7904 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7909 * The NT machine wants to know the biggest size of value and data
7911 * cf: MSDN EnumPrinterData remark section
7914 if ( !in_value_len && !in_data_len && (key_index != -1) )
7916 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7918 biggest_valuesize = 0;
7919 biggest_datasize = 0;
7921 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7923 for ( i=0; i<num_values; i++ )
7925 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7927 name_length = strlen(val->valuename);
7928 if ( strlen(val->valuename) > biggest_valuesize )
7929 biggest_valuesize = name_length;
7931 if ( val->size > biggest_datasize )
7932 biggest_datasize = val->size;
7934 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7938 /* the value is an UNICODE string but real_value_size is the length
7939 in bytes including the trailing 0 */
7941 *out_value_len = 2 * (1+biggest_valuesize);
7942 *out_data_len = biggest_datasize;
7944 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7950 * the value len is wrong in NT sp3
7951 * that's the number of bytes not the number of unicode chars
7954 if ( key_index != -1 )
7955 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7960 /* out_value should default to "" or else NT4 has
7961 problems unmarshalling the response */
7963 *out_max_value_len=(in_value_len/sizeof(uint16));
7965 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7967 result = WERR_NOMEM;
7971 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7973 /* the data is counted in bytes */
7975 *out_max_data_len = in_data_len;
7976 *out_data_len = in_data_len;
7978 /* only allocate when given a non-zero data_len */
7980 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7982 result = WERR_NOMEM;
7986 result = WERR_NO_MORE_ITEMS;
7992 * - counted in bytes in the request
7993 * - counted in UNICODE chars in the max reply
7994 * - counted in bytes in the real size
7996 * take a pause *before* coding not *during* coding
8000 *out_max_value_len=(in_value_len/sizeof(uint16));
8001 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8003 result = WERR_NOMEM;
8007 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8011 *out_type = regval_type( val );
8013 /* data - counted in bytes */
8015 *out_max_data_len = in_data_len;
8016 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8018 result = WERR_NOMEM;
8021 data_len = regval_size(val);
8023 memcpy( *data_out, regval_data_p(val), data_len );
8024 *out_data_len = data_len;
8028 free_a_printer(&printer, 2);
8032 /****************************************************************************
8033 ****************************************************************************/
8035 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8037 POLICY_HND *handle = &q_u->handle;
8038 UNISTR2 *value = &q_u->value;
8039 uint32 type = q_u->type;
8040 uint8 *data = q_u->data;
8041 uint32 real_len = q_u->real_len;
8043 NT_PRINTER_INFO_LEVEL *printer = NULL;
8045 WERROR status = WERR_OK;
8046 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8049 DEBUG(5,("spoolss_setprinterdata\n"));
8052 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8056 if ( Printer->printer_type == SPLHND_SERVER ) {
8057 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8058 return WERR_INVALID_PARAM;
8061 if (!get_printer_snum(p,handle, &snum))
8065 * Access check : NT returns "access denied" if you make a
8066 * SetPrinterData call without the necessary privildge.
8067 * we were originally returning OK if nothing changed
8068 * which made Win2k issue **a lot** of SetPrinterData
8069 * when connecting to a printer --jerry
8072 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8074 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8075 status = WERR_ACCESS_DENIED;
8079 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8080 if (!W_ERROR_IS_OK(status))
8083 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8086 * When client side code sets a magic printer data key, detect it and save
8087 * the current printer data and the magic key's data (its the DEVMODE) for
8088 * future printer/driver initializations.
8090 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8092 /* Set devmode and printer initialization info */
8093 status = save_driver_init( printer, 2, data, real_len );
8095 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8099 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8100 type, data, real_len );
8101 if ( W_ERROR_IS_OK(status) )
8102 status = mod_a_printer(printer, 2);
8106 free_a_printer(&printer, 2);
8111 /****************************************************************************
8112 ****************************************************************************/
8114 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8116 POLICY_HND *handle = &q_u->handle;
8117 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8120 DEBUG(5,("_spoolss_resetprinter\n"));
8123 * All we do is to check to see if the handle and queue is valid.
8124 * This call really doesn't mean anything to us because we only
8125 * support RAW printing. --jerry
8129 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8133 if (!get_printer_snum(p,handle, &snum))
8137 /* blindly return success */
8142 /****************************************************************************
8143 ****************************************************************************/
8145 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8147 POLICY_HND *handle = &q_u->handle;
8148 UNISTR2 *value = &q_u->valuename;
8150 NT_PRINTER_INFO_LEVEL *printer = NULL;
8152 WERROR status = WERR_OK;
8153 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8156 DEBUG(5,("spoolss_deleteprinterdata\n"));
8159 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8163 if (!get_printer_snum(p, handle, &snum))
8166 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8167 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8168 return WERR_ACCESS_DENIED;
8171 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8172 if (!W_ERROR_IS_OK(status))
8175 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8177 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8179 if ( W_ERROR_IS_OK(status) )
8180 mod_a_printer( printer, 2 );
8182 free_a_printer(&printer, 2);
8187 /****************************************************************************
8188 ****************************************************************************/
8190 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8192 POLICY_HND *handle = &q_u->handle;
8193 FORM *form = &q_u->form;
8194 nt_forms_struct tmpForm;
8196 WERROR status = WERR_OK;
8197 NT_PRINTER_INFO_LEVEL *printer = NULL;
8200 nt_forms_struct *list=NULL;
8201 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8203 DEBUG(5,("spoolss_addform\n"));
8206 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8211 /* forms can be added on printer of on the print server handle */
8213 if ( Printer->printer_type == SPLHND_PRINTER )
8215 if (!get_printer_snum(p,handle, &snum))
8218 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8219 if (!W_ERROR_IS_OK(status))
8223 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8224 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8225 status = WERR_ACCESS_DENIED;
8229 /* can't add if builtin */
8231 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8232 status = WERR_ALREADY_EXISTS;
8236 count = get_ntforms(&list);
8238 if(!add_a_form(&list, form, &count)) {
8239 status = WERR_NOMEM;
8243 write_ntforms(&list, count);
8246 * ChangeID must always be set if this is a printer
8249 if ( Printer->printer_type == SPLHND_PRINTER )
8250 status = mod_a_printer(printer, 2);
8254 free_a_printer(&printer, 2);
8260 /****************************************************************************
8261 ****************************************************************************/
8263 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8265 POLICY_HND *handle = &q_u->handle;
8266 UNISTR2 *form_name = &q_u->name;
8267 nt_forms_struct tmpForm;
8269 nt_forms_struct *list=NULL;
8270 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8272 WERROR status = WERR_OK;
8273 NT_PRINTER_INFO_LEVEL *printer = NULL;
8275 DEBUG(5,("spoolss_deleteform\n"));
8278 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8282 /* forms can be deleted on printer of on the print server handle */
8284 if ( Printer->printer_type == SPLHND_PRINTER )
8286 if (!get_printer_snum(p,handle, &snum))
8289 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8290 if (!W_ERROR_IS_OK(status))
8294 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8295 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8296 status = WERR_ACCESS_DENIED;
8300 /* can't delete if builtin */
8302 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8303 status = WERR_INVALID_PARAM;
8307 count = get_ntforms(&list);
8309 if ( !delete_a_form(&list, form_name, &count, &status ))
8313 * ChangeID must always be set if this is a printer
8316 if ( Printer->printer_type == SPLHND_PRINTER )
8317 status = mod_a_printer(printer, 2);
8321 free_a_printer(&printer, 2);
8327 /****************************************************************************
8328 ****************************************************************************/
8330 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8332 POLICY_HND *handle = &q_u->handle;
8333 FORM *form = &q_u->form;
8334 nt_forms_struct tmpForm;
8336 WERROR status = WERR_OK;
8337 NT_PRINTER_INFO_LEVEL *printer = NULL;
8340 nt_forms_struct *list=NULL;
8341 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8343 DEBUG(5,("spoolss_setform\n"));
8346 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8350 /* forms can be modified on printer of on the print server handle */
8352 if ( Printer->printer_type == SPLHND_PRINTER )
8354 if (!get_printer_snum(p,handle, &snum))
8357 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8358 if (!W_ERROR_IS_OK(status))
8362 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8363 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8364 status = WERR_ACCESS_DENIED;
8368 /* can't set if builtin */
8369 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8370 status = WERR_INVALID_PARAM;
8374 count = get_ntforms(&list);
8375 update_a_form(&list, form, count);
8376 write_ntforms(&list, count);
8379 * ChangeID must always be set if this is a printer
8382 if ( Printer->printer_type == SPLHND_PRINTER )
8383 status = mod_a_printer(printer, 2);
8388 free_a_printer(&printer, 2);
8394 /****************************************************************************
8395 enumprintprocessors level 1.
8396 ****************************************************************************/
8398 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8400 PRINTPROCESSOR_1 *info_1=NULL;
8401 WERROR result = WERR_OK;
8403 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8408 init_unistr(&info_1->name, "winprint");
8410 *needed += spoolss_size_printprocessor_info_1(info_1);
8412 if (*needed > offered) {
8413 result = WERR_INSUFFICIENT_BUFFER;
8417 if (!rpcbuf_alloc_size(buffer, *needed)) {
8418 result = WERR_NOMEM;
8422 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8427 if ( !W_ERROR_IS_OK(result) )
8433 /****************************************************************************
8434 ****************************************************************************/
8436 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8438 uint32 level = q_u->level;
8439 RPC_BUFFER *buffer = NULL;
8440 uint32 offered = q_u->offered;
8441 uint32 *needed = &r_u->needed;
8442 uint32 *returned = &r_u->returned;
8444 /* that's an [in out] buffer */
8446 if (!q_u->buffer && (offered!=0)) {
8447 return WERR_INVALID_PARAM;
8450 rpcbuf_move(q_u->buffer, &r_u->buffer);
8451 buffer = r_u->buffer;
8453 DEBUG(5,("spoolss_enumprintprocessors\n"));
8456 * Enumerate the print processors ...
8458 * Just reply with "winprint", to keep NT happy
8459 * and I can use my nice printer checker.
8467 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8469 return WERR_UNKNOWN_LEVEL;
8473 /****************************************************************************
8474 enumprintprocdatatypes level 1.
8475 ****************************************************************************/
8477 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8479 PRINTPROCDATATYPE_1 *info_1=NULL;
8480 WERROR result = WERR_NOMEM;
8482 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8487 init_unistr(&info_1->name, "RAW");
8489 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8491 if (*needed > offered) {
8492 result = WERR_INSUFFICIENT_BUFFER;
8496 if (!rpcbuf_alloc_size(buffer, *needed)) {
8497 result = WERR_NOMEM;
8501 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8506 if ( !W_ERROR_IS_OK(result) )
8512 /****************************************************************************
8513 ****************************************************************************/
8515 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8517 uint32 level = q_u->level;
8518 RPC_BUFFER *buffer = NULL;
8519 uint32 offered = q_u->offered;
8520 uint32 *needed = &r_u->needed;
8521 uint32 *returned = &r_u->returned;
8523 /* that's an [in out] buffer */
8525 if (!q_u->buffer && (offered!=0)) {
8526 return WERR_INVALID_PARAM;
8529 rpcbuf_move(q_u->buffer, &r_u->buffer);
8530 buffer = r_u->buffer;
8532 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8539 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8541 return WERR_UNKNOWN_LEVEL;
8545 /****************************************************************************
8546 enumprintmonitors level 1.
8547 ****************************************************************************/
8549 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8551 PRINTMONITOR_1 *info_1;
8552 WERROR result = WERR_OK;
8555 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8560 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8561 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8563 for ( i=0; i<*returned; i++ ) {
8564 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8567 if (*needed > offered) {
8568 result = WERR_INSUFFICIENT_BUFFER;
8572 if (!rpcbuf_alloc_size(buffer, *needed)) {
8573 result = WERR_NOMEM;
8577 for ( i=0; i<*returned; i++ ) {
8578 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8584 if ( !W_ERROR_IS_OK(result) )
8590 /****************************************************************************
8591 enumprintmonitors level 2.
8592 ****************************************************************************/
8594 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8596 PRINTMONITOR_2 *info_2;
8597 WERROR result = WERR_OK;
8600 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8605 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8606 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8607 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8609 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8610 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8611 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8613 for ( i=0; i<*returned; i++ ) {
8614 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8617 if (*needed > offered) {
8618 result = WERR_INSUFFICIENT_BUFFER;
8622 if (!rpcbuf_alloc_size(buffer, *needed)) {
8623 result = WERR_NOMEM;
8627 for ( i=0; i<*returned; i++ ) {
8628 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8634 if ( !W_ERROR_IS_OK(result) )
8640 /****************************************************************************
8641 ****************************************************************************/
8643 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8645 uint32 level = q_u->level;
8646 RPC_BUFFER *buffer = NULL;
8647 uint32 offered = q_u->offered;
8648 uint32 *needed = &r_u->needed;
8649 uint32 *returned = &r_u->returned;
8651 /* that's an [in out] buffer */
8653 if (!q_u->buffer && (offered!=0)) {
8654 return WERR_INVALID_PARAM;
8657 rpcbuf_move(q_u->buffer, &r_u->buffer);
8658 buffer = r_u->buffer;
8660 DEBUG(5,("spoolss_enumprintmonitors\n"));
8663 * Enumerate the print monitors ...
8665 * Just reply with "Local Port", to keep NT happy
8666 * and I can use my nice printer checker.
8674 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8676 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8678 return WERR_UNKNOWN_LEVEL;
8682 /****************************************************************************
8683 ****************************************************************************/
8685 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8686 NT_PRINTER_INFO_LEVEL *ntprinter,
8687 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8692 JOB_INFO_1 *info_1=NULL;
8693 WERROR result = WERR_OK;
8695 info_1=SMB_MALLOC_P(JOB_INFO_1);
8697 if (info_1 == NULL) {
8701 for (i=0; i<count && found==False; i++) {
8702 if ((*queue)[i].job==(int)jobid)
8708 /* NT treats not found as bad param... yet another bad choice */
8709 return WERR_INVALID_PARAM;
8712 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8714 *needed += spoolss_size_job_info_1(info_1);
8716 if (*needed > offered) {
8717 result = WERR_INSUFFICIENT_BUFFER;
8721 if (!rpcbuf_alloc_size(buffer, *needed)) {
8722 result = WERR_NOMEM;
8726 smb_io_job_info_1("", buffer, info_1, 0);
8734 /****************************************************************************
8735 ****************************************************************************/
8737 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8738 NT_PRINTER_INFO_LEVEL *ntprinter,
8739 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8746 DEVICEMODE *devmode = NULL;
8747 NT_DEVICEMODE *nt_devmode = NULL;
8749 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8752 ZERO_STRUCTP(info_2);
8754 for ( i=0; i<count && found==False; i++ )
8756 if ((*queue)[i].job == (int)jobid)
8761 /* NT treats not found as bad param... yet another bad
8763 result = WERR_INVALID_PARAM;
8768 * if the print job does not have a DEVMODE associated with it,
8769 * just use the one for the printer. A NULL devicemode is not
8770 * a failure condition
8773 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8774 devmode = construct_dev_mode(snum);
8776 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8777 ZERO_STRUCTP( devmode );
8778 convert_nt_devicemode( devmode, nt_devmode );
8782 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8784 *needed += spoolss_size_job_info_2(info_2);
8786 if (*needed > offered) {
8787 result = WERR_INSUFFICIENT_BUFFER;
8791 if (!rpcbuf_alloc_size(buffer, *needed)) {
8792 result = WERR_NOMEM;
8796 smb_io_job_info_2("", buffer, info_2, 0);
8801 /* Cleanup allocated memory */
8803 free_job_info_2(info_2); /* Also frees devmode */
8809 /****************************************************************************
8810 ****************************************************************************/
8812 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8814 POLICY_HND *handle = &q_u->handle;
8815 uint32 jobid = q_u->jobid;
8816 uint32 level = q_u->level;
8817 RPC_BUFFER *buffer = NULL;
8818 uint32 offered = q_u->offered;
8819 uint32 *needed = &r_u->needed;
8820 WERROR wstatus = WERR_OK;
8821 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8824 print_queue_struct *queue = NULL;
8825 print_status_struct prt_status;
8827 /* that's an [in out] buffer */
8829 if (!q_u->buffer && (offered!=0)) {
8830 return WERR_INVALID_PARAM;
8833 rpcbuf_move(q_u->buffer, &r_u->buffer);
8834 buffer = r_u->buffer;
8836 DEBUG(5,("spoolss_getjob\n"));
8840 if (!get_printer_snum(p, handle, &snum))
8843 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8844 if ( !W_ERROR_IS_OK(wstatus) )
8847 count = print_queue_status(snum, &queue, &prt_status);
8849 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8850 count, prt_status.status, prt_status.message));
8854 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8855 buffer, offered, needed);
8858 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8859 buffer, offered, needed);
8862 wstatus = WERR_UNKNOWN_LEVEL;
8867 free_a_printer( &ntprinter, 2 );
8872 /********************************************************************
8873 spoolss_getprinterdataex
8875 From MSDN documentation of GetPrinterDataEx: pass request
8876 to GetPrinterData if key is "PrinterDriverData".
8877 ********************************************************************/
8879 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8881 POLICY_HND *handle = &q_u->handle;
8882 uint32 in_size = q_u->size;
8883 uint32 *type = &r_u->type;
8884 uint32 *out_size = &r_u->size;
8885 uint8 **data = &r_u->data;
8886 uint32 *needed = &r_u->needed;
8887 fstring keyname, valuename;
8889 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8891 NT_PRINTER_INFO_LEVEL *printer = NULL;
8893 WERROR status = WERR_OK;
8895 DEBUG(4,("_spoolss_getprinterdataex\n"));
8897 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8898 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8900 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8901 keyname, valuename));
8903 /* in case of problem, return some default values */
8907 *out_size = in_size;
8910 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8911 status = WERR_BADFID;
8915 /* Is the handle to a printer or to the server? */
8917 if (Printer->printer_type == SPLHND_SERVER) {
8918 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8919 status = WERR_INVALID_PARAM;
8923 if ( !get_printer_snum(p,handle, &snum) )
8926 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8927 if ( !W_ERROR_IS_OK(status) )
8930 /* check to see if the keyname is valid */
8931 if ( !strlen(keyname) ) {
8932 status = WERR_INVALID_PARAM;
8936 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8937 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8938 free_a_printer( &printer, 2 );
8939 status = WERR_BADFILE;
8943 /* When given a new keyname, we should just create it */
8945 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8947 if (*needed > *out_size)
8948 status = WERR_MORE_DATA;
8951 if ( !W_ERROR_IS_OK(status) )
8953 DEBUG(5, ("error: allocating %d\n", *out_size));
8955 /* reply this param doesn't exist */
8959 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8960 status = WERR_NOMEM;
8970 free_a_printer( &printer, 2 );
8975 /********************************************************************
8976 * spoolss_setprinterdataex
8977 ********************************************************************/
8979 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8981 POLICY_HND *handle = &q_u->handle;
8982 uint32 type = q_u->type;
8983 uint8 *data = q_u->data;
8984 uint32 real_len = q_u->real_len;
8986 NT_PRINTER_INFO_LEVEL *printer = NULL;
8988 WERROR status = WERR_OK;
8989 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8994 DEBUG(4,("_spoolss_setprinterdataex\n"));
8996 /* From MSDN documentation of SetPrinterDataEx: pass request to
8997 SetPrinterData if key is "PrinterDriverData" */
9000 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9004 if ( Printer->printer_type == SPLHND_SERVER ) {
9005 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9006 return WERR_INVALID_PARAM;
9009 if ( !get_printer_snum(p,handle, &snum) )
9013 * Access check : NT returns "access denied" if you make a
9014 * SetPrinterData call without the necessary privildge.
9015 * we were originally returning OK if nothing changed
9016 * which made Win2k issue **a lot** of SetPrinterData
9017 * when connecting to a printer --jerry
9020 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9022 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9023 return WERR_ACCESS_DENIED;
9026 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9027 if (!W_ERROR_IS_OK(status))
9030 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9031 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9033 /* check for OID in valuename */
9035 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9041 /* save the registry data */
9043 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9045 if ( W_ERROR_IS_OK(status) )
9047 /* save the OID if one was specified */
9049 fstrcat( keyname, "\\" );
9050 fstrcat( keyname, SPOOL_OID_KEY );
9053 * I'm not checking the status here on purpose. Don't know
9054 * if this is right, but I'm returning the status from the
9055 * previous set_printer_dataex() call. I have no idea if
9056 * this is right. --jerry
9059 set_printer_dataex( printer, keyname, valuename,
9060 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9063 status = mod_a_printer(printer, 2);
9066 free_a_printer(&printer, 2);
9072 /********************************************************************
9073 * spoolss_deleteprinterdataex
9074 ********************************************************************/
9076 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9078 POLICY_HND *handle = &q_u->handle;
9079 UNISTR2 *value = &q_u->valuename;
9080 UNISTR2 *key = &q_u->keyname;
9082 NT_PRINTER_INFO_LEVEL *printer = NULL;
9084 WERROR status = WERR_OK;
9085 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9086 pstring valuename, keyname;
9088 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9091 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9095 if (!get_printer_snum(p, handle, &snum))
9098 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9099 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9100 return WERR_ACCESS_DENIED;
9103 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9104 if (!W_ERROR_IS_OK(status))
9107 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9108 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9110 status = delete_printer_dataex( printer, keyname, valuename );
9112 if ( W_ERROR_IS_OK(status) )
9113 mod_a_printer( printer, 2 );
9115 free_a_printer(&printer, 2);
9120 /********************************************************************
9121 * spoolss_enumprinterkey
9122 ********************************************************************/
9125 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9128 fstring *keynames = NULL;
9129 uint16 *enumkeys = NULL;
9132 POLICY_HND *handle = &q_u->handle;
9133 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9134 NT_PRINTER_DATA *data;
9135 NT_PRINTER_INFO_LEVEL *printer = NULL;
9137 WERROR status = WERR_BADFILE;
9140 DEBUG(4,("_spoolss_enumprinterkey\n"));
9143 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9147 if ( !get_printer_snum(p,handle, &snum) )
9150 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9151 if (!W_ERROR_IS_OK(status))
9154 /* get the list of subkey names */
9156 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9157 data = printer->info_2->data;
9159 num_keys = get_printer_subkeys( data, key, &keynames );
9161 if ( num_keys == -1 ) {
9162 status = WERR_BADFILE;
9166 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9168 r_u->needed = printerkey_len*2;
9170 if ( q_u->size < r_u->needed ) {
9171 status = WERR_MORE_DATA;
9175 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9176 status = WERR_NOMEM;
9182 if ( q_u->size < r_u->needed )
9183 status = WERR_MORE_DATA;
9186 free_a_printer( &printer, 2 );
9187 SAFE_FREE( keynames );
9192 /********************************************************************
9193 * spoolss_deleteprinterkey
9194 ********************************************************************/
9196 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9198 POLICY_HND *handle = &q_u->handle;
9199 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9201 NT_PRINTER_INFO_LEVEL *printer = NULL;
9205 DEBUG(5,("spoolss_deleteprinterkey\n"));
9208 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9212 /* if keyname == NULL, return error */
9214 if ( !q_u->keyname.buffer )
9215 return WERR_INVALID_PARAM;
9217 if (!get_printer_snum(p, handle, &snum))
9220 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9221 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9222 return WERR_ACCESS_DENIED;
9225 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9226 if (!W_ERROR_IS_OK(status))
9229 /* delete the key and all subneys */
9231 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9233 status = delete_all_printer_data( printer->info_2, key );
9235 if ( W_ERROR_IS_OK(status) )
9236 status = mod_a_printer(printer, 2);
9238 free_a_printer( &printer, 2 );
9244 /********************************************************************
9245 * spoolss_enumprinterdataex
9246 ********************************************************************/
9248 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9250 POLICY_HND *handle = &q_u->handle;
9251 uint32 in_size = q_u->size;
9254 NT_PRINTER_INFO_LEVEL *printer = NULL;
9255 PRINTER_ENUM_VALUES *enum_values = NULL;
9256 NT_PRINTER_DATA *p_data;
9258 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9263 REGISTRY_VALUE *val;
9268 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9271 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9276 * first check for a keyname of NULL or "". Win2k seems to send
9277 * this a lot and we should send back WERR_INVALID_PARAM
9278 * no need to spend time looking up the printer in this case.
9282 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9283 if ( !strlen(key) ) {
9284 result = WERR_INVALID_PARAM;
9288 /* get the printer off of disk */
9290 if (!get_printer_snum(p,handle, &snum))
9293 ZERO_STRUCT(printer);
9294 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9295 if (!W_ERROR_IS_OK(result))
9298 /* now look for a match on the key name */
9300 p_data = printer->info_2->data;
9302 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9303 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9305 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9306 result = WERR_INVALID_PARAM;
9313 /* allocate the memory for the array of pointers -- if necessary */
9315 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9318 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9320 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9321 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9322 result = WERR_NOMEM;
9326 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9330 * loop through all params and build the array to pass
9331 * back to the client
9334 for ( i=0; i<num_entries; i++ )
9336 /* lookup the registry value */
9338 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9339 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9343 value_name = regval_name( val );
9344 init_unistr( &enum_values[i].valuename, value_name );
9345 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9346 enum_values[i].type = regval_type( val );
9348 data_len = regval_size( val );
9350 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9352 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9354 result = WERR_NOMEM;
9358 enum_values[i].data_len = data_len;
9360 /* keep track of the size of the array in bytes */
9362 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9365 /* housekeeping information in the reply */
9367 r_u->needed = needed;
9368 r_u->returned = num_entries;
9370 if (needed > in_size) {
9371 result = WERR_MORE_DATA;
9375 /* copy data into the reply */
9377 r_u->ctr.size = r_u->needed;
9378 r_u->ctr.size_of_array = r_u->returned;
9379 r_u->ctr.values = enum_values;
9385 free_a_printer(&printer, 2);
9390 /****************************************************************************
9391 ****************************************************************************/
9393 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9395 init_unistr(&info->name, name);
9398 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9399 UNISTR2 *environment,
9406 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9407 WERROR result = WERR_OK;
9409 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9411 if (!get_short_archi(long_archi))
9412 return WERR_INVALID_ENVIRONMENT;
9414 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9417 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9419 fill_printprocessordirectory_1(info, path);
9421 *needed += spoolss_size_printprocessordirectory_info_1(info);
9423 if (*needed > offered) {
9424 result = WERR_INSUFFICIENT_BUFFER;
9428 if (!rpcbuf_alloc_size(buffer, *needed)) {
9429 result = WERR_INSUFFICIENT_BUFFER;
9433 smb_io_printprocessordirectory_1("", buffer, info, 0);
9441 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9443 uint32 level = q_u->level;
9444 RPC_BUFFER *buffer = NULL;
9445 uint32 offered = q_u->offered;
9446 uint32 *needed = &r_u->needed;
9449 /* that's an [in out] buffer */
9451 if (!q_u->buffer && (offered!=0)) {
9452 return WERR_INVALID_PARAM;
9455 rpcbuf_move(q_u->buffer, &r_u->buffer);
9456 buffer = r_u->buffer;
9458 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9464 result = getprintprocessordirectory_level_1
9465 (&q_u->name, &q_u->environment, buffer, offered, needed);
9468 result = WERR_UNKNOWN_LEVEL;
9474 /*******************************************************************
9475 Streams the monitor UI DLL name in UNICODE
9476 *******************************************************************/
9478 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9479 RPC_BUFFER *out, uint32 *needed )
9481 const char *dllname = "tcpmonui.dll";
9483 *needed = (strlen(dllname)+1) * 2;
9485 if ( rpcbuf_get_size(out) < *needed ) {
9486 return WERR_INSUFFICIENT_BUFFER;
9489 if ( !make_monitorui_buf( out, dllname ) ) {
9496 /*******************************************************************
9497 Create a new TCP/IP port
9498 *******************************************************************/
9500 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9501 RPC_BUFFER *out, uint32 *needed )
9503 NT_PORT_DATA_1 port1;
9506 ZERO_STRUCT( port1 );
9508 /* convert to our internal port data structure */
9510 if ( !convert_port_data_1( &port1, in ) ) {
9514 /* create the device URI and call the add_port_hook() */
9516 switch ( port1.protocol ) {
9517 case PORT_PROTOCOL_DIRECT:
9518 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9521 case PORT_PROTOCOL_LPR:
9522 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9526 return WERR_UNKNOWN_PORT;
9529 return add_port_hook( token, port1.name, device_uri );
9532 /*******************************************************************
9533 *******************************************************************/
9535 struct xcv_api_table xcvtcp_cmds[] = {
9536 { "MonitorUI", xcvtcp_monitorui },
9537 { "AddPort", xcvtcp_addport},
9541 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9542 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9547 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9549 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9550 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9551 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9554 return WERR_BADFUNC;
9557 /*******************************************************************
9558 *******************************************************************/
9559 #if 0 /* don't support management using the "Local Port" monitor */
9561 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9562 RPC_BUFFER *out, uint32 *needed )
9564 const char *dllname = "localui.dll";
9566 *needed = (strlen(dllname)+1) * 2;
9568 if ( rpcbuf_get_size(out) < *needed ) {
9569 return WERR_INSUFFICIENT_BUFFER;
9572 if ( !make_monitorui_buf( out, dllname )) {
9579 /*******************************************************************
9580 *******************************************************************/
9582 struct xcv_api_table xcvlocal_cmds[] = {
9583 { "MonitorUI", xcvlocal_monitorui },
9587 struct xcv_api_table xcvlocal_cmds[] = {
9594 /*******************************************************************
9595 *******************************************************************/
9597 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9598 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9603 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9605 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9606 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9607 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9609 return WERR_BADFUNC;
9612 /*******************************************************************
9613 *******************************************************************/
9615 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9617 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9621 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9625 /* Has to be a handle to the TCP/IP port monitor */
9627 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9628 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9632 /* requires administrative access to the server */
9634 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9635 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9636 return WERR_ACCESS_DENIED;
9639 /* Get the command name. There's numerous commands supported by the
9640 TCPMON interface. */
9642 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9643 q_u->dataname.uni_str_len*2, 0);
9645 /* Allocate the outgoing buffer */
9647 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9649 switch ( Printer->printer_type ) {
9650 case SPLHND_PORTMON_TCP:
9651 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9652 &q_u->indata, &r_u->outdata, &r_u->needed );
9653 case SPLHND_PORTMON_LOCAL:
9654 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9655 &q_u->indata, &r_u->outdata, &r_u->needed );
9658 return WERR_INVALID_PRINT_MONITOR;