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 ( !share_defined( sharename ) )
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 Printer_entry *Printer=NULL;
1514 if ( !q_u->printername )
1515 return WERR_INVALID_PRINTER_NAME;
1517 /* some sanity check because you can open a printer or a print server */
1518 /* aka: \\server\printer or \\server */
1520 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1522 DEBUGADD(3,("checking name: %s\n",name));
1524 if (!open_printer_hnd(p, handle, name, 0))
1525 return WERR_INVALID_PRINTER_NAME;
1527 Printer=find_printer_index_by_hnd(p, handle);
1529 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1530 "handle we created for printer %s\n", name ));
1531 close_printer_handle(p,handle);
1532 return WERR_INVALID_PRINTER_NAME;
1536 * First case: the user is opening the print server:
1538 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1539 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1541 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1542 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1543 * or if the user is listed in the smb.conf printer admin parameter.
1545 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1546 * client view printer folder, but does not show the MSAPW.
1548 * Note: this test needs code to check access rights here too. Jeremy
1549 * could you look at this?
1551 * Second case: the user is opening a printer:
1552 * NT doesn't let us connect to a printer if the connecting user
1553 * doesn't have print permission.
1555 * Third case: user is opening a Port Monitor
1556 * access checks same as opening a handle to the print server.
1559 switch (Printer->printer_type )
1562 case SPLHND_PORTMON_TCP:
1563 case SPLHND_PORTMON_LOCAL:
1564 /* Printserver handles use global struct... */
1568 /* Map standard access rights to object specific access rights */
1570 se_map_standard(&printer_default->access_required,
1571 &printserver_std_mapping);
1573 /* Deny any object specific bits that don't apply to print
1574 servers (i.e printer and job specific bits) */
1576 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1578 if (printer_default->access_required &
1579 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1580 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1581 close_printer_handle(p, handle);
1582 return WERR_ACCESS_DENIED;
1585 /* Allow admin access */
1587 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1589 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1591 if (!lp_ms_add_printer_wizard()) {
1592 close_printer_handle(p, handle);
1593 return WERR_ACCESS_DENIED;
1596 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1597 and not a printer admin, then fail */
1599 if ((p->pipe_user.ut.uid != 0) &&
1600 !user_has_privileges(p->pipe_user.nt_user_token,
1602 !token_contains_name_in_list(
1603 uidtoname(p->pipe_user.ut.uid), NULL,
1604 p->pipe_user.nt_user_token,
1605 lp_printer_admin(snum))) {
1606 close_printer_handle(p, handle);
1607 return WERR_ACCESS_DENIED;
1610 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1614 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1617 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1618 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1620 /* We fall through to return WERR_OK */
1623 case SPLHND_PRINTER:
1624 /* NT doesn't let us connect to a printer if the connecting user
1625 doesn't have print permission. */
1627 if (!get_printer_snum(p, handle, &snum)) {
1628 close_printer_handle(p, handle);
1632 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1634 /* map an empty access mask to the minimum access mask */
1635 if (printer_default->access_required == 0x0)
1636 printer_default->access_required = PRINTER_ACCESS_USE;
1639 * If we are not serving the printer driver for this printer,
1640 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1641 * will keep NT clients happy --jerry
1644 if (lp_use_client_driver(snum)
1645 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1647 printer_default->access_required = PRINTER_ACCESS_USE;
1650 /* check smb.conf parameters and the the sec_desc */
1652 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1653 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1654 return WERR_ACCESS_DENIED;
1657 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1658 p->pipe_user.nt_user_token, snum) ||
1659 !print_access_check(&p->pipe_user, snum,
1660 printer_default->access_required)) {
1661 DEBUG(3, ("access DENIED for printer open\n"));
1662 close_printer_handle(p, handle);
1663 return WERR_ACCESS_DENIED;
1666 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1667 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1668 close_printer_handle(p, handle);
1669 return WERR_ACCESS_DENIED;
1672 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1673 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1675 printer_default->access_required = PRINTER_ACCESS_USE;
1677 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1678 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1683 /* sanity check to prevent programmer error */
1687 Printer->access_granted = printer_default->access_required;
1690 * If the client sent a devmode in the OpenPrinter() call, then
1691 * save it here in case we get a job submission on this handle
1694 if ( (Printer->printer_type != SPLHND_SERVER)
1695 && q_u->printer_default.devmode_cont.devmode_ptr )
1697 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1698 &Printer->nt_devmode );
1701 #if 0 /* JERRY -- I'm doubtful this is really effective */
1702 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1703 optimization in Windows 2000 clients --jerry */
1705 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1706 && (RA_WIN2K == get_remote_arch()) )
1708 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1709 sys_usleep( 500000 );
1716 /****************************************************************************
1717 ****************************************************************************/
1719 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1720 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1726 /* allocate memory if needed. Messy because
1727 convert_printer_info is used to update an existing
1728 printer or build a new one */
1730 if ( !printer->info_2 ) {
1731 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1732 if ( !printer->info_2 ) {
1733 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1738 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1739 printer->info_2->setuptime = time(NULL);
1747 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1748 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1754 printer->info_3=NULL;
1755 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1759 printer->info_6=NULL;
1760 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1770 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1771 NT_DEVICEMODE **pp_nt_devmode)
1773 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1776 * Ensure nt_devmode is a valid pointer
1777 * as we will be overwriting it.
1780 if (nt_devmode == NULL) {
1781 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1782 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1786 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1787 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1789 nt_devmode->specversion=devmode->specversion;
1790 nt_devmode->driverversion=devmode->driverversion;
1791 nt_devmode->size=devmode->size;
1792 nt_devmode->fields=devmode->fields;
1793 nt_devmode->orientation=devmode->orientation;
1794 nt_devmode->papersize=devmode->papersize;
1795 nt_devmode->paperlength=devmode->paperlength;
1796 nt_devmode->paperwidth=devmode->paperwidth;
1797 nt_devmode->scale=devmode->scale;
1798 nt_devmode->copies=devmode->copies;
1799 nt_devmode->defaultsource=devmode->defaultsource;
1800 nt_devmode->printquality=devmode->printquality;
1801 nt_devmode->color=devmode->color;
1802 nt_devmode->duplex=devmode->duplex;
1803 nt_devmode->yresolution=devmode->yresolution;
1804 nt_devmode->ttoption=devmode->ttoption;
1805 nt_devmode->collate=devmode->collate;
1807 nt_devmode->logpixels=devmode->logpixels;
1808 nt_devmode->bitsperpel=devmode->bitsperpel;
1809 nt_devmode->pelswidth=devmode->pelswidth;
1810 nt_devmode->pelsheight=devmode->pelsheight;
1811 nt_devmode->displayflags=devmode->displayflags;
1812 nt_devmode->displayfrequency=devmode->displayfrequency;
1813 nt_devmode->icmmethod=devmode->icmmethod;
1814 nt_devmode->icmintent=devmode->icmintent;
1815 nt_devmode->mediatype=devmode->mediatype;
1816 nt_devmode->dithertype=devmode->dithertype;
1817 nt_devmode->reserved1=devmode->reserved1;
1818 nt_devmode->reserved2=devmode->reserved2;
1819 nt_devmode->panningwidth=devmode->panningwidth;
1820 nt_devmode->panningheight=devmode->panningheight;
1823 * Only change private and driverextra if the incoming devmode
1824 * has a new one. JRA.
1827 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1828 SAFE_FREE(nt_devmode->nt_dev_private);
1829 nt_devmode->driverextra=devmode->driverextra;
1830 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1832 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1835 *pp_nt_devmode = nt_devmode;
1840 /********************************************************************
1841 * _spoolss_enddocprinter_internal.
1842 ********************************************************************/
1844 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1846 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1850 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1854 if (!get_printer_snum(p, handle, &snum))
1857 Printer->document_started=False;
1858 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1859 /* error codes unhandled so far ... */
1864 /********************************************************************
1865 * api_spoolss_closeprinter
1866 ********************************************************************/
1868 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1870 POLICY_HND *handle = &q_u->handle;
1872 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1874 if (Printer && Printer->document_started)
1875 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1877 if (!close_printer_handle(p, handle))
1880 /* clear the returned printer handle. Observed behavior
1881 from Win2k server. Don't think this really matters.
1882 Previous code just copied the value of the closed
1885 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1890 /********************************************************************
1891 * api_spoolss_deleteprinter
1893 ********************************************************************/
1895 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1897 POLICY_HND *handle = &q_u->handle;
1898 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1901 if (Printer && Printer->document_started)
1902 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1904 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1906 result = delete_printer_handle(p, handle);
1908 update_c_setprinter(False);
1913 /*******************************************************************
1914 * static function to lookup the version id corresponding to an
1915 * long architecture string
1916 ******************************************************************/
1918 static int get_version_id (char * arch)
1921 struct table_node archi_table[]= {
1923 {"Windows 4.0", "WIN40", 0 },
1924 {"Windows NT x86", "W32X86", 2 },
1925 {"Windows NT R4000", "W32MIPS", 2 },
1926 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1927 {"Windows NT PowerPC", "W32PPC", 2 },
1928 {"Windows IA64", "IA64", 3 },
1929 {"Windows x64", "x64", 3 },
1933 for (i=0; archi_table[i].long_archi != NULL; i++)
1935 if (strcmp(arch, archi_table[i].long_archi) == 0)
1936 return (archi_table[i].version);
1942 /********************************************************************
1943 * _spoolss_deleteprinterdriver
1944 ********************************************************************/
1946 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1950 NT_PRINTER_DRIVER_INFO_LEVEL info;
1951 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1954 WERROR status_win2k = WERR_ACCESS_DENIED;
1955 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1957 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1958 and not a printer admin, then fail */
1960 if ( (p->pipe_user.ut.uid != 0)
1961 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
1962 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
1963 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
1965 return WERR_ACCESS_DENIED;
1968 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1969 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1971 /* check that we have a valid driver name first */
1973 if ((version=get_version_id(arch)) == -1)
1974 return WERR_INVALID_ENVIRONMENT;
1977 ZERO_STRUCT(info_win2k);
1979 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1981 /* try for Win2k driver if "Windows NT x86" */
1983 if ( version == 2 ) {
1985 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1986 status = WERR_UNKNOWN_PRINTER_DRIVER;
1990 /* otherwise it was a failure */
1992 status = WERR_UNKNOWN_PRINTER_DRIVER;
1998 if (printer_driver_in_use(info.info_3)) {
1999 status = WERR_PRINTER_DRIVER_IN_USE;
2005 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2007 /* if we get to here, we now have 2 driver info structures to remove */
2008 /* remove the Win2k driver first*/
2010 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2011 free_a_printer_driver( info_win2k, 3 );
2013 /* this should not have failed---if it did, report to client */
2014 if ( !W_ERROR_IS_OK(status_win2k) )
2016 status = status_win2k;
2022 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2024 /* if at least one of the deletes succeeded return OK */
2026 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2030 free_a_printer_driver( info, 3 );
2035 /********************************************************************
2036 * spoolss_deleteprinterdriverex
2037 ********************************************************************/
2039 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2043 NT_PRINTER_DRIVER_INFO_LEVEL info;
2044 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2046 uint32 flags = q_u->delete_flags;
2049 WERROR status_win2k = WERR_ACCESS_DENIED;
2050 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2052 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2053 and not a printer admin, then fail */
2055 if ( (p->pipe_user.ut.uid != 0)
2056 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2057 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2058 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2060 return WERR_ACCESS_DENIED;
2063 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2064 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2066 /* check that we have a valid driver name first */
2067 if ((version=get_version_id(arch)) == -1) {
2068 /* this is what NT returns */
2069 return WERR_INVALID_ENVIRONMENT;
2072 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2073 version = q_u->version;
2076 ZERO_STRUCT(info_win2k);
2078 status = get_a_printer_driver(&info, 3, driver, arch, version);
2080 if ( !W_ERROR_IS_OK(status) )
2083 * if the client asked for a specific version,
2084 * or this is something other than Windows NT x86,
2088 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2091 /* try for Win2k driver if "Windows NT x86" */
2094 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2095 status = WERR_UNKNOWN_PRINTER_DRIVER;
2100 if ( printer_driver_in_use(info.info_3) ) {
2101 status = WERR_PRINTER_DRIVER_IN_USE;
2106 * we have a couple of cases to consider.
2107 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2108 * then the delete should fail if **any** files overlap with
2110 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2111 * non-overlapping files
2112 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2113 * is set, the do not delete any files
2114 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2117 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2119 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2121 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2122 /* no idea of the correct error here */
2123 status = WERR_ACCESS_DENIED;
2128 /* also check for W32X86/3 if necessary; maybe we already have? */
2130 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2131 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2134 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2135 /* no idea of the correct error here */
2136 free_a_printer_driver( info_win2k, 3 );
2137 status = WERR_ACCESS_DENIED;
2141 /* if we get to here, we now have 2 driver info structures to remove */
2142 /* remove the Win2k driver first*/
2144 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2145 free_a_printer_driver( info_win2k, 3 );
2147 /* this should not have failed---if it did, report to client */
2149 if ( !W_ERROR_IS_OK(status_win2k) )
2154 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2156 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2159 free_a_printer_driver( info, 3 );
2165 /****************************************************************************
2166 Internal routine for retreiving printerdata
2167 ***************************************************************************/
2169 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2170 const char *key, const char *value, uint32 *type, uint8 **data,
2171 uint32 *needed, uint32 in_size )
2173 REGISTRY_VALUE *val;
2177 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2178 return WERR_BADFILE;
2180 *type = regval_type( val );
2182 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2184 size = regval_size( val );
2186 /* copy the min(in_size, len) */
2189 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2191 /* special case for 0 length values */
2193 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2197 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2206 DEBUG(5,("get_printer_dataex: copy done\n"));
2211 /****************************************************************************
2212 Internal routine for removing printerdata
2213 ***************************************************************************/
2215 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2217 return delete_printer_data( printer->info_2, key, value );
2220 /****************************************************************************
2221 Internal routine for storing printerdata
2222 ***************************************************************************/
2224 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2225 uint32 type, uint8 *data, int real_len )
2227 /* the registry objects enforce uniqueness based on value name */
2229 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2232 /********************************************************************
2233 GetPrinterData on a printer server Handle.
2234 ********************************************************************/
2236 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2240 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2242 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2244 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2250 if (!StrCaseCmp(value, "BeepEnabled")) {
2252 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2254 SIVAL(*data, 0, 0x00);
2259 if (!StrCaseCmp(value, "EventLog")) {
2261 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2263 /* formally was 0x1b */
2264 SIVAL(*data, 0, 0x0);
2269 if (!StrCaseCmp(value, "NetPopup")) {
2271 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2273 SIVAL(*data, 0, 0x00);
2278 if (!StrCaseCmp(value, "MajorVersion")) {
2280 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2283 /* Windows NT 4.0 seems to not allow uploading of drivers
2284 to a server that reports 0x3 as the MajorVersion.
2285 need to investigate more how Win2k gets around this .
2288 if ( RA_WINNT == get_remote_arch() )
2297 if (!StrCaseCmp(value, "MinorVersion")) {
2299 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2307 * uint32 size = 0x114
2309 * uint32 minor = [0|1]
2310 * uint32 build = [2195|2600]
2311 * extra unicode string = e.g. "Service Pack 3"
2313 if (!StrCaseCmp(value, "OSVersion")) {
2317 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2320 SIVAL(*data, 0, *needed); /* size */
2321 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2323 SIVAL(*data, 12, 2195); /* build */
2325 /* leave extra string empty */
2331 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2332 const char *string="C:\\PRINTERS";
2334 *needed = 2*(strlen(string)+1);
2335 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2337 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2339 /* it's done by hand ready to go on the wire */
2340 for (i=0; i<strlen(string); i++) {
2341 (*data)[2*i]=string[i];
2342 (*data)[2*i+1]='\0';
2347 if (!StrCaseCmp(value, "Architecture")) {
2348 const char *string="Windows NT x86";
2350 *needed = 2*(strlen(string)+1);
2351 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2353 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2354 for (i=0; i<strlen(string); i++) {
2355 (*data)[2*i]=string[i];
2356 (*data)[2*i+1]='\0';
2361 if (!StrCaseCmp(value, "DsPresent")) {
2363 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2366 /* only show the publish check box if we are a
2367 memeber of a AD domain */
2369 if ( lp_security() == SEC_ADS )
2370 SIVAL(*data, 0, 0x01);
2372 SIVAL(*data, 0, 0x00);
2378 if (!StrCaseCmp(value, "DNSMachineName")) {
2381 if (!get_mydnsfullname(hostname))
2382 return WERR_BADFILE;
2384 *needed = 2*(strlen(hostname)+1);
2385 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2387 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2388 for (i=0; i<strlen(hostname); i++) {
2389 (*data)[2*i]=hostname[i];
2390 (*data)[2*i+1]='\0';
2396 return WERR_BADFILE;
2399 /********************************************************************
2400 * spoolss_getprinterdata
2401 ********************************************************************/
2403 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2405 POLICY_HND *handle = &q_u->handle;
2406 UNISTR2 *valuename = &q_u->valuename;
2407 uint32 in_size = q_u->size;
2408 uint32 *type = &r_u->type;
2409 uint32 *out_size = &r_u->size;
2410 uint8 **data = &r_u->data;
2411 uint32 *needed = &r_u->needed;
2414 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2415 NT_PRINTER_INFO_LEVEL *printer = NULL;
2419 * Reminder: when it's a string, the length is in BYTES
2420 * even if UNICODE is negociated.
2425 *out_size = in_size;
2427 /* in case of problem, return some default values */
2432 DEBUG(4,("_spoolss_getprinterdata\n"));
2435 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2436 status = WERR_BADFID;
2440 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2442 if ( Printer->printer_type == SPLHND_SERVER )
2443 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2446 if ( !get_printer_snum(p,handle, &snum) ) {
2447 status = WERR_BADFID;
2451 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2452 if ( !W_ERROR_IS_OK(status) )
2455 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2457 if ( strequal(value, "ChangeId") ) {
2459 *needed = sizeof(uint32);
2460 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2461 status = WERR_NOMEM;
2464 SIVAL( *data, 0, printer->info_2->changeid );
2468 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2471 if (*needed > *out_size)
2472 status = WERR_MORE_DATA;
2475 if ( !W_ERROR_IS_OK(status) )
2477 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2479 /* reply this param doesn't exist */
2482 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2484 free_a_printer( &printer, 2 );
2493 /* cleanup & exit */
2496 free_a_printer( &printer, 2 );
2501 /*********************************************************
2502 Connect to the client machine.
2503 **********************************************************/
2505 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2506 struct in_addr *client_ip, const char *remote_machine)
2509 struct cli_state *the_cli;
2510 struct in_addr rm_addr;
2512 if ( is_zero_ip(*client_ip) ) {
2513 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2514 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2518 if ( ismyip( rm_addr )) {
2519 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2523 rm_addr.s_addr = client_ip->s_addr;
2524 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2525 inet_ntoa(*client_ip) ));
2528 /* setup the connection */
2530 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2531 &rm_addr, 0, "IPC$", "IPC",
2535 0, lp_client_signing(), NULL );
2537 if ( !NT_STATUS_IS_OK( ret ) ) {
2538 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2543 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2544 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2545 cli_shutdown(the_cli);
2550 * Ok - we have an anonymous connection to the IPC$ share.
2551 * Now start the NT Domain stuff :-).
2554 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2555 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2556 remote_machine, nt_errstr(ret)));
2557 cli_shutdown(the_cli);
2561 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2563 (*pp_pipe)->cli = the_cli;
2568 /***************************************************************************
2569 Connect to the client.
2570 ****************************************************************************/
2572 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2573 uint32 localprinter, uint32 type,
2574 POLICY_HND *handle, struct in_addr *client_ip)
2579 * If it's the first connection, contact the client
2580 * and connect to the IPC$ share anonymously
2582 if (smb_connections==0) {
2583 fstring unix_printer;
2585 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2587 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2590 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2591 /* Tell the connections db we're now interested in printer
2592 * notify messages. */
2593 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2597 * Tell the specific printing tdb we want messages for this printer
2598 * by registering our PID.
2601 if (!print_notify_register_pid(snum))
2602 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2606 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2609 if (!W_ERROR_IS_OK(result))
2610 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2611 dos_errstr(result)));
2613 return (W_ERROR_IS_OK(result));
2616 /********************************************************************
2618 * ReplyFindFirstPrinterChangeNotifyEx
2620 * before replying OK: status=0 a rpc call is made to the workstation
2621 * asking ReplyOpenPrinter
2623 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2624 * called from api_spoolss_rffpcnex
2625 ********************************************************************/
2627 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2629 POLICY_HND *handle = &q_u->handle;
2630 uint32 flags = q_u->flags;
2631 uint32 options = q_u->options;
2632 UNISTR2 *localmachine = &q_u->localmachine;
2633 uint32 printerlocal = q_u->printerlocal;
2635 SPOOL_NOTIFY_OPTION *option = q_u->option;
2636 struct in_addr client_ip;
2638 /* store the notify value in the printer struct */
2640 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2643 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2647 Printer->notify.flags=flags;
2648 Printer->notify.options=options;
2649 Printer->notify.printerlocal=printerlocal;
2651 if (Printer->notify.option)
2652 free_spool_notify_option(&Printer->notify.option);
2654 Printer->notify.option=dup_spool_notify_option(option);
2656 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2657 sizeof(Printer->notify.localmachine)-1);
2659 /* Connect to the client machine and send a ReplyOpenPrinter */
2661 if ( Printer->printer_type == SPLHND_SERVER)
2663 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2664 !get_printer_snum(p, handle, &snum) )
2667 client_ip.s_addr = inet_addr(p->conn->client_address);
2669 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2670 Printer->notify.printerlocal, 1,
2671 &Printer->notify.client_hnd, &client_ip))
2672 return WERR_SERVER_UNAVAILABLE;
2674 Printer->notify.client_connected=True;
2679 /*******************************************************************
2680 * fill a notify_info_data with the servername
2681 ********************************************************************/
2683 void spoolss_notify_server_name(int snum,
2684 SPOOL_NOTIFY_INFO_DATA *data,
2685 print_queue_struct *queue,
2686 NT_PRINTER_INFO_LEVEL *printer,
2687 TALLOC_CTX *mem_ctx)
2692 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2694 data->notify_data.data.length = len;
2695 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2697 if (!data->notify_data.data.string) {
2698 data->notify_data.data.length = 0;
2702 memcpy(data->notify_data.data.string, temp, len);
2705 /*******************************************************************
2706 * fill a notify_info_data with the printername (not including the servername).
2707 ********************************************************************/
2709 void spoolss_notify_printer_name(int snum,
2710 SPOOL_NOTIFY_INFO_DATA *data,
2711 print_queue_struct *queue,
2712 NT_PRINTER_INFO_LEVEL *printer,
2713 TALLOC_CTX *mem_ctx)
2718 /* the notify name should not contain the \\server\ part */
2719 char *p = strrchr(printer->info_2->printername, '\\');
2722 p = printer->info_2->printername;
2727 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2729 data->notify_data.data.length = len;
2730 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2732 if (!data->notify_data.data.string) {
2733 data->notify_data.data.length = 0;
2737 memcpy(data->notify_data.data.string, temp, len);
2740 /*******************************************************************
2741 * fill a notify_info_data with the servicename
2742 ********************************************************************/
2744 void spoolss_notify_share_name(int snum,
2745 SPOOL_NOTIFY_INFO_DATA *data,
2746 print_queue_struct *queue,
2747 NT_PRINTER_INFO_LEVEL *printer,
2748 TALLOC_CTX *mem_ctx)
2753 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2755 data->notify_data.data.length = len;
2756 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2758 if (!data->notify_data.data.string) {
2759 data->notify_data.data.length = 0;
2763 memcpy(data->notify_data.data.string, temp, len);
2766 /*******************************************************************
2767 * fill a notify_info_data with the port name
2768 ********************************************************************/
2770 void spoolss_notify_port_name(int snum,
2771 SPOOL_NOTIFY_INFO_DATA *data,
2772 print_queue_struct *queue,
2773 NT_PRINTER_INFO_LEVEL *printer,
2774 TALLOC_CTX *mem_ctx)
2779 /* even if it's strange, that's consistant in all the code */
2781 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2783 data->notify_data.data.length = len;
2784 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2786 if (!data->notify_data.data.string) {
2787 data->notify_data.data.length = 0;
2791 memcpy(data->notify_data.data.string, temp, len);
2794 /*******************************************************************
2795 * fill a notify_info_data with the printername
2796 * but it doesn't exist, have to see what to do
2797 ********************************************************************/
2799 void spoolss_notify_driver_name(int snum,
2800 SPOOL_NOTIFY_INFO_DATA *data,
2801 print_queue_struct *queue,
2802 NT_PRINTER_INFO_LEVEL *printer,
2803 TALLOC_CTX *mem_ctx)
2808 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2810 data->notify_data.data.length = len;
2811 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2813 if (!data->notify_data.data.string) {
2814 data->notify_data.data.length = 0;
2818 memcpy(data->notify_data.data.string, temp, len);
2821 /*******************************************************************
2822 * fill a notify_info_data with the comment
2823 ********************************************************************/
2825 void spoolss_notify_comment(int snum,
2826 SPOOL_NOTIFY_INFO_DATA *data,
2827 print_queue_struct *queue,
2828 NT_PRINTER_INFO_LEVEL *printer,
2829 TALLOC_CTX *mem_ctx)
2834 if (*printer->info_2->comment == '\0')
2835 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2837 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2839 data->notify_data.data.length = len;
2840 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2842 if (!data->notify_data.data.string) {
2843 data->notify_data.data.length = 0;
2847 memcpy(data->notify_data.data.string, temp, len);
2850 /*******************************************************************
2851 * fill a notify_info_data with the comment
2852 * location = "Room 1, floor 2, building 3"
2853 ********************************************************************/
2855 void spoolss_notify_location(int snum,
2856 SPOOL_NOTIFY_INFO_DATA *data,
2857 print_queue_struct *queue,
2858 NT_PRINTER_INFO_LEVEL *printer,
2859 TALLOC_CTX *mem_ctx)
2864 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2866 data->notify_data.data.length = len;
2867 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2869 if (!data->notify_data.data.string) {
2870 data->notify_data.data.length = 0;
2874 memcpy(data->notify_data.data.string, temp, len);
2877 /*******************************************************************
2878 * fill a notify_info_data with the device mode
2879 * jfm:xxxx don't to it for know but that's a real problem !!!
2880 ********************************************************************/
2882 static void spoolss_notify_devmode(int snum,
2883 SPOOL_NOTIFY_INFO_DATA *data,
2884 print_queue_struct *queue,
2885 NT_PRINTER_INFO_LEVEL *printer,
2886 TALLOC_CTX *mem_ctx)
2890 /*******************************************************************
2891 * fill a notify_info_data with the separator file name
2892 ********************************************************************/
2894 void spoolss_notify_sepfile(int snum,
2895 SPOOL_NOTIFY_INFO_DATA *data,
2896 print_queue_struct *queue,
2897 NT_PRINTER_INFO_LEVEL *printer,
2898 TALLOC_CTX *mem_ctx)
2903 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2905 data->notify_data.data.length = len;
2906 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2908 if (!data->notify_data.data.string) {
2909 data->notify_data.data.length = 0;
2913 memcpy(data->notify_data.data.string, temp, len);
2916 /*******************************************************************
2917 * fill a notify_info_data with the print processor
2918 * jfm:xxxx return always winprint to indicate we don't do anything to it
2919 ********************************************************************/
2921 void spoolss_notify_print_processor(int snum,
2922 SPOOL_NOTIFY_INFO_DATA *data,
2923 print_queue_struct *queue,
2924 NT_PRINTER_INFO_LEVEL *printer,
2925 TALLOC_CTX *mem_ctx)
2930 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2932 data->notify_data.data.length = len;
2933 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2935 if (!data->notify_data.data.string) {
2936 data->notify_data.data.length = 0;
2940 memcpy(data->notify_data.data.string, temp, len);
2943 /*******************************************************************
2944 * fill a notify_info_data with the print processor options
2945 * jfm:xxxx send an empty string
2946 ********************************************************************/
2948 void spoolss_notify_parameters(int snum,
2949 SPOOL_NOTIFY_INFO_DATA *data,
2950 print_queue_struct *queue,
2951 NT_PRINTER_INFO_LEVEL *printer,
2952 TALLOC_CTX *mem_ctx)
2957 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2959 data->notify_data.data.length = len;
2960 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2962 if (!data->notify_data.data.string) {
2963 data->notify_data.data.length = 0;
2967 memcpy(data->notify_data.data.string, temp, len);
2970 /*******************************************************************
2971 * fill a notify_info_data with the data type
2972 * jfm:xxxx always send RAW as data type
2973 ********************************************************************/
2975 void spoolss_notify_datatype(int snum,
2976 SPOOL_NOTIFY_INFO_DATA *data,
2977 print_queue_struct *queue,
2978 NT_PRINTER_INFO_LEVEL *printer,
2979 TALLOC_CTX *mem_ctx)
2984 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2986 data->notify_data.data.length = len;
2987 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2989 if (!data->notify_data.data.string) {
2990 data->notify_data.data.length = 0;
2994 memcpy(data->notify_data.data.string, temp, len);
2997 /*******************************************************************
2998 * fill a notify_info_data with the security descriptor
2999 * jfm:xxxx send an null pointer to say no security desc
3000 * have to implement security before !
3001 ********************************************************************/
3003 static void spoolss_notify_security_desc(int snum,
3004 SPOOL_NOTIFY_INFO_DATA *data,
3005 print_queue_struct *queue,
3006 NT_PRINTER_INFO_LEVEL *printer,
3007 TALLOC_CTX *mem_ctx)
3009 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3010 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3013 /*******************************************************************
3014 * fill a notify_info_data with the attributes
3015 * jfm:xxxx a samba printer is always shared
3016 ********************************************************************/
3018 void spoolss_notify_attributes(int snum,
3019 SPOOL_NOTIFY_INFO_DATA *data,
3020 print_queue_struct *queue,
3021 NT_PRINTER_INFO_LEVEL *printer,
3022 TALLOC_CTX *mem_ctx)
3024 data->notify_data.value[0] = printer->info_2->attributes;
3025 data->notify_data.value[1] = 0;
3028 /*******************************************************************
3029 * fill a notify_info_data with the priority
3030 ********************************************************************/
3032 static void spoolss_notify_priority(int snum,
3033 SPOOL_NOTIFY_INFO_DATA *data,
3034 print_queue_struct *queue,
3035 NT_PRINTER_INFO_LEVEL *printer,
3036 TALLOC_CTX *mem_ctx)
3038 data->notify_data.value[0] = printer->info_2->priority;
3039 data->notify_data.value[1] = 0;
3042 /*******************************************************************
3043 * fill a notify_info_data with the default priority
3044 ********************************************************************/
3046 static void spoolss_notify_default_priority(int snum,
3047 SPOOL_NOTIFY_INFO_DATA *data,
3048 print_queue_struct *queue,
3049 NT_PRINTER_INFO_LEVEL *printer,
3050 TALLOC_CTX *mem_ctx)
3052 data->notify_data.value[0] = printer->info_2->default_priority;
3053 data->notify_data.value[1] = 0;
3056 /*******************************************************************
3057 * fill a notify_info_data with the start time
3058 ********************************************************************/
3060 static void spoolss_notify_start_time(int snum,
3061 SPOOL_NOTIFY_INFO_DATA *data,
3062 print_queue_struct *queue,
3063 NT_PRINTER_INFO_LEVEL *printer,
3064 TALLOC_CTX *mem_ctx)
3066 data->notify_data.value[0] = printer->info_2->starttime;
3067 data->notify_data.value[1] = 0;
3070 /*******************************************************************
3071 * fill a notify_info_data with the until time
3072 ********************************************************************/
3074 static void spoolss_notify_until_time(int snum,
3075 SPOOL_NOTIFY_INFO_DATA *data,
3076 print_queue_struct *queue,
3077 NT_PRINTER_INFO_LEVEL *printer,
3078 TALLOC_CTX *mem_ctx)
3080 data->notify_data.value[0] = printer->info_2->untiltime;
3081 data->notify_data.value[1] = 0;
3084 /*******************************************************************
3085 * fill a notify_info_data with the status
3086 ********************************************************************/
3088 static void spoolss_notify_status(int snum,
3089 SPOOL_NOTIFY_INFO_DATA *data,
3090 print_queue_struct *queue,
3091 NT_PRINTER_INFO_LEVEL *printer,
3092 TALLOC_CTX *mem_ctx)
3094 print_status_struct status;
3096 print_queue_length(snum, &status);
3097 data->notify_data.value[0]=(uint32) status.status;
3098 data->notify_data.value[1] = 0;
3101 /*******************************************************************
3102 * fill a notify_info_data with the number of jobs queued
3103 ********************************************************************/
3105 void spoolss_notify_cjobs(int snum,
3106 SPOOL_NOTIFY_INFO_DATA *data,
3107 print_queue_struct *queue,
3108 NT_PRINTER_INFO_LEVEL *printer,
3109 TALLOC_CTX *mem_ctx)
3111 data->notify_data.value[0] = print_queue_length(snum, NULL);
3112 data->notify_data.value[1] = 0;
3115 /*******************************************************************
3116 * fill a notify_info_data with the average ppm
3117 ********************************************************************/
3119 static void spoolss_notify_average_ppm(int snum,
3120 SPOOL_NOTIFY_INFO_DATA *data,
3121 print_queue_struct *queue,
3122 NT_PRINTER_INFO_LEVEL *printer,
3123 TALLOC_CTX *mem_ctx)
3125 /* always respond 8 pages per minutes */
3126 /* a little hard ! */
3127 data->notify_data.value[0] = printer->info_2->averageppm;
3128 data->notify_data.value[1] = 0;
3131 /*******************************************************************
3132 * fill a notify_info_data with username
3133 ********************************************************************/
3135 static void spoolss_notify_username(int snum,
3136 SPOOL_NOTIFY_INFO_DATA *data,
3137 print_queue_struct *queue,
3138 NT_PRINTER_INFO_LEVEL *printer,
3139 TALLOC_CTX *mem_ctx)
3144 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3146 data->notify_data.data.length = len;
3147 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3149 if (!data->notify_data.data.string) {
3150 data->notify_data.data.length = 0;
3154 memcpy(data->notify_data.data.string, temp, len);
3157 /*******************************************************************
3158 * fill a notify_info_data with job status
3159 ********************************************************************/
3161 static void spoolss_notify_job_status(int snum,
3162 SPOOL_NOTIFY_INFO_DATA *data,
3163 print_queue_struct *queue,
3164 NT_PRINTER_INFO_LEVEL *printer,
3165 TALLOC_CTX *mem_ctx)
3167 data->notify_data.value[0]=nt_printj_status(queue->status);
3168 data->notify_data.value[1] = 0;
3171 /*******************************************************************
3172 * fill a notify_info_data with job name
3173 ********************************************************************/
3175 static void spoolss_notify_job_name(int snum,
3176 SPOOL_NOTIFY_INFO_DATA *data,
3177 print_queue_struct *queue,
3178 NT_PRINTER_INFO_LEVEL *printer,
3179 TALLOC_CTX *mem_ctx)
3184 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3186 data->notify_data.data.length = len;
3187 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3189 if (!data->notify_data.data.string) {
3190 data->notify_data.data.length = 0;
3194 memcpy(data->notify_data.data.string, temp, len);
3197 /*******************************************************************
3198 * fill a notify_info_data with job status
3199 ********************************************************************/
3201 static void spoolss_notify_job_status_string(int snum,
3202 SPOOL_NOTIFY_INFO_DATA *data,
3203 print_queue_struct *queue,
3204 NT_PRINTER_INFO_LEVEL *printer,
3205 TALLOC_CTX *mem_ctx)
3208 * Now we're returning job status codes we just return a "" here. JRA.
3215 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3218 switch (queue->status) {
3223 p = ""; /* NT provides the paused string */
3232 #endif /* NO LONGER NEEDED. */
3234 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3236 data->notify_data.data.length = len;
3237 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3239 if (!data->notify_data.data.string) {
3240 data->notify_data.data.length = 0;
3244 memcpy(data->notify_data.data.string, temp, len);
3247 /*******************************************************************
3248 * fill a notify_info_data with job time
3249 ********************************************************************/
3251 static void spoolss_notify_job_time(int snum,
3252 SPOOL_NOTIFY_INFO_DATA *data,
3253 print_queue_struct *queue,
3254 NT_PRINTER_INFO_LEVEL *printer,
3255 TALLOC_CTX *mem_ctx)
3257 data->notify_data.value[0]=0x0;
3258 data->notify_data.value[1]=0;
3261 /*******************************************************************
3262 * fill a notify_info_data with job size
3263 ********************************************************************/
3265 static void spoolss_notify_job_size(int snum,
3266 SPOOL_NOTIFY_INFO_DATA *data,
3267 print_queue_struct *queue,
3268 NT_PRINTER_INFO_LEVEL *printer,
3269 TALLOC_CTX *mem_ctx)
3271 data->notify_data.value[0]=queue->size;
3272 data->notify_data.value[1]=0;
3275 /*******************************************************************
3276 * fill a notify_info_data with page info
3277 ********************************************************************/
3278 static void spoolss_notify_total_pages(int snum,
3279 SPOOL_NOTIFY_INFO_DATA *data,
3280 print_queue_struct *queue,
3281 NT_PRINTER_INFO_LEVEL *printer,
3282 TALLOC_CTX *mem_ctx)
3284 data->notify_data.value[0]=queue->page_count;
3285 data->notify_data.value[1]=0;
3288 /*******************************************************************
3289 * fill a notify_info_data with pages printed info.
3290 ********************************************************************/
3291 static void spoolss_notify_pages_printed(int snum,
3292 SPOOL_NOTIFY_INFO_DATA *data,
3293 print_queue_struct *queue,
3294 NT_PRINTER_INFO_LEVEL *printer,
3295 TALLOC_CTX *mem_ctx)
3297 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3298 data->notify_data.value[1]=0;
3301 /*******************************************************************
3302 Fill a notify_info_data with job position.
3303 ********************************************************************/
3305 static void spoolss_notify_job_position(int snum,
3306 SPOOL_NOTIFY_INFO_DATA *data,
3307 print_queue_struct *queue,
3308 NT_PRINTER_INFO_LEVEL *printer,
3309 TALLOC_CTX *mem_ctx)
3311 data->notify_data.value[0]=queue->job;
3312 data->notify_data.value[1]=0;
3315 /*******************************************************************
3316 Fill a notify_info_data with submitted time.
3317 ********************************************************************/
3319 static void spoolss_notify_submitted_time(int snum,
3320 SPOOL_NOTIFY_INFO_DATA *data,
3321 print_queue_struct *queue,
3322 NT_PRINTER_INFO_LEVEL *printer,
3323 TALLOC_CTX *mem_ctx)
3330 t=gmtime(&queue->time);
3332 len = sizeof(SYSTEMTIME);
3334 data->notify_data.data.length = len;
3335 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3337 if (!data->notify_data.data.string) {
3338 data->notify_data.data.length = 0;
3342 make_systemtime(&st, t);
3345 * Systemtime must be linearized as a set of UINT16's.
3346 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3349 p = (char *)data->notify_data.data.string;
3350 SSVAL(p, 0, st.year);
3351 SSVAL(p, 2, st.month);
3352 SSVAL(p, 4, st.dayofweek);
3353 SSVAL(p, 6, st.day);
3354 SSVAL(p, 8, st.hour);
3355 SSVAL(p, 10, st.minute);
3356 SSVAL(p, 12, st.second);
3357 SSVAL(p, 14, st.milliseconds);
3360 struct s_notify_info_data_table
3366 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3367 print_queue_struct *queue,
3368 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3371 /* A table describing the various print notification constants and
3372 whether the notification data is a pointer to a variable sized
3373 buffer, a one value uint32 or a two value uint32. */
3375 static const struct s_notify_info_data_table notify_info_data_table[] =
3377 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3378 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3379 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3380 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3381 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3382 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3383 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3384 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3385 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3386 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3387 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3388 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3389 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3403 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3404 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3405 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3406 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3407 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3408 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3409 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3410 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3411 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3412 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3413 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3414 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3415 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3426 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3429 /*******************************************************************
3430 Return the size of info_data structure.
3431 ********************************************************************/
3433 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3437 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3438 if ( (notify_info_data_table[i].type == type)
3439 && (notify_info_data_table[i].field == field) ) {
3440 switch(notify_info_data_table[i].size) {
3441 case NOTIFY_ONE_VALUE:
3442 case NOTIFY_TWO_VALUE:
3447 /* The only pointer notify data I have seen on
3448 the wire is the submitted time and this has
3449 the notify size set to 4. -tpot */
3451 case NOTIFY_POINTER:
3454 case NOTIFY_SECDESC:
3460 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3465 /*******************************************************************
3466 Return the type of notify_info_data.
3467 ********************************************************************/
3469 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3473 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3474 if (notify_info_data_table[i].type == type &&
3475 notify_info_data_table[i].field == field)
3476 return notify_info_data_table[i].size;
3482 /****************************************************************************
3483 ****************************************************************************/
3485 static BOOL search_notify(uint16 type, uint16 field, int *value)
3489 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3490 if (notify_info_data_table[i].type == type &&
3491 notify_info_data_table[i].field == field &&
3492 notify_info_data_table[i].fn != NULL) {
3501 /****************************************************************************
3502 ****************************************************************************/
3504 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3506 info_data->type = type;
3507 info_data->field = field;
3508 info_data->reserved = 0;
3510 info_data->size = size_of_notify_info_data(type, field);
3511 info_data->enc_type = type_of_notify_info_data(type, field);
3516 /*******************************************************************
3518 * fill a notify_info struct with info asked
3520 ********************************************************************/
3522 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3523 snum, SPOOL_NOTIFY_OPTION_TYPE
3524 *option_type, uint32 id,
3525 TALLOC_CTX *mem_ctx)
3531 SPOOL_NOTIFY_INFO_DATA *current_data;
3532 NT_PRINTER_INFO_LEVEL *printer = NULL;
3533 print_queue_struct *queue=NULL;
3535 type=option_type->type;
3537 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3538 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3539 option_type->count, lp_servicename(snum)));
3541 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3544 for(field_num=0; field_num<option_type->count; field_num++) {
3545 field = option_type->fields[field_num];
3547 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3549 if (!search_notify(type, field, &j) )
3552 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3553 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3557 current_data = &info->data[info->count];
3559 construct_info_data(current_data, type, field, id);
3561 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3562 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3564 notify_info_data_table[j].fn(snum, current_data, queue,
3570 free_a_printer(&printer, 2);
3574 /*******************************************************************
3576 * fill a notify_info struct with info asked
3578 ********************************************************************/
3580 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3581 SPOOL_NOTIFY_INFO *info,
3582 NT_PRINTER_INFO_LEVEL *printer,
3583 int snum, SPOOL_NOTIFY_OPTION_TYPE
3584 *option_type, uint32 id,
3585 TALLOC_CTX *mem_ctx)
3591 SPOOL_NOTIFY_INFO_DATA *current_data;
3593 DEBUG(4,("construct_notify_jobs_info\n"));
3595 type = option_type->type;
3597 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3598 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3599 option_type->count));
3601 for(field_num=0; field_num<option_type->count; field_num++) {
3602 field = option_type->fields[field_num];
3604 if (!search_notify(type, field, &j) )
3607 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3608 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3612 current_data=&(info->data[info->count]);
3614 construct_info_data(current_data, type, field, id);
3615 notify_info_data_table[j].fn(snum, current_data, queue,
3624 * JFM: The enumeration is not that simple, it's even non obvious.
3626 * let's take an example: I want to monitor the PRINTER SERVER for
3627 * the printer's name and the number of jobs currently queued.
3628 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3629 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3631 * I have 3 printers on the back of my server.
3633 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3636 * 1 printer 1 name 1
3637 * 2 printer 1 cjob 1
3638 * 3 printer 2 name 2
3639 * 4 printer 2 cjob 2
3640 * 5 printer 3 name 3
3641 * 6 printer 3 name 3
3643 * that's the print server case, the printer case is even worse.
3646 /*******************************************************************
3648 * enumerate all printers on the printserver
3649 * fill a notify_info struct with info asked
3651 ********************************************************************/
3653 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3654 SPOOL_NOTIFY_INFO *info,
3655 TALLOC_CTX *mem_ctx)
3658 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3659 int n_services=lp_numservices();
3661 SPOOL_NOTIFY_OPTION *option;
3662 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3664 DEBUG(4,("printserver_notify_info\n"));
3669 option=Printer->notify.option;
3674 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3675 sending a ffpcn() request first */
3680 for (i=0; i<option->count; i++) {
3681 option_type=&(option->ctr.type[i]);
3683 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3686 for (snum=0; snum<n_services; snum++)
3688 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3689 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3695 * Debugging information, don't delete.
3698 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3699 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3700 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3702 for (i=0; i<info->count; i++) {
3703 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3704 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3705 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3712 /*******************************************************************
3714 * fill a notify_info struct with info asked
3716 ********************************************************************/
3718 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3719 TALLOC_CTX *mem_ctx)
3722 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3725 SPOOL_NOTIFY_OPTION *option;
3726 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3728 print_queue_struct *queue=NULL;
3729 print_status_struct status;
3731 DEBUG(4,("printer_notify_info\n"));
3736 option=Printer->notify.option;
3742 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3743 sending a ffpcn() request first */
3748 get_printer_snum(p, hnd, &snum);
3750 for (i=0; i<option->count; i++) {
3751 option_type=&option->ctr.type[i];
3753 switch ( option_type->type ) {
3754 case PRINTER_NOTIFY_TYPE:
3755 if(construct_notify_printer_info(Printer, info, snum,
3761 case JOB_NOTIFY_TYPE: {
3762 NT_PRINTER_INFO_LEVEL *printer = NULL;
3764 count = print_queue_status(snum, &queue, &status);
3766 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3769 for (j=0; j<count; j++) {
3770 construct_notify_jobs_info(&queue[j], info,
3777 free_a_printer(&printer, 2);
3787 * Debugging information, don't delete.
3790 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3791 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3792 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3794 for (i=0; i<info->count; i++) {
3795 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3796 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3797 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3803 /********************************************************************
3805 ********************************************************************/
3807 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3809 POLICY_HND *handle = &q_u->handle;
3810 SPOOL_NOTIFY_INFO *info = &r_u->info;
3812 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3813 WERROR result = WERR_BADFID;
3815 /* we always have a NOTIFY_INFO struct */
3819 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3820 OUR_HANDLE(handle)));
3824 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3827 * We are now using the change value, and
3828 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3829 * I don't have a global notification system, I'm sending back all the
3830 * informations even when _NOTHING_ has changed.
3833 /* We need to keep track of the change value to send back in
3834 RRPCN replies otherwise our updates are ignored. */
3836 Printer->notify.fnpcn = True;
3838 if (Printer->notify.client_connected) {
3839 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3840 Printer->notify.change = q_u->change;
3843 /* just ignore the SPOOL_NOTIFY_OPTION */
3845 switch (Printer->printer_type) {
3847 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3850 case SPLHND_PRINTER:
3851 result = printer_notify_info(p, handle, info, p->mem_ctx);
3855 Printer->notify.fnpcn = False;
3861 /********************************************************************
3862 * construct_printer_info_0
3863 * fill a printer_info_0 struct
3864 ********************************************************************/
3866 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3870 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3871 counter_printer_0 *session_counter;
3872 uint32 global_counter;
3875 print_status_struct status;
3877 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3880 count = print_queue_length(snum, &status);
3882 /* check if we already have a counter for this printer */
3883 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3884 if (session_counter->snum == snum)
3888 /* it's the first time, add it to the list */
3889 if (session_counter==NULL) {
3890 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3891 free_a_printer(&ntprinter, 2);
3894 ZERO_STRUCTP(session_counter);
3895 session_counter->snum=snum;
3896 session_counter->counter=0;
3897 DLIST_ADD(counter_list, session_counter);
3901 session_counter->counter++;
3904 * the global_counter should be stored in a TDB as it's common to all the clients
3905 * and should be zeroed on samba startup
3907 global_counter=session_counter->counter;
3909 pstrcpy(chaine,ntprinter->info_2->printername);
3911 init_unistr(&printer->printername, chaine);
3913 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3914 init_unistr(&printer->servername, chaine);
3916 printer->cjobs = count;
3917 printer->total_jobs = 0;
3918 printer->total_bytes = 0;
3920 setuptime = (time_t)ntprinter->info_2->setuptime;
3921 t=gmtime(&setuptime);
3923 printer->year = t->tm_year+1900;
3924 printer->month = t->tm_mon+1;
3925 printer->dayofweek = t->tm_wday;
3926 printer->day = t->tm_mday;
3927 printer->hour = t->tm_hour;
3928 printer->minute = t->tm_min;
3929 printer->second = t->tm_sec;
3930 printer->milliseconds = 0;
3932 printer->global_counter = global_counter;
3933 printer->total_pages = 0;
3935 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3936 printer->major_version = 0x0005; /* NT 5 */
3937 printer->build_version = 0x0893; /* build 2195 */
3939 printer->unknown7 = 0x1;
3940 printer->unknown8 = 0x0;
3941 printer->unknown9 = 0x0;
3942 printer->session_counter = session_counter->counter;
3943 printer->unknown11 = 0x0;
3944 printer->printer_errors = 0x0; /* number of print failure */
3945 printer->unknown13 = 0x0;
3946 printer->unknown14 = 0x1;
3947 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3948 printer->unknown16 = 0x0;
3949 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3950 printer->unknown18 = 0x0;
3951 printer->status = nt_printq_status(status.status);
3952 printer->unknown20 = 0x0;
3953 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3954 printer->unknown22 = 0x0;
3955 printer->unknown23 = 0x6; /* 6 ???*/
3956 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3957 printer->unknown25 = 0;
3958 printer->unknown26 = 0;
3959 printer->unknown27 = 0;
3960 printer->unknown28 = 0;
3961 printer->unknown29 = 0;
3963 free_a_printer(&ntprinter,2);
3967 /********************************************************************
3968 * construct_printer_info_1
3969 * fill a printer_info_1 struct
3970 ********************************************************************/
3971 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3975 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3977 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3980 printer->flags=flags;
3982 if (*ntprinter->info_2->comment == '\0') {
3983 init_unistr(&printer->comment, lp_comment(snum));
3984 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3985 ntprinter->info_2->drivername, lp_comment(snum));
3988 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3989 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3990 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3993 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3995 init_unistr(&printer->description, chaine);
3996 init_unistr(&printer->name, chaine2);
3998 free_a_printer(&ntprinter,2);
4003 /****************************************************************************
4004 Free a DEVMODE struct.
4005 ****************************************************************************/
4007 static void free_dev_mode(DEVICEMODE *dev)
4012 SAFE_FREE(dev->dev_private);
4017 /****************************************************************************
4018 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4019 should be valid upon entry
4020 ****************************************************************************/
4022 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4024 if ( !devmode || !ntdevmode )
4027 init_unistr(&devmode->devicename, ntdevmode->devicename);
4029 init_unistr(&devmode->formname, ntdevmode->formname);
4031 devmode->specversion = ntdevmode->specversion;
4032 devmode->driverversion = ntdevmode->driverversion;
4033 devmode->size = ntdevmode->size;
4034 devmode->driverextra = ntdevmode->driverextra;
4035 devmode->fields = ntdevmode->fields;
4037 devmode->orientation = ntdevmode->orientation;
4038 devmode->papersize = ntdevmode->papersize;
4039 devmode->paperlength = ntdevmode->paperlength;
4040 devmode->paperwidth = ntdevmode->paperwidth;
4041 devmode->scale = ntdevmode->scale;
4042 devmode->copies = ntdevmode->copies;
4043 devmode->defaultsource = ntdevmode->defaultsource;
4044 devmode->printquality = ntdevmode->printquality;
4045 devmode->color = ntdevmode->color;
4046 devmode->duplex = ntdevmode->duplex;
4047 devmode->yresolution = ntdevmode->yresolution;
4048 devmode->ttoption = ntdevmode->ttoption;
4049 devmode->collate = ntdevmode->collate;
4050 devmode->icmmethod = ntdevmode->icmmethod;
4051 devmode->icmintent = ntdevmode->icmintent;
4052 devmode->mediatype = ntdevmode->mediatype;
4053 devmode->dithertype = ntdevmode->dithertype;
4055 if (ntdevmode->nt_dev_private != NULL) {
4056 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4063 /****************************************************************************
4064 Create a DEVMODE struct. Returns malloced memory.
4065 ****************************************************************************/
4067 DEVICEMODE *construct_dev_mode(const char *servicename)
4069 NT_PRINTER_INFO_LEVEL *printer = NULL;
4070 DEVICEMODE *devmode = NULL;
4072 DEBUG(7,("construct_dev_mode\n"));
4074 DEBUGADD(8,("getting printer characteristics\n"));
4076 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4079 if ( !printer->info_2->devmode ) {
4080 DEBUG(5, ("BONG! There was no device mode!\n"));
4084 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4085 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4089 ZERO_STRUCTP(devmode);
4091 DEBUGADD(8,("loading DEVICEMODE\n"));
4093 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4094 free_dev_mode( devmode );
4099 free_a_printer(&printer,2);
4104 /********************************************************************
4105 * construct_printer_info_2
4106 * fill a printer_info_2 struct
4107 ********************************************************************/
4109 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4112 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4114 print_status_struct status;
4116 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4119 count = print_queue_length(snum, &status);
4121 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4122 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4123 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4124 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4125 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4127 if (*ntprinter->info_2->comment == '\0')
4128 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4130 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4132 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4133 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4134 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4135 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4136 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4138 printer->attributes = ntprinter->info_2->attributes;
4140 printer->priority = ntprinter->info_2->priority; /* priority */
4141 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4142 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4143 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4144 printer->status = nt_printq_status(status.status); /* status */
4145 printer->cjobs = count; /* jobs */
4146 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4148 if ( !(printer->devmode = construct_dev_mode(lp_const_servicename(snum))) )
4149 DEBUG(8, ("Returning NULL Devicemode!\n"));
4151 printer->secdesc = NULL;
4153 if ( ntprinter->info_2->secdesc_buf
4154 && ntprinter->info_2->secdesc_buf->len != 0 )
4156 /* don't use talloc_steal() here unless you do a deep steal of all
4157 the SEC_DESC members */
4159 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4160 ntprinter->info_2->secdesc_buf->sec );
4163 free_a_printer(&ntprinter, 2);
4168 /********************************************************************
4169 * construct_printer_info_3
4170 * fill a printer_info_3 struct
4171 ********************************************************************/
4173 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4175 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4176 PRINTER_INFO_3 *printer = NULL;
4178 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4182 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4183 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4187 ZERO_STRUCTP(printer);
4189 /* These are the components of the SD we are returning. */
4191 printer->flags = 0x4;
4193 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4194 /* don't use talloc_steal() here unless you do a deep steal of all
4195 the SEC_DESC members */
4197 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4198 ntprinter->info_2->secdesc_buf->sec );
4201 free_a_printer(&ntprinter, 2);
4203 *pp_printer = printer;
4207 /********************************************************************
4208 * construct_printer_info_4
4209 * fill a printer_info_4 struct
4210 ********************************************************************/
4212 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4214 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4216 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4219 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4220 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4221 printer->attributes = ntprinter->info_2->attributes;
4223 free_a_printer(&ntprinter, 2);
4227 /********************************************************************
4228 * construct_printer_info_5
4229 * fill a printer_info_5 struct
4230 ********************************************************************/
4232 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4234 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4236 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4239 init_unistr(&printer->printername, ntprinter->info_2->printername);
4240 init_unistr(&printer->portname, ntprinter->info_2->portname);
4241 printer->attributes = ntprinter->info_2->attributes;
4243 /* these two are not used by NT+ according to MSDN */
4245 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4246 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4248 free_a_printer(&ntprinter, 2);
4253 /********************************************************************
4254 * construct_printer_info_7
4255 * fill a printer_info_7 struct
4256 ********************************************************************/
4258 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4260 char *guid_str = NULL;
4263 if (is_printer_published(print_hnd, snum, &guid)) {
4264 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4265 strupper_m(guid_str);
4266 init_unistr(&printer->guid, guid_str);
4267 printer->action = SPOOL_DS_PUBLISH;
4269 init_unistr(&printer->guid, "");
4270 printer->action = SPOOL_DS_UNPUBLISH;
4276 /********************************************************************
4277 Spoolss_enumprinters.
4278 ********************************************************************/
4280 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4284 int n_services=lp_numservices();
4285 PRINTER_INFO_1 *printers=NULL;
4286 PRINTER_INFO_1 current_prt;
4287 WERROR result = WERR_OK;
4289 DEBUG(4,("enum_all_printers_info_1\n"));
4291 for (snum=0; snum<n_services; snum++) {
4292 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4293 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4295 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4296 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4297 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4301 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4303 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4309 /* check the required size. */
4310 for (i=0; i<*returned; i++)
4311 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4313 if (*needed > offered) {
4314 result = WERR_INSUFFICIENT_BUFFER;
4318 if (!rpcbuf_alloc_size(buffer, *needed)) {
4319 result = WERR_NOMEM;
4323 /* fill the buffer with the structures */
4324 for (i=0; i<*returned; i++)
4325 smb_io_printer_info_1("", buffer, &printers[i], 0);
4330 SAFE_FREE(printers);
4332 if ( !W_ERROR_IS_OK(result) )
4338 /********************************************************************
4339 enum_all_printers_info_1_local.
4340 *********************************************************************/
4342 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4344 DEBUG(4,("enum_all_printers_info_1_local\n"));
4346 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4349 /********************************************************************
4350 enum_all_printers_info_1_name.
4351 *********************************************************************/
4353 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4357 DEBUG(4,("enum_all_printers_info_1_name\n"));
4359 if ((name[0] == '\\') && (name[1] == '\\'))
4362 if (is_myname_or_ipaddr(s)) {
4363 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4366 return WERR_INVALID_NAME;
4369 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4370 /********************************************************************
4371 enum_all_printers_info_1_remote.
4372 *********************************************************************/
4374 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4376 PRINTER_INFO_1 *printer;
4377 fstring printername;
4380 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4381 WERROR result = WERR_OK;
4383 /* JFM: currently it's more a place holder than anything else.
4384 * In the spooler world there is a notion of server registration.
4385 * the print servers are registered on the PDC (in the same domain)
4387 * We should have a TDB here. The registration is done thru an
4388 * undocumented RPC call.
4391 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4396 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4397 slprintf(desc, sizeof(desc)-1,"%s", name);
4398 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4400 init_unistr(&printer->description, desc);
4401 init_unistr(&printer->name, printername);
4402 init_unistr(&printer->comment, comment);
4403 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4405 /* check the required size. */
4406 *needed += spoolss_size_printer_info_1(printer);
4408 if (*needed > offered) {
4409 result = WERR_INSUFFICIENT_BUFFER;
4413 if (!rpcbuf_alloc_size(buffer, *needed)) {
4414 result = WERR_NOMEM;
4418 /* fill the buffer with the structures */
4419 smb_io_printer_info_1("", buffer, printer, 0);
4425 if ( !W_ERROR_IS_OK(result) )
4433 /********************************************************************
4434 enum_all_printers_info_1_network.
4435 *********************************************************************/
4437 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4441 DEBUG(4,("enum_all_printers_info_1_network\n"));
4443 /* If we respond to a enum_printers level 1 on our name with flags
4444 set to PRINTER_ENUM_REMOTE with a list of printers then these
4445 printers incorrectly appear in the APW browse list.
4446 Specifically the printers for the server appear at the workgroup
4447 level where all the other servers in the domain are
4448 listed. Windows responds to this call with a
4449 WERR_CAN_NOT_COMPLETE so we should do the same. */
4451 if (name[0] == '\\' && name[1] == '\\')
4454 if (is_myname_or_ipaddr(s))
4455 return WERR_CAN_NOT_COMPLETE;
4457 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4460 /********************************************************************
4461 * api_spoolss_enumprinters
4463 * called from api_spoolss_enumprinters (see this to understand)
4464 ********************************************************************/
4466 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4470 int n_services=lp_numservices();
4471 PRINTER_INFO_2 *printers=NULL;
4472 PRINTER_INFO_2 current_prt;
4473 WERROR result = WERR_OK;
4477 for (snum=0; snum<n_services; snum++) {
4478 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4479 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4481 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4482 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4483 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4488 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4490 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4497 /* check the required size. */
4498 for (i=0; i<*returned; i++)
4499 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4501 if (*needed > offered) {
4502 result = WERR_INSUFFICIENT_BUFFER;
4506 if (!rpcbuf_alloc_size(buffer, *needed)) {
4507 result = WERR_NOMEM;
4511 /* fill the buffer with the structures */
4512 for (i=0; i<*returned; i++)
4513 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4518 for (i=0; i<*returned; i++)
4519 free_devmode(printers[i].devmode);
4521 SAFE_FREE(printers);
4523 if ( !W_ERROR_IS_OK(result) )
4529 /********************************************************************
4530 * handle enumeration of printers at level 1
4531 ********************************************************************/
4533 static WERROR enumprinters_level1( uint32 flags, fstring name,
4534 RPC_BUFFER *buffer, uint32 offered,
4535 uint32 *needed, uint32 *returned)
4537 /* Not all the flags are equals */
4539 if (flags & PRINTER_ENUM_LOCAL)
4540 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4542 if (flags & PRINTER_ENUM_NAME)
4543 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4545 #if 0 /* JERRY - disabled for now */
4546 if (flags & PRINTER_ENUM_REMOTE)
4547 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4550 if (flags & PRINTER_ENUM_NETWORK)
4551 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4553 return WERR_OK; /* NT4sp5 does that */
4556 /********************************************************************
4557 * handle enumeration of printers at level 2
4558 ********************************************************************/
4560 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4561 RPC_BUFFER *buffer, uint32 offered,
4562 uint32 *needed, uint32 *returned)
4564 char *s = servername;
4566 if (flags & PRINTER_ENUM_LOCAL) {
4567 return enum_all_printers_info_2(buffer, offered, needed, returned);
4570 if (flags & PRINTER_ENUM_NAME) {
4571 if ((servername[0] == '\\') && (servername[1] == '\\'))
4573 if (is_myname_or_ipaddr(s))
4574 return enum_all_printers_info_2(buffer, offered, needed, returned);
4576 return WERR_INVALID_NAME;
4579 if (flags & PRINTER_ENUM_REMOTE)
4580 return WERR_UNKNOWN_LEVEL;
4585 /********************************************************************
4586 * handle enumeration of printers at level 5
4587 ********************************************************************/
4589 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4590 RPC_BUFFER *buffer, uint32 offered,
4591 uint32 *needed, uint32 *returned)
4593 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4597 /********************************************************************
4598 * api_spoolss_enumprinters
4600 * called from api_spoolss_enumprinters (see this to understand)
4601 ********************************************************************/
4603 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4605 uint32 flags = q_u->flags;
4606 UNISTR2 *servername = &q_u->servername;
4607 uint32 level = q_u->level;
4608 RPC_BUFFER *buffer = NULL;
4609 uint32 offered = q_u->offered;
4610 uint32 *needed = &r_u->needed;
4611 uint32 *returned = &r_u->returned;
4615 /* that's an [in out] buffer */
4617 if (!q_u->buffer && (offered!=0)) {
4618 return WERR_INVALID_PARAM;
4621 rpcbuf_move(q_u->buffer, &r_u->buffer);
4622 buffer = r_u->buffer;
4624 DEBUG(4,("_spoolss_enumprinters\n"));
4631 * flags==PRINTER_ENUM_NAME
4632 * if name=="" then enumerates all printers
4633 * if name!="" then enumerate the printer
4634 * flags==PRINTER_ENUM_REMOTE
4635 * name is NULL, enumerate printers
4636 * Level 2: name!="" enumerates printers, name can't be NULL
4637 * Level 3: doesn't exist
4638 * Level 4: does a local registry lookup
4639 * Level 5: same as Level 2
4642 unistr2_to_ascii(name, servername, sizeof(name)-1);
4647 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4649 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4651 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4656 return WERR_UNKNOWN_LEVEL;
4659 /****************************************************************************
4660 ****************************************************************************/
4662 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4664 PRINTER_INFO_0 *printer=NULL;
4665 WERROR result = WERR_OK;
4667 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4670 construct_printer_info_0(print_hnd, printer, snum);
4672 /* check the required size. */
4673 *needed += spoolss_size_printer_info_0(printer);
4675 if (*needed > offered) {
4676 result = WERR_INSUFFICIENT_BUFFER;
4680 if (!rpcbuf_alloc_size(buffer, *needed)) {
4681 result = WERR_NOMEM;
4685 /* fill the buffer with the structures */
4686 smb_io_printer_info_0("", buffer, printer, 0);
4696 /****************************************************************************
4697 ****************************************************************************/
4699 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4701 PRINTER_INFO_1 *printer=NULL;
4702 WERROR result = WERR_OK;
4704 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4707 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4709 /* check the required size. */
4710 *needed += spoolss_size_printer_info_1(printer);
4712 if (*needed > offered) {
4713 result = WERR_INSUFFICIENT_BUFFER;
4717 if (!rpcbuf_alloc_size(buffer, *needed)) {
4718 result = WERR_NOMEM;
4722 /* fill the buffer with the structures */
4723 smb_io_printer_info_1("", buffer, printer, 0);
4732 /****************************************************************************
4733 ****************************************************************************/
4735 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4737 PRINTER_INFO_2 *printer=NULL;
4738 WERROR result = WERR_OK;
4740 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4743 construct_printer_info_2(print_hnd, printer, snum);
4745 /* check the required size. */
4746 *needed += spoolss_size_printer_info_2(printer);
4748 if (*needed > offered) {
4749 result = WERR_INSUFFICIENT_BUFFER;
4753 if (!rpcbuf_alloc_size(buffer, *needed)) {
4754 result = WERR_NOMEM;
4758 /* fill the buffer with the structures */
4759 if (!smb_io_printer_info_2("", buffer, printer, 0))
4760 result = WERR_NOMEM;
4764 free_printer_info_2(printer);
4769 /****************************************************************************
4770 ****************************************************************************/
4772 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4774 PRINTER_INFO_3 *printer=NULL;
4775 WERROR result = WERR_OK;
4777 if (!construct_printer_info_3(print_hnd, &printer, snum))
4780 /* check the required size. */
4781 *needed += spoolss_size_printer_info_3(printer);
4783 if (*needed > offered) {
4784 result = WERR_INSUFFICIENT_BUFFER;
4788 if (!rpcbuf_alloc_size(buffer, *needed)) {
4789 result = WERR_NOMEM;
4793 /* fill the buffer with the structures */
4794 smb_io_printer_info_3("", buffer, printer, 0);
4798 free_printer_info_3(printer);
4803 /****************************************************************************
4804 ****************************************************************************/
4806 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4808 PRINTER_INFO_4 *printer=NULL;
4809 WERROR result = WERR_OK;
4811 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4814 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4819 /* check the required size. */
4820 *needed += spoolss_size_printer_info_4(printer);
4822 if (*needed > offered) {
4823 result = WERR_INSUFFICIENT_BUFFER;
4827 if (!rpcbuf_alloc_size(buffer, *needed)) {
4828 result = WERR_NOMEM;
4832 /* fill the buffer with the structures */
4833 smb_io_printer_info_4("", buffer, printer, 0);
4837 free_printer_info_4(printer);
4842 /****************************************************************************
4843 ****************************************************************************/
4845 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4847 PRINTER_INFO_5 *printer=NULL;
4848 WERROR result = WERR_OK;
4850 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4853 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4854 free_printer_info_5(printer);
4858 /* check the required size. */
4859 *needed += spoolss_size_printer_info_5(printer);
4861 if (*needed > offered) {
4862 result = WERR_INSUFFICIENT_BUFFER;
4866 if (!rpcbuf_alloc_size(buffer, *needed)) {
4867 result = WERR_NOMEM;
4871 /* fill the buffer with the structures */
4872 smb_io_printer_info_5("", buffer, printer, 0);
4876 free_printer_info_5(printer);
4881 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4883 PRINTER_INFO_7 *printer=NULL;
4884 WERROR result = WERR_OK;
4886 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4889 if (!construct_printer_info_7(print_hnd, printer, snum))
4892 /* check the required size. */
4893 *needed += spoolss_size_printer_info_7(printer);
4895 if (*needed > offered) {
4896 result = WERR_INSUFFICIENT_BUFFER;
4900 if (!rpcbuf_alloc_size(buffer, *needed)) {
4901 result = WERR_NOMEM;
4906 /* fill the buffer with the structures */
4907 smb_io_printer_info_7("", buffer, printer, 0);
4911 free_printer_info_7(printer);
4916 /****************************************************************************
4917 ****************************************************************************/
4919 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4921 POLICY_HND *handle = &q_u->handle;
4922 uint32 level = q_u->level;
4923 RPC_BUFFER *buffer = NULL;
4924 uint32 offered = q_u->offered;
4925 uint32 *needed = &r_u->needed;
4926 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4930 /* that's an [in out] buffer */
4932 if (!q_u->buffer && (offered!=0)) {
4933 return WERR_INVALID_PARAM;
4936 rpcbuf_move(q_u->buffer, &r_u->buffer);
4937 buffer = r_u->buffer;
4941 if (!get_printer_snum(p, handle, &snum))
4946 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4948 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4950 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4952 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4954 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4956 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4958 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4960 return WERR_UNKNOWN_LEVEL;
4963 /********************************************************************
4964 * fill a DRIVER_INFO_1 struct
4965 ********************************************************************/
4967 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4969 init_unistr( &info->name, driver.info_3->name);
4972 /********************************************************************
4973 * construct_printer_driver_info_1
4974 ********************************************************************/
4976 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4978 NT_PRINTER_INFO_LEVEL *printer = NULL;
4979 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4981 ZERO_STRUCT(driver);
4983 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4984 return WERR_INVALID_PRINTER_NAME;
4986 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4987 return WERR_UNKNOWN_PRINTER_DRIVER;
4989 fill_printer_driver_info_1(info, driver, servername, architecture);
4991 free_a_printer(&printer,2);
4996 /********************************************************************
4997 * construct_printer_driver_info_2
4998 * fill a printer_info_2 struct
4999 ********************************************************************/
5001 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5005 info->version=driver.info_3->cversion;
5007 init_unistr( &info->name, driver.info_3->name );
5008 init_unistr( &info->architecture, driver.info_3->environment );
5011 if (strlen(driver.info_3->driverpath)) {
5012 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5013 init_unistr( &info->driverpath, temp );
5015 init_unistr( &info->driverpath, "" );
5017 if (strlen(driver.info_3->datafile)) {
5018 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5019 init_unistr( &info->datafile, temp );
5021 init_unistr( &info->datafile, "" );
5023 if (strlen(driver.info_3->configfile)) {
5024 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5025 init_unistr( &info->configfile, temp );
5027 init_unistr( &info->configfile, "" );
5030 /********************************************************************
5031 * construct_printer_driver_info_2
5032 * fill a printer_info_2 struct
5033 ********************************************************************/
5035 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5037 NT_PRINTER_INFO_LEVEL *printer = NULL;
5038 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5040 ZERO_STRUCT(printer);
5041 ZERO_STRUCT(driver);
5043 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5044 return WERR_INVALID_PRINTER_NAME;
5046 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5047 return WERR_UNKNOWN_PRINTER_DRIVER;
5049 fill_printer_driver_info_2(info, driver, servername);
5051 free_a_printer(&printer,2);
5056 /********************************************************************
5057 * copy a strings array and convert to UNICODE
5059 * convert an array of ascii string to a UNICODE string
5060 ********************************************************************/
5062 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5069 DEBUG(6,("init_unistr_array\n"));
5080 v = ""; /* hack to handle null lists */
5083 /* hack to allow this to be used in places other than when generating
5084 the list of dependent files */
5087 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5091 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5093 /* add one extra unit16 for the second terminating NULL */
5095 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5096 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5103 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5108 /* special case for ""; we need to add both NULL's here */
5110 (*uni_array)[j++]=0x0000;
5111 (*uni_array)[j]=0x0000;
5114 DEBUGADD(6,("last one:done\n"));
5116 /* return size of array in uint16's */
5121 /********************************************************************
5122 * construct_printer_info_3
5123 * fill a printer_info_3 struct
5124 ********************************************************************/
5126 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5132 info->version=driver.info_3->cversion;
5134 init_unistr( &info->name, driver.info_3->name );
5135 init_unistr( &info->architecture, driver.info_3->environment );
5137 if (strlen(driver.info_3->driverpath)) {
5138 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5139 init_unistr( &info->driverpath, temp );
5141 init_unistr( &info->driverpath, "" );
5143 if (strlen(driver.info_3->datafile)) {
5144 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5145 init_unistr( &info->datafile, temp );
5147 init_unistr( &info->datafile, "" );
5149 if (strlen(driver.info_3->configfile)) {
5150 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5151 init_unistr( &info->configfile, temp );
5153 init_unistr( &info->configfile, "" );
5155 if (strlen(driver.info_3->helpfile)) {
5156 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5157 init_unistr( &info->helpfile, temp );
5159 init_unistr( &info->helpfile, "" );
5161 init_unistr( &info->monitorname, driver.info_3->monitorname );
5162 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5164 info->dependentfiles=NULL;
5165 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5168 /********************************************************************
5169 * construct_printer_info_3
5170 * fill a printer_info_3 struct
5171 ********************************************************************/
5173 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5175 NT_PRINTER_INFO_LEVEL *printer = NULL;
5176 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5178 ZERO_STRUCT(driver);
5180 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5181 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5182 if (!W_ERROR_IS_OK(status))
5183 return WERR_INVALID_PRINTER_NAME;
5185 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5186 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5191 * I put this code in during testing. Helpful when commenting out the
5192 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5193 * as win2k always queries the driver using an infor level of 6.
5194 * I've left it in (but ifdef'd out) because I'll probably
5195 * use it in experimentation again in the future. --jerry 22/01/2002
5198 if (!W_ERROR_IS_OK(status)) {
5200 * Is this a W2k client ?
5203 /* Yes - try again with a WinNT driver. */
5205 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5206 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5210 if (!W_ERROR_IS_OK(status)) {
5211 free_a_printer(&printer,2);
5212 return WERR_UNKNOWN_PRINTER_DRIVER;
5220 fill_printer_driver_info_3(info, driver, servername);
5222 free_a_printer(&printer,2);
5227 /********************************************************************
5228 * construct_printer_info_6
5229 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5230 ********************************************************************/
5232 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5238 memset(&nullstr, '\0', sizeof(fstring));
5240 info->version=driver.info_3->cversion;
5242 init_unistr( &info->name, driver.info_3->name );
5243 init_unistr( &info->architecture, driver.info_3->environment );
5245 if (strlen(driver.info_3->driverpath)) {
5246 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5247 init_unistr( &info->driverpath, temp );
5249 init_unistr( &info->driverpath, "" );
5251 if (strlen(driver.info_3->datafile)) {
5252 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5253 init_unistr( &info->datafile, temp );
5255 init_unistr( &info->datafile, "" );
5257 if (strlen(driver.info_3->configfile)) {
5258 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5259 init_unistr( &info->configfile, temp );
5261 init_unistr( &info->configfile, "" );
5263 if (strlen(driver.info_3->helpfile)) {
5264 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5265 init_unistr( &info->helpfile, temp );
5267 init_unistr( &info->helpfile, "" );
5269 init_unistr( &info->monitorname, driver.info_3->monitorname );
5270 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5272 info->dependentfiles = NULL;
5273 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5275 info->previousdrivernames=NULL;
5276 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5278 info->driver_date.low=0;
5279 info->driver_date.high=0;
5282 info->driver_version_low=0;
5283 info->driver_version_high=0;
5285 init_unistr( &info->mfgname, "");
5286 init_unistr( &info->oem_url, "");
5287 init_unistr( &info->hardware_id, "");
5288 init_unistr( &info->provider, "");
5291 /********************************************************************
5292 * construct_printer_info_6
5293 * fill a printer_info_6 struct
5294 ********************************************************************/
5296 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5297 fstring servername, fstring architecture, uint32 version)
5299 NT_PRINTER_INFO_LEVEL *printer = NULL;
5300 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5303 ZERO_STRUCT(driver);
5305 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5307 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5309 if (!W_ERROR_IS_OK(status))
5310 return WERR_INVALID_PRINTER_NAME;
5312 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5314 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5316 if (!W_ERROR_IS_OK(status))
5319 * Is this a W2k client ?
5323 free_a_printer(&printer,2);
5324 return WERR_UNKNOWN_PRINTER_DRIVER;
5327 /* Yes - try again with a WinNT driver. */
5329 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5330 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5331 if (!W_ERROR_IS_OK(status)) {
5332 free_a_printer(&printer,2);
5333 return WERR_UNKNOWN_PRINTER_DRIVER;
5337 fill_printer_driver_info_6(info, driver, servername);
5339 free_a_printer(&printer,2);
5340 free_a_printer_driver(driver, 3);
5345 /****************************************************************************
5346 ****************************************************************************/
5348 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5350 SAFE_FREE(info->dependentfiles);
5353 /****************************************************************************
5354 ****************************************************************************/
5356 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5358 SAFE_FREE(info->dependentfiles);
5361 /****************************************************************************
5362 ****************************************************************************/
5364 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5366 DRIVER_INFO_1 *info=NULL;
5369 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5372 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5373 if (!W_ERROR_IS_OK(result))
5376 /* check the required size. */
5377 *needed += spoolss_size_printer_driver_info_1(info);
5379 if (*needed > offered) {
5380 result = WERR_INSUFFICIENT_BUFFER;
5384 if (!rpcbuf_alloc_size(buffer, *needed)) {
5385 result = WERR_NOMEM;
5389 /* fill the buffer with the structures */
5390 smb_io_printer_driver_info_1("", buffer, info, 0);
5399 /****************************************************************************
5400 ****************************************************************************/
5402 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5404 DRIVER_INFO_2 *info=NULL;
5407 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5410 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5411 if (!W_ERROR_IS_OK(result))
5414 /* check the required size. */
5415 *needed += spoolss_size_printer_driver_info_2(info);
5417 if (*needed > offered) {
5418 result = WERR_INSUFFICIENT_BUFFER;
5422 if (!rpcbuf_alloc_size(buffer, *needed)) {
5423 result = WERR_NOMEM;
5427 /* fill the buffer with the structures */
5428 smb_io_printer_driver_info_2("", buffer, info, 0);
5437 /****************************************************************************
5438 ****************************************************************************/
5440 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5447 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5448 if (!W_ERROR_IS_OK(result))
5451 /* check the required size. */
5452 *needed += spoolss_size_printer_driver_info_3(&info);
5454 if (*needed > offered) {
5455 result = WERR_INSUFFICIENT_BUFFER;
5459 if (!rpcbuf_alloc_size(buffer, *needed)) {
5460 result = WERR_NOMEM;
5464 /* fill the buffer with the structures */
5465 smb_io_printer_driver_info_3("", buffer, &info, 0);
5468 free_printer_driver_info_3(&info);
5473 /****************************************************************************
5474 ****************************************************************************/
5476 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5483 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5484 if (!W_ERROR_IS_OK(result))
5487 /* check the required size. */
5488 *needed += spoolss_size_printer_driver_info_6(&info);
5490 if (*needed > offered) {
5491 result = WERR_INSUFFICIENT_BUFFER;
5495 if (!rpcbuf_alloc_size(buffer, *needed)) {
5496 result = WERR_NOMEM;
5500 /* fill the buffer with the structures */
5501 smb_io_printer_driver_info_6("", buffer, &info, 0);
5504 free_printer_driver_info_6(&info);
5509 /****************************************************************************
5510 ****************************************************************************/
5512 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5514 POLICY_HND *handle = &q_u->handle;
5515 UNISTR2 *uni_arch = &q_u->architecture;
5516 uint32 level = q_u->level;
5517 uint32 clientmajorversion = q_u->clientmajorversion;
5518 RPC_BUFFER *buffer = NULL;
5519 uint32 offered = q_u->offered;
5520 uint32 *needed = &r_u->needed;
5521 uint32 *servermajorversion = &r_u->servermajorversion;
5522 uint32 *serverminorversion = &r_u->serverminorversion;
5523 Printer_entry *printer;
5526 fstring architecture;
5529 /* that's an [in out] buffer */
5531 if (!q_u->buffer && (offered!=0)) {
5532 return WERR_INVALID_PARAM;
5535 rpcbuf_move(q_u->buffer, &r_u->buffer);
5536 buffer = r_u->buffer;
5538 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5540 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5541 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5542 return WERR_INVALID_PRINTER_NAME;
5546 *servermajorversion = 0;
5547 *serverminorversion = 0;
5549 fstrcpy(servername, get_server_name( printer ));
5550 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5552 if (!get_printer_snum(p, handle, &snum))
5557 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5559 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5561 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5563 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5566 /* apparently this call is the equivalent of
5567 EnumPrinterDataEx() for the DsDriver key */
5572 return WERR_UNKNOWN_LEVEL;
5575 /****************************************************************************
5576 ****************************************************************************/
5578 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5580 POLICY_HND *handle = &q_u->handle;
5582 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5585 DEBUG(3,("Error in startpageprinter printer handle\n"));
5589 Printer->page_started=True;
5593 /****************************************************************************
5594 ****************************************************************************/
5596 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5598 POLICY_HND *handle = &q_u->handle;
5601 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5604 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5608 if (!get_printer_snum(p, handle, &snum))
5611 Printer->page_started=False;
5612 print_job_endpage(snum, Printer->jobid);
5617 /********************************************************************
5618 * api_spoolss_getprinter
5619 * called from the spoolss dispatcher
5621 ********************************************************************/
5623 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5625 POLICY_HND *handle = &q_u->handle;
5626 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5627 uint32 *jobid = &r_u->jobid;
5629 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5633 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5636 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5641 * a nice thing with NT is it doesn't listen to what you tell it.
5642 * when asked to send _only_ RAW datas, it tries to send datas
5645 * So I add checks like in NT Server ...
5648 if (info_1->p_datatype != 0) {
5649 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5650 if (strcmp(datatype, "RAW") != 0) {
5652 return WERR_INVALID_DATATYPE;
5656 /* get the share number of the printer */
5657 if (!get_printer_snum(p, handle, &snum)) {
5661 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5663 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5665 /* An error occured in print_job_start() so return an appropriate
5668 if (Printer->jobid == -1) {
5669 return map_werror_from_unix(errno);
5672 Printer->document_started=True;
5673 (*jobid) = Printer->jobid;
5678 /********************************************************************
5679 * api_spoolss_getprinter
5680 * called from the spoolss dispatcher
5682 ********************************************************************/
5684 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5686 POLICY_HND *handle = &q_u->handle;
5688 return _spoolss_enddocprinter_internal(p, handle);
5691 /****************************************************************************
5692 ****************************************************************************/
5694 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5696 POLICY_HND *handle = &q_u->handle;
5697 uint32 buffer_size = q_u->buffer_size;
5698 uint8 *buffer = q_u->buffer;
5699 uint32 *buffer_written = &q_u->buffer_size2;
5701 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5704 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5705 r_u->buffer_written = q_u->buffer_size2;
5709 if (!get_printer_snum(p, handle, &snum))
5712 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5713 (SMB_OFF_T)-1, (size_t)buffer_size);
5714 if (*buffer_written == (uint32)-1) {
5715 r_u->buffer_written = 0;
5716 if (errno == ENOSPC)
5717 return WERR_NO_SPOOL_SPACE;
5719 return WERR_ACCESS_DENIED;
5722 r_u->buffer_written = q_u->buffer_size2;
5727 /********************************************************************
5728 * api_spoolss_getprinter
5729 * called from the spoolss dispatcher
5731 ********************************************************************/
5733 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5737 WERROR errcode = WERR_BADFUNC;
5738 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5741 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5745 if (!get_printer_snum(p, handle, &snum))
5749 case PRINTER_CONTROL_PAUSE:
5750 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5754 case PRINTER_CONTROL_RESUME:
5755 case PRINTER_CONTROL_UNPAUSE:
5756 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5760 case PRINTER_CONTROL_PURGE:
5761 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5766 return WERR_UNKNOWN_LEVEL;
5772 /********************************************************************
5773 * api_spoolss_abortprinter
5774 * From MSDN: "Deletes printer's spool file if printer is configured
5776 ********************************************************************/
5778 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5780 POLICY_HND *handle = &q_u->handle;
5781 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5783 WERROR errcode = WERR_OK;
5786 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5790 if (!get_printer_snum(p, handle, &snum))
5793 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5798 /********************************************************************
5799 * called by spoolss_api_setprinter
5800 * when updating a printer description
5801 ********************************************************************/
5803 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5804 const SPOOL_PRINTER_INFO_LEVEL *info,
5805 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5807 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5811 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5813 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5814 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5815 OUR_HANDLE(handle)));
5817 result = WERR_BADFID;
5821 /* Check the user has permissions to change the security
5822 descriptor. By experimentation with two NT machines, the user
5823 requires Full Access to the printer to change security
5826 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5827 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5828 result = WERR_ACCESS_DENIED;
5832 /* NT seems to like setting the security descriptor even though
5833 nothing may have actually changed. */
5835 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5837 if (DEBUGLEVEL >= 10) {
5841 the_acl = old_secdesc_ctr->sec->dacl;
5842 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5843 PRINTERNAME(snum), the_acl->num_aces));
5845 for (i = 0; i < the_acl->num_aces; i++) {
5848 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5850 DEBUG(10, ("%s 0x%08x\n", sid_str,
5851 the_acl->ace[i].info.mask));
5854 the_acl = secdesc_ctr->sec->dacl;
5857 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5858 PRINTERNAME(snum), the_acl->num_aces));
5860 for (i = 0; i < the_acl->num_aces; i++) {
5863 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5865 DEBUG(10, ("%s 0x%08x\n", sid_str,
5866 the_acl->ace[i].info.mask));
5869 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5873 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5874 if (!new_secdesc_ctr) {
5875 result = WERR_NOMEM;
5879 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5884 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5891 /********************************************************************
5892 Canonicalize printer info from a client
5894 ATTN: It does not matter what we set the servername to hear
5895 since we do the necessary work in get_a_printer() to set it to
5896 the correct value based on what the client sent in the
5897 _spoolss_open_printer_ex().
5898 ********************************************************************/
5900 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5902 fstring printername;
5905 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5906 "portname=%s drivername=%s comment=%s location=%s\n",
5907 info->servername, info->printername, info->sharename,
5908 info->portname, info->drivername, info->comment, info->location));
5910 /* we force some elements to "correct" values */
5911 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5912 fstrcpy(info->sharename, lp_servicename(snum));
5914 /* check to see if we allow printername != sharename */
5916 if ( lp_force_printername(snum) ) {
5917 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5918 global_myname(), info->sharename );
5921 /* make sure printername is in \\server\printername format */
5923 fstrcpy( printername, info->printername );
5925 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5926 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5930 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5931 global_myname(), p );
5934 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5935 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5942 /****************************************************************************
5943 ****************************************************************************/
5945 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
5947 char *cmd = lp_addport_cmd();
5951 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5952 BOOL is_print_op = False;
5955 return WERR_ACCESS_DENIED;
5958 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
5961 is_print_op = user_has_privileges( token, &se_printop );
5963 DEBUG(10,("Running [%s]\n", command));
5965 /********* BEGIN SePrintOperatorPrivilege **********/
5970 ret = smbrun(command, &fd);
5975 /********* END SePrintOperatorPrivilege **********/
5977 DEBUGADD(10,("returned [%d]\n", ret));
5982 return WERR_ACCESS_DENIED;
5988 /****************************************************************************
5989 ****************************************************************************/
5991 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5993 char *cmd = lp_addprinter_cmd();
5999 fstring remote_machine = "%m";
6000 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6001 BOOL is_print_op = False;
6003 standard_sub_basic(current_user_info.smb_name,
6004 current_user_info.domain,
6005 remote_machine,sizeof(remote_machine));
6007 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6008 cmd, printer->info_2->printername, printer->info_2->sharename,
6009 printer->info_2->portname, printer->info_2->drivername,
6010 printer->info_2->location, printer->info_2->comment, remote_machine);
6013 is_print_op = user_has_privileges( token, &se_printop );
6015 DEBUG(10,("Running [%s]\n", command));
6017 /********* BEGIN SePrintOperatorPrivilege **********/
6022 if ( (ret = smbrun(command, &fd)) == 0 ) {
6023 /* Tell everyone we updated smb.conf. */
6024 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6030 /********* END SePrintOperatorPrivilege **********/
6032 DEBUGADD(10,("returned [%d]\n", ret));
6040 /* reload our services immediately */
6041 reload_services( False );
6044 /* Get lines and convert them back to dos-codepage */
6045 qlines = fd_lines_load(fd, &numlines, 0);
6046 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6049 /* Set the portname to what the script says the portname should be. */
6050 /* but don't require anything to be return from the script exit a good error code */
6053 /* Set the portname to what the script says the portname should be. */
6054 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6055 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6058 file_lines_free(qlines);
6063 /********************************************************************
6064 * Called by spoolss_api_setprinter
6065 * when updating a printer description.
6066 ********************************************************************/
6068 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6069 const SPOOL_PRINTER_INFO_LEVEL *info,
6070 DEVICEMODE *devmode)
6073 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6074 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6079 DEBUG(8,("update_printer\n"));
6084 result = WERR_BADFID;
6088 if (!get_printer_snum(p, handle, &snum)) {
6089 result = WERR_BADFID;
6093 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6094 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6095 result = WERR_BADFID;
6099 DEBUGADD(8,("Converting info_2 struct\n"));
6102 * convert_printer_info converts the incoming
6103 * info from the client and overwrites the info
6104 * just read from the tdb in the pointer 'printer'.
6107 if (!convert_printer_info(info, printer, level)) {
6108 result = WERR_NOMEM;
6113 /* we have a valid devmode
6114 convert it and link it*/
6116 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6117 if (!convert_devicemode(printer->info_2->printername, devmode,
6118 &printer->info_2->devmode)) {
6119 result = WERR_NOMEM;
6124 /* Do sanity check on the requested changes for Samba */
6126 if (!check_printer_ok(printer->info_2, snum)) {
6127 result = WERR_INVALID_PARAM;
6131 /* FIXME!!! If the driver has changed we really should verify that
6132 it is installed before doing much else --jerry */
6134 /* Check calling user has permission to update printer description */
6136 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6137 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6138 result = WERR_ACCESS_DENIED;
6142 /* Call addprinter hook */
6143 /* Check changes to see if this is really needed */
6145 if ( *lp_addprinter_cmd()
6146 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6147 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6148 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6149 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6151 /* add_printer_hook() will call reload_services() */
6153 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6154 result = WERR_ACCESS_DENIED;
6160 * When a *new* driver is bound to a printer, the drivername is used to
6161 * lookup previously saved driver initialization info, which is then
6162 * bound to the printer, simulating what happens in the Windows arch.
6164 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6166 if (!set_driver_init(printer, 2))
6168 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6169 printer->info_2->drivername));
6172 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6173 printer->info_2->drivername));
6175 notify_printer_driver(snum, printer->info_2->drivername);
6179 * flag which changes actually occured. This is a small subset of
6180 * all the possible changes. We also have to update things in the
6184 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6185 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6186 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6187 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6189 notify_printer_comment(snum, printer->info_2->comment);
6192 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6193 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6194 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6195 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6197 notify_printer_sharename(snum, printer->info_2->sharename);
6200 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6203 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6206 pname = printer->info_2->printername;
6209 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6210 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6211 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6213 notify_printer_printername( snum, pname );
6216 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6217 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6218 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6219 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6221 notify_printer_port(snum, printer->info_2->portname);
6224 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6225 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6226 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6227 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6229 notify_printer_location(snum, printer->info_2->location);
6232 /* here we need to update some more DsSpooler keys */
6233 /* uNCName, serverName, shortServerName */
6235 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6236 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6237 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6238 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6239 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6241 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6242 global_myname(), printer->info_2->sharename );
6243 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6244 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6245 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6247 /* Update printer info */
6248 result = mod_a_printer(printer, 2);
6251 free_a_printer(&printer, 2);
6252 free_a_printer(&old_printer, 2);
6258 /****************************************************************************
6259 ****************************************************************************/
6260 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6261 const SPOOL_PRINTER_INFO_LEVEL *info)
6264 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6266 Printer_entry *Printer;
6268 if ( lp_security() != SEC_ADS ) {
6269 return WERR_UNKNOWN_LEVEL;
6272 Printer = find_printer_index_by_hnd(p, handle);
6274 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6279 if (!get_printer_snum(p, handle, &snum))
6282 nt_printer_publish(Printer, snum, info7->action);
6286 return WERR_UNKNOWN_LEVEL;
6289 /****************************************************************************
6290 ****************************************************************************/
6292 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6294 POLICY_HND *handle = &q_u->handle;
6295 uint32 level = q_u->level;
6296 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6297 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6298 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6299 uint32 command = q_u->command;
6302 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6305 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6309 /* check the level */
6312 return control_printer(handle, command, p);
6314 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6315 if (!W_ERROR_IS_OK(result))
6318 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6321 return update_printer_sec(handle, level, info, p,
6324 return publish_or_unpublish_printer(p, handle, info);
6326 return WERR_UNKNOWN_LEVEL;
6330 /****************************************************************************
6331 ****************************************************************************/
6333 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6335 POLICY_HND *handle = &q_u->handle;
6336 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6339 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6343 if (Printer->notify.client_connected==True) {
6346 if ( Printer->printer_type == SPLHND_SERVER)
6348 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6349 !get_printer_snum(p, handle, &snum) )
6352 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6355 Printer->notify.flags=0;
6356 Printer->notify.options=0;
6357 Printer->notify.localmachine[0]='\0';
6358 Printer->notify.printerlocal=0;
6359 if (Printer->notify.option)
6360 free_spool_notify_option(&Printer->notify.option);
6361 Printer->notify.client_connected=False;
6366 /****************************************************************************
6367 ****************************************************************************/
6369 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6371 /* that's an [in out] buffer */
6373 if (!q_u->buffer && (q_u->offered!=0)) {
6374 return WERR_INVALID_PARAM;
6377 rpcbuf_move(q_u->buffer, &r_u->buffer);
6380 return WERR_INVALID_PARAM; /* this is what a NT server
6381 returns for AddJob. AddJob
6382 must fail on non-local
6386 /****************************************************************************
6387 ****************************************************************************/
6389 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6390 int position, int snum,
6391 NT_PRINTER_INFO_LEVEL *ntprinter)
6395 t=gmtime(&queue->time);
6397 job_info->jobid=queue->job;
6398 init_unistr(&job_info->printername, lp_servicename(snum));
6399 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6400 init_unistr(&job_info->username, queue->fs_user);
6401 init_unistr(&job_info->document, queue->fs_file);
6402 init_unistr(&job_info->datatype, "RAW");
6403 init_unistr(&job_info->text_status, "");
6404 job_info->status=nt_printj_status(queue->status);
6405 job_info->priority=queue->priority;
6406 job_info->position=position;
6407 job_info->totalpages=queue->page_count;
6408 job_info->pagesprinted=0;
6410 make_systemtime(&job_info->submitted, t);
6413 /****************************************************************************
6414 ****************************************************************************/
6416 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6417 int position, int snum,
6418 NT_PRINTER_INFO_LEVEL *ntprinter,
6419 DEVICEMODE *devmode)
6423 t=gmtime(&queue->time);
6425 job_info->jobid=queue->job;
6427 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6429 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6430 init_unistr(&job_info->username, queue->fs_user);
6431 init_unistr(&job_info->document, queue->fs_file);
6432 init_unistr(&job_info->notifyname, queue->fs_user);
6433 init_unistr(&job_info->datatype, "RAW");
6434 init_unistr(&job_info->printprocessor, "winprint");
6435 init_unistr(&job_info->parameters, "");
6436 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6437 init_unistr(&job_info->text_status, "");
6439 /* and here the security descriptor */
6441 job_info->status=nt_printj_status(queue->status);
6442 job_info->priority=queue->priority;
6443 job_info->position=position;
6444 job_info->starttime=0;
6445 job_info->untiltime=0;
6446 job_info->totalpages=queue->page_count;
6447 job_info->size=queue->size;
6448 make_systemtime(&(job_info->submitted), t);
6449 job_info->timeelapsed=0;
6450 job_info->pagesprinted=0;
6452 job_info->devmode = devmode;
6457 /****************************************************************************
6458 Enumjobs at level 1.
6459 ****************************************************************************/
6461 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6462 NT_PRINTER_INFO_LEVEL *ntprinter,
6463 RPC_BUFFER *buffer, uint32 offered,
6464 uint32 *needed, uint32 *returned)
6468 WERROR result = WERR_OK;
6470 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6477 for (i=0; i<*returned; i++)
6478 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6482 /* check the required size. */
6483 for (i=0; i<*returned; i++)
6484 (*needed) += spoolss_size_job_info_1(&info[i]);
6486 if (*needed > offered) {
6487 result = WERR_INSUFFICIENT_BUFFER;
6491 if (!rpcbuf_alloc_size(buffer, *needed)) {
6492 result = WERR_NOMEM;
6496 /* fill the buffer with the structures */
6497 for (i=0; i<*returned; i++)
6498 smb_io_job_info_1("", buffer, &info[i], 0);
6504 if ( !W_ERROR_IS_OK(result) )
6510 /****************************************************************************
6511 Enumjobs at level 2.
6512 ****************************************************************************/
6514 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6515 NT_PRINTER_INFO_LEVEL *ntprinter,
6516 RPC_BUFFER *buffer, uint32 offered,
6517 uint32 *needed, uint32 *returned)
6519 JOB_INFO_2 *info = NULL;
6521 WERROR result = WERR_OK;
6522 DEVICEMODE *devmode = NULL;
6524 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6529 /* this should not be a failure condition if the devmode is NULL */
6531 devmode = construct_dev_mode(lp_const_servicename(snum));
6533 for (i=0; i<*returned; i++)
6534 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6536 free_a_printer(&ntprinter, 2);
6539 /* check the required size. */
6540 for (i=0; i<*returned; i++)
6541 (*needed) += spoolss_size_job_info_2(&info[i]);
6543 if (*needed > offered) {
6544 result = WERR_INSUFFICIENT_BUFFER;
6548 if (!rpcbuf_alloc_size(buffer, *needed)) {
6549 result = WERR_NOMEM;
6553 /* fill the buffer with the structures */
6554 for (i=0; i<*returned; i++)
6555 smb_io_job_info_2("", buffer, &info[i], 0);
6558 free_devmode(devmode);
6561 if ( !W_ERROR_IS_OK(result) )
6568 /****************************************************************************
6570 ****************************************************************************/
6572 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6574 POLICY_HND *handle = &q_u->handle;
6575 uint32 level = q_u->level;
6576 RPC_BUFFER *buffer = NULL;
6577 uint32 offered = q_u->offered;
6578 uint32 *needed = &r_u->needed;
6579 uint32 *returned = &r_u->returned;
6581 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6583 print_status_struct prt_status;
6584 print_queue_struct *queue=NULL;
6586 /* that's an [in out] buffer */
6588 if (!q_u->buffer && (offered!=0)) {
6589 return WERR_INVALID_PARAM;
6592 rpcbuf_move(q_u->buffer, &r_u->buffer);
6593 buffer = r_u->buffer;
6595 DEBUG(4,("_spoolss_enumjobs\n"));
6600 /* lookup the printer snum and tdb entry */
6602 if (!get_printer_snum(p, handle, &snum))
6605 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6606 if ( !W_ERROR_IS_OK(wret) )
6609 *returned = print_queue_status(snum, &queue, &prt_status);
6610 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6612 if (*returned == 0) {
6619 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6622 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6627 wret = WERR_UNKNOWN_LEVEL;
6630 free_a_printer( &ntprinter, 2 );
6634 /****************************************************************************
6635 ****************************************************************************/
6637 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6642 /****************************************************************************
6643 ****************************************************************************/
6645 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6647 POLICY_HND *handle = &q_u->handle;
6648 uint32 jobid = q_u->jobid;
6649 uint32 command = q_u->command;
6652 WERROR errcode = WERR_BADFUNC;
6654 if (!get_printer_snum(p, handle, &snum)) {
6658 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6659 return WERR_INVALID_PRINTER_NAME;
6663 case JOB_CONTROL_CANCEL:
6664 case JOB_CONTROL_DELETE:
6665 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6669 case JOB_CONTROL_PAUSE:
6670 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6674 case JOB_CONTROL_RESTART:
6675 case JOB_CONTROL_RESUME:
6676 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6681 return WERR_UNKNOWN_LEVEL;
6687 /****************************************************************************
6688 Enumerates all printer drivers at level 1.
6689 ****************************************************************************/
6691 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6696 fstring *list = NULL;
6697 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6698 DRIVER_INFO_1 *driver_info_1=NULL;
6699 WERROR result = WERR_OK;
6703 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6705 ndrivers=get_ntdrivers(&list, architecture, version);
6706 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6708 if(ndrivers == -1) {
6709 SAFE_FREE(driver_info_1);
6714 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6715 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6721 for (i=0; i<ndrivers; i++) {
6723 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6724 ZERO_STRUCT(driver);
6725 status = get_a_printer_driver(&driver, 3, list[i],
6726 architecture, version);
6727 if (!W_ERROR_IS_OK(status)) {
6729 SAFE_FREE(driver_info_1);
6732 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6733 free_a_printer_driver(driver, 3);
6736 *returned+=ndrivers;
6740 /* check the required size. */
6741 for (i=0; i<*returned; i++) {
6742 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6743 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6746 if (*needed > offered) {
6747 result = WERR_INSUFFICIENT_BUFFER;
6751 if (!rpcbuf_alloc_size(buffer, *needed)) {
6752 result = WERR_NOMEM;
6756 /* fill the buffer with the driver structures */
6757 for (i=0; i<*returned; i++) {
6758 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6759 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6763 SAFE_FREE(driver_info_1);
6765 if ( !W_ERROR_IS_OK(result) )
6771 /****************************************************************************
6772 Enumerates all printer drivers at level 2.
6773 ****************************************************************************/
6775 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6780 fstring *list = NULL;
6781 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6782 DRIVER_INFO_2 *driver_info_2=NULL;
6783 WERROR result = WERR_OK;
6787 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6789 ndrivers=get_ntdrivers(&list, architecture, version);
6790 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6792 if(ndrivers == -1) {
6793 SAFE_FREE(driver_info_2);
6798 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6799 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6805 for (i=0; i<ndrivers; i++) {
6808 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6809 ZERO_STRUCT(driver);
6810 status = get_a_printer_driver(&driver, 3, list[i],
6811 architecture, version);
6812 if (!W_ERROR_IS_OK(status)) {
6814 SAFE_FREE(driver_info_2);
6817 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6818 free_a_printer_driver(driver, 3);
6821 *returned+=ndrivers;
6825 /* check the required size. */
6826 for (i=0; i<*returned; i++) {
6827 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6828 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6831 if (*needed > offered) {
6832 result = WERR_INSUFFICIENT_BUFFER;
6836 if (!rpcbuf_alloc_size(buffer, *needed)) {
6837 result = WERR_NOMEM;
6841 /* fill the buffer with the form structures */
6842 for (i=0; i<*returned; i++) {
6843 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6844 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6848 SAFE_FREE(driver_info_2);
6850 if ( !W_ERROR_IS_OK(result) )
6856 /****************************************************************************
6857 Enumerates all printer drivers at level 3.
6858 ****************************************************************************/
6860 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6865 fstring *list = NULL;
6866 DRIVER_INFO_3 *driver_info_3=NULL;
6867 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6868 WERROR result = WERR_OK;
6872 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6874 ndrivers=get_ntdrivers(&list, architecture, version);
6875 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6877 if(ndrivers == -1) {
6878 SAFE_FREE(driver_info_3);
6883 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6884 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6890 for (i=0; i<ndrivers; i++) {
6893 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6894 ZERO_STRUCT(driver);
6895 status = get_a_printer_driver(&driver, 3, list[i],
6896 architecture, version);
6897 if (!W_ERROR_IS_OK(status)) {
6899 SAFE_FREE(driver_info_3);
6902 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6903 free_a_printer_driver(driver, 3);
6906 *returned+=ndrivers;
6910 /* check the required size. */
6911 for (i=0; i<*returned; i++) {
6912 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6913 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6916 if (*needed > offered) {
6917 result = WERR_INSUFFICIENT_BUFFER;
6921 if (!rpcbuf_alloc_size(buffer, *needed)) {
6922 result = WERR_NOMEM;
6926 /* fill the buffer with the driver structures */
6927 for (i=0; i<*returned; i++) {
6928 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6929 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6933 for (i=0; i<*returned; i++) {
6934 SAFE_FREE(driver_info_3[i].dependentfiles);
6937 SAFE_FREE(driver_info_3);
6939 if ( !W_ERROR_IS_OK(result) )
6945 /****************************************************************************
6946 Enumerates all printer drivers.
6947 ****************************************************************************/
6949 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6951 uint32 level = q_u->level;
6952 RPC_BUFFER *buffer = NULL;
6953 uint32 offered = q_u->offered;
6954 uint32 *needed = &r_u->needed;
6955 uint32 *returned = &r_u->returned;
6958 fstring architecture;
6960 /* that's an [in out] buffer */
6962 if (!q_u->buffer && (offered!=0)) {
6963 return WERR_INVALID_PARAM;
6966 rpcbuf_move(q_u->buffer, &r_u->buffer);
6967 buffer = r_u->buffer;
6969 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6974 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6975 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6977 if ( !is_myname_or_ipaddr( servername ) )
6978 return WERR_UNKNOWN_PRINTER_DRIVER;
6982 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6984 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6986 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6988 return WERR_UNKNOWN_LEVEL;
6992 /****************************************************************************
6993 ****************************************************************************/
6995 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6997 form->flag=list->flag;
6998 init_unistr(&form->name, list->name);
6999 form->width=list->width;
7000 form->length=list->length;
7001 form->left=list->left;
7002 form->top=list->top;
7003 form->right=list->right;
7004 form->bottom=list->bottom;
7007 /****************************************************************************
7008 ****************************************************************************/
7010 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7012 uint32 level = q_u->level;
7013 RPC_BUFFER *buffer = NULL;
7014 uint32 offered = q_u->offered;
7015 uint32 *needed = &r_u->needed;
7016 uint32 *numofforms = &r_u->numofforms;
7017 uint32 numbuiltinforms;
7019 nt_forms_struct *list=NULL;
7020 nt_forms_struct *builtinlist=NULL;
7025 /* that's an [in out] buffer */
7027 if (!q_u->buffer && (offered!=0) ) {
7028 return WERR_INVALID_PARAM;
7031 rpcbuf_move(q_u->buffer, &r_u->buffer);
7032 buffer = r_u->buffer;
7034 DEBUG(4,("_spoolss_enumforms\n"));
7035 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7036 DEBUGADD(5,("Info level [%d]\n", level));
7038 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7039 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7040 *numofforms = get_ntforms(&list);
7041 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7042 *numofforms += numbuiltinforms;
7044 if (*numofforms == 0) {
7045 SAFE_FREE(builtinlist);
7047 return WERR_NO_MORE_ITEMS;
7052 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7053 SAFE_FREE(builtinlist);
7059 /* construct the list of form structures */
7060 for (i=0; i<numbuiltinforms; i++) {
7061 DEBUGADD(6,("Filling form number [%d]\n",i));
7062 fill_form_1(&forms_1[i], &builtinlist[i]);
7065 SAFE_FREE(builtinlist);
7067 for (; i<*numofforms; i++) {
7068 DEBUGADD(6,("Filling form number [%d]\n",i));
7069 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7074 /* check the required size. */
7075 for (i=0; i<numbuiltinforms; i++) {
7076 DEBUGADD(6,("adding form [%d]'s size\n",i));
7077 buffer_size += spoolss_size_form_1(&forms_1[i]);
7079 for (; i<*numofforms; i++) {
7080 DEBUGADD(6,("adding form [%d]'s size\n",i));
7081 buffer_size += spoolss_size_form_1(&forms_1[i]);
7084 *needed=buffer_size;
7086 if (*needed > offered) {
7089 return WERR_INSUFFICIENT_BUFFER;
7092 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7098 /* fill the buffer with the form structures */
7099 for (i=0; i<numbuiltinforms; i++) {
7100 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7101 smb_io_form_1("", buffer, &forms_1[i], 0);
7103 for (; i<*numofforms; i++) {
7104 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7105 smb_io_form_1("", buffer, &forms_1[i], 0);
7114 SAFE_FREE(builtinlist);
7115 return WERR_UNKNOWN_LEVEL;
7119 /****************************************************************************
7120 ****************************************************************************/
7122 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7124 uint32 level = q_u->level;
7125 UNISTR2 *uni_formname = &q_u->formname;
7126 RPC_BUFFER *buffer = NULL;
7127 uint32 offered = q_u->offered;
7128 uint32 *needed = &r_u->needed;
7130 nt_forms_struct *list=NULL;
7131 nt_forms_struct builtin_form;
7136 int numofforms=0, i=0;
7138 /* that's an [in out] buffer */
7140 if (!q_u->buffer && (offered!=0)) {
7141 return WERR_INVALID_PARAM;
7144 rpcbuf_move(q_u->buffer, &r_u->buffer);
7145 buffer = r_u->buffer;
7147 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7149 DEBUG(4,("_spoolss_getform\n"));
7150 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7151 DEBUGADD(5,("Info level [%d]\n", level));
7153 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7154 if (!foundBuiltin) {
7155 numofforms = get_ntforms(&list);
7156 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7158 if (numofforms == 0)
7165 fill_form_1(&form_1, &builtin_form);
7168 /* Check if the requested name is in the list of form structures */
7169 for (i=0; i<numofforms; i++) {
7171 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7173 if (strequal(form_name, list[i].name)) {
7174 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7175 fill_form_1(&form_1, &list[i]);
7181 if (i == numofforms) {
7185 /* check the required size. */
7187 *needed=spoolss_size_form_1(&form_1);
7189 if (*needed > offered)
7190 return WERR_INSUFFICIENT_BUFFER;
7192 if (!rpcbuf_alloc_size(buffer, buffer_size))
7195 /* fill the buffer with the form structures */
7196 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7197 smb_io_form_1("", buffer, &form_1, 0);
7203 return WERR_UNKNOWN_LEVEL;
7207 /****************************************************************************
7208 ****************************************************************************/
7210 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7212 init_unistr(&port->port_name, name);
7215 /****************************************************************************
7216 TODO: This probably needs distinguish between TCP/IP and Local ports
7218 ****************************************************************************/
7220 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7222 init_unistr(&port->port_name, name);
7223 init_unistr(&port->monitor_name, "Local Monitor");
7224 init_unistr(&port->description, SPL_LOCAL_PORT );
7225 port->port_type=PORT_TYPE_WRITE;
7230 /****************************************************************************
7231 wrapper around the enumer ports command
7232 ****************************************************************************/
7234 WERROR enumports_hook( int *count, char ***lines )
7236 char *cmd = lp_enumports_cmd();
7246 /* if no hook then just fill in the default port */
7249 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7250 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7255 /* we have a valid enumport command */
7257 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7259 DEBUG(10,("Running [%s]\n", command));
7260 ret = smbrun(command, &fd);
7261 DEBUG(10,("Returned [%d]\n", ret));
7266 return WERR_ACCESS_DENIED;
7270 qlines = fd_lines_load(fd, &numlines, 0);
7271 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7281 /****************************************************************************
7283 ****************************************************************************/
7285 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7287 PORT_INFO_1 *ports=NULL;
7289 WERROR result = WERR_OK;
7290 char **qlines = NULL;
7293 result = enumports_hook( &numlines, &qlines );
7294 if (!W_ERROR_IS_OK(result)) {
7295 file_lines_free(qlines);
7300 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7301 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7302 dos_errstr(WERR_NOMEM)));
7303 file_lines_free(qlines);
7307 for (i=0; i<numlines; i++) {
7308 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7309 fill_port_1(&ports[i], qlines[i]);
7312 file_lines_free(qlines);
7314 *returned = numlines;
7316 /* check the required size. */
7317 for (i=0; i<*returned; i++) {
7318 DEBUGADD(6,("adding port [%d]'s size\n", i));
7319 *needed += spoolss_size_port_info_1(&ports[i]);
7322 if (*needed > offered) {
7323 result = WERR_INSUFFICIENT_BUFFER;
7327 if (!rpcbuf_alloc_size(buffer, *needed)) {
7328 result = WERR_NOMEM;
7332 /* fill the buffer with the ports structures */
7333 for (i=0; i<*returned; i++) {
7334 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7335 smb_io_port_1("", buffer, &ports[i], 0);
7341 if ( !W_ERROR_IS_OK(result) )
7347 /****************************************************************************
7349 ****************************************************************************/
7351 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7353 PORT_INFO_2 *ports=NULL;
7355 WERROR result = WERR_OK;
7356 char **qlines = NULL;
7359 result = enumports_hook( &numlines, &qlines );
7360 if ( !W_ERROR_IS_OK(result)) {
7361 file_lines_free(qlines);
7366 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7367 file_lines_free(qlines);
7371 for (i=0; i<numlines; i++) {
7372 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7373 fill_port_2(&(ports[i]), qlines[i]);
7377 file_lines_free(qlines);
7379 *returned = numlines;
7381 /* check the required size. */
7382 for (i=0; i<*returned; i++) {
7383 DEBUGADD(6,("adding port [%d]'s size\n", i));
7384 *needed += spoolss_size_port_info_2(&ports[i]);
7387 if (*needed > offered) {
7388 result = WERR_INSUFFICIENT_BUFFER;
7392 if (!rpcbuf_alloc_size(buffer, *needed)) {
7393 result = WERR_NOMEM;
7397 /* fill the buffer with the ports structures */
7398 for (i=0; i<*returned; i++) {
7399 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7400 smb_io_port_2("", buffer, &ports[i], 0);
7406 if ( !W_ERROR_IS_OK(result) )
7412 /****************************************************************************
7414 ****************************************************************************/
7416 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7418 uint32 level = q_u->level;
7419 RPC_BUFFER *buffer = NULL;
7420 uint32 offered = q_u->offered;
7421 uint32 *needed = &r_u->needed;
7422 uint32 *returned = &r_u->returned;
7424 /* that's an [in out] buffer */
7426 if (!q_u->buffer && (offered!=0)) {
7427 return WERR_INVALID_PARAM;
7430 rpcbuf_move(q_u->buffer, &r_u->buffer);
7431 buffer = r_u->buffer;
7433 DEBUG(4,("_spoolss_enumports\n"));
7440 return enumports_level_1(buffer, offered, needed, returned);
7442 return enumports_level_2(buffer, offered, needed, returned);
7444 return WERR_UNKNOWN_LEVEL;
7448 /****************************************************************************
7449 ****************************************************************************/
7451 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7452 const SPOOL_PRINTER_INFO_LEVEL *info,
7453 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7454 uint32 user_switch, const SPOOL_USER_CTR *user,
7457 NT_PRINTER_INFO_LEVEL *printer = NULL;
7460 WERROR err = WERR_OK;
7462 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7463 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7467 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7468 if (!convert_printer_info(info, printer, 2)) {
7469 free_a_printer(&printer, 2);
7473 /* check to see if the printer already exists */
7475 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7476 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7477 printer->info_2->sharename));
7478 free_a_printer(&printer, 2);
7479 return WERR_PRINTER_ALREADY_EXISTS;
7482 /* FIXME!!! smbd should check to see if the driver is installed before
7483 trying to add a printer like this --jerry */
7485 if (*lp_addprinter_cmd() ) {
7486 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7487 free_a_printer(&printer,2);
7488 return WERR_ACCESS_DENIED;
7491 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7492 "smb.conf parameter \"addprinter command\" is defined. This"
7493 "parameter must exist for this call to succeed\n",
7494 printer->info_2->sharename ));
7497 /* use our primary netbios name since get_a_printer() will convert
7498 it to what the client expects on a case by case basis */
7500 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7501 printer->info_2->sharename);
7504 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7505 free_a_printer(&printer,2);
7506 return WERR_ACCESS_DENIED;
7509 /* you must be a printer admin to add a new printer */
7510 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7511 free_a_printer(&printer,2);
7512 return WERR_ACCESS_DENIED;
7516 * Do sanity check on the requested changes for Samba.
7519 if (!check_printer_ok(printer->info_2, snum)) {
7520 free_a_printer(&printer,2);
7521 return WERR_INVALID_PARAM;
7525 * When a printer is created, the drivername bound to the printer is used
7526 * to lookup previously saved driver initialization info, which is then
7527 * bound to the new printer, simulating what happens in the Windows arch.
7532 set_driver_init(printer, 2);
7536 /* A valid devmode was included, convert and link it
7538 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7540 if (!convert_devicemode(printer->info_2->printername, devmode,
7541 &printer->info_2->devmode))
7545 /* write the ASCII on disk */
7546 err = mod_a_printer(printer, 2);
7547 if (!W_ERROR_IS_OK(err)) {
7548 free_a_printer(&printer,2);
7552 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7553 /* Handle open failed - remove addition. */
7554 del_a_printer(printer->info_2->sharename);
7555 free_a_printer(&printer,2);
7556 return WERR_ACCESS_DENIED;
7559 update_c_setprinter(False);
7560 free_a_printer(&printer,2);
7565 /****************************************************************************
7566 ****************************************************************************/
7568 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7570 UNISTR2 *uni_srv_name = q_u->server_name;
7571 uint32 level = q_u->level;
7572 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7573 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7574 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7575 uint32 user_switch = q_u->user_switch;
7576 SPOOL_USER_CTR *user = &q_u->user_ctr;
7577 POLICY_HND *handle = &r_u->handle;
7581 /* we don't handle yet */
7582 /* but I know what to do ... */
7583 return WERR_UNKNOWN_LEVEL;
7585 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7587 user_switch, user, handle);
7589 return WERR_UNKNOWN_LEVEL;
7593 /****************************************************************************
7594 ****************************************************************************/
7596 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7598 uint32 level = q_u->level;
7599 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7600 WERROR err = WERR_OK;
7601 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7602 fstring driver_name;
7605 ZERO_STRUCT(driver);
7607 if (!convert_printer_driver_info(info, &driver, level)) {
7612 DEBUG(5,("Cleaning driver's information\n"));
7613 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7614 if (!W_ERROR_IS_OK(err))
7617 DEBUG(5,("Moving driver to final destination\n"));
7618 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7622 if (add_a_printer_driver(driver, level)!=0) {
7623 err = WERR_ACCESS_DENIED;
7628 * I think this is where he DrvUpgradePrinter() hook would be
7629 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7630 * server. Right now, we just need to send ourselves a message
7631 * to update each printer bound to this driver. --jerry
7634 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7635 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7640 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7641 * decide if the driver init data should be deleted. The rules are:
7642 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7643 * 2) delete init data only if there is no 2k/Xp driver
7644 * 3) always delete init data
7645 * The generalized rule is always use init data from the highest order driver.
7646 * It is necessary to follow the driver install by an initialization step to
7647 * finish off this process.
7650 version = driver.info_3->cversion;
7651 else if (level == 6)
7652 version = driver.info_6->version;
7657 * 9x printer driver - never delete init data
7660 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7665 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7666 * there is no 2k/Xp driver init data for this driver name.
7670 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7672 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7674 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7676 if (!del_driver_init(driver_name))
7677 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7680 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7682 free_a_printer_driver(driver1,3);
7683 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7690 * 2k or Xp printer driver - always delete init data
7693 if (!del_driver_init(driver_name))
7694 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7698 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7704 free_a_printer_driver(driver, level);
7708 /********************************************************************
7709 * spoolss_addprinterdriverex
7710 ********************************************************************/
7712 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7714 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7715 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7718 * we only support the semantics of AddPrinterDriver()
7719 * i.e. only copy files that are newer than existing ones
7722 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7723 return WERR_ACCESS_DENIED;
7725 ZERO_STRUCT(q_u_local);
7726 ZERO_STRUCT(r_u_local);
7728 /* just pass the information off to _spoolss_addprinterdriver() */
7729 q_u_local.server_name_ptr = q_u->server_name_ptr;
7730 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7731 q_u_local.level = q_u->level;
7732 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7734 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7737 /****************************************************************************
7738 ****************************************************************************/
7740 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7742 init_unistr(&info->name, name);
7745 /****************************************************************************
7746 ****************************************************************************/
7748 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7754 const char *short_archi;
7755 DRIVER_DIRECTORY_1 *info=NULL;
7756 WERROR result = WERR_OK;
7758 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7759 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7761 /* check for beginning double '\'s and that the server
7764 pservername = servername;
7765 if ( *pservername == '\\' && strlen(servername)>2 ) {
7769 if ( !is_myname_or_ipaddr( pservername ) )
7770 return WERR_INVALID_PARAM;
7772 if (!(short_archi = get_short_archi(long_archi)))
7773 return WERR_INVALID_ENVIRONMENT;
7775 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7778 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7780 DEBUG(4,("printer driver directory: [%s]\n", path));
7782 fill_driverdir_1(info, path);
7784 *needed += spoolss_size_driverdir_info_1(info);
7786 if (*needed > offered) {
7787 result = WERR_INSUFFICIENT_BUFFER;
7791 if (!rpcbuf_alloc_size(buffer, *needed)) {
7792 result = WERR_NOMEM;
7796 smb_io_driverdir_1("", buffer, info, 0);
7804 /****************************************************************************
7805 ****************************************************************************/
7807 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7809 UNISTR2 *name = &q_u->name;
7810 UNISTR2 *uni_environment = &q_u->environment;
7811 uint32 level = q_u->level;
7812 RPC_BUFFER *buffer = NULL;
7813 uint32 offered = q_u->offered;
7814 uint32 *needed = &r_u->needed;
7816 /* that's an [in out] buffer */
7818 if (!q_u->buffer && (offered!=0)) {
7819 return WERR_INVALID_PARAM;
7822 rpcbuf_move(q_u->buffer, &r_u->buffer);
7823 buffer = r_u->buffer;
7825 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7831 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7833 return WERR_UNKNOWN_LEVEL;
7837 /****************************************************************************
7838 ****************************************************************************/
7840 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7842 POLICY_HND *handle = &q_u->handle;
7843 uint32 idx = q_u->index;
7844 uint32 in_value_len = q_u->valuesize;
7845 uint32 in_data_len = q_u->datasize;
7846 uint32 *out_max_value_len = &r_u->valuesize;
7847 uint16 **out_value = &r_u->value;
7848 uint32 *out_value_len = &r_u->realvaluesize;
7849 uint32 *out_type = &r_u->type;
7850 uint32 *out_max_data_len = &r_u->datasize;
7851 uint8 **data_out = &r_u->data;
7852 uint32 *out_data_len = &r_u->realdatasize;
7854 NT_PRINTER_INFO_LEVEL *printer = NULL;
7856 uint32 biggest_valuesize;
7857 uint32 biggest_datasize;
7859 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7862 REGISTRY_VALUE *val = NULL;
7863 NT_PRINTER_DATA *p_data;
7864 int i, key_index, num_values;
7869 *out_max_data_len = 0;
7873 DEBUG(5,("spoolss_enumprinterdata\n"));
7876 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7880 if (!get_printer_snum(p,handle, &snum))
7883 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7884 if (!W_ERROR_IS_OK(result))
7887 p_data = printer->info_2->data;
7888 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7893 * The NT machine wants to know the biggest size of value and data
7895 * cf: MSDN EnumPrinterData remark section
7898 if ( !in_value_len && !in_data_len && (key_index != -1) )
7900 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7902 biggest_valuesize = 0;
7903 biggest_datasize = 0;
7905 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7907 for ( i=0; i<num_values; i++ )
7909 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7911 name_length = strlen(val->valuename);
7912 if ( strlen(val->valuename) > biggest_valuesize )
7913 biggest_valuesize = name_length;
7915 if ( val->size > biggest_datasize )
7916 biggest_datasize = val->size;
7918 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7922 /* the value is an UNICODE string but real_value_size is the length
7923 in bytes including the trailing 0 */
7925 *out_value_len = 2 * (1+biggest_valuesize);
7926 *out_data_len = biggest_datasize;
7928 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7934 * the value len is wrong in NT sp3
7935 * that's the number of bytes not the number of unicode chars
7938 if ( key_index != -1 )
7939 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7944 /* out_value should default to "" or else NT4 has
7945 problems unmarshalling the response */
7947 *out_max_value_len=(in_value_len/sizeof(uint16));
7949 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7951 result = WERR_NOMEM;
7955 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7957 /* the data is counted in bytes */
7959 *out_max_data_len = in_data_len;
7960 *out_data_len = in_data_len;
7962 /* only allocate when given a non-zero data_len */
7964 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7966 result = WERR_NOMEM;
7970 result = WERR_NO_MORE_ITEMS;
7976 * - counted in bytes in the request
7977 * - counted in UNICODE chars in the max reply
7978 * - counted in bytes in the real size
7980 * take a pause *before* coding not *during* coding
7984 *out_max_value_len=(in_value_len/sizeof(uint16));
7985 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7987 result = WERR_NOMEM;
7991 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
7995 *out_type = regval_type( val );
7997 /* data - counted in bytes */
7999 *out_max_data_len = in_data_len;
8000 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8002 result = WERR_NOMEM;
8005 data_len = regval_size(val);
8007 memcpy( *data_out, regval_data_p(val), data_len );
8008 *out_data_len = data_len;
8012 free_a_printer(&printer, 2);
8016 /****************************************************************************
8017 ****************************************************************************/
8019 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8021 POLICY_HND *handle = &q_u->handle;
8022 UNISTR2 *value = &q_u->value;
8023 uint32 type = q_u->type;
8024 uint8 *data = q_u->data;
8025 uint32 real_len = q_u->real_len;
8027 NT_PRINTER_INFO_LEVEL *printer = NULL;
8029 WERROR status = WERR_OK;
8030 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8033 DEBUG(5,("spoolss_setprinterdata\n"));
8036 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8040 if ( Printer->printer_type == SPLHND_SERVER ) {
8041 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8042 return WERR_INVALID_PARAM;
8045 if (!get_printer_snum(p,handle, &snum))
8049 * Access check : NT returns "access denied" if you make a
8050 * SetPrinterData call without the necessary privildge.
8051 * we were originally returning OK if nothing changed
8052 * which made Win2k issue **a lot** of SetPrinterData
8053 * when connecting to a printer --jerry
8056 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8058 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8059 status = WERR_ACCESS_DENIED;
8063 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8064 if (!W_ERROR_IS_OK(status))
8067 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8070 * When client side code sets a magic printer data key, detect it and save
8071 * the current printer data and the magic key's data (its the DEVMODE) for
8072 * future printer/driver initializations.
8074 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8076 /* Set devmode and printer initialization info */
8077 status = save_driver_init( printer, 2, data, real_len );
8079 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8083 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8084 type, data, real_len );
8085 if ( W_ERROR_IS_OK(status) )
8086 status = mod_a_printer(printer, 2);
8090 free_a_printer(&printer, 2);
8095 /****************************************************************************
8096 ****************************************************************************/
8098 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8100 POLICY_HND *handle = &q_u->handle;
8101 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8104 DEBUG(5,("_spoolss_resetprinter\n"));
8107 * All we do is to check to see if the handle and queue is valid.
8108 * This call really doesn't mean anything to us because we only
8109 * support RAW printing. --jerry
8113 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8117 if (!get_printer_snum(p,handle, &snum))
8121 /* blindly return success */
8126 /****************************************************************************
8127 ****************************************************************************/
8129 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8131 POLICY_HND *handle = &q_u->handle;
8132 UNISTR2 *value = &q_u->valuename;
8134 NT_PRINTER_INFO_LEVEL *printer = NULL;
8136 WERROR status = WERR_OK;
8137 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8140 DEBUG(5,("spoolss_deleteprinterdata\n"));
8143 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8147 if (!get_printer_snum(p, handle, &snum))
8150 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8151 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8152 return WERR_ACCESS_DENIED;
8155 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8156 if (!W_ERROR_IS_OK(status))
8159 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8161 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8163 if ( W_ERROR_IS_OK(status) )
8164 mod_a_printer( printer, 2 );
8166 free_a_printer(&printer, 2);
8171 /****************************************************************************
8172 ****************************************************************************/
8174 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8176 POLICY_HND *handle = &q_u->handle;
8177 FORM *form = &q_u->form;
8178 nt_forms_struct tmpForm;
8180 WERROR status = WERR_OK;
8181 NT_PRINTER_INFO_LEVEL *printer = NULL;
8184 nt_forms_struct *list=NULL;
8185 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8187 DEBUG(5,("spoolss_addform\n"));
8190 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8195 /* forms can be added on printer of on the print server handle */
8197 if ( Printer->printer_type == SPLHND_PRINTER )
8199 if (!get_printer_snum(p,handle, &snum))
8202 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8203 if (!W_ERROR_IS_OK(status))
8207 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8208 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8209 status = WERR_ACCESS_DENIED;
8213 /* can't add if builtin */
8215 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8216 status = WERR_ALREADY_EXISTS;
8220 count = get_ntforms(&list);
8222 if(!add_a_form(&list, form, &count)) {
8223 status = WERR_NOMEM;
8227 write_ntforms(&list, count);
8230 * ChangeID must always be set if this is a printer
8233 if ( Printer->printer_type == SPLHND_PRINTER )
8234 status = mod_a_printer(printer, 2);
8238 free_a_printer(&printer, 2);
8244 /****************************************************************************
8245 ****************************************************************************/
8247 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8249 POLICY_HND *handle = &q_u->handle;
8250 UNISTR2 *form_name = &q_u->name;
8251 nt_forms_struct tmpForm;
8253 nt_forms_struct *list=NULL;
8254 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8256 WERROR status = WERR_OK;
8257 NT_PRINTER_INFO_LEVEL *printer = NULL;
8259 DEBUG(5,("spoolss_deleteform\n"));
8262 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8266 /* forms can be deleted on printer of on the print server handle */
8268 if ( Printer->printer_type == SPLHND_PRINTER )
8270 if (!get_printer_snum(p,handle, &snum))
8273 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8274 if (!W_ERROR_IS_OK(status))
8278 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8279 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8280 status = WERR_ACCESS_DENIED;
8284 /* can't delete if builtin */
8286 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8287 status = WERR_INVALID_PARAM;
8291 count = get_ntforms(&list);
8293 if ( !delete_a_form(&list, form_name, &count, &status ))
8297 * ChangeID must always be set if this is a printer
8300 if ( Printer->printer_type == SPLHND_PRINTER )
8301 status = mod_a_printer(printer, 2);
8305 free_a_printer(&printer, 2);
8311 /****************************************************************************
8312 ****************************************************************************/
8314 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8316 POLICY_HND *handle = &q_u->handle;
8317 FORM *form = &q_u->form;
8318 nt_forms_struct tmpForm;
8320 WERROR status = WERR_OK;
8321 NT_PRINTER_INFO_LEVEL *printer = NULL;
8324 nt_forms_struct *list=NULL;
8325 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8327 DEBUG(5,("spoolss_setform\n"));
8330 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8334 /* forms can be modified on printer of on the print server handle */
8336 if ( Printer->printer_type == SPLHND_PRINTER )
8338 if (!get_printer_snum(p,handle, &snum))
8341 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8342 if (!W_ERROR_IS_OK(status))
8346 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8347 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8348 status = WERR_ACCESS_DENIED;
8352 /* can't set if builtin */
8353 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8354 status = WERR_INVALID_PARAM;
8358 count = get_ntforms(&list);
8359 update_a_form(&list, form, count);
8360 write_ntforms(&list, count);
8363 * ChangeID must always be set if this is a printer
8366 if ( Printer->printer_type == SPLHND_PRINTER )
8367 status = mod_a_printer(printer, 2);
8372 free_a_printer(&printer, 2);
8378 /****************************************************************************
8379 enumprintprocessors level 1.
8380 ****************************************************************************/
8382 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8384 PRINTPROCESSOR_1 *info_1=NULL;
8385 WERROR result = WERR_OK;
8387 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8392 init_unistr(&info_1->name, "winprint");
8394 *needed += spoolss_size_printprocessor_info_1(info_1);
8396 if (*needed > offered) {
8397 result = WERR_INSUFFICIENT_BUFFER;
8401 if (!rpcbuf_alloc_size(buffer, *needed)) {
8402 result = WERR_NOMEM;
8406 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8411 if ( !W_ERROR_IS_OK(result) )
8417 /****************************************************************************
8418 ****************************************************************************/
8420 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8422 uint32 level = q_u->level;
8423 RPC_BUFFER *buffer = NULL;
8424 uint32 offered = q_u->offered;
8425 uint32 *needed = &r_u->needed;
8426 uint32 *returned = &r_u->returned;
8428 /* that's an [in out] buffer */
8430 if (!q_u->buffer && (offered!=0)) {
8431 return WERR_INVALID_PARAM;
8434 rpcbuf_move(q_u->buffer, &r_u->buffer);
8435 buffer = r_u->buffer;
8437 DEBUG(5,("spoolss_enumprintprocessors\n"));
8440 * Enumerate the print processors ...
8442 * Just reply with "winprint", to keep NT happy
8443 * and I can use my nice printer checker.
8451 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8453 return WERR_UNKNOWN_LEVEL;
8457 /****************************************************************************
8458 enumprintprocdatatypes level 1.
8459 ****************************************************************************/
8461 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8463 PRINTPROCDATATYPE_1 *info_1=NULL;
8464 WERROR result = WERR_NOMEM;
8466 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8471 init_unistr(&info_1->name, "RAW");
8473 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8475 if (*needed > offered) {
8476 result = WERR_INSUFFICIENT_BUFFER;
8480 if (!rpcbuf_alloc_size(buffer, *needed)) {
8481 result = WERR_NOMEM;
8485 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8490 if ( !W_ERROR_IS_OK(result) )
8496 /****************************************************************************
8497 ****************************************************************************/
8499 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8501 uint32 level = q_u->level;
8502 RPC_BUFFER *buffer = NULL;
8503 uint32 offered = q_u->offered;
8504 uint32 *needed = &r_u->needed;
8505 uint32 *returned = &r_u->returned;
8507 /* that's an [in out] buffer */
8509 if (!q_u->buffer && (offered!=0)) {
8510 return WERR_INVALID_PARAM;
8513 rpcbuf_move(q_u->buffer, &r_u->buffer);
8514 buffer = r_u->buffer;
8516 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8523 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8525 return WERR_UNKNOWN_LEVEL;
8529 /****************************************************************************
8530 enumprintmonitors level 1.
8531 ****************************************************************************/
8533 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8535 PRINTMONITOR_1 *info_1;
8536 WERROR result = WERR_OK;
8539 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8544 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8545 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8547 for ( i=0; i<*returned; i++ ) {
8548 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8551 if (*needed > offered) {
8552 result = WERR_INSUFFICIENT_BUFFER;
8556 if (!rpcbuf_alloc_size(buffer, *needed)) {
8557 result = WERR_NOMEM;
8561 for ( i=0; i<*returned; i++ ) {
8562 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8568 if ( !W_ERROR_IS_OK(result) )
8574 /****************************************************************************
8575 enumprintmonitors level 2.
8576 ****************************************************************************/
8578 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8580 PRINTMONITOR_2 *info_2;
8581 WERROR result = WERR_OK;
8584 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8589 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8590 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8591 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8593 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8594 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8595 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8597 for ( i=0; i<*returned; i++ ) {
8598 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8601 if (*needed > offered) {
8602 result = WERR_INSUFFICIENT_BUFFER;
8606 if (!rpcbuf_alloc_size(buffer, *needed)) {
8607 result = WERR_NOMEM;
8611 for ( i=0; i<*returned; i++ ) {
8612 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8618 if ( !W_ERROR_IS_OK(result) )
8624 /****************************************************************************
8625 ****************************************************************************/
8627 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8629 uint32 level = q_u->level;
8630 RPC_BUFFER *buffer = NULL;
8631 uint32 offered = q_u->offered;
8632 uint32 *needed = &r_u->needed;
8633 uint32 *returned = &r_u->returned;
8635 /* that's an [in out] buffer */
8637 if (!q_u->buffer && (offered!=0)) {
8638 return WERR_INVALID_PARAM;
8641 rpcbuf_move(q_u->buffer, &r_u->buffer);
8642 buffer = r_u->buffer;
8644 DEBUG(5,("spoolss_enumprintmonitors\n"));
8647 * Enumerate the print monitors ...
8649 * Just reply with "Local Port", to keep NT happy
8650 * and I can use my nice printer checker.
8658 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8660 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8662 return WERR_UNKNOWN_LEVEL;
8666 /****************************************************************************
8667 ****************************************************************************/
8669 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8670 NT_PRINTER_INFO_LEVEL *ntprinter,
8671 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8676 JOB_INFO_1 *info_1=NULL;
8677 WERROR result = WERR_OK;
8679 info_1=SMB_MALLOC_P(JOB_INFO_1);
8681 if (info_1 == NULL) {
8685 for (i=0; i<count && found==False; i++) {
8686 if ((*queue)[i].job==(int)jobid)
8692 /* NT treats not found as bad param... yet another bad choice */
8693 return WERR_INVALID_PARAM;
8696 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8698 *needed += spoolss_size_job_info_1(info_1);
8700 if (*needed > offered) {
8701 result = WERR_INSUFFICIENT_BUFFER;
8705 if (!rpcbuf_alloc_size(buffer, *needed)) {
8706 result = WERR_NOMEM;
8710 smb_io_job_info_1("", buffer, info_1, 0);
8718 /****************************************************************************
8719 ****************************************************************************/
8721 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8722 NT_PRINTER_INFO_LEVEL *ntprinter,
8723 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8730 DEVICEMODE *devmode = NULL;
8731 NT_DEVICEMODE *nt_devmode = NULL;
8733 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8736 ZERO_STRUCTP(info_2);
8738 for ( i=0; i<count && found==False; i++ )
8740 if ((*queue)[i].job == (int)jobid)
8745 /* NT treats not found as bad param... yet another bad
8747 result = WERR_INVALID_PARAM;
8752 * if the print job does not have a DEVMODE associated with it,
8753 * just use the one for the printer. A NULL devicemode is not
8754 * a failure condition
8757 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8758 devmode = construct_dev_mode(lp_const_servicename(snum));
8760 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8761 ZERO_STRUCTP( devmode );
8762 convert_nt_devicemode( devmode, nt_devmode );
8766 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8768 *needed += spoolss_size_job_info_2(info_2);
8770 if (*needed > offered) {
8771 result = WERR_INSUFFICIENT_BUFFER;
8775 if (!rpcbuf_alloc_size(buffer, *needed)) {
8776 result = WERR_NOMEM;
8780 smb_io_job_info_2("", buffer, info_2, 0);
8785 /* Cleanup allocated memory */
8787 free_job_info_2(info_2); /* Also frees devmode */
8793 /****************************************************************************
8794 ****************************************************************************/
8796 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8798 POLICY_HND *handle = &q_u->handle;
8799 uint32 jobid = q_u->jobid;
8800 uint32 level = q_u->level;
8801 RPC_BUFFER *buffer = NULL;
8802 uint32 offered = q_u->offered;
8803 uint32 *needed = &r_u->needed;
8804 WERROR wstatus = WERR_OK;
8805 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8808 print_queue_struct *queue = NULL;
8809 print_status_struct prt_status;
8811 /* that's an [in out] buffer */
8813 if (!q_u->buffer && (offered!=0)) {
8814 return WERR_INVALID_PARAM;
8817 rpcbuf_move(q_u->buffer, &r_u->buffer);
8818 buffer = r_u->buffer;
8820 DEBUG(5,("spoolss_getjob\n"));
8824 if (!get_printer_snum(p, handle, &snum))
8827 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8828 if ( !W_ERROR_IS_OK(wstatus) )
8831 count = print_queue_status(snum, &queue, &prt_status);
8833 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8834 count, prt_status.status, prt_status.message));
8838 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8839 buffer, offered, needed);
8842 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8843 buffer, offered, needed);
8846 wstatus = WERR_UNKNOWN_LEVEL;
8851 free_a_printer( &ntprinter, 2 );
8856 /********************************************************************
8857 spoolss_getprinterdataex
8859 From MSDN documentation of GetPrinterDataEx: pass request
8860 to GetPrinterData if key is "PrinterDriverData".
8861 ********************************************************************/
8863 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8865 POLICY_HND *handle = &q_u->handle;
8866 uint32 in_size = q_u->size;
8867 uint32 *type = &r_u->type;
8868 uint32 *out_size = &r_u->size;
8869 uint8 **data = &r_u->data;
8870 uint32 *needed = &r_u->needed;
8871 fstring keyname, valuename;
8873 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8875 NT_PRINTER_INFO_LEVEL *printer = NULL;
8877 WERROR status = WERR_OK;
8879 DEBUG(4,("_spoolss_getprinterdataex\n"));
8881 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8882 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8884 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8885 keyname, valuename));
8887 /* in case of problem, return some default values */
8891 *out_size = in_size;
8894 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8895 status = WERR_BADFID;
8899 /* Is the handle to a printer or to the server? */
8901 if (Printer->printer_type == SPLHND_SERVER) {
8902 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8903 status = WERR_INVALID_PARAM;
8907 if ( !get_printer_snum(p,handle, &snum) )
8910 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8911 if ( !W_ERROR_IS_OK(status) )
8914 /* check to see if the keyname is valid */
8915 if ( !strlen(keyname) ) {
8916 status = WERR_INVALID_PARAM;
8920 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8921 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8922 free_a_printer( &printer, 2 );
8923 status = WERR_BADFILE;
8927 /* When given a new keyname, we should just create it */
8929 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8931 if (*needed > *out_size)
8932 status = WERR_MORE_DATA;
8935 if ( !W_ERROR_IS_OK(status) )
8937 DEBUG(5, ("error: allocating %d\n", *out_size));
8939 /* reply this param doesn't exist */
8943 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8944 status = WERR_NOMEM;
8954 free_a_printer( &printer, 2 );
8959 /********************************************************************
8960 * spoolss_setprinterdataex
8961 ********************************************************************/
8963 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8965 POLICY_HND *handle = &q_u->handle;
8966 uint32 type = q_u->type;
8967 uint8 *data = q_u->data;
8968 uint32 real_len = q_u->real_len;
8970 NT_PRINTER_INFO_LEVEL *printer = NULL;
8972 WERROR status = WERR_OK;
8973 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8978 DEBUG(4,("_spoolss_setprinterdataex\n"));
8980 /* From MSDN documentation of SetPrinterDataEx: pass request to
8981 SetPrinterData if key is "PrinterDriverData" */
8984 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8988 if ( Printer->printer_type == SPLHND_SERVER ) {
8989 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8990 return WERR_INVALID_PARAM;
8993 if ( !get_printer_snum(p,handle, &snum) )
8997 * Access check : NT returns "access denied" if you make a
8998 * SetPrinterData call without the necessary privildge.
8999 * we were originally returning OK if nothing changed
9000 * which made Win2k issue **a lot** of SetPrinterData
9001 * when connecting to a printer --jerry
9004 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9006 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9007 return WERR_ACCESS_DENIED;
9010 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9011 if (!W_ERROR_IS_OK(status))
9014 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9015 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9017 /* check for OID in valuename */
9019 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9025 /* save the registry data */
9027 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9029 if ( W_ERROR_IS_OK(status) )
9031 /* save the OID if one was specified */
9033 fstrcat( keyname, "\\" );
9034 fstrcat( keyname, SPOOL_OID_KEY );
9037 * I'm not checking the status here on purpose. Don't know
9038 * if this is right, but I'm returning the status from the
9039 * previous set_printer_dataex() call. I have no idea if
9040 * this is right. --jerry
9043 set_printer_dataex( printer, keyname, valuename,
9044 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9047 status = mod_a_printer(printer, 2);
9050 free_a_printer(&printer, 2);
9056 /********************************************************************
9057 * spoolss_deleteprinterdataex
9058 ********************************************************************/
9060 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9062 POLICY_HND *handle = &q_u->handle;
9063 UNISTR2 *value = &q_u->valuename;
9064 UNISTR2 *key = &q_u->keyname;
9066 NT_PRINTER_INFO_LEVEL *printer = NULL;
9068 WERROR status = WERR_OK;
9069 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9070 pstring valuename, keyname;
9072 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9075 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9079 if (!get_printer_snum(p, handle, &snum))
9082 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9083 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9084 return WERR_ACCESS_DENIED;
9087 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9088 if (!W_ERROR_IS_OK(status))
9091 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9092 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9094 status = delete_printer_dataex( printer, keyname, valuename );
9096 if ( W_ERROR_IS_OK(status) )
9097 mod_a_printer( printer, 2 );
9099 free_a_printer(&printer, 2);
9104 /********************************************************************
9105 * spoolss_enumprinterkey
9106 ********************************************************************/
9109 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9112 fstring *keynames = NULL;
9113 uint16 *enumkeys = NULL;
9116 POLICY_HND *handle = &q_u->handle;
9117 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9118 NT_PRINTER_DATA *data;
9119 NT_PRINTER_INFO_LEVEL *printer = NULL;
9121 WERROR status = WERR_BADFILE;
9124 DEBUG(4,("_spoolss_enumprinterkey\n"));
9127 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9131 if ( !get_printer_snum(p,handle, &snum) )
9134 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9135 if (!W_ERROR_IS_OK(status))
9138 /* get the list of subkey names */
9140 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9141 data = printer->info_2->data;
9143 num_keys = get_printer_subkeys( data, key, &keynames );
9145 if ( num_keys == -1 ) {
9146 status = WERR_BADFILE;
9150 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9152 r_u->needed = printerkey_len*2;
9154 if ( q_u->size < r_u->needed ) {
9155 status = WERR_MORE_DATA;
9159 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9160 status = WERR_NOMEM;
9166 if ( q_u->size < r_u->needed )
9167 status = WERR_MORE_DATA;
9170 free_a_printer( &printer, 2 );
9171 SAFE_FREE( keynames );
9176 /********************************************************************
9177 * spoolss_deleteprinterkey
9178 ********************************************************************/
9180 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9182 POLICY_HND *handle = &q_u->handle;
9183 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9185 NT_PRINTER_INFO_LEVEL *printer = NULL;
9189 DEBUG(5,("spoolss_deleteprinterkey\n"));
9192 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9196 /* if keyname == NULL, return error */
9198 if ( !q_u->keyname.buffer )
9199 return WERR_INVALID_PARAM;
9201 if (!get_printer_snum(p, handle, &snum))
9204 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9205 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9206 return WERR_ACCESS_DENIED;
9209 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9210 if (!W_ERROR_IS_OK(status))
9213 /* delete the key and all subneys */
9215 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9217 status = delete_all_printer_data( printer->info_2, key );
9219 if ( W_ERROR_IS_OK(status) )
9220 status = mod_a_printer(printer, 2);
9222 free_a_printer( &printer, 2 );
9228 /********************************************************************
9229 * spoolss_enumprinterdataex
9230 ********************************************************************/
9232 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9234 POLICY_HND *handle = &q_u->handle;
9235 uint32 in_size = q_u->size;
9238 NT_PRINTER_INFO_LEVEL *printer = NULL;
9239 PRINTER_ENUM_VALUES *enum_values = NULL;
9240 NT_PRINTER_DATA *p_data;
9242 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9247 REGISTRY_VALUE *val;
9252 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9255 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9260 * first check for a keyname of NULL or "". Win2k seems to send
9261 * this a lot and we should send back WERR_INVALID_PARAM
9262 * no need to spend time looking up the printer in this case.
9266 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9267 if ( !strlen(key) ) {
9268 result = WERR_INVALID_PARAM;
9272 /* get the printer off of disk */
9274 if (!get_printer_snum(p,handle, &snum))
9277 ZERO_STRUCT(printer);
9278 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9279 if (!W_ERROR_IS_OK(result))
9282 /* now look for a match on the key name */
9284 p_data = printer->info_2->data;
9286 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9287 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9289 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9290 result = WERR_INVALID_PARAM;
9297 /* allocate the memory for the array of pointers -- if necessary */
9299 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9302 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9304 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9305 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9306 result = WERR_NOMEM;
9310 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9314 * loop through all params and build the array to pass
9315 * back to the client
9318 for ( i=0; i<num_entries; i++ )
9320 /* lookup the registry value */
9322 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9323 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9327 value_name = regval_name( val );
9328 init_unistr( &enum_values[i].valuename, value_name );
9329 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9330 enum_values[i].type = regval_type( val );
9332 data_len = regval_size( val );
9334 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9336 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9338 result = WERR_NOMEM;
9342 enum_values[i].data_len = data_len;
9344 /* keep track of the size of the array in bytes */
9346 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9349 /* housekeeping information in the reply */
9351 r_u->needed = needed;
9352 r_u->returned = num_entries;
9354 if (needed > in_size) {
9355 result = WERR_MORE_DATA;
9359 /* copy data into the reply */
9361 r_u->ctr.size = r_u->needed;
9362 r_u->ctr.size_of_array = r_u->returned;
9363 r_u->ctr.values = enum_values;
9369 free_a_printer(&printer, 2);
9374 /****************************************************************************
9375 ****************************************************************************/
9377 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9379 init_unistr(&info->name, name);
9382 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9383 UNISTR2 *environment,
9390 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9391 WERROR result = WERR_OK;
9393 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9395 if (!get_short_archi(long_archi))
9396 return WERR_INVALID_ENVIRONMENT;
9398 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9401 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9403 fill_printprocessordirectory_1(info, path);
9405 *needed += spoolss_size_printprocessordirectory_info_1(info);
9407 if (*needed > offered) {
9408 result = WERR_INSUFFICIENT_BUFFER;
9412 if (!rpcbuf_alloc_size(buffer, *needed)) {
9413 result = WERR_INSUFFICIENT_BUFFER;
9417 smb_io_printprocessordirectory_1("", buffer, info, 0);
9425 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9427 uint32 level = q_u->level;
9428 RPC_BUFFER *buffer = NULL;
9429 uint32 offered = q_u->offered;
9430 uint32 *needed = &r_u->needed;
9433 /* that's an [in out] buffer */
9435 if (!q_u->buffer && (offered!=0)) {
9436 return WERR_INVALID_PARAM;
9439 rpcbuf_move(q_u->buffer, &r_u->buffer);
9440 buffer = r_u->buffer;
9442 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9448 result = getprintprocessordirectory_level_1
9449 (&q_u->name, &q_u->environment, buffer, offered, needed);
9452 result = WERR_UNKNOWN_LEVEL;
9458 /*******************************************************************
9459 Streams the monitor UI DLL name in UNICODE
9460 *******************************************************************/
9462 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9463 RPC_BUFFER *out, uint32 *needed )
9465 const char *dllname = "tcpmonui.dll";
9467 *needed = (strlen(dllname)+1) * 2;
9469 if ( rpcbuf_get_size(out) < *needed ) {
9470 return WERR_INSUFFICIENT_BUFFER;
9473 if ( !make_monitorui_buf( out, dllname ) ) {
9480 /*******************************************************************
9481 Create a new TCP/IP port
9482 *******************************************************************/
9484 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9485 RPC_BUFFER *out, uint32 *needed )
9487 NT_PORT_DATA_1 port1;
9490 ZERO_STRUCT( port1 );
9492 /* convert to our internal port data structure */
9494 if ( !convert_port_data_1( &port1, in ) ) {
9498 /* create the device URI and call the add_port_hook() */
9500 switch ( port1.protocol ) {
9501 case PORT_PROTOCOL_DIRECT:
9502 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9505 case PORT_PROTOCOL_LPR:
9506 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9510 return WERR_UNKNOWN_PORT;
9513 return add_port_hook( token, port1.name, device_uri );
9516 /*******************************************************************
9517 *******************************************************************/
9519 struct xcv_api_table xcvtcp_cmds[] = {
9520 { "MonitorUI", xcvtcp_monitorui },
9521 { "AddPort", xcvtcp_addport},
9525 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9526 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9531 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9533 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9534 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9535 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9538 return WERR_BADFUNC;
9541 /*******************************************************************
9542 *******************************************************************/
9543 #if 0 /* don't support management using the "Local Port" monitor */
9545 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9546 RPC_BUFFER *out, uint32 *needed )
9548 const char *dllname = "localui.dll";
9550 *needed = (strlen(dllname)+1) * 2;
9552 if ( rpcbuf_get_size(out) < *needed ) {
9553 return WERR_INSUFFICIENT_BUFFER;
9556 if ( !make_monitorui_buf( out, dllname )) {
9563 /*******************************************************************
9564 *******************************************************************/
9566 struct xcv_api_table xcvlocal_cmds[] = {
9567 { "MonitorUI", xcvlocal_monitorui },
9571 struct xcv_api_table xcvlocal_cmds[] = {
9578 /*******************************************************************
9579 *******************************************************************/
9581 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9582 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9587 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9589 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9590 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9591 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9593 return WERR_BADFUNC;
9596 /*******************************************************************
9597 *******************************************************************/
9599 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9601 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9605 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9609 /* Has to be a handle to the TCP/IP port monitor */
9611 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9612 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9616 /* requires administrative access to the server */
9618 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9619 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9620 return WERR_ACCESS_DENIED;
9623 /* Get the command name. There's numerous commands supported by the
9624 TCPMON interface. */
9626 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9627 q_u->dataname.uni_str_len*2, 0);
9629 /* Allocate the outgoing buffer */
9631 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9633 switch ( Printer->printer_type ) {
9634 case SPLHND_PORTMON_TCP:
9635 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9636 &q_u->indata, &r_u->outdata, &r_u->needed );
9637 case SPLHND_PORTMON_LOCAL:
9638 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9639 &q_u->indata, &r_u->outdata, &r_u->needed );
9642 return WERR_INVALID_PRINT_MONITOR;