2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 extern userdom_struct current_user_info;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 const char *long_archi;
45 const char *short_archi;
49 static Printer_entry *printers_list;
51 typedef struct _counter_printer_0 {
52 struct _counter_printer_0 *next;
53 struct _counter_printer_0 *prev;
59 static counter_printer_0 *counter_list;
61 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
62 static uint32 smb_connections=0;
65 /* in printing/nt_printing.c */
67 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
69 /* API table for Xcv Monitor functions */
71 struct xcv_api_table {
73 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
77 /* translate between internal status numbers and NT status numbers */
78 static int nt_printj_status(int v)
84 return JOB_STATUS_PAUSED;
86 return JOB_STATUS_SPOOLING;
88 return JOB_STATUS_PRINTING;
90 return JOB_STATUS_ERROR;
92 return JOB_STATUS_DELETING;
94 return JOB_STATUS_OFFLINE;
96 return JOB_STATUS_PAPEROUT;
98 return JOB_STATUS_PRINTED;
100 return JOB_STATUS_DELETED;
102 return JOB_STATUS_BLOCKED;
103 case LPQ_USER_INTERVENTION:
104 return JOB_STATUS_USER_INTERVENTION;
109 static int nt_printq_status(int v)
113 return PRINTER_STATUS_PAUSED;
122 /****************************************************************************
123 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
124 ****************************************************************************/
126 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
131 SAFE_FREE((*pp)->ctr.type);
135 /***************************************************************************
136 Disconnect from the client
137 ****************************************************************************/
139 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
144 * Tell the specific printing tdb we no longer want messages for this printer
145 * by deregistering our PID.
148 if (!print_notify_deregister_pid(snum))
149 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
151 /* weird if the test succeds !!! */
152 if (smb_connections==0) {
153 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
157 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
159 if (!W_ERROR_IS_OK(result))
160 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
161 dos_errstr(result)));
163 /* if it's the last connection, deconnect the IPC$ share */
164 if (smb_connections==1) {
166 cli_shutdown( notify_cli_pipe->cli );
167 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
169 message_deregister(MSG_PRINTER_NOTIFY2);
171 /* Tell the connections db we're no longer interested in
172 * printer notify messages. */
174 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
180 /****************************************************************************
181 Functions to free a printer entry datastruct.
182 ****************************************************************************/
184 static void free_printer_entry(void *ptr)
186 Printer_entry *Printer = (Printer_entry *)ptr;
188 if (Printer->notify.client_connected==True) {
191 if ( Printer->printer_type == SPLHND_SERVER) {
193 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
194 } else if (Printer->printer_type == SPLHND_PRINTER) {
195 snum = print_queue_snum(Printer->sharename);
197 srv_spoolss_replycloseprinter(snum,
198 &Printer->notify.client_hnd);
202 Printer->notify.flags=0;
203 Printer->notify.options=0;
204 Printer->notify.localmachine[0]='\0';
205 Printer->notify.printerlocal=0;
206 free_spool_notify_option(&Printer->notify.option);
207 Printer->notify.option=NULL;
208 Printer->notify.client_connected=False;
210 free_nt_devicemode( &Printer->nt_devmode );
211 free_a_printer( &Printer->printer_info, 2 );
213 talloc_destroy( Printer->ctx );
215 /* Remove from the internal list. */
216 DLIST_REMOVE(printers_list, Printer);
221 /****************************************************************************
222 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
223 ****************************************************************************/
225 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
227 SPOOL_NOTIFY_OPTION *new_sp = NULL;
232 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
239 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
241 if (!new_sp->ctr.type) {
250 /****************************************************************************
251 find printer index by handle
252 ****************************************************************************/
254 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
256 Printer_entry *find_printer = NULL;
258 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
259 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
266 /****************************************************************************
267 Close printer index by handle.
268 ****************************************************************************/
270 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
272 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
275 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
279 close_policy_hnd(p, hnd);
284 /****************************************************************************
285 Delete a printer given a handle.
286 ****************************************************************************/
287 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
289 char *cmd = lp_deleteprinter_cmd();
292 SE_PRIV se_printop = SE_PRINT_OPERATOR;
293 BOOL is_print_op = False;
295 /* can't fail if we don't try */
300 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
303 is_print_op = user_has_privileges( token, &se_printop );
305 DEBUG(10,("Running [%s]\n", command));
307 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
312 if ( (ret = smbrun(command, NULL)) == 0 ) {
313 /* Tell everyone we updated smb.conf. */
314 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
320 /********** END SePrintOperatorPrivlege BLOCK **********/
322 DEBUGADD(10,("returned [%d]\n", ret));
325 return WERR_BADFID; /* What to return here? */
327 /* go ahead and re-read the services immediately */
328 reload_services( False );
330 if ( share_defined( sharename ) )
331 return WERR_ACCESS_DENIED;
336 /****************************************************************************
337 Delete a printer given a handle.
338 ****************************************************************************/
340 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
342 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
345 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
350 * It turns out that Windows allows delete printer on a handle
351 * opened by an admin user, then used on a pipe handle created
352 * by an anonymous user..... but they're working on security.... riiight !
356 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
357 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
358 return WERR_ACCESS_DENIED;
361 /* this does not need a become root since the access check has been
362 done on the handle already */
364 if (del_a_printer( Printer->sharename ) != 0) {
365 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
369 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
372 /****************************************************************************
373 Return the snum of a printer corresponding to an handle.
374 ****************************************************************************/
376 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
378 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
381 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
385 switch (Printer->printer_type) {
387 DEBUG(4,("short name:%s\n", Printer->sharename));
388 *number = print_queue_snum(Printer->sharename);
389 return (*number != -1);
397 /****************************************************************************
398 Set printer handle type.
399 Check if it's \\server or \\server\printer
400 ****************************************************************************/
402 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
404 DEBUG(3,("Setting printer type=%s\n", handlename));
406 if ( strlen(handlename) < 3 ) {
407 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
411 /* it's a print server */
412 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
413 DEBUGADD(4,("Printer is a print server\n"));
414 Printer->printer_type = SPLHND_SERVER;
416 /* it's a printer (set_printer_hnd_name() will handle port monitors */
418 DEBUGADD(4,("Printer is a printer\n"));
419 Printer->printer_type = SPLHND_PRINTER;
425 /****************************************************************************
426 Set printer handle name.. Accept names like \\server, \\server\printer,
427 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
428 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
429 XcvDataPort() interface.
430 ****************************************************************************/
432 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
435 int n_services=lp_numservices();
436 char *aprinter, *printername;
437 const char *servername;
440 NT_PRINTER_INFO_LEVEL *printer = NULL;
443 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
445 aprinter = handlename;
446 if ( *handlename == '\\' ) {
447 servername = handlename + 2;
448 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
457 /* save the servername to fill in replies on this handle */
459 if ( !is_myname_or_ipaddr( servername ) )
462 fstrcpy( Printer->servername, servername );
464 if ( Printer->printer_type == SPLHND_SERVER )
467 if ( Printer->printer_type != SPLHND_PRINTER )
470 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
472 /* check for the Port Monitor Interface */
474 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
475 Printer->printer_type = SPLHND_PORTMON_TCP;
476 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
479 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
480 Printer->printer_type = SPLHND_PORTMON_LOCAL;
481 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
485 /* Search all sharenames first as this is easier than pulling
486 the printer_info_2 off of disk. Don't use find_service() since
487 that calls out to map_username() */
489 /* do another loop to look for printernames */
491 for (snum=0; !found && snum<n_services; snum++) {
493 /* no point going on if this is not a printer */
495 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
498 fstrcpy(sname, lp_servicename(snum));
499 if ( strequal( aprinter, sname ) ) {
504 /* no point looking up the printer object if
505 we aren't allowing printername != sharename */
507 if ( lp_force_printername(snum) )
510 fstrcpy(sname, lp_servicename(snum));
513 result = get_a_printer( NULL, &printer, 2, sname );
514 if ( !W_ERROR_IS_OK(result) ) {
515 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
516 sname, dos_errstr(result)));
520 /* printername is always returned as \\server\printername */
521 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
522 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
523 printer->info_2->printername));
524 free_a_printer( &printer, 2);
530 if ( strequal(printername, aprinter) ) {
531 free_a_printer( &printer, 2);
536 DEBUGADD(10, ("printername: %s\n", printername));
538 free_a_printer( &printer, 2);
541 free_a_printer( &printer, 2);
544 DEBUGADD(4,("Printer not found\n"));
548 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
550 fstrcpy(Printer->sharename, sname);
555 /****************************************************************************
556 Find first available printer slot. creates a printer handle for you.
557 ****************************************************************************/
559 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
561 Printer_entry *new_printer;
563 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
565 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
568 ZERO_STRUCTP(new_printer);
570 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
571 SAFE_FREE(new_printer);
575 /* Add to the internal list. */
576 DLIST_ADD(printers_list, new_printer);
578 new_printer->notify.option=NULL;
580 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
581 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
582 close_printer_handle(p, hnd);
586 if (!set_printer_hnd_printertype(new_printer, name)) {
587 close_printer_handle(p, hnd);
591 if (!set_printer_hnd_name(new_printer, name)) {
592 close_printer_handle(p, hnd);
596 new_printer->access_granted = access_granted;
598 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
603 /***************************************************************************
604 check to see if the client motify handle is monitoring the notification
605 given by (notify_type, notify_field).
606 **************************************************************************/
608 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
614 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
617 SPOOL_NOTIFY_OPTION *option = p->notify.option;
621 * Flags should always be zero when the change notify
622 * is registered by the client's spooler. A user Win32 app
623 * might use the flags though instead of the NOTIFY_OPTION_INFO
632 return is_monitoring_event_flags(
633 p->notify.flags, notify_type, notify_field);
635 for (i = 0; i < option->count; i++) {
637 /* Check match for notify_type */
639 if (option->ctr.type[i].type != notify_type)
642 /* Check match for field */
644 for (j = 0; j < option->ctr.type[i].count; j++) {
645 if (option->ctr.type[i].fields[j] == notify_field) {
651 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
652 p->servername, p->sharename, notify_type, notify_field));
657 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
659 static void notify_one_value(struct spoolss_notify_msg *msg,
660 SPOOL_NOTIFY_INFO_DATA *data,
663 data->notify_data.value[0] = msg->notify.value[0];
664 data->notify_data.value[1] = 0;
667 static void notify_string(struct spoolss_notify_msg *msg,
668 SPOOL_NOTIFY_INFO_DATA *data,
673 /* The length of the message includes the trailing \0 */
675 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
677 data->notify_data.data.length = msg->len * 2;
678 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
680 if (!data->notify_data.data.string) {
681 data->notify_data.data.length = 0;
685 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
688 static void notify_system_time(struct spoolss_notify_msg *msg,
689 SPOOL_NOTIFY_INFO_DATA *data,
695 if (msg->len != sizeof(time_t)) {
696 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
701 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
702 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
706 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
707 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
712 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
717 data->notify_data.data.length = prs_offset(&ps);
718 data->notify_data.data.string = (uint16 *)
719 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 = (char *)
912 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
914 return ctr->num_groups;
917 /***********************************************************************
918 Send a change notication message on all handles which have a call
920 **********************************************************************/
922 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
925 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
926 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
927 SPOOLSS_NOTIFY_MSG *messages;
928 int sending_msg_count;
931 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
935 messages = msg_group->msgs;
938 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
942 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
944 /* loop over all printers */
946 for (p = printers_list; p; p = p->next) {
947 SPOOL_NOTIFY_INFO_DATA *data;
952 /* Is there notification on this handle? */
954 if ( !p->notify.client_connected )
957 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
959 /* For this printer? Print servers always receive
962 if ( ( p->printer_type == SPLHND_PRINTER ) &&
963 ( !strequal(msg_group->printername, p->sharename) ) )
966 DEBUG(10,("Our printer\n"));
968 /* allocate the max entries possible */
970 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
977 /* build the array of change notifications */
979 sending_msg_count = 0;
981 for ( i=0; i<msg_group->num_msgs; i++ ) {
982 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
984 /* Are we monitoring this event? */
986 if (!is_monitoring_event(p, msg->type, msg->field))
992 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
993 msg->type, msg->field, p->sharename));
996 * if the is a printer notification handle and not a job notification
997 * type, then set the id to 0. Other wise just use what was specified
1000 * When registering change notification on a print server handle
1001 * we always need to send back the id (snum) matching the printer
1002 * for which the change took place. For change notify registered
1003 * on a printer handle, this does not matter and the id should be 0.
1008 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1014 /* Convert unix jobid to smb jobid */
1016 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1017 id = sysjob_to_jobid(msg->id);
1020 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1025 construct_info_data( &data[data_len], msg->type, msg->field, id );
1028 case PRINTER_NOTIFY_TYPE:
1029 if ( printer_notify_table[msg->field].fn )
1030 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1033 case JOB_NOTIFY_TYPE:
1034 if ( job_notify_table[msg->field].fn )
1035 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1039 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1046 if ( sending_msg_count ) {
1047 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1048 data_len, data, p->notify.change, 0 );
1053 DEBUG(8,("send_notify2_changes: Exit...\n"));
1057 /***********************************************************************
1058 **********************************************************************/
1060 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1063 uint32 tv_sec, tv_usec;
1066 /* Unpack message */
1068 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1071 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1073 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1076 tdb_unpack((char *)buf + offset, len - offset, "dd",
1077 &msg->notify.value[0], &msg->notify.value[1]);
1079 tdb_unpack((char *)buf + offset, len - offset, "B",
1080 &msg->len, &msg->notify.data);
1082 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1083 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1085 tv->tv_sec = tv_sec;
1086 tv->tv_usec = tv_usec;
1089 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1090 msg->notify.value[1]));
1092 dump_data(3, msg->notify.data, msg->len);
1097 /********************************************************************
1098 Receive a notify2 message list
1099 ********************************************************************/
1101 static void receive_notify2_message_list(int msg_type, struct process_id src,
1102 void *msg, size_t len)
1104 size_t msg_count, i;
1105 char *buf = (char *)msg;
1108 SPOOLSS_NOTIFY_MSG notify;
1109 SPOOLSS_NOTIFY_MSG_CTR messages;
1113 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1117 msg_count = IVAL(buf, 0);
1120 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1122 if (msg_count == 0) {
1123 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1127 /* initialize the container */
1129 ZERO_STRUCT( messages );
1130 notify_msg_ctr_init( &messages );
1133 * build message groups for each printer identified
1134 * in a change_notify msg. Remember that a PCN message
1135 * includes the handle returned for the srv_spoolss_replyopenprinter()
1136 * call. Therefore messages are grouped according to printer handle.
1139 for ( i=0; i<msg_count; i++ ) {
1140 struct timeval msg_tv;
1142 if (msg_ptr + 4 - buf > len) {
1143 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1147 msg_len = IVAL(msg_ptr,0);
1150 if (msg_ptr + msg_len - buf > len) {
1151 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1155 /* unpack messages */
1157 ZERO_STRUCT( notify );
1158 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1161 /* add to correct list in container */
1163 notify_msg_ctr_addmsg( &messages, ¬ify );
1165 /* free memory that might have been allocated by notify2_unpack_msg() */
1167 if ( notify.len != 0 )
1168 SAFE_FREE( notify.notify.data );
1171 /* process each group of messages */
1173 num_groups = notify_msg_ctr_numgroups( &messages );
1174 for ( i=0; i<num_groups; i++ )
1175 send_notify2_changes( &messages, i );
1180 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1182 notify_msg_ctr_destroy( &messages );
1187 /********************************************************************
1188 Send a message to ourself about new driver being installed
1189 so we can upgrade the information for each printer bound to this
1191 ********************************************************************/
1193 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1195 int len = strlen(drivername);
1200 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1203 message_send_pid(pid_to_procid(sys_getpid()),
1204 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1209 /**********************************************************************
1210 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1211 over all printers, upgrading ones as necessary
1212 **********************************************************************/
1214 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1218 int n_services = lp_numservices();
1220 len = MIN(len,sizeof(drivername)-1);
1221 strncpy(drivername, (const char *)buf, len);
1223 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1225 /* Iterate the printer list */
1227 for (snum=0; snum<n_services; snum++)
1229 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1232 NT_PRINTER_INFO_LEVEL *printer = NULL;
1234 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1235 if (!W_ERROR_IS_OK(result))
1238 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1240 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1242 /* all we care about currently is the change_id */
1244 result = mod_a_printer(printer, 2);
1245 if (!W_ERROR_IS_OK(result)) {
1246 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1247 dos_errstr(result)));
1251 free_a_printer(&printer, 2);
1258 /********************************************************************
1259 Update the cache for all printq's with a registered client
1261 ********************************************************************/
1263 void update_monitored_printq_cache( void )
1265 Printer_entry *printer = printers_list;
1268 /* loop through all printers and update the cache where
1269 client_connected == True */
1272 if ( (printer->printer_type == SPLHND_PRINTER)
1273 && printer->notify.client_connected )
1275 snum = print_queue_snum(printer->sharename);
1276 print_queue_status( snum, NULL, NULL );
1279 printer = printer->next;
1284 /********************************************************************
1285 Send a message to ourself about new driver being installed
1286 so we can upgrade the information for each printer bound to this
1288 ********************************************************************/
1290 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1292 int len = strlen(drivername);
1297 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1300 message_send_pid(pid_to_procid(sys_getpid()),
1301 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1306 /**********************************************************************
1307 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1308 over all printers, resetting printer data as neessary
1309 **********************************************************************/
1311 void reset_all_printerdata(int msg_type, struct process_id src,
1312 void *buf, size_t len)
1316 int n_services = lp_numservices();
1318 len = MIN( len, sizeof(drivername)-1 );
1319 strncpy( drivername, (const char *)buf, len );
1321 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1323 /* Iterate the printer list */
1325 for ( snum=0; snum<n_services; snum++ )
1327 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1330 NT_PRINTER_INFO_LEVEL *printer = NULL;
1332 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1333 if ( !W_ERROR_IS_OK(result) )
1337 * if the printer is bound to the driver,
1338 * then reset to the new driver initdata
1341 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1343 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1345 if ( !set_driver_init(printer, 2) ) {
1346 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1347 printer->info_2->printername, printer->info_2->drivername));
1350 result = mod_a_printer( printer, 2 );
1351 if ( !W_ERROR_IS_OK(result) ) {
1352 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1353 get_dos_error_msg(result)));
1357 free_a_printer( &printer, 2 );
1366 /********************************************************************
1367 Copy routines used by convert_to_openprinterex()
1368 *******************************************************************/
1370 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1378 DEBUG (8,("dup_devmode\n"));
1380 /* bulk copy first */
1382 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1386 /* dup the pointer members separately */
1388 len = unistrlen(devmode->devicename.buffer);
1390 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1391 if (!d->devicename.buffer) {
1394 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1399 len = unistrlen(devmode->formname.buffer);
1401 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1402 if (!d->devicename.buffer) {
1405 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1409 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1410 devmode->driverextra);
1411 if (!d->dev_private) {
1417 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1419 if (!new_ctr || !ctr)
1422 DEBUG(8,("copy_devmode_ctr\n"));
1424 new_ctr->size = ctr->size;
1425 new_ctr->devmode_ptr = ctr->devmode_ptr;
1427 if(ctr->devmode_ptr)
1428 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1431 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1433 if (!new_def || !def)
1436 DEBUG(8,("copy_printer_defaults\n"));
1438 new_def->datatype_ptr = def->datatype_ptr;
1440 if (def->datatype_ptr)
1441 copy_unistr2(&new_def->datatype, &def->datatype);
1443 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1445 new_def->access_required = def->access_required;
1448 /********************************************************************
1449 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1450 * SPOOL_Q_OPEN_PRINTER_EX structure
1451 ********************************************************************/
1453 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1455 if (!q_u_ex || !q_u)
1458 DEBUG(8,("convert_to_openprinterex\n"));
1460 if ( q_u->printername ) {
1461 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1462 if (q_u_ex->printername == NULL)
1464 copy_unistr2(q_u_ex->printername, q_u->printername);
1467 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1472 /********************************************************************
1473 * spoolss_open_printer
1475 * called from the spoolss dispatcher
1476 ********************************************************************/
1478 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1480 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1481 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1486 ZERO_STRUCT(q_u_ex);
1487 ZERO_STRUCT(r_u_ex);
1489 /* convert the OpenPrinter() call to OpenPrinterEx() */
1491 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1492 if (!W_ERROR_IS_OK(r_u_ex.status))
1493 return r_u_ex.status;
1495 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1497 /* convert back to OpenPrinter() */
1499 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1504 /********************************************************************
1505 ********************************************************************/
1507 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1509 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1510 POLICY_HND *handle = &r_u->handle;
1514 Printer_entry *Printer=NULL;
1516 if ( !q_u->printername )
1517 return WERR_INVALID_PRINTER_NAME;
1519 /* some sanity check because you can open a printer or a print server */
1520 /* aka: \\server\printer or \\server */
1522 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1524 DEBUGADD(3,("checking name: %s\n",name));
1526 if (!open_printer_hnd(p, handle, name, 0))
1527 return WERR_INVALID_PRINTER_NAME;
1529 Printer=find_printer_index_by_hnd(p, handle);
1531 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1532 "handle we created for printer %s\n", name ));
1533 close_printer_handle(p,handle);
1534 return WERR_INVALID_PRINTER_NAME;
1538 * First case: the user is opening the print server:
1540 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1541 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1543 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1544 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1545 * or if the user is listed in the smb.conf printer admin parameter.
1547 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1548 * client view printer folder, but does not show the MSAPW.
1550 * Note: this test needs code to check access rights here too. Jeremy
1551 * could you look at this?
1553 * Second case: the user is opening a printer:
1554 * NT doesn't let us connect to a printer if the connecting user
1555 * doesn't have print permission.
1557 * Third case: user is opening a Port Monitor
1558 * access checks same as opening a handle to the print server.
1561 switch (Printer->printer_type )
1564 case SPLHND_PORTMON_TCP:
1565 case SPLHND_PORTMON_LOCAL:
1566 /* Printserver handles use global struct... */
1570 /* Map standard access rights to object specific access rights */
1572 se_map_standard(&printer_default->access_required,
1573 &printserver_std_mapping);
1575 /* Deny any object specific bits that don't apply to print
1576 servers (i.e printer and job specific bits) */
1578 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1580 if (printer_default->access_required &
1581 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1582 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1583 close_printer_handle(p, handle);
1584 return WERR_ACCESS_DENIED;
1587 /* Allow admin access */
1589 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1591 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1593 if (!lp_ms_add_printer_wizard()) {
1594 close_printer_handle(p, handle);
1595 return WERR_ACCESS_DENIED;
1598 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1599 and not a printer admin, then fail */
1601 if ((p->pipe_user.ut.uid != 0) &&
1602 !user_has_privileges(p->pipe_user.nt_user_token,
1604 !token_contains_name_in_list(
1605 uidtoname(p->pipe_user.ut.uid), NULL,
1606 p->pipe_user.nt_user_token,
1607 lp_printer_admin(snum))) {
1608 close_printer_handle(p, handle);
1609 return WERR_ACCESS_DENIED;
1612 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1616 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1619 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1620 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1622 /* We fall through to return WERR_OK */
1625 case SPLHND_PRINTER:
1626 /* NT doesn't let us connect to a printer if the connecting user
1627 doesn't have print permission. */
1629 if (!get_printer_snum(p, handle, &snum)) {
1630 close_printer_handle(p, handle);
1634 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1636 /* map an empty access mask to the minimum access mask */
1637 if (printer_default->access_required == 0x0)
1638 printer_default->access_required = PRINTER_ACCESS_USE;
1641 * If we are not serving the printer driver for this printer,
1642 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1643 * will keep NT clients happy --jerry
1646 if (lp_use_client_driver(snum)
1647 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1649 printer_default->access_required = PRINTER_ACCESS_USE;
1652 /* check smb.conf parameters and the the sec_desc */
1654 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1655 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1656 return WERR_ACCESS_DENIED;
1659 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1660 p->pipe_user.nt_user_token, snum) ||
1661 !print_access_check(&p->pipe_user, snum,
1662 printer_default->access_required)) {
1663 DEBUG(3, ("access DENIED for printer open\n"));
1664 close_printer_handle(p, handle);
1665 return WERR_ACCESS_DENIED;
1668 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1669 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1670 close_printer_handle(p, handle);
1671 return WERR_ACCESS_DENIED;
1674 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1675 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1677 printer_default->access_required = PRINTER_ACCESS_USE;
1679 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1680 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1685 /* sanity check to prevent programmer error */
1689 Printer->access_granted = printer_default->access_required;
1692 * If the client sent a devmode in the OpenPrinter() call, then
1693 * save it here in case we get a job submission on this handle
1696 if ( (Printer->printer_type != SPLHND_SERVER)
1697 && q_u->printer_default.devmode_cont.devmode_ptr )
1699 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1700 &Printer->nt_devmode );
1703 #if 0 /* JERRY -- I'm doubtful this is really effective */
1704 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1705 optimization in Windows 2000 clients --jerry */
1707 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1708 && (RA_WIN2K == get_remote_arch()) )
1710 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1711 sys_usleep( 500000 );
1718 /****************************************************************************
1719 ****************************************************************************/
1721 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1722 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1728 /* allocate memory if needed. Messy because
1729 convert_printer_info is used to update an existing
1730 printer or build a new one */
1732 if ( !printer->info_2 ) {
1733 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1734 if ( !printer->info_2 ) {
1735 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1740 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1741 printer->info_2->setuptime = time(NULL);
1749 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1750 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1756 printer->info_3=NULL;
1757 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1761 printer->info_6=NULL;
1762 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1772 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1773 NT_DEVICEMODE **pp_nt_devmode)
1775 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1778 * Ensure nt_devmode is a valid pointer
1779 * as we will be overwriting it.
1782 if (nt_devmode == NULL) {
1783 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1784 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1788 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1789 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1791 nt_devmode->specversion=devmode->specversion;
1792 nt_devmode->driverversion=devmode->driverversion;
1793 nt_devmode->size=devmode->size;
1794 nt_devmode->fields=devmode->fields;
1795 nt_devmode->orientation=devmode->orientation;
1796 nt_devmode->papersize=devmode->papersize;
1797 nt_devmode->paperlength=devmode->paperlength;
1798 nt_devmode->paperwidth=devmode->paperwidth;
1799 nt_devmode->scale=devmode->scale;
1800 nt_devmode->copies=devmode->copies;
1801 nt_devmode->defaultsource=devmode->defaultsource;
1802 nt_devmode->printquality=devmode->printquality;
1803 nt_devmode->color=devmode->color;
1804 nt_devmode->duplex=devmode->duplex;
1805 nt_devmode->yresolution=devmode->yresolution;
1806 nt_devmode->ttoption=devmode->ttoption;
1807 nt_devmode->collate=devmode->collate;
1809 nt_devmode->logpixels=devmode->logpixels;
1810 nt_devmode->bitsperpel=devmode->bitsperpel;
1811 nt_devmode->pelswidth=devmode->pelswidth;
1812 nt_devmode->pelsheight=devmode->pelsheight;
1813 nt_devmode->displayflags=devmode->displayflags;
1814 nt_devmode->displayfrequency=devmode->displayfrequency;
1815 nt_devmode->icmmethod=devmode->icmmethod;
1816 nt_devmode->icmintent=devmode->icmintent;
1817 nt_devmode->mediatype=devmode->mediatype;
1818 nt_devmode->dithertype=devmode->dithertype;
1819 nt_devmode->reserved1=devmode->reserved1;
1820 nt_devmode->reserved2=devmode->reserved2;
1821 nt_devmode->panningwidth=devmode->panningwidth;
1822 nt_devmode->panningheight=devmode->panningheight;
1825 * Only change private and driverextra if the incoming devmode
1826 * has a new one. JRA.
1829 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1830 SAFE_FREE(nt_devmode->nt_dev_private);
1831 nt_devmode->driverextra=devmode->driverextra;
1832 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1834 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1837 *pp_nt_devmode = nt_devmode;
1842 /********************************************************************
1843 * _spoolss_enddocprinter_internal.
1844 ********************************************************************/
1846 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1848 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1852 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1856 if (!get_printer_snum(p, handle, &snum))
1859 Printer->document_started=False;
1860 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1861 /* error codes unhandled so far ... */
1866 /********************************************************************
1867 * api_spoolss_closeprinter
1868 ********************************************************************/
1870 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1872 POLICY_HND *handle = &q_u->handle;
1874 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1876 if (Printer && Printer->document_started)
1877 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1879 if (!close_printer_handle(p, handle))
1882 /* clear the returned printer handle. Observed behavior
1883 from Win2k server. Don't think this really matters.
1884 Previous code just copied the value of the closed
1887 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1892 /********************************************************************
1893 * api_spoolss_deleteprinter
1895 ********************************************************************/
1897 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1899 POLICY_HND *handle = &q_u->handle;
1900 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1903 if (Printer && Printer->document_started)
1904 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1906 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1908 result = delete_printer_handle(p, handle);
1910 update_c_setprinter(False);
1915 /*******************************************************************
1916 * static function to lookup the version id corresponding to an
1917 * long architecture string
1918 ******************************************************************/
1920 static int get_version_id (char * arch)
1923 struct table_node archi_table[]= {
1925 {"Windows 4.0", "WIN40", 0 },
1926 {"Windows NT x86", "W32X86", 2 },
1927 {"Windows NT R4000", "W32MIPS", 2 },
1928 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1929 {"Windows NT PowerPC", "W32PPC", 2 },
1930 {"Windows IA64", "IA64", 3 },
1931 {"Windows x64", "x64", 3 },
1935 for (i=0; archi_table[i].long_archi != NULL; i++)
1937 if (strcmp(arch, archi_table[i].long_archi) == 0)
1938 return (archi_table[i].version);
1944 /********************************************************************
1945 * _spoolss_deleteprinterdriver
1946 ********************************************************************/
1948 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1952 NT_PRINTER_DRIVER_INFO_LEVEL info;
1953 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1956 WERROR status_win2k = WERR_ACCESS_DENIED;
1957 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1959 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1960 and not a printer admin, then fail */
1962 if ( (p->pipe_user.ut.uid != 0)
1963 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
1964 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
1965 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
1967 return WERR_ACCESS_DENIED;
1970 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1971 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1973 /* check that we have a valid driver name first */
1975 if ((version=get_version_id(arch)) == -1)
1976 return WERR_INVALID_ENVIRONMENT;
1979 ZERO_STRUCT(info_win2k);
1981 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1983 /* try for Win2k driver if "Windows NT x86" */
1985 if ( version == 2 ) {
1987 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1988 status = WERR_UNKNOWN_PRINTER_DRIVER;
1992 /* otherwise it was a failure */
1994 status = WERR_UNKNOWN_PRINTER_DRIVER;
2000 if (printer_driver_in_use(info.info_3)) {
2001 status = WERR_PRINTER_DRIVER_IN_USE;
2007 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2009 /* if we get to here, we now have 2 driver info structures to remove */
2010 /* remove the Win2k driver first*/
2012 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2013 free_a_printer_driver( info_win2k, 3 );
2015 /* this should not have failed---if it did, report to client */
2016 if ( !W_ERROR_IS_OK(status_win2k) )
2018 status = status_win2k;
2024 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2026 /* if at least one of the deletes succeeded return OK */
2028 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2032 free_a_printer_driver( info, 3 );
2037 /********************************************************************
2038 * spoolss_deleteprinterdriverex
2039 ********************************************************************/
2041 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2045 NT_PRINTER_DRIVER_INFO_LEVEL info;
2046 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2048 uint32 flags = q_u->delete_flags;
2051 WERROR status_win2k = WERR_ACCESS_DENIED;
2052 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2054 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2055 and not a printer admin, then fail */
2057 if ( (p->pipe_user.ut.uid != 0)
2058 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2059 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2060 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2062 return WERR_ACCESS_DENIED;
2065 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2066 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2068 /* check that we have a valid driver name first */
2069 if ((version=get_version_id(arch)) == -1) {
2070 /* this is what NT returns */
2071 return WERR_INVALID_ENVIRONMENT;
2074 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2075 version = q_u->version;
2078 ZERO_STRUCT(info_win2k);
2080 status = get_a_printer_driver(&info, 3, driver, arch, version);
2082 if ( !W_ERROR_IS_OK(status) )
2085 * if the client asked for a specific version,
2086 * or this is something other than Windows NT x86,
2090 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2093 /* try for Win2k driver if "Windows NT x86" */
2096 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2097 status = WERR_UNKNOWN_PRINTER_DRIVER;
2102 if ( printer_driver_in_use(info.info_3) ) {
2103 status = WERR_PRINTER_DRIVER_IN_USE;
2108 * we have a couple of cases to consider.
2109 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2110 * then the delete should fail if **any** files overlap with
2112 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2113 * non-overlapping files
2114 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2115 * is set, the do not delete any files
2116 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2119 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2121 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2123 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2124 /* no idea of the correct error here */
2125 status = WERR_ACCESS_DENIED;
2130 /* also check for W32X86/3 if necessary; maybe we already have? */
2132 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2133 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2136 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2137 /* no idea of the correct error here */
2138 free_a_printer_driver( info_win2k, 3 );
2139 status = WERR_ACCESS_DENIED;
2143 /* if we get to here, we now have 2 driver info structures to remove */
2144 /* remove the Win2k driver first*/
2146 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2147 free_a_printer_driver( info_win2k, 3 );
2149 /* this should not have failed---if it did, report to client */
2151 if ( !W_ERROR_IS_OK(status_win2k) )
2156 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2158 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2161 free_a_printer_driver( info, 3 );
2167 /****************************************************************************
2168 Internal routine for retreiving printerdata
2169 ***************************************************************************/
2171 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2172 const char *key, const char *value, uint32 *type, uint8 **data,
2173 uint32 *needed, uint32 in_size )
2175 REGISTRY_VALUE *val;
2179 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2180 return WERR_BADFILE;
2182 *type = regval_type( val );
2184 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2186 size = regval_size( val );
2188 /* copy the min(in_size, len) */
2191 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2193 /* special case for 0 length values */
2195 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2199 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2208 DEBUG(5,("get_printer_dataex: copy done\n"));
2213 /****************************************************************************
2214 Internal routine for removing printerdata
2215 ***************************************************************************/
2217 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2219 return delete_printer_data( printer->info_2, key, value );
2222 /****************************************************************************
2223 Internal routine for storing printerdata
2224 ***************************************************************************/
2226 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2227 uint32 type, uint8 *data, int real_len )
2229 /* the registry objects enforce uniqueness based on value name */
2231 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2234 /********************************************************************
2235 GetPrinterData on a printer server Handle.
2236 ********************************************************************/
2238 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2242 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2244 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2246 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2252 if (!StrCaseCmp(value, "BeepEnabled")) {
2254 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2256 SIVAL(*data, 0, 0x00);
2261 if (!StrCaseCmp(value, "EventLog")) {
2263 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2265 /* formally was 0x1b */
2266 SIVAL(*data, 0, 0x0);
2271 if (!StrCaseCmp(value, "NetPopup")) {
2273 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2275 SIVAL(*data, 0, 0x00);
2280 if (!StrCaseCmp(value, "MajorVersion")) {
2282 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2285 /* Windows NT 4.0 seems to not allow uploading of drivers
2286 to a server that reports 0x3 as the MajorVersion.
2287 need to investigate more how Win2k gets around this .
2290 if ( RA_WINNT == get_remote_arch() )
2299 if (!StrCaseCmp(value, "MinorVersion")) {
2301 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2309 * uint32 size = 0x114
2311 * uint32 minor = [0|1]
2312 * uint32 build = [2195|2600]
2313 * extra unicode string = e.g. "Service Pack 3"
2315 if (!StrCaseCmp(value, "OSVersion")) {
2319 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2322 SIVAL(*data, 0, *needed); /* size */
2323 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2325 SIVAL(*data, 12, 2195); /* build */
2327 /* leave extra string empty */
2333 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2334 const char *string="C:\\PRINTERS";
2336 *needed = 2*(strlen(string)+1);
2337 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2339 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2341 /* it's done by hand ready to go on the wire */
2342 for (i=0; i<strlen(string); i++) {
2343 (*data)[2*i]=string[i];
2344 (*data)[2*i+1]='\0';
2349 if (!StrCaseCmp(value, "Architecture")) {
2350 const char *string="Windows NT x86";
2352 *needed = 2*(strlen(string)+1);
2353 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2355 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2356 for (i=0; i<strlen(string); i++) {
2357 (*data)[2*i]=string[i];
2358 (*data)[2*i+1]='\0';
2363 if (!StrCaseCmp(value, "DsPresent")) {
2365 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2368 /* only show the publish check box if we are a
2369 memeber of a AD domain */
2371 if ( lp_security() == SEC_ADS )
2372 SIVAL(*data, 0, 0x01);
2374 SIVAL(*data, 0, 0x00);
2380 if (!StrCaseCmp(value, "DNSMachineName")) {
2383 if (!get_mydnsfullname(hostname))
2384 return WERR_BADFILE;
2386 *needed = 2*(strlen(hostname)+1);
2387 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2389 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2390 for (i=0; i<strlen(hostname); i++) {
2391 (*data)[2*i]=hostname[i];
2392 (*data)[2*i+1]='\0';
2398 return WERR_BADFILE;
2401 /********************************************************************
2402 * spoolss_getprinterdata
2403 ********************************************************************/
2405 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2407 POLICY_HND *handle = &q_u->handle;
2408 UNISTR2 *valuename = &q_u->valuename;
2409 uint32 in_size = q_u->size;
2410 uint32 *type = &r_u->type;
2411 uint32 *out_size = &r_u->size;
2412 uint8 **data = &r_u->data;
2413 uint32 *needed = &r_u->needed;
2416 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2417 NT_PRINTER_INFO_LEVEL *printer = NULL;
2421 * Reminder: when it's a string, the length is in BYTES
2422 * even if UNICODE is negociated.
2427 *out_size = in_size;
2429 /* in case of problem, return some default values */
2434 DEBUG(4,("_spoolss_getprinterdata\n"));
2437 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2438 status = WERR_BADFID;
2442 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2444 if ( Printer->printer_type == SPLHND_SERVER )
2445 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2448 if ( !get_printer_snum(p,handle, &snum) ) {
2449 status = WERR_BADFID;
2453 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2454 if ( !W_ERROR_IS_OK(status) )
2457 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2459 if ( strequal(value, "ChangeId") ) {
2461 *needed = sizeof(uint32);
2462 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2463 status = WERR_NOMEM;
2466 SIVAL( *data, 0, printer->info_2->changeid );
2470 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2473 if (*needed > *out_size)
2474 status = WERR_MORE_DATA;
2477 if ( !W_ERROR_IS_OK(status) )
2479 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2481 /* reply this param doesn't exist */
2484 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2486 free_a_printer( &printer, 2 );
2495 /* cleanup & exit */
2498 free_a_printer( &printer, 2 );
2503 /*********************************************************
2504 Connect to the client machine.
2505 **********************************************************/
2507 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2508 struct in_addr *client_ip, const char *remote_machine)
2511 struct cli_state *the_cli;
2512 struct in_addr rm_addr;
2514 if ( is_zero_ip(*client_ip) ) {
2515 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2516 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2520 if ( ismyip( rm_addr )) {
2521 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2525 rm_addr.s_addr = client_ip->s_addr;
2526 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2527 inet_ntoa(*client_ip) ));
2530 /* setup the connection */
2532 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2533 &rm_addr, 0, "IPC$", "IPC",
2537 0, lp_client_signing(), NULL );
2539 if ( !NT_STATUS_IS_OK( ret ) ) {
2540 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2545 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2546 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2547 cli_shutdown(the_cli);
2552 * Ok - we have an anonymous connection to the IPC$ share.
2553 * Now start the NT Domain stuff :-).
2556 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2557 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2558 remote_machine, nt_errstr(ret)));
2559 cli_shutdown(the_cli);
2563 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2565 (*pp_pipe)->cli = the_cli;
2570 /***************************************************************************
2571 Connect to the client.
2572 ****************************************************************************/
2574 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2575 uint32 localprinter, uint32 type,
2576 POLICY_HND *handle, struct in_addr *client_ip)
2581 * If it's the first connection, contact the client
2582 * and connect to the IPC$ share anonymously
2584 if (smb_connections==0) {
2585 fstring unix_printer;
2587 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2589 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2592 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2593 /* Tell the connections db we're now interested in printer
2594 * notify messages. */
2595 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2599 * Tell the specific printing tdb we want messages for this printer
2600 * by registering our PID.
2603 if (!print_notify_register_pid(snum))
2604 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2608 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2611 if (!W_ERROR_IS_OK(result))
2612 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2613 dos_errstr(result)));
2615 return (W_ERROR_IS_OK(result));
2618 /********************************************************************
2620 * ReplyFindFirstPrinterChangeNotifyEx
2622 * before replying OK: status=0 a rpc call is made to the workstation
2623 * asking ReplyOpenPrinter
2625 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2626 * called from api_spoolss_rffpcnex
2627 ********************************************************************/
2629 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2631 POLICY_HND *handle = &q_u->handle;
2632 uint32 flags = q_u->flags;
2633 uint32 options = q_u->options;
2634 UNISTR2 *localmachine = &q_u->localmachine;
2635 uint32 printerlocal = q_u->printerlocal;
2637 SPOOL_NOTIFY_OPTION *option = q_u->option;
2638 struct in_addr client_ip;
2640 /* store the notify value in the printer struct */
2642 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2645 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2649 Printer->notify.flags=flags;
2650 Printer->notify.options=options;
2651 Printer->notify.printerlocal=printerlocal;
2653 if (Printer->notify.option)
2654 free_spool_notify_option(&Printer->notify.option);
2656 Printer->notify.option=dup_spool_notify_option(option);
2658 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2659 sizeof(Printer->notify.localmachine)-1);
2661 /* Connect to the client machine and send a ReplyOpenPrinter */
2663 if ( Printer->printer_type == SPLHND_SERVER)
2665 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2666 !get_printer_snum(p, handle, &snum) )
2669 client_ip.s_addr = inet_addr(p->conn->client_address);
2671 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2672 Printer->notify.printerlocal, 1,
2673 &Printer->notify.client_hnd, &client_ip))
2674 return WERR_SERVER_UNAVAILABLE;
2676 Printer->notify.client_connected=True;
2681 /*******************************************************************
2682 * fill a notify_info_data with the servername
2683 ********************************************************************/
2685 void spoolss_notify_server_name(int snum,
2686 SPOOL_NOTIFY_INFO_DATA *data,
2687 print_queue_struct *queue,
2688 NT_PRINTER_INFO_LEVEL *printer,
2689 TALLOC_CTX *mem_ctx)
2694 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2696 data->notify_data.data.length = len;
2697 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2699 if (!data->notify_data.data.string) {
2700 data->notify_data.data.length = 0;
2704 memcpy(data->notify_data.data.string, temp, len);
2707 /*******************************************************************
2708 * fill a notify_info_data with the printername (not including the servername).
2709 ********************************************************************/
2711 void spoolss_notify_printer_name(int snum,
2712 SPOOL_NOTIFY_INFO_DATA *data,
2713 print_queue_struct *queue,
2714 NT_PRINTER_INFO_LEVEL *printer,
2715 TALLOC_CTX *mem_ctx)
2720 /* the notify name should not contain the \\server\ part */
2721 char *p = strrchr(printer->info_2->printername, '\\');
2724 p = printer->info_2->printername;
2729 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2731 data->notify_data.data.length = len;
2732 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2734 if (!data->notify_data.data.string) {
2735 data->notify_data.data.length = 0;
2739 memcpy(data->notify_data.data.string, temp, len);
2742 /*******************************************************************
2743 * fill a notify_info_data with the servicename
2744 ********************************************************************/
2746 void spoolss_notify_share_name(int snum,
2747 SPOOL_NOTIFY_INFO_DATA *data,
2748 print_queue_struct *queue,
2749 NT_PRINTER_INFO_LEVEL *printer,
2750 TALLOC_CTX *mem_ctx)
2755 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2757 data->notify_data.data.length = len;
2758 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2760 if (!data->notify_data.data.string) {
2761 data->notify_data.data.length = 0;
2765 memcpy(data->notify_data.data.string, temp, len);
2768 /*******************************************************************
2769 * fill a notify_info_data with the port name
2770 ********************************************************************/
2772 void spoolss_notify_port_name(int snum,
2773 SPOOL_NOTIFY_INFO_DATA *data,
2774 print_queue_struct *queue,
2775 NT_PRINTER_INFO_LEVEL *printer,
2776 TALLOC_CTX *mem_ctx)
2781 /* even if it's strange, that's consistant in all the code */
2783 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2785 data->notify_data.data.length = len;
2786 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2788 if (!data->notify_data.data.string) {
2789 data->notify_data.data.length = 0;
2793 memcpy(data->notify_data.data.string, temp, len);
2796 /*******************************************************************
2797 * fill a notify_info_data with the printername
2798 * but it doesn't exist, have to see what to do
2799 ********************************************************************/
2801 void spoolss_notify_driver_name(int snum,
2802 SPOOL_NOTIFY_INFO_DATA *data,
2803 print_queue_struct *queue,
2804 NT_PRINTER_INFO_LEVEL *printer,
2805 TALLOC_CTX *mem_ctx)
2810 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2812 data->notify_data.data.length = len;
2813 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2815 if (!data->notify_data.data.string) {
2816 data->notify_data.data.length = 0;
2820 memcpy(data->notify_data.data.string, temp, len);
2823 /*******************************************************************
2824 * fill a notify_info_data with the comment
2825 ********************************************************************/
2827 void spoolss_notify_comment(int snum,
2828 SPOOL_NOTIFY_INFO_DATA *data,
2829 print_queue_struct *queue,
2830 NT_PRINTER_INFO_LEVEL *printer,
2831 TALLOC_CTX *mem_ctx)
2836 if (*printer->info_2->comment == '\0')
2837 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2839 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2841 data->notify_data.data.length = len;
2842 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2844 if (!data->notify_data.data.string) {
2845 data->notify_data.data.length = 0;
2849 memcpy(data->notify_data.data.string, temp, len);
2852 /*******************************************************************
2853 * fill a notify_info_data with the comment
2854 * location = "Room 1, floor 2, building 3"
2855 ********************************************************************/
2857 void spoolss_notify_location(int snum,
2858 SPOOL_NOTIFY_INFO_DATA *data,
2859 print_queue_struct *queue,
2860 NT_PRINTER_INFO_LEVEL *printer,
2861 TALLOC_CTX *mem_ctx)
2866 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2868 data->notify_data.data.length = len;
2869 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2871 if (!data->notify_data.data.string) {
2872 data->notify_data.data.length = 0;
2876 memcpy(data->notify_data.data.string, temp, len);
2879 /*******************************************************************
2880 * fill a notify_info_data with the device mode
2881 * jfm:xxxx don't to it for know but that's a real problem !!!
2882 ********************************************************************/
2884 static void spoolss_notify_devmode(int snum,
2885 SPOOL_NOTIFY_INFO_DATA *data,
2886 print_queue_struct *queue,
2887 NT_PRINTER_INFO_LEVEL *printer,
2888 TALLOC_CTX *mem_ctx)
2892 /*******************************************************************
2893 * fill a notify_info_data with the separator file name
2894 ********************************************************************/
2896 void spoolss_notify_sepfile(int snum,
2897 SPOOL_NOTIFY_INFO_DATA *data,
2898 print_queue_struct *queue,
2899 NT_PRINTER_INFO_LEVEL *printer,
2900 TALLOC_CTX *mem_ctx)
2905 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2907 data->notify_data.data.length = len;
2908 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2910 if (!data->notify_data.data.string) {
2911 data->notify_data.data.length = 0;
2915 memcpy(data->notify_data.data.string, temp, len);
2918 /*******************************************************************
2919 * fill a notify_info_data with the print processor
2920 * jfm:xxxx return always winprint to indicate we don't do anything to it
2921 ********************************************************************/
2923 void spoolss_notify_print_processor(int snum,
2924 SPOOL_NOTIFY_INFO_DATA *data,
2925 print_queue_struct *queue,
2926 NT_PRINTER_INFO_LEVEL *printer,
2927 TALLOC_CTX *mem_ctx)
2932 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2934 data->notify_data.data.length = len;
2935 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2937 if (!data->notify_data.data.string) {
2938 data->notify_data.data.length = 0;
2942 memcpy(data->notify_data.data.string, temp, len);
2945 /*******************************************************************
2946 * fill a notify_info_data with the print processor options
2947 * jfm:xxxx send an empty string
2948 ********************************************************************/
2950 void spoolss_notify_parameters(int snum,
2951 SPOOL_NOTIFY_INFO_DATA *data,
2952 print_queue_struct *queue,
2953 NT_PRINTER_INFO_LEVEL *printer,
2954 TALLOC_CTX *mem_ctx)
2959 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2961 data->notify_data.data.length = len;
2962 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2964 if (!data->notify_data.data.string) {
2965 data->notify_data.data.length = 0;
2969 memcpy(data->notify_data.data.string, temp, len);
2972 /*******************************************************************
2973 * fill a notify_info_data with the data type
2974 * jfm:xxxx always send RAW as data type
2975 ********************************************************************/
2977 void spoolss_notify_datatype(int snum,
2978 SPOOL_NOTIFY_INFO_DATA *data,
2979 print_queue_struct *queue,
2980 NT_PRINTER_INFO_LEVEL *printer,
2981 TALLOC_CTX *mem_ctx)
2986 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2988 data->notify_data.data.length = len;
2989 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2991 if (!data->notify_data.data.string) {
2992 data->notify_data.data.length = 0;
2996 memcpy(data->notify_data.data.string, temp, len);
2999 /*******************************************************************
3000 * fill a notify_info_data with the security descriptor
3001 * jfm:xxxx send an null pointer to say no security desc
3002 * have to implement security before !
3003 ********************************************************************/
3005 static void spoolss_notify_security_desc(int snum,
3006 SPOOL_NOTIFY_INFO_DATA *data,
3007 print_queue_struct *queue,
3008 NT_PRINTER_INFO_LEVEL *printer,
3009 TALLOC_CTX *mem_ctx)
3011 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3012 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3015 /*******************************************************************
3016 * fill a notify_info_data with the attributes
3017 * jfm:xxxx a samba printer is always shared
3018 ********************************************************************/
3020 void spoolss_notify_attributes(int snum,
3021 SPOOL_NOTIFY_INFO_DATA *data,
3022 print_queue_struct *queue,
3023 NT_PRINTER_INFO_LEVEL *printer,
3024 TALLOC_CTX *mem_ctx)
3026 data->notify_data.value[0] = printer->info_2->attributes;
3027 data->notify_data.value[1] = 0;
3030 /*******************************************************************
3031 * fill a notify_info_data with the priority
3032 ********************************************************************/
3034 static void spoolss_notify_priority(int snum,
3035 SPOOL_NOTIFY_INFO_DATA *data,
3036 print_queue_struct *queue,
3037 NT_PRINTER_INFO_LEVEL *printer,
3038 TALLOC_CTX *mem_ctx)
3040 data->notify_data.value[0] = printer->info_2->priority;
3041 data->notify_data.value[1] = 0;
3044 /*******************************************************************
3045 * fill a notify_info_data with the default priority
3046 ********************************************************************/
3048 static void spoolss_notify_default_priority(int snum,
3049 SPOOL_NOTIFY_INFO_DATA *data,
3050 print_queue_struct *queue,
3051 NT_PRINTER_INFO_LEVEL *printer,
3052 TALLOC_CTX *mem_ctx)
3054 data->notify_data.value[0] = printer->info_2->default_priority;
3055 data->notify_data.value[1] = 0;
3058 /*******************************************************************
3059 * fill a notify_info_data with the start time
3060 ********************************************************************/
3062 static void spoolss_notify_start_time(int snum,
3063 SPOOL_NOTIFY_INFO_DATA *data,
3064 print_queue_struct *queue,
3065 NT_PRINTER_INFO_LEVEL *printer,
3066 TALLOC_CTX *mem_ctx)
3068 data->notify_data.value[0] = printer->info_2->starttime;
3069 data->notify_data.value[1] = 0;
3072 /*******************************************************************
3073 * fill a notify_info_data with the until time
3074 ********************************************************************/
3076 static void spoolss_notify_until_time(int snum,
3077 SPOOL_NOTIFY_INFO_DATA *data,
3078 print_queue_struct *queue,
3079 NT_PRINTER_INFO_LEVEL *printer,
3080 TALLOC_CTX *mem_ctx)
3082 data->notify_data.value[0] = printer->info_2->untiltime;
3083 data->notify_data.value[1] = 0;
3086 /*******************************************************************
3087 * fill a notify_info_data with the status
3088 ********************************************************************/
3090 static void spoolss_notify_status(int snum,
3091 SPOOL_NOTIFY_INFO_DATA *data,
3092 print_queue_struct *queue,
3093 NT_PRINTER_INFO_LEVEL *printer,
3094 TALLOC_CTX *mem_ctx)
3096 print_status_struct status;
3098 print_queue_length(snum, &status);
3099 data->notify_data.value[0]=(uint32) status.status;
3100 data->notify_data.value[1] = 0;
3103 /*******************************************************************
3104 * fill a notify_info_data with the number of jobs queued
3105 ********************************************************************/
3107 void spoolss_notify_cjobs(int snum,
3108 SPOOL_NOTIFY_INFO_DATA *data,
3109 print_queue_struct *queue,
3110 NT_PRINTER_INFO_LEVEL *printer,
3111 TALLOC_CTX *mem_ctx)
3113 data->notify_data.value[0] = print_queue_length(snum, NULL);
3114 data->notify_data.value[1] = 0;
3117 /*******************************************************************
3118 * fill a notify_info_data with the average ppm
3119 ********************************************************************/
3121 static void spoolss_notify_average_ppm(int snum,
3122 SPOOL_NOTIFY_INFO_DATA *data,
3123 print_queue_struct *queue,
3124 NT_PRINTER_INFO_LEVEL *printer,
3125 TALLOC_CTX *mem_ctx)
3127 /* always respond 8 pages per minutes */
3128 /* a little hard ! */
3129 data->notify_data.value[0] = printer->info_2->averageppm;
3130 data->notify_data.value[1] = 0;
3133 /*******************************************************************
3134 * fill a notify_info_data with username
3135 ********************************************************************/
3137 static void spoolss_notify_username(int snum,
3138 SPOOL_NOTIFY_INFO_DATA *data,
3139 print_queue_struct *queue,
3140 NT_PRINTER_INFO_LEVEL *printer,
3141 TALLOC_CTX *mem_ctx)
3146 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3148 data->notify_data.data.length = len;
3149 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3151 if (!data->notify_data.data.string) {
3152 data->notify_data.data.length = 0;
3156 memcpy(data->notify_data.data.string, temp, len);
3159 /*******************************************************************
3160 * fill a notify_info_data with job status
3161 ********************************************************************/
3163 static void spoolss_notify_job_status(int snum,
3164 SPOOL_NOTIFY_INFO_DATA *data,
3165 print_queue_struct *queue,
3166 NT_PRINTER_INFO_LEVEL *printer,
3167 TALLOC_CTX *mem_ctx)
3169 data->notify_data.value[0]=nt_printj_status(queue->status);
3170 data->notify_data.value[1] = 0;
3173 /*******************************************************************
3174 * fill a notify_info_data with job name
3175 ********************************************************************/
3177 static void spoolss_notify_job_name(int snum,
3178 SPOOL_NOTIFY_INFO_DATA *data,
3179 print_queue_struct *queue,
3180 NT_PRINTER_INFO_LEVEL *printer,
3181 TALLOC_CTX *mem_ctx)
3186 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3188 data->notify_data.data.length = len;
3189 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3191 if (!data->notify_data.data.string) {
3192 data->notify_data.data.length = 0;
3196 memcpy(data->notify_data.data.string, temp, len);
3199 /*******************************************************************
3200 * fill a notify_info_data with job status
3201 ********************************************************************/
3203 static void spoolss_notify_job_status_string(int snum,
3204 SPOOL_NOTIFY_INFO_DATA *data,
3205 print_queue_struct *queue,
3206 NT_PRINTER_INFO_LEVEL *printer,
3207 TALLOC_CTX *mem_ctx)
3210 * Now we're returning job status codes we just return a "" here. JRA.
3217 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3220 switch (queue->status) {
3225 p = ""; /* NT provides the paused string */
3234 #endif /* NO LONGER NEEDED. */
3236 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3238 data->notify_data.data.length = len;
3239 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3241 if (!data->notify_data.data.string) {
3242 data->notify_data.data.length = 0;
3246 memcpy(data->notify_data.data.string, temp, len);
3249 /*******************************************************************
3250 * fill a notify_info_data with job time
3251 ********************************************************************/
3253 static void spoolss_notify_job_time(int snum,
3254 SPOOL_NOTIFY_INFO_DATA *data,
3255 print_queue_struct *queue,
3256 NT_PRINTER_INFO_LEVEL *printer,
3257 TALLOC_CTX *mem_ctx)
3259 data->notify_data.value[0]=0x0;
3260 data->notify_data.value[1]=0;
3263 /*******************************************************************
3264 * fill a notify_info_data with job size
3265 ********************************************************************/
3267 static void spoolss_notify_job_size(int snum,
3268 SPOOL_NOTIFY_INFO_DATA *data,
3269 print_queue_struct *queue,
3270 NT_PRINTER_INFO_LEVEL *printer,
3271 TALLOC_CTX *mem_ctx)
3273 data->notify_data.value[0]=queue->size;
3274 data->notify_data.value[1]=0;
3277 /*******************************************************************
3278 * fill a notify_info_data with page info
3279 ********************************************************************/
3280 static void spoolss_notify_total_pages(int snum,
3281 SPOOL_NOTIFY_INFO_DATA *data,
3282 print_queue_struct *queue,
3283 NT_PRINTER_INFO_LEVEL *printer,
3284 TALLOC_CTX *mem_ctx)
3286 data->notify_data.value[0]=queue->page_count;
3287 data->notify_data.value[1]=0;
3290 /*******************************************************************
3291 * fill a notify_info_data with pages printed info.
3292 ********************************************************************/
3293 static void spoolss_notify_pages_printed(int snum,
3294 SPOOL_NOTIFY_INFO_DATA *data,
3295 print_queue_struct *queue,
3296 NT_PRINTER_INFO_LEVEL *printer,
3297 TALLOC_CTX *mem_ctx)
3299 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3300 data->notify_data.value[1]=0;
3303 /*******************************************************************
3304 Fill a notify_info_data with job position.
3305 ********************************************************************/
3307 static void spoolss_notify_job_position(int snum,
3308 SPOOL_NOTIFY_INFO_DATA *data,
3309 print_queue_struct *queue,
3310 NT_PRINTER_INFO_LEVEL *printer,
3311 TALLOC_CTX *mem_ctx)
3313 data->notify_data.value[0]=queue->job;
3314 data->notify_data.value[1]=0;
3317 /*******************************************************************
3318 Fill a notify_info_data with submitted time.
3319 ********************************************************************/
3321 static void spoolss_notify_submitted_time(int snum,
3322 SPOOL_NOTIFY_INFO_DATA *data,
3323 print_queue_struct *queue,
3324 NT_PRINTER_INFO_LEVEL *printer,
3325 TALLOC_CTX *mem_ctx)
3332 t=gmtime(&queue->time);
3334 len = sizeof(SYSTEMTIME);
3336 data->notify_data.data.length = len;
3337 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3339 if (!data->notify_data.data.string) {
3340 data->notify_data.data.length = 0;
3344 make_systemtime(&st, t);
3347 * Systemtime must be linearized as a set of UINT16's.
3348 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3351 p = (char *)data->notify_data.data.string;
3352 SSVAL(p, 0, st.year);
3353 SSVAL(p, 2, st.month);
3354 SSVAL(p, 4, st.dayofweek);
3355 SSVAL(p, 6, st.day);
3356 SSVAL(p, 8, st.hour);
3357 SSVAL(p, 10, st.minute);
3358 SSVAL(p, 12, st.second);
3359 SSVAL(p, 14, st.milliseconds);
3362 struct s_notify_info_data_table
3368 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3369 print_queue_struct *queue,
3370 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3373 /* A table describing the various print notification constants and
3374 whether the notification data is a pointer to a variable sized
3375 buffer, a one value uint32 or a two value uint32. */
3377 static const struct s_notify_info_data_table notify_info_data_table[] =
3379 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3380 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3381 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3382 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3383 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3384 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3385 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3386 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3387 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3388 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3389 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3405 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3406 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3407 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3408 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3409 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3410 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3411 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3412 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3413 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3414 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3415 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3428 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3431 /*******************************************************************
3432 Return the size of info_data structure.
3433 ********************************************************************/
3435 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3439 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3440 if ( (notify_info_data_table[i].type == type)
3441 && (notify_info_data_table[i].field == field) ) {
3442 switch(notify_info_data_table[i].size) {
3443 case NOTIFY_ONE_VALUE:
3444 case NOTIFY_TWO_VALUE:
3449 /* The only pointer notify data I have seen on
3450 the wire is the submitted time and this has
3451 the notify size set to 4. -tpot */
3453 case NOTIFY_POINTER:
3456 case NOTIFY_SECDESC:
3462 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3467 /*******************************************************************
3468 Return the type of notify_info_data.
3469 ********************************************************************/
3471 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3475 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3476 if (notify_info_data_table[i].type == type &&
3477 notify_info_data_table[i].field == field)
3478 return notify_info_data_table[i].size;
3484 /****************************************************************************
3485 ****************************************************************************/
3487 static BOOL search_notify(uint16 type, uint16 field, int *value)
3491 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3492 if (notify_info_data_table[i].type == type &&
3493 notify_info_data_table[i].field == field &&
3494 notify_info_data_table[i].fn != NULL) {
3503 /****************************************************************************
3504 ****************************************************************************/
3506 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3508 info_data->type = type;
3509 info_data->field = field;
3510 info_data->reserved = 0;
3512 info_data->size = size_of_notify_info_data(type, field);
3513 info_data->enc_type = type_of_notify_info_data(type, field);
3518 /*******************************************************************
3520 * fill a notify_info struct with info asked
3522 ********************************************************************/
3524 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3525 snum, SPOOL_NOTIFY_OPTION_TYPE
3526 *option_type, uint32 id,
3527 TALLOC_CTX *mem_ctx)
3533 SPOOL_NOTIFY_INFO_DATA *current_data;
3534 NT_PRINTER_INFO_LEVEL *printer = NULL;
3535 print_queue_struct *queue=NULL;
3537 type=option_type->type;
3539 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3540 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3541 option_type->count, lp_servicename(snum)));
3543 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3546 for(field_num=0; field_num<option_type->count; field_num++) {
3547 field = option_type->fields[field_num];
3549 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3551 if (!search_notify(type, field, &j) )
3554 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3555 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3556 free_a_printer(&printer, 2);
3560 current_data = &info->data[info->count];
3562 construct_info_data(current_data, type, field, id);
3564 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3565 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3567 notify_info_data_table[j].fn(snum, current_data, queue,
3573 free_a_printer(&printer, 2);
3577 /*******************************************************************
3579 * fill a notify_info struct with info asked
3581 ********************************************************************/
3583 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3584 SPOOL_NOTIFY_INFO *info,
3585 NT_PRINTER_INFO_LEVEL *printer,
3586 int snum, SPOOL_NOTIFY_OPTION_TYPE
3587 *option_type, uint32 id,
3588 TALLOC_CTX *mem_ctx)
3594 SPOOL_NOTIFY_INFO_DATA *current_data;
3596 DEBUG(4,("construct_notify_jobs_info\n"));
3598 type = option_type->type;
3600 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3601 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3602 option_type->count));
3604 for(field_num=0; field_num<option_type->count; field_num++) {
3605 field = option_type->fields[field_num];
3607 if (!search_notify(type, field, &j) )
3610 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3611 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3615 current_data=&(info->data[info->count]);
3617 construct_info_data(current_data, type, field, id);
3618 notify_info_data_table[j].fn(snum, current_data, queue,
3627 * JFM: The enumeration is not that simple, it's even non obvious.
3629 * let's take an example: I want to monitor the PRINTER SERVER for
3630 * the printer's name and the number of jobs currently queued.
3631 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3632 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3634 * I have 3 printers on the back of my server.
3636 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3639 * 1 printer 1 name 1
3640 * 2 printer 1 cjob 1
3641 * 3 printer 2 name 2
3642 * 4 printer 2 cjob 2
3643 * 5 printer 3 name 3
3644 * 6 printer 3 name 3
3646 * that's the print server case, the printer case is even worse.
3649 /*******************************************************************
3651 * enumerate all printers on the printserver
3652 * fill a notify_info struct with info asked
3654 ********************************************************************/
3656 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3657 SPOOL_NOTIFY_INFO *info,
3658 TALLOC_CTX *mem_ctx)
3661 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3662 int n_services=lp_numservices();
3664 SPOOL_NOTIFY_OPTION *option;
3665 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3667 DEBUG(4,("printserver_notify_info\n"));
3672 option=Printer->notify.option;
3677 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3678 sending a ffpcn() request first */
3683 for (i=0; i<option->count; i++) {
3684 option_type=&(option->ctr.type[i]);
3686 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3689 for (snum=0; snum<n_services; snum++)
3691 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3692 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3698 * Debugging information, don't delete.
3701 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3702 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3703 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3705 for (i=0; i<info->count; i++) {
3706 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3707 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3708 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3715 /*******************************************************************
3717 * fill a notify_info struct with info asked
3719 ********************************************************************/
3721 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3722 TALLOC_CTX *mem_ctx)
3725 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3728 SPOOL_NOTIFY_OPTION *option;
3729 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3731 print_queue_struct *queue=NULL;
3732 print_status_struct status;
3734 DEBUG(4,("printer_notify_info\n"));
3739 option=Printer->notify.option;
3745 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3746 sending a ffpcn() request first */
3751 get_printer_snum(p, hnd, &snum);
3753 for (i=0; i<option->count; i++) {
3754 option_type=&option->ctr.type[i];
3756 switch ( option_type->type ) {
3757 case PRINTER_NOTIFY_TYPE:
3758 if(construct_notify_printer_info(Printer, info, snum,
3764 case JOB_NOTIFY_TYPE: {
3765 NT_PRINTER_INFO_LEVEL *printer = NULL;
3767 count = print_queue_status(snum, &queue, &status);
3769 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3772 for (j=0; j<count; j++) {
3773 construct_notify_jobs_info(&queue[j], info,
3780 free_a_printer(&printer, 2);
3790 * Debugging information, don't delete.
3793 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3794 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3795 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3797 for (i=0; i<info->count; i++) {
3798 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3799 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3800 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3806 /********************************************************************
3808 ********************************************************************/
3810 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3812 POLICY_HND *handle = &q_u->handle;
3813 SPOOL_NOTIFY_INFO *info = &r_u->info;
3815 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3816 WERROR result = WERR_BADFID;
3818 /* we always have a NOTIFY_INFO struct */
3822 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3823 OUR_HANDLE(handle)));
3827 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3830 * We are now using the change value, and
3831 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3832 * I don't have a global notification system, I'm sending back all the
3833 * informations even when _NOTHING_ has changed.
3836 /* We need to keep track of the change value to send back in
3837 RRPCN replies otherwise our updates are ignored. */
3839 Printer->notify.fnpcn = True;
3841 if (Printer->notify.client_connected) {
3842 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3843 Printer->notify.change = q_u->change;
3846 /* just ignore the SPOOL_NOTIFY_OPTION */
3848 switch (Printer->printer_type) {
3850 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3853 case SPLHND_PRINTER:
3854 result = printer_notify_info(p, handle, info, p->mem_ctx);
3858 Printer->notify.fnpcn = False;
3864 /********************************************************************
3865 * construct_printer_info_0
3866 * fill a printer_info_0 struct
3867 ********************************************************************/
3869 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3873 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3874 counter_printer_0 *session_counter;
3875 uint32 global_counter;
3878 print_status_struct status;
3880 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3883 count = print_queue_length(snum, &status);
3885 /* check if we already have a counter for this printer */
3886 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3887 if (session_counter->snum == snum)
3891 /* it's the first time, add it to the list */
3892 if (session_counter==NULL) {
3893 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3894 free_a_printer(&ntprinter, 2);
3897 ZERO_STRUCTP(session_counter);
3898 session_counter->snum=snum;
3899 session_counter->counter=0;
3900 DLIST_ADD(counter_list, session_counter);
3904 session_counter->counter++;
3907 * the global_counter should be stored in a TDB as it's common to all the clients
3908 * and should be zeroed on samba startup
3910 global_counter=session_counter->counter;
3912 pstrcpy(chaine,ntprinter->info_2->printername);
3914 init_unistr(&printer->printername, chaine);
3916 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3917 init_unistr(&printer->servername, chaine);
3919 printer->cjobs = count;
3920 printer->total_jobs = 0;
3921 printer->total_bytes = 0;
3923 setuptime = (time_t)ntprinter->info_2->setuptime;
3924 t=gmtime(&setuptime);
3926 printer->year = t->tm_year+1900;
3927 printer->month = t->tm_mon+1;
3928 printer->dayofweek = t->tm_wday;
3929 printer->day = t->tm_mday;
3930 printer->hour = t->tm_hour;
3931 printer->minute = t->tm_min;
3932 printer->second = t->tm_sec;
3933 printer->milliseconds = 0;
3935 printer->global_counter = global_counter;
3936 printer->total_pages = 0;
3938 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3939 printer->major_version = 0x0005; /* NT 5 */
3940 printer->build_version = 0x0893; /* build 2195 */
3942 printer->unknown7 = 0x1;
3943 printer->unknown8 = 0x0;
3944 printer->unknown9 = 0x0;
3945 printer->session_counter = session_counter->counter;
3946 printer->unknown11 = 0x0;
3947 printer->printer_errors = 0x0; /* number of print failure */
3948 printer->unknown13 = 0x0;
3949 printer->unknown14 = 0x1;
3950 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3951 printer->unknown16 = 0x0;
3952 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3953 printer->unknown18 = 0x0;
3954 printer->status = nt_printq_status(status.status);
3955 printer->unknown20 = 0x0;
3956 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3957 printer->unknown22 = 0x0;
3958 printer->unknown23 = 0x6; /* 6 ???*/
3959 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3960 printer->unknown25 = 0;
3961 printer->unknown26 = 0;
3962 printer->unknown27 = 0;
3963 printer->unknown28 = 0;
3964 printer->unknown29 = 0;
3966 free_a_printer(&ntprinter,2);
3970 /********************************************************************
3971 * construct_printer_info_1
3972 * fill a printer_info_1 struct
3973 ********************************************************************/
3974 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3978 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3980 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3983 printer->flags=flags;
3985 if (*ntprinter->info_2->comment == '\0') {
3986 init_unistr(&printer->comment, lp_comment(snum));
3987 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3988 ntprinter->info_2->drivername, lp_comment(snum));
3991 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3992 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3993 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3996 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3998 init_unistr(&printer->description, chaine);
3999 init_unistr(&printer->name, chaine2);
4001 free_a_printer(&ntprinter,2);
4006 /****************************************************************************
4007 Free a DEVMODE struct.
4008 ****************************************************************************/
4010 static void free_dev_mode(DEVICEMODE *dev)
4015 SAFE_FREE(dev->dev_private);
4020 /****************************************************************************
4021 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4022 should be valid upon entry
4023 ****************************************************************************/
4025 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4027 if ( !devmode || !ntdevmode )
4030 init_unistr(&devmode->devicename, ntdevmode->devicename);
4032 init_unistr(&devmode->formname, ntdevmode->formname);
4034 devmode->specversion = ntdevmode->specversion;
4035 devmode->driverversion = ntdevmode->driverversion;
4036 devmode->size = ntdevmode->size;
4037 devmode->driverextra = ntdevmode->driverextra;
4038 devmode->fields = ntdevmode->fields;
4040 devmode->orientation = ntdevmode->orientation;
4041 devmode->papersize = ntdevmode->papersize;
4042 devmode->paperlength = ntdevmode->paperlength;
4043 devmode->paperwidth = ntdevmode->paperwidth;
4044 devmode->scale = ntdevmode->scale;
4045 devmode->copies = ntdevmode->copies;
4046 devmode->defaultsource = ntdevmode->defaultsource;
4047 devmode->printquality = ntdevmode->printquality;
4048 devmode->color = ntdevmode->color;
4049 devmode->duplex = ntdevmode->duplex;
4050 devmode->yresolution = ntdevmode->yresolution;
4051 devmode->ttoption = ntdevmode->ttoption;
4052 devmode->collate = ntdevmode->collate;
4053 devmode->icmmethod = ntdevmode->icmmethod;
4054 devmode->icmintent = ntdevmode->icmintent;
4055 devmode->mediatype = ntdevmode->mediatype;
4056 devmode->dithertype = ntdevmode->dithertype;
4058 if (ntdevmode->nt_dev_private != NULL) {
4059 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4066 /****************************************************************************
4067 Create a DEVMODE struct. Returns malloced memory.
4068 ****************************************************************************/
4070 DEVICEMODE *construct_dev_mode(const char *servicename)
4072 NT_PRINTER_INFO_LEVEL *printer = NULL;
4073 DEVICEMODE *devmode = NULL;
4075 DEBUG(7,("construct_dev_mode\n"));
4077 DEBUGADD(8,("getting printer characteristics\n"));
4079 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4082 if ( !printer->info_2->devmode ) {
4083 DEBUG(5, ("BONG! There was no device mode!\n"));
4087 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4088 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4092 ZERO_STRUCTP(devmode);
4094 DEBUGADD(8,("loading DEVICEMODE\n"));
4096 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4097 free_dev_mode( devmode );
4102 free_a_printer(&printer,2);
4107 /********************************************************************
4108 * construct_printer_info_2
4109 * fill a printer_info_2 struct
4110 ********************************************************************/
4112 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4115 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4117 print_status_struct status;
4119 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4122 count = print_queue_length(snum, &status);
4124 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4125 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4126 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4127 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4128 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4130 if (*ntprinter->info_2->comment == '\0')
4131 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4133 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4135 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4136 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4137 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4138 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4139 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4141 printer->attributes = ntprinter->info_2->attributes;
4143 printer->priority = ntprinter->info_2->priority; /* priority */
4144 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4145 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4146 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4147 printer->status = nt_printq_status(status.status); /* status */
4148 printer->cjobs = count; /* jobs */
4149 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4151 if ( !(printer->devmode = construct_dev_mode(lp_const_servicename(snum))) )
4152 DEBUG(8, ("Returning NULL Devicemode!\n"));
4154 printer->secdesc = NULL;
4156 if ( ntprinter->info_2->secdesc_buf
4157 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4159 /* don't use talloc_steal() here unless you do a deep steal of all
4160 the SEC_DESC members */
4162 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4163 ntprinter->info_2->secdesc_buf->sd );
4166 free_a_printer(&ntprinter, 2);
4171 /********************************************************************
4172 * construct_printer_info_3
4173 * fill a printer_info_3 struct
4174 ********************************************************************/
4176 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4178 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4179 PRINTER_INFO_3 *printer = NULL;
4181 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4185 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4186 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4187 free_a_printer(&ntprinter, 2);
4191 ZERO_STRUCTP(printer);
4193 /* These are the components of the SD we are returning. */
4195 printer->flags = 0x4;
4197 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4198 /* don't use talloc_steal() here unless you do a deep steal of all
4199 the SEC_DESC members */
4201 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4202 ntprinter->info_2->secdesc_buf->sd );
4205 free_a_printer(&ntprinter, 2);
4207 *pp_printer = printer;
4211 /********************************************************************
4212 * construct_printer_info_4
4213 * fill a printer_info_4 struct
4214 ********************************************************************/
4216 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4218 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4220 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4223 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4224 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4225 printer->attributes = ntprinter->info_2->attributes;
4227 free_a_printer(&ntprinter, 2);
4231 /********************************************************************
4232 * construct_printer_info_5
4233 * fill a printer_info_5 struct
4234 ********************************************************************/
4236 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4238 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4240 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4243 init_unistr(&printer->printername, ntprinter->info_2->printername);
4244 init_unistr(&printer->portname, ntprinter->info_2->portname);
4245 printer->attributes = ntprinter->info_2->attributes;
4247 /* these two are not used by NT+ according to MSDN */
4249 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4250 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4252 free_a_printer(&ntprinter, 2);
4257 /********************************************************************
4258 * construct_printer_info_7
4259 * fill a printer_info_7 struct
4260 ********************************************************************/
4262 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4264 char *guid_str = NULL;
4267 if (is_printer_published(print_hnd, snum, &guid)) {
4268 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4269 strupper_m(guid_str);
4270 init_unistr(&printer->guid, guid_str);
4271 printer->action = SPOOL_DS_PUBLISH;
4273 init_unistr(&printer->guid, "");
4274 printer->action = SPOOL_DS_UNPUBLISH;
4280 /********************************************************************
4281 Spoolss_enumprinters.
4282 ********************************************************************/
4284 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4288 int n_services=lp_numservices();
4289 PRINTER_INFO_1 *printers=NULL;
4290 PRINTER_INFO_1 current_prt;
4291 WERROR result = WERR_OK;
4293 DEBUG(4,("enum_all_printers_info_1\n"));
4295 for (snum=0; snum<n_services; snum++) {
4296 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4297 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4299 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4300 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4301 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4305 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4307 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4313 /* check the required size. */
4314 for (i=0; i<*returned; i++)
4315 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4317 if (*needed > offered) {
4318 result = WERR_INSUFFICIENT_BUFFER;
4322 if (!rpcbuf_alloc_size(buffer, *needed)) {
4323 result = WERR_NOMEM;
4327 /* fill the buffer with the structures */
4328 for (i=0; i<*returned; i++)
4329 smb_io_printer_info_1("", buffer, &printers[i], 0);
4334 SAFE_FREE(printers);
4336 if ( !W_ERROR_IS_OK(result) )
4342 /********************************************************************
4343 enum_all_printers_info_1_local.
4344 *********************************************************************/
4346 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4348 DEBUG(4,("enum_all_printers_info_1_local\n"));
4350 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4353 /********************************************************************
4354 enum_all_printers_info_1_name.
4355 *********************************************************************/
4357 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4361 DEBUG(4,("enum_all_printers_info_1_name\n"));
4363 if ((name[0] == '\\') && (name[1] == '\\'))
4366 if (is_myname_or_ipaddr(s)) {
4367 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4370 return WERR_INVALID_NAME;
4373 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4374 /********************************************************************
4375 enum_all_printers_info_1_remote.
4376 *********************************************************************/
4378 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4380 PRINTER_INFO_1 *printer;
4381 fstring printername;
4384 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4385 WERROR result = WERR_OK;
4387 /* JFM: currently it's more a place holder than anything else.
4388 * In the spooler world there is a notion of server registration.
4389 * the print servers are registered on the PDC (in the same domain)
4391 * We should have a TDB here. The registration is done thru an
4392 * undocumented RPC call.
4395 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4400 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4401 slprintf(desc, sizeof(desc)-1,"%s", name);
4402 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4404 init_unistr(&printer->description, desc);
4405 init_unistr(&printer->name, printername);
4406 init_unistr(&printer->comment, comment);
4407 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4409 /* check the required size. */
4410 *needed += spoolss_size_printer_info_1(printer);
4412 if (*needed > offered) {
4413 result = WERR_INSUFFICIENT_BUFFER;
4417 if (!rpcbuf_alloc_size(buffer, *needed)) {
4418 result = WERR_NOMEM;
4422 /* fill the buffer with the structures */
4423 smb_io_printer_info_1("", buffer, printer, 0);
4429 if ( !W_ERROR_IS_OK(result) )
4437 /********************************************************************
4438 enum_all_printers_info_1_network.
4439 *********************************************************************/
4441 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4445 DEBUG(4,("enum_all_printers_info_1_network\n"));
4447 /* If we respond to a enum_printers level 1 on our name with flags
4448 set to PRINTER_ENUM_REMOTE with a list of printers then these
4449 printers incorrectly appear in the APW browse list.
4450 Specifically the printers for the server appear at the workgroup
4451 level where all the other servers in the domain are
4452 listed. Windows responds to this call with a
4453 WERR_CAN_NOT_COMPLETE so we should do the same. */
4455 if (name[0] == '\\' && name[1] == '\\')
4458 if (is_myname_or_ipaddr(s))
4459 return WERR_CAN_NOT_COMPLETE;
4461 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4464 /********************************************************************
4465 * api_spoolss_enumprinters
4467 * called from api_spoolss_enumprinters (see this to understand)
4468 ********************************************************************/
4470 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4474 int n_services=lp_numservices();
4475 PRINTER_INFO_2 *printers=NULL;
4476 PRINTER_INFO_2 current_prt;
4477 WERROR result = WERR_OK;
4481 for (snum=0; snum<n_services; snum++) {
4482 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4483 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4485 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4486 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4487 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4492 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4494 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4501 /* check the required size. */
4502 for (i=0; i<*returned; i++)
4503 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4505 if (*needed > offered) {
4506 result = WERR_INSUFFICIENT_BUFFER;
4510 if (!rpcbuf_alloc_size(buffer, *needed)) {
4511 result = WERR_NOMEM;
4515 /* fill the buffer with the structures */
4516 for (i=0; i<*returned; i++)
4517 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4522 for (i=0; i<*returned; i++)
4523 free_devmode(printers[i].devmode);
4525 SAFE_FREE(printers);
4527 if ( !W_ERROR_IS_OK(result) )
4533 /********************************************************************
4534 * handle enumeration of printers at level 1
4535 ********************************************************************/
4537 static WERROR enumprinters_level1( uint32 flags, fstring name,
4538 RPC_BUFFER *buffer, uint32 offered,
4539 uint32 *needed, uint32 *returned)
4541 /* Not all the flags are equals */
4543 if (flags & PRINTER_ENUM_LOCAL)
4544 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4546 if (flags & PRINTER_ENUM_NAME)
4547 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4549 #if 0 /* JERRY - disabled for now */
4550 if (flags & PRINTER_ENUM_REMOTE)
4551 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4554 if (flags & PRINTER_ENUM_NETWORK)
4555 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4557 return WERR_OK; /* NT4sp5 does that */
4560 /********************************************************************
4561 * handle enumeration of printers at level 2
4562 ********************************************************************/
4564 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4565 RPC_BUFFER *buffer, uint32 offered,
4566 uint32 *needed, uint32 *returned)
4568 char *s = servername;
4570 if (flags & PRINTER_ENUM_LOCAL) {
4571 return enum_all_printers_info_2(buffer, offered, needed, returned);
4574 if (flags & PRINTER_ENUM_NAME) {
4575 if ((servername[0] == '\\') && (servername[1] == '\\'))
4577 if (is_myname_or_ipaddr(s))
4578 return enum_all_printers_info_2(buffer, offered, needed, returned);
4580 return WERR_INVALID_NAME;
4583 if (flags & PRINTER_ENUM_REMOTE)
4584 return WERR_UNKNOWN_LEVEL;
4589 /********************************************************************
4590 * handle enumeration of printers at level 5
4591 ********************************************************************/
4593 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4594 RPC_BUFFER *buffer, uint32 offered,
4595 uint32 *needed, uint32 *returned)
4597 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4601 /********************************************************************
4602 * api_spoolss_enumprinters
4604 * called from api_spoolss_enumprinters (see this to understand)
4605 ********************************************************************/
4607 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4609 uint32 flags = q_u->flags;
4610 UNISTR2 *servername = &q_u->servername;
4611 uint32 level = q_u->level;
4612 RPC_BUFFER *buffer = NULL;
4613 uint32 offered = q_u->offered;
4614 uint32 *needed = &r_u->needed;
4615 uint32 *returned = &r_u->returned;
4619 /* that's an [in out] buffer */
4621 if (!q_u->buffer && (offered!=0)) {
4622 return WERR_INVALID_PARAM;
4625 rpcbuf_move(q_u->buffer, &r_u->buffer);
4626 buffer = r_u->buffer;
4628 DEBUG(4,("_spoolss_enumprinters\n"));
4635 * flags==PRINTER_ENUM_NAME
4636 * if name=="" then enumerates all printers
4637 * if name!="" then enumerate the printer
4638 * flags==PRINTER_ENUM_REMOTE
4639 * name is NULL, enumerate printers
4640 * Level 2: name!="" enumerates printers, name can't be NULL
4641 * Level 3: doesn't exist
4642 * Level 4: does a local registry lookup
4643 * Level 5: same as Level 2
4646 unistr2_to_ascii(name, servername, sizeof(name)-1);
4651 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4653 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4655 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4660 return WERR_UNKNOWN_LEVEL;
4663 /****************************************************************************
4664 ****************************************************************************/
4666 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4668 PRINTER_INFO_0 *printer=NULL;
4669 WERROR result = WERR_OK;
4671 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4674 construct_printer_info_0(print_hnd, printer, snum);
4676 /* check the required size. */
4677 *needed += spoolss_size_printer_info_0(printer);
4679 if (*needed > offered) {
4680 result = WERR_INSUFFICIENT_BUFFER;
4684 if (!rpcbuf_alloc_size(buffer, *needed)) {
4685 result = WERR_NOMEM;
4689 /* fill the buffer with the structures */
4690 smb_io_printer_info_0("", buffer, printer, 0);
4700 /****************************************************************************
4701 ****************************************************************************/
4703 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4705 PRINTER_INFO_1 *printer=NULL;
4706 WERROR result = WERR_OK;
4708 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4711 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4713 /* check the required size. */
4714 *needed += spoolss_size_printer_info_1(printer);
4716 if (*needed > offered) {
4717 result = WERR_INSUFFICIENT_BUFFER;
4721 if (!rpcbuf_alloc_size(buffer, *needed)) {
4722 result = WERR_NOMEM;
4726 /* fill the buffer with the structures */
4727 smb_io_printer_info_1("", buffer, printer, 0);
4736 /****************************************************************************
4737 ****************************************************************************/
4739 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4741 PRINTER_INFO_2 *printer=NULL;
4742 WERROR result = WERR_OK;
4744 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4747 construct_printer_info_2(print_hnd, printer, snum);
4749 /* check the required size. */
4750 *needed += spoolss_size_printer_info_2(printer);
4752 if (*needed > offered) {
4753 result = WERR_INSUFFICIENT_BUFFER;
4757 if (!rpcbuf_alloc_size(buffer, *needed)) {
4758 result = WERR_NOMEM;
4762 /* fill the buffer with the structures */
4763 if (!smb_io_printer_info_2("", buffer, printer, 0))
4764 result = WERR_NOMEM;
4768 free_printer_info_2(printer);
4773 /****************************************************************************
4774 ****************************************************************************/
4776 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4778 PRINTER_INFO_3 *printer=NULL;
4779 WERROR result = WERR_OK;
4781 if (!construct_printer_info_3(print_hnd, &printer, snum))
4784 /* check the required size. */
4785 *needed += spoolss_size_printer_info_3(printer);
4787 if (*needed > offered) {
4788 result = WERR_INSUFFICIENT_BUFFER;
4792 if (!rpcbuf_alloc_size(buffer, *needed)) {
4793 result = WERR_NOMEM;
4797 /* fill the buffer with the structures */
4798 smb_io_printer_info_3("", buffer, printer, 0);
4802 free_printer_info_3(printer);
4807 /****************************************************************************
4808 ****************************************************************************/
4810 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4812 PRINTER_INFO_4 *printer=NULL;
4813 WERROR result = WERR_OK;
4815 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4818 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4823 /* check the required size. */
4824 *needed += spoolss_size_printer_info_4(printer);
4826 if (*needed > offered) {
4827 result = WERR_INSUFFICIENT_BUFFER;
4831 if (!rpcbuf_alloc_size(buffer, *needed)) {
4832 result = WERR_NOMEM;
4836 /* fill the buffer with the structures */
4837 smb_io_printer_info_4("", buffer, printer, 0);
4841 free_printer_info_4(printer);
4846 /****************************************************************************
4847 ****************************************************************************/
4849 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4851 PRINTER_INFO_5 *printer=NULL;
4852 WERROR result = WERR_OK;
4854 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4857 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4858 free_printer_info_5(printer);
4862 /* check the required size. */
4863 *needed += spoolss_size_printer_info_5(printer);
4865 if (*needed > offered) {
4866 result = WERR_INSUFFICIENT_BUFFER;
4870 if (!rpcbuf_alloc_size(buffer, *needed)) {
4871 result = WERR_NOMEM;
4875 /* fill the buffer with the structures */
4876 smb_io_printer_info_5("", buffer, printer, 0);
4880 free_printer_info_5(printer);
4885 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4887 PRINTER_INFO_7 *printer=NULL;
4888 WERROR result = WERR_OK;
4890 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4893 if (!construct_printer_info_7(print_hnd, printer, snum))
4896 /* check the required size. */
4897 *needed += spoolss_size_printer_info_7(printer);
4899 if (*needed > offered) {
4900 result = WERR_INSUFFICIENT_BUFFER;
4904 if (!rpcbuf_alloc_size(buffer, *needed)) {
4905 result = WERR_NOMEM;
4910 /* fill the buffer with the structures */
4911 smb_io_printer_info_7("", buffer, printer, 0);
4915 free_printer_info_7(printer);
4920 /****************************************************************************
4921 ****************************************************************************/
4923 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4925 POLICY_HND *handle = &q_u->handle;
4926 uint32 level = q_u->level;
4927 RPC_BUFFER *buffer = NULL;
4928 uint32 offered = q_u->offered;
4929 uint32 *needed = &r_u->needed;
4930 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4934 /* that's an [in out] buffer */
4936 if (!q_u->buffer && (offered!=0)) {
4937 return WERR_INVALID_PARAM;
4940 rpcbuf_move(q_u->buffer, &r_u->buffer);
4941 buffer = r_u->buffer;
4945 if (!get_printer_snum(p, handle, &snum))
4950 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4952 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4954 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4956 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4958 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4960 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4962 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4964 return WERR_UNKNOWN_LEVEL;
4967 /********************************************************************
4968 * fill a DRIVER_INFO_1 struct
4969 ********************************************************************/
4971 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4973 init_unistr( &info->name, driver.info_3->name);
4976 /********************************************************************
4977 * construct_printer_driver_info_1
4978 ********************************************************************/
4980 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4982 NT_PRINTER_INFO_LEVEL *printer = NULL;
4983 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4985 ZERO_STRUCT(driver);
4987 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4988 return WERR_INVALID_PRINTER_NAME;
4990 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
4991 free_a_printer(&printer, 2);
4992 return WERR_UNKNOWN_PRINTER_DRIVER;
4995 fill_printer_driver_info_1(info, driver, servername, architecture);
4997 free_a_printer(&printer,2);
5002 /********************************************************************
5003 * construct_printer_driver_info_2
5004 * fill a printer_info_2 struct
5005 ********************************************************************/
5007 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5011 info->version=driver.info_3->cversion;
5013 init_unistr( &info->name, driver.info_3->name );
5014 init_unistr( &info->architecture, driver.info_3->environment );
5017 if (strlen(driver.info_3->driverpath)) {
5018 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5019 init_unistr( &info->driverpath, temp );
5021 init_unistr( &info->driverpath, "" );
5023 if (strlen(driver.info_3->datafile)) {
5024 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5025 init_unistr( &info->datafile, temp );
5027 init_unistr( &info->datafile, "" );
5029 if (strlen(driver.info_3->configfile)) {
5030 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5031 init_unistr( &info->configfile, temp );
5033 init_unistr( &info->configfile, "" );
5036 /********************************************************************
5037 * construct_printer_driver_info_2
5038 * fill a printer_info_2 struct
5039 ********************************************************************/
5041 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5043 NT_PRINTER_INFO_LEVEL *printer = NULL;
5044 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5046 ZERO_STRUCT(printer);
5047 ZERO_STRUCT(driver);
5049 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5050 return WERR_INVALID_PRINTER_NAME;
5052 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5053 free_a_printer(&printer, 2);
5054 return WERR_UNKNOWN_PRINTER_DRIVER;
5057 fill_printer_driver_info_2(info, driver, servername);
5059 free_a_printer(&printer,2);
5064 /********************************************************************
5065 * copy a strings array and convert to UNICODE
5067 * convert an array of ascii string to a UNICODE string
5068 ********************************************************************/
5070 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5077 DEBUG(6,("init_unistr_array\n"));
5088 v = ""; /* hack to handle null lists */
5091 /* hack to allow this to be used in places other than when generating
5092 the list of dependent files */
5095 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5099 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5101 /* add one extra unit16 for the second terminating NULL */
5103 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5104 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5111 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5116 /* special case for ""; we need to add both NULL's here */
5118 (*uni_array)[j++]=0x0000;
5119 (*uni_array)[j]=0x0000;
5122 DEBUGADD(6,("last one:done\n"));
5124 /* return size of array in uint16's */
5129 /********************************************************************
5130 * construct_printer_info_3
5131 * fill a printer_info_3 struct
5132 ********************************************************************/
5134 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5140 info->version=driver.info_3->cversion;
5142 init_unistr( &info->name, driver.info_3->name );
5143 init_unistr( &info->architecture, driver.info_3->environment );
5145 if (strlen(driver.info_3->driverpath)) {
5146 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5147 init_unistr( &info->driverpath, temp );
5149 init_unistr( &info->driverpath, "" );
5151 if (strlen(driver.info_3->datafile)) {
5152 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5153 init_unistr( &info->datafile, temp );
5155 init_unistr( &info->datafile, "" );
5157 if (strlen(driver.info_3->configfile)) {
5158 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5159 init_unistr( &info->configfile, temp );
5161 init_unistr( &info->configfile, "" );
5163 if (strlen(driver.info_3->helpfile)) {
5164 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5165 init_unistr( &info->helpfile, temp );
5167 init_unistr( &info->helpfile, "" );
5169 init_unistr( &info->monitorname, driver.info_3->monitorname );
5170 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5172 info->dependentfiles=NULL;
5173 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5176 /********************************************************************
5177 * construct_printer_info_3
5178 * fill a printer_info_3 struct
5179 ********************************************************************/
5181 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5183 NT_PRINTER_INFO_LEVEL *printer = NULL;
5184 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5186 ZERO_STRUCT(driver);
5188 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5189 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5190 if (!W_ERROR_IS_OK(status))
5191 return WERR_INVALID_PRINTER_NAME;
5193 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5194 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5199 * I put this code in during testing. Helpful when commenting out the
5200 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5201 * as win2k always queries the driver using an infor level of 6.
5202 * I've left it in (but ifdef'd out) because I'll probably
5203 * use it in experimentation again in the future. --jerry 22/01/2002
5206 if (!W_ERROR_IS_OK(status)) {
5208 * Is this a W2k client ?
5211 /* Yes - try again with a WinNT driver. */
5213 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5214 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5218 if (!W_ERROR_IS_OK(status)) {
5219 free_a_printer(&printer,2);
5220 return WERR_UNKNOWN_PRINTER_DRIVER;
5228 fill_printer_driver_info_3(info, driver, servername);
5230 free_a_printer(&printer,2);
5235 /********************************************************************
5236 * construct_printer_info_6
5237 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5238 ********************************************************************/
5240 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5246 memset(&nullstr, '\0', sizeof(fstring));
5248 info->version=driver.info_3->cversion;
5250 init_unistr( &info->name, driver.info_3->name );
5251 init_unistr( &info->architecture, driver.info_3->environment );
5253 if (strlen(driver.info_3->driverpath)) {
5254 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5255 init_unistr( &info->driverpath, temp );
5257 init_unistr( &info->driverpath, "" );
5259 if (strlen(driver.info_3->datafile)) {
5260 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5261 init_unistr( &info->datafile, temp );
5263 init_unistr( &info->datafile, "" );
5265 if (strlen(driver.info_3->configfile)) {
5266 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5267 init_unistr( &info->configfile, temp );
5269 init_unistr( &info->configfile, "" );
5271 if (strlen(driver.info_3->helpfile)) {
5272 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5273 init_unistr( &info->helpfile, temp );
5275 init_unistr( &info->helpfile, "" );
5277 init_unistr( &info->monitorname, driver.info_3->monitorname );
5278 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5280 info->dependentfiles = NULL;
5281 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5283 info->previousdrivernames=NULL;
5284 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5286 info->driver_date=0;
5289 info->driver_version_low=0;
5290 info->driver_version_high=0;
5292 init_unistr( &info->mfgname, "");
5293 init_unistr( &info->oem_url, "");
5294 init_unistr( &info->hardware_id, "");
5295 init_unistr( &info->provider, "");
5298 /********************************************************************
5299 * construct_printer_info_6
5300 * fill a printer_info_6 struct
5301 ********************************************************************/
5303 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5304 fstring servername, fstring architecture, uint32 version)
5306 NT_PRINTER_INFO_LEVEL *printer = NULL;
5307 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5310 ZERO_STRUCT(driver);
5312 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5314 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5316 if (!W_ERROR_IS_OK(status))
5317 return WERR_INVALID_PRINTER_NAME;
5319 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5321 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5323 if (!W_ERROR_IS_OK(status))
5326 * Is this a W2k client ?
5330 free_a_printer(&printer,2);
5331 return WERR_UNKNOWN_PRINTER_DRIVER;
5334 /* Yes - try again with a WinNT driver. */
5336 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5337 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5338 if (!W_ERROR_IS_OK(status)) {
5339 free_a_printer(&printer,2);
5340 return WERR_UNKNOWN_PRINTER_DRIVER;
5344 fill_printer_driver_info_6(info, driver, servername);
5346 free_a_printer(&printer,2);
5347 free_a_printer_driver(driver, 3);
5352 /****************************************************************************
5353 ****************************************************************************/
5355 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5357 SAFE_FREE(info->dependentfiles);
5360 /****************************************************************************
5361 ****************************************************************************/
5363 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5365 SAFE_FREE(info->dependentfiles);
5368 /****************************************************************************
5369 ****************************************************************************/
5371 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5373 DRIVER_INFO_1 *info=NULL;
5376 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5379 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5380 if (!W_ERROR_IS_OK(result))
5383 /* check the required size. */
5384 *needed += spoolss_size_printer_driver_info_1(info);
5386 if (*needed > offered) {
5387 result = WERR_INSUFFICIENT_BUFFER;
5391 if (!rpcbuf_alloc_size(buffer, *needed)) {
5392 result = WERR_NOMEM;
5396 /* fill the buffer with the structures */
5397 smb_io_printer_driver_info_1("", buffer, info, 0);
5406 /****************************************************************************
5407 ****************************************************************************/
5409 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5411 DRIVER_INFO_2 *info=NULL;
5414 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5417 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5418 if (!W_ERROR_IS_OK(result))
5421 /* check the required size. */
5422 *needed += spoolss_size_printer_driver_info_2(info);
5424 if (*needed > offered) {
5425 result = WERR_INSUFFICIENT_BUFFER;
5429 if (!rpcbuf_alloc_size(buffer, *needed)) {
5430 result = WERR_NOMEM;
5434 /* fill the buffer with the structures */
5435 smb_io_printer_driver_info_2("", buffer, info, 0);
5444 /****************************************************************************
5445 ****************************************************************************/
5447 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5454 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5455 if (!W_ERROR_IS_OK(result))
5458 /* check the required size. */
5459 *needed += spoolss_size_printer_driver_info_3(&info);
5461 if (*needed > offered) {
5462 result = WERR_INSUFFICIENT_BUFFER;
5466 if (!rpcbuf_alloc_size(buffer, *needed)) {
5467 result = WERR_NOMEM;
5471 /* fill the buffer with the structures */
5472 smb_io_printer_driver_info_3("", buffer, &info, 0);
5475 free_printer_driver_info_3(&info);
5480 /****************************************************************************
5481 ****************************************************************************/
5483 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5490 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5491 if (!W_ERROR_IS_OK(result))
5494 /* check the required size. */
5495 *needed += spoolss_size_printer_driver_info_6(&info);
5497 if (*needed > offered) {
5498 result = WERR_INSUFFICIENT_BUFFER;
5502 if (!rpcbuf_alloc_size(buffer, *needed)) {
5503 result = WERR_NOMEM;
5507 /* fill the buffer with the structures */
5508 smb_io_printer_driver_info_6("", buffer, &info, 0);
5511 free_printer_driver_info_6(&info);
5516 /****************************************************************************
5517 ****************************************************************************/
5519 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5521 POLICY_HND *handle = &q_u->handle;
5522 UNISTR2 *uni_arch = &q_u->architecture;
5523 uint32 level = q_u->level;
5524 uint32 clientmajorversion = q_u->clientmajorversion;
5525 RPC_BUFFER *buffer = NULL;
5526 uint32 offered = q_u->offered;
5527 uint32 *needed = &r_u->needed;
5528 uint32 *servermajorversion = &r_u->servermajorversion;
5529 uint32 *serverminorversion = &r_u->serverminorversion;
5530 Printer_entry *printer;
5533 fstring architecture;
5536 /* that's an [in out] buffer */
5538 if (!q_u->buffer && (offered!=0)) {
5539 return WERR_INVALID_PARAM;
5542 rpcbuf_move(q_u->buffer, &r_u->buffer);
5543 buffer = r_u->buffer;
5545 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5547 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5548 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5549 return WERR_INVALID_PRINTER_NAME;
5553 *servermajorversion = 0;
5554 *serverminorversion = 0;
5556 fstrcpy(servername, get_server_name( printer ));
5557 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5559 if (!get_printer_snum(p, handle, &snum))
5564 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5566 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5568 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5570 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5573 /* apparently this call is the equivalent of
5574 EnumPrinterDataEx() for the DsDriver key */
5579 return WERR_UNKNOWN_LEVEL;
5582 /****************************************************************************
5583 ****************************************************************************/
5585 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5587 POLICY_HND *handle = &q_u->handle;
5589 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5592 DEBUG(3,("Error in startpageprinter printer handle\n"));
5596 Printer->page_started=True;
5600 /****************************************************************************
5601 ****************************************************************************/
5603 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5605 POLICY_HND *handle = &q_u->handle;
5608 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5611 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5615 if (!get_printer_snum(p, handle, &snum))
5618 Printer->page_started=False;
5619 print_job_endpage(snum, Printer->jobid);
5624 /********************************************************************
5625 * api_spoolss_getprinter
5626 * called from the spoolss dispatcher
5628 ********************************************************************/
5630 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5632 POLICY_HND *handle = &q_u->handle;
5633 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5634 uint32 *jobid = &r_u->jobid;
5636 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5640 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5643 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5648 * a nice thing with NT is it doesn't listen to what you tell it.
5649 * when asked to send _only_ RAW datas, it tries to send datas
5652 * So I add checks like in NT Server ...
5655 if (info_1->p_datatype != 0) {
5656 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5657 if (strcmp(datatype, "RAW") != 0) {
5659 return WERR_INVALID_DATATYPE;
5663 /* get the share number of the printer */
5664 if (!get_printer_snum(p, handle, &snum)) {
5668 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5670 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5672 /* An error occured in print_job_start() so return an appropriate
5675 if (Printer->jobid == -1) {
5676 return map_werror_from_unix(errno);
5679 Printer->document_started=True;
5680 (*jobid) = Printer->jobid;
5685 /********************************************************************
5686 * api_spoolss_getprinter
5687 * called from the spoolss dispatcher
5689 ********************************************************************/
5691 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5693 POLICY_HND *handle = &q_u->handle;
5695 return _spoolss_enddocprinter_internal(p, handle);
5698 /****************************************************************************
5699 ****************************************************************************/
5701 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5703 POLICY_HND *handle = &q_u->handle;
5704 uint32 buffer_size = q_u->buffer_size;
5705 uint8 *buffer = q_u->buffer;
5706 uint32 *buffer_written = &q_u->buffer_size2;
5708 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5711 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5712 r_u->buffer_written = q_u->buffer_size2;
5716 if (!get_printer_snum(p, handle, &snum))
5719 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5720 (SMB_OFF_T)-1, (size_t)buffer_size);
5721 if (*buffer_written == (uint32)-1) {
5722 r_u->buffer_written = 0;
5723 if (errno == ENOSPC)
5724 return WERR_NO_SPOOL_SPACE;
5726 return WERR_ACCESS_DENIED;
5729 r_u->buffer_written = q_u->buffer_size2;
5734 /********************************************************************
5735 * api_spoolss_getprinter
5736 * called from the spoolss dispatcher
5738 ********************************************************************/
5740 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5744 WERROR errcode = WERR_BADFUNC;
5745 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5748 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5752 if (!get_printer_snum(p, handle, &snum))
5756 case PRINTER_CONTROL_PAUSE:
5757 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5761 case PRINTER_CONTROL_RESUME:
5762 case PRINTER_CONTROL_UNPAUSE:
5763 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5767 case PRINTER_CONTROL_PURGE:
5768 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5773 return WERR_UNKNOWN_LEVEL;
5779 /********************************************************************
5780 * api_spoolss_abortprinter
5781 * From MSDN: "Deletes printer's spool file if printer is configured
5783 ********************************************************************/
5785 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5787 POLICY_HND *handle = &q_u->handle;
5788 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5790 WERROR errcode = WERR_OK;
5793 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5797 if (!get_printer_snum(p, handle, &snum))
5800 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5805 /********************************************************************
5806 * called by spoolss_api_setprinter
5807 * when updating a printer description
5808 ********************************************************************/
5810 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5811 const SPOOL_PRINTER_INFO_LEVEL *info,
5812 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5814 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5818 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5820 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5821 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5822 OUR_HANDLE(handle)));
5824 result = WERR_BADFID;
5828 /* Check the user has permissions to change the security
5829 descriptor. By experimentation with two NT machines, the user
5830 requires Full Access to the printer to change security
5833 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5834 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5835 result = WERR_ACCESS_DENIED;
5839 /* NT seems to like setting the security descriptor even though
5840 nothing may have actually changed. */
5842 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5844 if (DEBUGLEVEL >= 10) {
5848 the_acl = old_secdesc_ctr->sd->dacl;
5849 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5850 PRINTERNAME(snum), the_acl->num_aces));
5852 for (i = 0; i < the_acl->num_aces; i++) {
5855 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5857 DEBUG(10, ("%s 0x%08x\n", sid_str,
5858 the_acl->aces[i].access_mask));
5861 the_acl = secdesc_ctr->sd->dacl;
5864 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5865 PRINTERNAME(snum), the_acl->num_aces));
5867 for (i = 0; i < the_acl->num_aces; i++) {
5870 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5872 DEBUG(10, ("%s 0x%08x\n", sid_str,
5873 the_acl->aces[i].access_mask));
5876 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5880 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5881 if (!new_secdesc_ctr) {
5882 result = WERR_NOMEM;
5886 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5891 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5898 /********************************************************************
5899 Canonicalize printer info from a client
5901 ATTN: It does not matter what we set the servername to hear
5902 since we do the necessary work in get_a_printer() to set it to
5903 the correct value based on what the client sent in the
5904 _spoolss_open_printer_ex().
5905 ********************************************************************/
5907 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5909 fstring printername;
5912 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5913 "portname=%s drivername=%s comment=%s location=%s\n",
5914 info->servername, info->printername, info->sharename,
5915 info->portname, info->drivername, info->comment, info->location));
5917 /* we force some elements to "correct" values */
5918 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5919 fstrcpy(info->sharename, lp_servicename(snum));
5921 /* check to see if we allow printername != sharename */
5923 if ( lp_force_printername(snum) ) {
5924 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5925 global_myname(), info->sharename );
5928 /* make sure printername is in \\server\printername format */
5930 fstrcpy( printername, info->printername );
5932 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5933 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5937 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5938 global_myname(), p );
5941 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5942 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5949 /****************************************************************************
5950 ****************************************************************************/
5952 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
5954 char *cmd = lp_addport_cmd();
5958 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5959 BOOL is_print_op = False;
5962 return WERR_ACCESS_DENIED;
5965 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
5968 is_print_op = user_has_privileges( token, &se_printop );
5970 DEBUG(10,("Running [%s]\n", command));
5972 /********* BEGIN SePrintOperatorPrivilege **********/
5977 ret = smbrun(command, &fd);
5982 /********* END SePrintOperatorPrivilege **********/
5984 DEBUGADD(10,("returned [%d]\n", ret));
5989 return WERR_ACCESS_DENIED;
5995 /****************************************************************************
5996 ****************************************************************************/
5998 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6000 char *cmd = lp_addprinter_cmd();
6006 fstring remote_machine = "%m";
6007 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6008 BOOL is_print_op = False;
6010 standard_sub_basic(current_user_info.smb_name,
6011 current_user_info.domain,
6012 remote_machine,sizeof(remote_machine));
6014 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6015 cmd, printer->info_2->printername, printer->info_2->sharename,
6016 printer->info_2->portname, printer->info_2->drivername,
6017 printer->info_2->location, printer->info_2->comment, remote_machine);
6020 is_print_op = user_has_privileges( token, &se_printop );
6022 DEBUG(10,("Running [%s]\n", command));
6024 /********* BEGIN SePrintOperatorPrivilege **********/
6029 if ( (ret = smbrun(command, &fd)) == 0 ) {
6030 /* Tell everyone we updated smb.conf. */
6031 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6037 /********* END SePrintOperatorPrivilege **********/
6039 DEBUGADD(10,("returned [%d]\n", ret));
6047 /* reload our services immediately */
6048 reload_services( False );
6051 /* Get lines and convert them back to dos-codepage */
6052 qlines = fd_lines_load(fd, &numlines, 0);
6053 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6056 /* Set the portname to what the script says the portname should be. */
6057 /* but don't require anything to be return from the script exit a good error code */
6060 /* Set the portname to what the script says the portname should be. */
6061 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6062 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6065 file_lines_free(qlines);
6070 /********************************************************************
6071 * Called by spoolss_api_setprinter
6072 * when updating a printer description.
6073 ********************************************************************/
6075 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6076 const SPOOL_PRINTER_INFO_LEVEL *info,
6077 DEVICEMODE *devmode)
6080 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6081 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6086 DEBUG(8,("update_printer\n"));
6091 result = WERR_BADFID;
6095 if (!get_printer_snum(p, handle, &snum)) {
6096 result = WERR_BADFID;
6100 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6101 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6102 result = WERR_BADFID;
6106 DEBUGADD(8,("Converting info_2 struct\n"));
6109 * convert_printer_info converts the incoming
6110 * info from the client and overwrites the info
6111 * just read from the tdb in the pointer 'printer'.
6114 if (!convert_printer_info(info, printer, level)) {
6115 result = WERR_NOMEM;
6120 /* we have a valid devmode
6121 convert it and link it*/
6123 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6124 if (!convert_devicemode(printer->info_2->printername, devmode,
6125 &printer->info_2->devmode)) {
6126 result = WERR_NOMEM;
6131 /* Do sanity check on the requested changes for Samba */
6133 if (!check_printer_ok(printer->info_2, snum)) {
6134 result = WERR_INVALID_PARAM;
6138 /* FIXME!!! If the driver has changed we really should verify that
6139 it is installed before doing much else --jerry */
6141 /* Check calling user has permission to update printer description */
6143 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6144 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6145 result = WERR_ACCESS_DENIED;
6149 /* Call addprinter hook */
6150 /* Check changes to see if this is really needed */
6152 if ( *lp_addprinter_cmd()
6153 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6154 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6155 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6156 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6158 /* add_printer_hook() will call reload_services() */
6160 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6161 result = WERR_ACCESS_DENIED;
6167 * When a *new* driver is bound to a printer, the drivername is used to
6168 * lookup previously saved driver initialization info, which is then
6169 * bound to the printer, simulating what happens in the Windows arch.
6171 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6173 if (!set_driver_init(printer, 2))
6175 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6176 printer->info_2->drivername));
6179 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6180 printer->info_2->drivername));
6182 notify_printer_driver(snum, printer->info_2->drivername);
6186 * flag which changes actually occured. This is a small subset of
6187 * all the possible changes. We also have to update things in the
6191 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6192 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6193 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6194 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6196 notify_printer_comment(snum, printer->info_2->comment);
6199 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6200 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6201 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6202 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6204 notify_printer_sharename(snum, printer->info_2->sharename);
6207 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6210 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6213 pname = printer->info_2->printername;
6216 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6217 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6218 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6220 notify_printer_printername( snum, pname );
6223 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6224 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6225 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6226 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6228 notify_printer_port(snum, printer->info_2->portname);
6231 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6232 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6233 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6234 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6236 notify_printer_location(snum, printer->info_2->location);
6239 /* here we need to update some more DsSpooler keys */
6240 /* uNCName, serverName, shortServerName */
6242 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6243 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6244 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6245 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6246 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6248 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6249 global_myname(), printer->info_2->sharename );
6250 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6251 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6252 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6254 /* Update printer info */
6255 result = mod_a_printer(printer, 2);
6258 free_a_printer(&printer, 2);
6259 free_a_printer(&old_printer, 2);
6265 /****************************************************************************
6266 ****************************************************************************/
6267 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6268 const SPOOL_PRINTER_INFO_LEVEL *info)
6271 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6273 Printer_entry *Printer;
6275 if ( lp_security() != SEC_ADS ) {
6276 return WERR_UNKNOWN_LEVEL;
6279 Printer = find_printer_index_by_hnd(p, handle);
6281 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6286 if (!get_printer_snum(p, handle, &snum))
6289 nt_printer_publish(Printer, snum, info7->action);
6293 return WERR_UNKNOWN_LEVEL;
6296 /****************************************************************************
6297 ****************************************************************************/
6299 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6301 POLICY_HND *handle = &q_u->handle;
6302 uint32 level = q_u->level;
6303 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6304 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6305 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6306 uint32 command = q_u->command;
6309 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6312 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6316 /* check the level */
6319 return control_printer(handle, command, p);
6321 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6322 if (!W_ERROR_IS_OK(result))
6325 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6328 return update_printer_sec(handle, level, info, p,
6331 return publish_or_unpublish_printer(p, handle, info);
6333 return WERR_UNKNOWN_LEVEL;
6337 /****************************************************************************
6338 ****************************************************************************/
6340 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6342 POLICY_HND *handle = &q_u->handle;
6343 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6346 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6350 if (Printer->notify.client_connected==True) {
6353 if ( Printer->printer_type == SPLHND_SERVER)
6355 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6356 !get_printer_snum(p, handle, &snum) )
6359 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6362 Printer->notify.flags=0;
6363 Printer->notify.options=0;
6364 Printer->notify.localmachine[0]='\0';
6365 Printer->notify.printerlocal=0;
6366 if (Printer->notify.option)
6367 free_spool_notify_option(&Printer->notify.option);
6368 Printer->notify.client_connected=False;
6373 /****************************************************************************
6374 ****************************************************************************/
6376 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6378 /* that's an [in out] buffer */
6380 if (!q_u->buffer && (q_u->offered!=0)) {
6381 return WERR_INVALID_PARAM;
6384 rpcbuf_move(q_u->buffer, &r_u->buffer);
6387 return WERR_INVALID_PARAM; /* this is what a NT server
6388 returns for AddJob. AddJob
6389 must fail on non-local
6393 /****************************************************************************
6394 ****************************************************************************/
6396 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6397 int position, int snum,
6398 const NT_PRINTER_INFO_LEVEL *ntprinter)
6402 t=gmtime(&queue->time);
6404 job_info->jobid=queue->job;
6405 init_unistr(&job_info->printername, lp_servicename(snum));
6406 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6407 init_unistr(&job_info->username, queue->fs_user);
6408 init_unistr(&job_info->document, queue->fs_file);
6409 init_unistr(&job_info->datatype, "RAW");
6410 init_unistr(&job_info->text_status, "");
6411 job_info->status=nt_printj_status(queue->status);
6412 job_info->priority=queue->priority;
6413 job_info->position=position;
6414 job_info->totalpages=queue->page_count;
6415 job_info->pagesprinted=0;
6417 make_systemtime(&job_info->submitted, t);
6420 /****************************************************************************
6421 ****************************************************************************/
6423 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6424 int position, int snum,
6425 const NT_PRINTER_INFO_LEVEL *ntprinter,
6426 DEVICEMODE *devmode)
6430 t=gmtime(&queue->time);
6432 job_info->jobid=queue->job;
6434 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6436 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6437 init_unistr(&job_info->username, queue->fs_user);
6438 init_unistr(&job_info->document, queue->fs_file);
6439 init_unistr(&job_info->notifyname, queue->fs_user);
6440 init_unistr(&job_info->datatype, "RAW");
6441 init_unistr(&job_info->printprocessor, "winprint");
6442 init_unistr(&job_info->parameters, "");
6443 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6444 init_unistr(&job_info->text_status, "");
6446 /* and here the security descriptor */
6448 job_info->status=nt_printj_status(queue->status);
6449 job_info->priority=queue->priority;
6450 job_info->position=position;
6451 job_info->starttime=0;
6452 job_info->untiltime=0;
6453 job_info->totalpages=queue->page_count;
6454 job_info->size=queue->size;
6455 make_systemtime(&(job_info->submitted), t);
6456 job_info->timeelapsed=0;
6457 job_info->pagesprinted=0;
6459 job_info->devmode = devmode;
6464 /****************************************************************************
6465 Enumjobs at level 1.
6466 ****************************************************************************/
6468 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6469 const NT_PRINTER_INFO_LEVEL *ntprinter,
6470 RPC_BUFFER *buffer, uint32 offered,
6471 uint32 *needed, uint32 *returned)
6475 WERROR result = WERR_OK;
6477 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6483 for (i=0; i<*returned; i++)
6484 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6486 /* check the required size. */
6487 for (i=0; i<*returned; i++)
6488 (*needed) += spoolss_size_job_info_1(&info[i]);
6490 if (*needed > offered) {
6491 result = WERR_INSUFFICIENT_BUFFER;
6495 if (!rpcbuf_alloc_size(buffer, *needed)) {
6496 result = WERR_NOMEM;
6500 /* fill the buffer with the structures */
6501 for (i=0; i<*returned; i++)
6502 smb_io_job_info_1("", buffer, &info[i], 0);
6508 if ( !W_ERROR_IS_OK(result) )
6514 /****************************************************************************
6515 Enumjobs at level 2.
6516 ****************************************************************************/
6518 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6519 const NT_PRINTER_INFO_LEVEL *ntprinter,
6520 RPC_BUFFER *buffer, uint32 offered,
6521 uint32 *needed, uint32 *returned)
6523 JOB_INFO_2 *info = NULL;
6525 WERROR result = WERR_OK;
6526 DEVICEMODE *devmode = NULL;
6528 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6533 /* this should not be a failure condition if the devmode is NULL */
6535 devmode = construct_dev_mode(lp_const_servicename(snum));
6537 for (i=0; i<*returned; i++)
6538 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6540 /* check the required size. */
6541 for (i=0; i<*returned; i++)
6542 (*needed) += spoolss_size_job_info_2(&info[i]);
6544 if (*needed > offered) {
6545 result = WERR_INSUFFICIENT_BUFFER;
6549 if (!rpcbuf_alloc_size(buffer, *needed)) {
6550 result = WERR_NOMEM;
6554 /* fill the buffer with the structures */
6555 for (i=0; i<*returned; i++)
6556 smb_io_job_info_2("", buffer, &info[i], 0);
6559 free_devmode(devmode);
6562 if ( !W_ERROR_IS_OK(result) )
6569 /****************************************************************************
6571 ****************************************************************************/
6573 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6575 POLICY_HND *handle = &q_u->handle;
6576 uint32 level = q_u->level;
6577 RPC_BUFFER *buffer = NULL;
6578 uint32 offered = q_u->offered;
6579 uint32 *needed = &r_u->needed;
6580 uint32 *returned = &r_u->returned;
6582 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6584 print_status_struct prt_status;
6585 print_queue_struct *queue=NULL;
6587 /* that's an [in out] buffer */
6589 if (!q_u->buffer && (offered!=0)) {
6590 return WERR_INVALID_PARAM;
6593 rpcbuf_move(q_u->buffer, &r_u->buffer);
6594 buffer = r_u->buffer;
6596 DEBUG(4,("_spoolss_enumjobs\n"));
6601 /* lookup the printer snum and tdb entry */
6603 if (!get_printer_snum(p, handle, &snum))
6606 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6607 if ( !W_ERROR_IS_OK(wret) )
6610 *returned = print_queue_status(snum, &queue, &prt_status);
6611 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6613 if (*returned == 0) {
6615 free_a_printer(&ntprinter, 2);
6621 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6624 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6628 wret = WERR_UNKNOWN_LEVEL;
6633 free_a_printer( &ntprinter, 2 );
6637 /****************************************************************************
6638 ****************************************************************************/
6640 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6645 /****************************************************************************
6646 ****************************************************************************/
6648 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6650 POLICY_HND *handle = &q_u->handle;
6651 uint32 jobid = q_u->jobid;
6652 uint32 command = q_u->command;
6655 WERROR errcode = WERR_BADFUNC;
6657 if (!get_printer_snum(p, handle, &snum)) {
6661 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6662 return WERR_INVALID_PRINTER_NAME;
6666 case JOB_CONTROL_CANCEL:
6667 case JOB_CONTROL_DELETE:
6668 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6672 case JOB_CONTROL_PAUSE:
6673 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6677 case JOB_CONTROL_RESTART:
6678 case JOB_CONTROL_RESUME:
6679 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6684 return WERR_UNKNOWN_LEVEL;
6690 /****************************************************************************
6691 Enumerates all printer drivers at level 1.
6692 ****************************************************************************/
6694 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6699 fstring *list = NULL;
6700 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6701 DRIVER_INFO_1 *driver_info_1=NULL;
6702 WERROR result = WERR_OK;
6706 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6708 ndrivers=get_ntdrivers(&list, architecture, version);
6709 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6711 if(ndrivers == -1) {
6712 SAFE_FREE(driver_info_1);
6717 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6718 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6724 for (i=0; i<ndrivers; i++) {
6726 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6727 ZERO_STRUCT(driver);
6728 status = get_a_printer_driver(&driver, 3, list[i],
6729 architecture, version);
6730 if (!W_ERROR_IS_OK(status)) {
6732 SAFE_FREE(driver_info_1);
6735 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6736 free_a_printer_driver(driver, 3);
6739 *returned+=ndrivers;
6743 /* check the required size. */
6744 for (i=0; i<*returned; i++) {
6745 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6746 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6749 if (*needed > offered) {
6750 result = WERR_INSUFFICIENT_BUFFER;
6754 if (!rpcbuf_alloc_size(buffer, *needed)) {
6755 result = WERR_NOMEM;
6759 /* fill the buffer with the driver structures */
6760 for (i=0; i<*returned; i++) {
6761 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6762 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6766 SAFE_FREE(driver_info_1);
6768 if ( !W_ERROR_IS_OK(result) )
6774 /****************************************************************************
6775 Enumerates all printer drivers at level 2.
6776 ****************************************************************************/
6778 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6783 fstring *list = NULL;
6784 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6785 DRIVER_INFO_2 *driver_info_2=NULL;
6786 WERROR result = WERR_OK;
6790 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6792 ndrivers=get_ntdrivers(&list, architecture, version);
6793 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6795 if(ndrivers == -1) {
6796 SAFE_FREE(driver_info_2);
6801 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6802 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6808 for (i=0; i<ndrivers; i++) {
6811 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6812 ZERO_STRUCT(driver);
6813 status = get_a_printer_driver(&driver, 3, list[i],
6814 architecture, version);
6815 if (!W_ERROR_IS_OK(status)) {
6817 SAFE_FREE(driver_info_2);
6820 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6821 free_a_printer_driver(driver, 3);
6824 *returned+=ndrivers;
6828 /* check the required size. */
6829 for (i=0; i<*returned; i++) {
6830 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6831 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6834 if (*needed > offered) {
6835 result = WERR_INSUFFICIENT_BUFFER;
6839 if (!rpcbuf_alloc_size(buffer, *needed)) {
6840 result = WERR_NOMEM;
6844 /* fill the buffer with the form structures */
6845 for (i=0; i<*returned; i++) {
6846 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6847 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6851 SAFE_FREE(driver_info_2);
6853 if ( !W_ERROR_IS_OK(result) )
6859 /****************************************************************************
6860 Enumerates all printer drivers at level 3.
6861 ****************************************************************************/
6863 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6868 fstring *list = NULL;
6869 DRIVER_INFO_3 *driver_info_3=NULL;
6870 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6871 WERROR result = WERR_OK;
6875 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6877 ndrivers=get_ntdrivers(&list, architecture, version);
6878 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6880 if(ndrivers == -1) {
6881 SAFE_FREE(driver_info_3);
6886 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6887 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6893 for (i=0; i<ndrivers; i++) {
6896 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6897 ZERO_STRUCT(driver);
6898 status = get_a_printer_driver(&driver, 3, list[i],
6899 architecture, version);
6900 if (!W_ERROR_IS_OK(status)) {
6902 SAFE_FREE(driver_info_3);
6905 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6906 free_a_printer_driver(driver, 3);
6909 *returned+=ndrivers;
6913 /* check the required size. */
6914 for (i=0; i<*returned; i++) {
6915 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6916 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6919 if (*needed > offered) {
6920 result = WERR_INSUFFICIENT_BUFFER;
6924 if (!rpcbuf_alloc_size(buffer, *needed)) {
6925 result = WERR_NOMEM;
6929 /* fill the buffer with the driver structures */
6930 for (i=0; i<*returned; i++) {
6931 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6932 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6936 for (i=0; i<*returned; i++) {
6937 SAFE_FREE(driver_info_3[i].dependentfiles);
6940 SAFE_FREE(driver_info_3);
6942 if ( !W_ERROR_IS_OK(result) )
6948 /****************************************************************************
6949 Enumerates all printer drivers.
6950 ****************************************************************************/
6952 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6954 uint32 level = q_u->level;
6955 RPC_BUFFER *buffer = NULL;
6956 uint32 offered = q_u->offered;
6957 uint32 *needed = &r_u->needed;
6958 uint32 *returned = &r_u->returned;
6961 fstring architecture;
6963 /* that's an [in out] buffer */
6965 if (!q_u->buffer && (offered!=0)) {
6966 return WERR_INVALID_PARAM;
6969 rpcbuf_move(q_u->buffer, &r_u->buffer);
6970 buffer = r_u->buffer;
6972 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6977 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6978 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6980 if ( !is_myname_or_ipaddr( servername ) )
6981 return WERR_UNKNOWN_PRINTER_DRIVER;
6985 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6987 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6989 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6991 return WERR_UNKNOWN_LEVEL;
6995 /****************************************************************************
6996 ****************************************************************************/
6998 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7000 form->flag=list->flag;
7001 init_unistr(&form->name, list->name);
7002 form->width=list->width;
7003 form->length=list->length;
7004 form->left=list->left;
7005 form->top=list->top;
7006 form->right=list->right;
7007 form->bottom=list->bottom;
7010 /****************************************************************************
7011 ****************************************************************************/
7013 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7015 uint32 level = q_u->level;
7016 RPC_BUFFER *buffer = NULL;
7017 uint32 offered = q_u->offered;
7018 uint32 *needed = &r_u->needed;
7019 uint32 *numofforms = &r_u->numofforms;
7020 uint32 numbuiltinforms;
7022 nt_forms_struct *list=NULL;
7023 nt_forms_struct *builtinlist=NULL;
7028 /* that's an [in out] buffer */
7030 if (!q_u->buffer && (offered!=0) ) {
7031 return WERR_INVALID_PARAM;
7034 rpcbuf_move(q_u->buffer, &r_u->buffer);
7035 buffer = r_u->buffer;
7037 DEBUG(4,("_spoolss_enumforms\n"));
7038 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7039 DEBUGADD(5,("Info level [%d]\n", level));
7041 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7042 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7043 *numofforms = get_ntforms(&list);
7044 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7045 *numofforms += numbuiltinforms;
7047 if (*numofforms == 0) {
7048 SAFE_FREE(builtinlist);
7050 return WERR_NO_MORE_ITEMS;
7055 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7056 SAFE_FREE(builtinlist);
7062 /* construct the list of form structures */
7063 for (i=0; i<numbuiltinforms; i++) {
7064 DEBUGADD(6,("Filling form number [%d]\n",i));
7065 fill_form_1(&forms_1[i], &builtinlist[i]);
7068 SAFE_FREE(builtinlist);
7070 for (; i<*numofforms; i++) {
7071 DEBUGADD(6,("Filling form number [%d]\n",i));
7072 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7077 /* check the required size. */
7078 for (i=0; i<numbuiltinforms; i++) {
7079 DEBUGADD(6,("adding form [%d]'s size\n",i));
7080 buffer_size += spoolss_size_form_1(&forms_1[i]);
7082 for (; i<*numofforms; i++) {
7083 DEBUGADD(6,("adding form [%d]'s size\n",i));
7084 buffer_size += spoolss_size_form_1(&forms_1[i]);
7087 *needed=buffer_size;
7089 if (*needed > offered) {
7092 return WERR_INSUFFICIENT_BUFFER;
7095 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7101 /* fill the buffer with the form structures */
7102 for (i=0; i<numbuiltinforms; i++) {
7103 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7104 smb_io_form_1("", buffer, &forms_1[i], 0);
7106 for (; i<*numofforms; i++) {
7107 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7108 smb_io_form_1("", buffer, &forms_1[i], 0);
7117 SAFE_FREE(builtinlist);
7118 return WERR_UNKNOWN_LEVEL;
7122 /****************************************************************************
7123 ****************************************************************************/
7125 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7127 uint32 level = q_u->level;
7128 UNISTR2 *uni_formname = &q_u->formname;
7129 RPC_BUFFER *buffer = NULL;
7130 uint32 offered = q_u->offered;
7131 uint32 *needed = &r_u->needed;
7133 nt_forms_struct *list=NULL;
7134 nt_forms_struct builtin_form;
7139 int numofforms=0, i=0;
7141 /* that's an [in out] buffer */
7143 if (!q_u->buffer && (offered!=0)) {
7144 return WERR_INVALID_PARAM;
7147 rpcbuf_move(q_u->buffer, &r_u->buffer);
7148 buffer = r_u->buffer;
7150 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7152 DEBUG(4,("_spoolss_getform\n"));
7153 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7154 DEBUGADD(5,("Info level [%d]\n", level));
7156 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7157 if (!foundBuiltin) {
7158 numofforms = get_ntforms(&list);
7159 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7161 if (numofforms == 0)
7168 fill_form_1(&form_1, &builtin_form);
7171 /* Check if the requested name is in the list of form structures */
7172 for (i=0; i<numofforms; i++) {
7174 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7176 if (strequal(form_name, list[i].name)) {
7177 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7178 fill_form_1(&form_1, &list[i]);
7184 if (i == numofforms) {
7188 /* check the required size. */
7190 *needed=spoolss_size_form_1(&form_1);
7192 if (*needed > offered)
7193 return WERR_INSUFFICIENT_BUFFER;
7195 if (!rpcbuf_alloc_size(buffer, buffer_size))
7198 /* fill the buffer with the form structures */
7199 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7200 smb_io_form_1("", buffer, &form_1, 0);
7206 return WERR_UNKNOWN_LEVEL;
7210 /****************************************************************************
7211 ****************************************************************************/
7213 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7215 init_unistr(&port->port_name, name);
7218 /****************************************************************************
7219 TODO: This probably needs distinguish between TCP/IP and Local ports
7221 ****************************************************************************/
7223 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7225 init_unistr(&port->port_name, name);
7226 init_unistr(&port->monitor_name, "Local Monitor");
7227 init_unistr(&port->description, SPL_LOCAL_PORT );
7228 port->port_type=PORT_TYPE_WRITE;
7233 /****************************************************************************
7234 wrapper around the enumer ports command
7235 ****************************************************************************/
7237 WERROR enumports_hook( int *count, char ***lines )
7239 char *cmd = lp_enumports_cmd();
7249 /* if no hook then just fill in the default port */
7252 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7253 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7258 /* we have a valid enumport command */
7260 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7262 DEBUG(10,("Running [%s]\n", command));
7263 ret = smbrun(command, &fd);
7264 DEBUG(10,("Returned [%d]\n", ret));
7269 return WERR_ACCESS_DENIED;
7273 qlines = fd_lines_load(fd, &numlines, 0);
7274 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7284 /****************************************************************************
7286 ****************************************************************************/
7288 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7290 PORT_INFO_1 *ports=NULL;
7292 WERROR result = WERR_OK;
7293 char **qlines = NULL;
7296 result = enumports_hook( &numlines, &qlines );
7297 if (!W_ERROR_IS_OK(result)) {
7298 file_lines_free(qlines);
7303 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7304 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7305 dos_errstr(WERR_NOMEM)));
7306 file_lines_free(qlines);
7310 for (i=0; i<numlines; i++) {
7311 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7312 fill_port_1(&ports[i], qlines[i]);
7315 file_lines_free(qlines);
7317 *returned = numlines;
7319 /* check the required size. */
7320 for (i=0; i<*returned; i++) {
7321 DEBUGADD(6,("adding port [%d]'s size\n", i));
7322 *needed += spoolss_size_port_info_1(&ports[i]);
7325 if (*needed > offered) {
7326 result = WERR_INSUFFICIENT_BUFFER;
7330 if (!rpcbuf_alloc_size(buffer, *needed)) {
7331 result = WERR_NOMEM;
7335 /* fill the buffer with the ports structures */
7336 for (i=0; i<*returned; i++) {
7337 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7338 smb_io_port_1("", buffer, &ports[i], 0);
7344 if ( !W_ERROR_IS_OK(result) )
7350 /****************************************************************************
7352 ****************************************************************************/
7354 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7356 PORT_INFO_2 *ports=NULL;
7358 WERROR result = WERR_OK;
7359 char **qlines = NULL;
7362 result = enumports_hook( &numlines, &qlines );
7363 if ( !W_ERROR_IS_OK(result)) {
7364 file_lines_free(qlines);
7369 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7370 file_lines_free(qlines);
7374 for (i=0; i<numlines; i++) {
7375 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7376 fill_port_2(&(ports[i]), qlines[i]);
7380 file_lines_free(qlines);
7382 *returned = numlines;
7384 /* check the required size. */
7385 for (i=0; i<*returned; i++) {
7386 DEBUGADD(6,("adding port [%d]'s size\n", i));
7387 *needed += spoolss_size_port_info_2(&ports[i]);
7390 if (*needed > offered) {
7391 result = WERR_INSUFFICIENT_BUFFER;
7395 if (!rpcbuf_alloc_size(buffer, *needed)) {
7396 result = WERR_NOMEM;
7400 /* fill the buffer with the ports structures */
7401 for (i=0; i<*returned; i++) {
7402 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7403 smb_io_port_2("", buffer, &ports[i], 0);
7409 if ( !W_ERROR_IS_OK(result) )
7415 /****************************************************************************
7417 ****************************************************************************/
7419 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7421 uint32 level = q_u->level;
7422 RPC_BUFFER *buffer = NULL;
7423 uint32 offered = q_u->offered;
7424 uint32 *needed = &r_u->needed;
7425 uint32 *returned = &r_u->returned;
7427 /* that's an [in out] buffer */
7429 if (!q_u->buffer && (offered!=0)) {
7430 return WERR_INVALID_PARAM;
7433 rpcbuf_move(q_u->buffer, &r_u->buffer);
7434 buffer = r_u->buffer;
7436 DEBUG(4,("_spoolss_enumports\n"));
7443 return enumports_level_1(buffer, offered, needed, returned);
7445 return enumports_level_2(buffer, offered, needed, returned);
7447 return WERR_UNKNOWN_LEVEL;
7451 /****************************************************************************
7452 ****************************************************************************/
7454 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7455 const SPOOL_PRINTER_INFO_LEVEL *info,
7456 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7457 uint32 user_switch, const SPOOL_USER_CTR *user,
7460 NT_PRINTER_INFO_LEVEL *printer = NULL;
7463 WERROR err = WERR_OK;
7465 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7466 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7470 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7471 if (!convert_printer_info(info, printer, 2)) {
7472 free_a_printer(&printer, 2);
7476 /* check to see if the printer already exists */
7478 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7479 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7480 printer->info_2->sharename));
7481 free_a_printer(&printer, 2);
7482 return WERR_PRINTER_ALREADY_EXISTS;
7485 /* FIXME!!! smbd should check to see if the driver is installed before
7486 trying to add a printer like this --jerry */
7488 if (*lp_addprinter_cmd() ) {
7489 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7490 free_a_printer(&printer,2);
7491 return WERR_ACCESS_DENIED;
7494 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7495 "smb.conf parameter \"addprinter command\" is defined. This"
7496 "parameter must exist for this call to succeed\n",
7497 printer->info_2->sharename ));
7500 /* use our primary netbios name since get_a_printer() will convert
7501 it to what the client expects on a case by case basis */
7503 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7504 printer->info_2->sharename);
7507 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7508 free_a_printer(&printer,2);
7509 return WERR_ACCESS_DENIED;
7512 /* you must be a printer admin to add a new printer */
7513 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7514 free_a_printer(&printer,2);
7515 return WERR_ACCESS_DENIED;
7519 * Do sanity check on the requested changes for Samba.
7522 if (!check_printer_ok(printer->info_2, snum)) {
7523 free_a_printer(&printer,2);
7524 return WERR_INVALID_PARAM;
7528 * When a printer is created, the drivername bound to the printer is used
7529 * to lookup previously saved driver initialization info, which is then
7530 * bound to the new printer, simulating what happens in the Windows arch.
7535 set_driver_init(printer, 2);
7539 /* A valid devmode was included, convert and link it
7541 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7543 if (!convert_devicemode(printer->info_2->printername, devmode,
7544 &printer->info_2->devmode))
7548 /* write the ASCII on disk */
7549 err = mod_a_printer(printer, 2);
7550 if (!W_ERROR_IS_OK(err)) {
7551 free_a_printer(&printer,2);
7555 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7556 /* Handle open failed - remove addition. */
7557 del_a_printer(printer->info_2->sharename);
7558 free_a_printer(&printer,2);
7559 return WERR_ACCESS_DENIED;
7562 update_c_setprinter(False);
7563 free_a_printer(&printer,2);
7568 /****************************************************************************
7569 ****************************************************************************/
7571 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7573 UNISTR2 *uni_srv_name = q_u->server_name;
7574 uint32 level = q_u->level;
7575 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7576 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7577 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7578 uint32 user_switch = q_u->user_switch;
7579 SPOOL_USER_CTR *user = &q_u->user_ctr;
7580 POLICY_HND *handle = &r_u->handle;
7584 /* we don't handle yet */
7585 /* but I know what to do ... */
7586 return WERR_UNKNOWN_LEVEL;
7588 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7590 user_switch, user, handle);
7592 return WERR_UNKNOWN_LEVEL;
7596 /****************************************************************************
7597 ****************************************************************************/
7599 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7601 uint32 level = q_u->level;
7602 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7603 WERROR err = WERR_OK;
7604 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7605 fstring driver_name;
7608 ZERO_STRUCT(driver);
7610 if (!convert_printer_driver_info(info, &driver, level)) {
7615 DEBUG(5,("Cleaning driver's information\n"));
7616 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7617 if (!W_ERROR_IS_OK(err))
7620 DEBUG(5,("Moving driver to final destination\n"));
7621 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7625 if (add_a_printer_driver(driver, level)!=0) {
7626 err = WERR_ACCESS_DENIED;
7631 * I think this is where he DrvUpgradePrinter() hook would be
7632 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7633 * server. Right now, we just need to send ourselves a message
7634 * to update each printer bound to this driver. --jerry
7637 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7638 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7643 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7644 * decide if the driver init data should be deleted. The rules are:
7645 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7646 * 2) delete init data only if there is no 2k/Xp driver
7647 * 3) always delete init data
7648 * The generalized rule is always use init data from the highest order driver.
7649 * It is necessary to follow the driver install by an initialization step to
7650 * finish off this process.
7653 version = driver.info_3->cversion;
7654 else if (level == 6)
7655 version = driver.info_6->version;
7660 * 9x printer driver - never delete init data
7663 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7668 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7669 * there is no 2k/Xp driver init data for this driver name.
7673 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7675 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7677 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7679 if (!del_driver_init(driver_name))
7680 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7683 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7685 free_a_printer_driver(driver1,3);
7686 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7693 * 2k or Xp printer driver - always delete init data
7696 if (!del_driver_init(driver_name))
7697 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7701 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7707 free_a_printer_driver(driver, level);
7711 /********************************************************************
7712 * spoolss_addprinterdriverex
7713 ********************************************************************/
7715 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7717 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7718 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7721 * we only support the semantics of AddPrinterDriver()
7722 * i.e. only copy files that are newer than existing ones
7725 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7726 return WERR_ACCESS_DENIED;
7728 ZERO_STRUCT(q_u_local);
7729 ZERO_STRUCT(r_u_local);
7731 /* just pass the information off to _spoolss_addprinterdriver() */
7732 q_u_local.server_name_ptr = q_u->server_name_ptr;
7733 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7734 q_u_local.level = q_u->level;
7735 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7737 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7740 /****************************************************************************
7741 ****************************************************************************/
7743 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7745 init_unistr(&info->name, name);
7748 /****************************************************************************
7749 ****************************************************************************/
7751 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7757 const char *short_archi;
7758 DRIVER_DIRECTORY_1 *info=NULL;
7759 WERROR result = WERR_OK;
7761 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7762 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7764 /* check for beginning double '\'s and that the server
7767 pservername = servername;
7768 if ( *pservername == '\\' && strlen(servername)>2 ) {
7772 if ( !is_myname_or_ipaddr( pservername ) )
7773 return WERR_INVALID_PARAM;
7775 if (!(short_archi = get_short_archi(long_archi)))
7776 return WERR_INVALID_ENVIRONMENT;
7778 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7781 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7783 DEBUG(4,("printer driver directory: [%s]\n", path));
7785 fill_driverdir_1(info, path);
7787 *needed += spoolss_size_driverdir_info_1(info);
7789 if (*needed > offered) {
7790 result = WERR_INSUFFICIENT_BUFFER;
7794 if (!rpcbuf_alloc_size(buffer, *needed)) {
7795 result = WERR_NOMEM;
7799 smb_io_driverdir_1("", buffer, info, 0);
7807 /****************************************************************************
7808 ****************************************************************************/
7810 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7812 UNISTR2 *name = &q_u->name;
7813 UNISTR2 *uni_environment = &q_u->environment;
7814 uint32 level = q_u->level;
7815 RPC_BUFFER *buffer = NULL;
7816 uint32 offered = q_u->offered;
7817 uint32 *needed = &r_u->needed;
7819 /* that's an [in out] buffer */
7821 if (!q_u->buffer && (offered!=0)) {
7822 return WERR_INVALID_PARAM;
7825 rpcbuf_move(q_u->buffer, &r_u->buffer);
7826 buffer = r_u->buffer;
7828 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7834 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7836 return WERR_UNKNOWN_LEVEL;
7840 /****************************************************************************
7841 ****************************************************************************/
7843 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7845 POLICY_HND *handle = &q_u->handle;
7846 uint32 idx = q_u->index;
7847 uint32 in_value_len = q_u->valuesize;
7848 uint32 in_data_len = q_u->datasize;
7849 uint32 *out_max_value_len = &r_u->valuesize;
7850 uint16 **out_value = &r_u->value;
7851 uint32 *out_value_len = &r_u->realvaluesize;
7852 uint32 *out_type = &r_u->type;
7853 uint32 *out_max_data_len = &r_u->datasize;
7854 uint8 **data_out = &r_u->data;
7855 uint32 *out_data_len = &r_u->realdatasize;
7857 NT_PRINTER_INFO_LEVEL *printer = NULL;
7859 uint32 biggest_valuesize;
7860 uint32 biggest_datasize;
7862 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7865 REGISTRY_VALUE *val = NULL;
7866 NT_PRINTER_DATA *p_data;
7867 int i, key_index, num_values;
7872 *out_max_data_len = 0;
7876 DEBUG(5,("spoolss_enumprinterdata\n"));
7879 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7883 if (!get_printer_snum(p,handle, &snum))
7886 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7887 if (!W_ERROR_IS_OK(result))
7890 p_data = printer->info_2->data;
7891 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7896 * The NT machine wants to know the biggest size of value and data
7898 * cf: MSDN EnumPrinterData remark section
7901 if ( !in_value_len && !in_data_len && (key_index != -1) )
7903 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7905 biggest_valuesize = 0;
7906 biggest_datasize = 0;
7908 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7910 for ( i=0; i<num_values; i++ )
7912 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7914 name_length = strlen(val->valuename);
7915 if ( strlen(val->valuename) > biggest_valuesize )
7916 biggest_valuesize = name_length;
7918 if ( val->size > biggest_datasize )
7919 biggest_datasize = val->size;
7921 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7925 /* the value is an UNICODE string but real_value_size is the length
7926 in bytes including the trailing 0 */
7928 *out_value_len = 2 * (1+biggest_valuesize);
7929 *out_data_len = biggest_datasize;
7931 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7937 * the value len is wrong in NT sp3
7938 * that's the number of bytes not the number of unicode chars
7941 if ( key_index != -1 )
7942 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7947 /* out_value should default to "" or else NT4 has
7948 problems unmarshalling the response */
7950 *out_max_value_len=(in_value_len/sizeof(uint16));
7952 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7954 result = WERR_NOMEM;
7958 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7960 /* the data is counted in bytes */
7962 *out_max_data_len = in_data_len;
7963 *out_data_len = in_data_len;
7965 /* only allocate when given a non-zero data_len */
7967 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7969 result = WERR_NOMEM;
7973 result = WERR_NO_MORE_ITEMS;
7979 * - counted in bytes in the request
7980 * - counted in UNICODE chars in the max reply
7981 * - counted in bytes in the real size
7983 * take a pause *before* coding not *during* coding
7987 *out_max_value_len=(in_value_len/sizeof(uint16));
7988 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7990 result = WERR_NOMEM;
7994 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
7998 *out_type = regval_type( val );
8000 /* data - counted in bytes */
8002 *out_max_data_len = in_data_len;
8003 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8005 result = WERR_NOMEM;
8008 data_len = regval_size(val);
8010 memcpy( *data_out, regval_data_p(val), data_len );
8011 *out_data_len = data_len;
8015 free_a_printer(&printer, 2);
8019 /****************************************************************************
8020 ****************************************************************************/
8022 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8024 POLICY_HND *handle = &q_u->handle;
8025 UNISTR2 *value = &q_u->value;
8026 uint32 type = q_u->type;
8027 uint8 *data = q_u->data;
8028 uint32 real_len = q_u->real_len;
8030 NT_PRINTER_INFO_LEVEL *printer = NULL;
8032 WERROR status = WERR_OK;
8033 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8036 DEBUG(5,("spoolss_setprinterdata\n"));
8039 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8043 if ( Printer->printer_type == SPLHND_SERVER ) {
8044 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8045 return WERR_INVALID_PARAM;
8048 if (!get_printer_snum(p,handle, &snum))
8052 * Access check : NT returns "access denied" if you make a
8053 * SetPrinterData call without the necessary privildge.
8054 * we were originally returning OK if nothing changed
8055 * which made Win2k issue **a lot** of SetPrinterData
8056 * when connecting to a printer --jerry
8059 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8061 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8062 status = WERR_ACCESS_DENIED;
8066 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8067 if (!W_ERROR_IS_OK(status))
8070 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8073 * When client side code sets a magic printer data key, detect it and save
8074 * the current printer data and the magic key's data (its the DEVMODE) for
8075 * future printer/driver initializations.
8077 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8079 /* Set devmode and printer initialization info */
8080 status = save_driver_init( printer, 2, data, real_len );
8082 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8086 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8087 type, data, real_len );
8088 if ( W_ERROR_IS_OK(status) )
8089 status = mod_a_printer(printer, 2);
8093 free_a_printer(&printer, 2);
8098 /****************************************************************************
8099 ****************************************************************************/
8101 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8103 POLICY_HND *handle = &q_u->handle;
8104 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8107 DEBUG(5,("_spoolss_resetprinter\n"));
8110 * All we do is to check to see if the handle and queue is valid.
8111 * This call really doesn't mean anything to us because we only
8112 * support RAW printing. --jerry
8116 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8120 if (!get_printer_snum(p,handle, &snum))
8124 /* blindly return success */
8129 /****************************************************************************
8130 ****************************************************************************/
8132 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8134 POLICY_HND *handle = &q_u->handle;
8135 UNISTR2 *value = &q_u->valuename;
8137 NT_PRINTER_INFO_LEVEL *printer = NULL;
8139 WERROR status = WERR_OK;
8140 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8143 DEBUG(5,("spoolss_deleteprinterdata\n"));
8146 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8150 if (!get_printer_snum(p, handle, &snum))
8153 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8154 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8155 return WERR_ACCESS_DENIED;
8158 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8159 if (!W_ERROR_IS_OK(status))
8162 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8164 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8166 if ( W_ERROR_IS_OK(status) )
8167 mod_a_printer( printer, 2 );
8169 free_a_printer(&printer, 2);
8174 /****************************************************************************
8175 ****************************************************************************/
8177 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8179 POLICY_HND *handle = &q_u->handle;
8180 FORM *form = &q_u->form;
8181 nt_forms_struct tmpForm;
8183 WERROR status = WERR_OK;
8184 NT_PRINTER_INFO_LEVEL *printer = NULL;
8187 nt_forms_struct *list=NULL;
8188 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8190 DEBUG(5,("spoolss_addform\n"));
8193 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8198 /* forms can be added on printer of on the print server handle */
8200 if ( Printer->printer_type == SPLHND_PRINTER )
8202 if (!get_printer_snum(p,handle, &snum))
8205 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8206 if (!W_ERROR_IS_OK(status))
8210 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8211 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8212 status = WERR_ACCESS_DENIED;
8216 /* can't add if builtin */
8218 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8219 status = WERR_ALREADY_EXISTS;
8223 count = get_ntforms(&list);
8225 if(!add_a_form(&list, form, &count)) {
8226 status = WERR_NOMEM;
8230 write_ntforms(&list, count);
8233 * ChangeID must always be set if this is a printer
8236 if ( Printer->printer_type == SPLHND_PRINTER )
8237 status = mod_a_printer(printer, 2);
8241 free_a_printer(&printer, 2);
8247 /****************************************************************************
8248 ****************************************************************************/
8250 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8252 POLICY_HND *handle = &q_u->handle;
8253 UNISTR2 *form_name = &q_u->name;
8254 nt_forms_struct tmpForm;
8256 nt_forms_struct *list=NULL;
8257 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8259 WERROR status = WERR_OK;
8260 NT_PRINTER_INFO_LEVEL *printer = NULL;
8262 DEBUG(5,("spoolss_deleteform\n"));
8265 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8269 /* forms can be deleted on printer of on the print server handle */
8271 if ( Printer->printer_type == SPLHND_PRINTER )
8273 if (!get_printer_snum(p,handle, &snum))
8276 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8277 if (!W_ERROR_IS_OK(status))
8281 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8282 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8283 status = WERR_ACCESS_DENIED;
8287 /* can't delete if builtin */
8289 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8290 status = WERR_INVALID_PARAM;
8294 count = get_ntforms(&list);
8296 if ( !delete_a_form(&list, form_name, &count, &status ))
8300 * ChangeID must always be set if this is a printer
8303 if ( Printer->printer_type == SPLHND_PRINTER )
8304 status = mod_a_printer(printer, 2);
8308 free_a_printer(&printer, 2);
8314 /****************************************************************************
8315 ****************************************************************************/
8317 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8319 POLICY_HND *handle = &q_u->handle;
8320 FORM *form = &q_u->form;
8321 nt_forms_struct tmpForm;
8323 WERROR status = WERR_OK;
8324 NT_PRINTER_INFO_LEVEL *printer = NULL;
8327 nt_forms_struct *list=NULL;
8328 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8330 DEBUG(5,("spoolss_setform\n"));
8333 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8337 /* forms can be modified on printer of on the print server handle */
8339 if ( Printer->printer_type == SPLHND_PRINTER )
8341 if (!get_printer_snum(p,handle, &snum))
8344 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8345 if (!W_ERROR_IS_OK(status))
8349 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8350 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8351 status = WERR_ACCESS_DENIED;
8355 /* can't set if builtin */
8356 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8357 status = WERR_INVALID_PARAM;
8361 count = get_ntforms(&list);
8362 update_a_form(&list, form, count);
8363 write_ntforms(&list, count);
8366 * ChangeID must always be set if this is a printer
8369 if ( Printer->printer_type == SPLHND_PRINTER )
8370 status = mod_a_printer(printer, 2);
8375 free_a_printer(&printer, 2);
8381 /****************************************************************************
8382 enumprintprocessors level 1.
8383 ****************************************************************************/
8385 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8387 PRINTPROCESSOR_1 *info_1=NULL;
8388 WERROR result = WERR_OK;
8390 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8395 init_unistr(&info_1->name, "winprint");
8397 *needed += spoolss_size_printprocessor_info_1(info_1);
8399 if (*needed > offered) {
8400 result = WERR_INSUFFICIENT_BUFFER;
8404 if (!rpcbuf_alloc_size(buffer, *needed)) {
8405 result = WERR_NOMEM;
8409 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8414 if ( !W_ERROR_IS_OK(result) )
8420 /****************************************************************************
8421 ****************************************************************************/
8423 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8425 uint32 level = q_u->level;
8426 RPC_BUFFER *buffer = NULL;
8427 uint32 offered = q_u->offered;
8428 uint32 *needed = &r_u->needed;
8429 uint32 *returned = &r_u->returned;
8431 /* that's an [in out] buffer */
8433 if (!q_u->buffer && (offered!=0)) {
8434 return WERR_INVALID_PARAM;
8437 rpcbuf_move(q_u->buffer, &r_u->buffer);
8438 buffer = r_u->buffer;
8440 DEBUG(5,("spoolss_enumprintprocessors\n"));
8443 * Enumerate the print processors ...
8445 * Just reply with "winprint", to keep NT happy
8446 * and I can use my nice printer checker.
8454 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8456 return WERR_UNKNOWN_LEVEL;
8460 /****************************************************************************
8461 enumprintprocdatatypes level 1.
8462 ****************************************************************************/
8464 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8466 PRINTPROCDATATYPE_1 *info_1=NULL;
8467 WERROR result = WERR_NOMEM;
8469 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8474 init_unistr(&info_1->name, "RAW");
8476 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8478 if (*needed > offered) {
8479 result = WERR_INSUFFICIENT_BUFFER;
8483 if (!rpcbuf_alloc_size(buffer, *needed)) {
8484 result = WERR_NOMEM;
8488 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8493 if ( !W_ERROR_IS_OK(result) )
8499 /****************************************************************************
8500 ****************************************************************************/
8502 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8504 uint32 level = q_u->level;
8505 RPC_BUFFER *buffer = NULL;
8506 uint32 offered = q_u->offered;
8507 uint32 *needed = &r_u->needed;
8508 uint32 *returned = &r_u->returned;
8510 /* that's an [in out] buffer */
8512 if (!q_u->buffer && (offered!=0)) {
8513 return WERR_INVALID_PARAM;
8516 rpcbuf_move(q_u->buffer, &r_u->buffer);
8517 buffer = r_u->buffer;
8519 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8526 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8528 return WERR_UNKNOWN_LEVEL;
8532 /****************************************************************************
8533 enumprintmonitors level 1.
8534 ****************************************************************************/
8536 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8538 PRINTMONITOR_1 *info_1;
8539 WERROR result = WERR_OK;
8542 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8547 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8548 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8550 for ( i=0; i<*returned; i++ ) {
8551 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8554 if (*needed > offered) {
8555 result = WERR_INSUFFICIENT_BUFFER;
8559 if (!rpcbuf_alloc_size(buffer, *needed)) {
8560 result = WERR_NOMEM;
8564 for ( i=0; i<*returned; i++ ) {
8565 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8571 if ( !W_ERROR_IS_OK(result) )
8577 /****************************************************************************
8578 enumprintmonitors level 2.
8579 ****************************************************************************/
8581 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8583 PRINTMONITOR_2 *info_2;
8584 WERROR result = WERR_OK;
8587 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8592 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8593 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8594 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8596 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8597 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8598 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8600 for ( i=0; i<*returned; i++ ) {
8601 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8604 if (*needed > offered) {
8605 result = WERR_INSUFFICIENT_BUFFER;
8609 if (!rpcbuf_alloc_size(buffer, *needed)) {
8610 result = WERR_NOMEM;
8614 for ( i=0; i<*returned; i++ ) {
8615 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8621 if ( !W_ERROR_IS_OK(result) )
8627 /****************************************************************************
8628 ****************************************************************************/
8630 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8632 uint32 level = q_u->level;
8633 RPC_BUFFER *buffer = NULL;
8634 uint32 offered = q_u->offered;
8635 uint32 *needed = &r_u->needed;
8636 uint32 *returned = &r_u->returned;
8638 /* that's an [in out] buffer */
8640 if (!q_u->buffer && (offered!=0)) {
8641 return WERR_INVALID_PARAM;
8644 rpcbuf_move(q_u->buffer, &r_u->buffer);
8645 buffer = r_u->buffer;
8647 DEBUG(5,("spoolss_enumprintmonitors\n"));
8650 * Enumerate the print monitors ...
8652 * Just reply with "Local Port", to keep NT happy
8653 * and I can use my nice printer checker.
8661 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8663 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8665 return WERR_UNKNOWN_LEVEL;
8669 /****************************************************************************
8670 ****************************************************************************/
8672 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8673 NT_PRINTER_INFO_LEVEL *ntprinter,
8674 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8679 JOB_INFO_1 *info_1=NULL;
8680 WERROR result = WERR_OK;
8682 info_1=SMB_MALLOC_P(JOB_INFO_1);
8684 if (info_1 == NULL) {
8688 for (i=0; i<count && found==False; i++) {
8689 if ((*queue)[i].job==(int)jobid)
8695 /* NT treats not found as bad param... yet another bad choice */
8696 return WERR_INVALID_PARAM;
8699 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8701 *needed += spoolss_size_job_info_1(info_1);
8703 if (*needed > offered) {
8704 result = WERR_INSUFFICIENT_BUFFER;
8708 if (!rpcbuf_alloc_size(buffer, *needed)) {
8709 result = WERR_NOMEM;
8713 smb_io_job_info_1("", buffer, info_1, 0);
8721 /****************************************************************************
8722 ****************************************************************************/
8724 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8725 NT_PRINTER_INFO_LEVEL *ntprinter,
8726 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8733 DEVICEMODE *devmode = NULL;
8734 NT_DEVICEMODE *nt_devmode = NULL;
8736 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8739 ZERO_STRUCTP(info_2);
8741 for ( i=0; i<count && found==False; i++ )
8743 if ((*queue)[i].job == (int)jobid)
8748 /* NT treats not found as bad param... yet another bad
8750 result = WERR_INVALID_PARAM;
8755 * if the print job does not have a DEVMODE associated with it,
8756 * just use the one for the printer. A NULL devicemode is not
8757 * a failure condition
8760 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8761 devmode = construct_dev_mode(lp_const_servicename(snum));
8763 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8764 ZERO_STRUCTP( devmode );
8765 convert_nt_devicemode( devmode, nt_devmode );
8769 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8771 *needed += spoolss_size_job_info_2(info_2);
8773 if (*needed > offered) {
8774 result = WERR_INSUFFICIENT_BUFFER;
8778 if (!rpcbuf_alloc_size(buffer, *needed)) {
8779 result = WERR_NOMEM;
8783 smb_io_job_info_2("", buffer, info_2, 0);
8788 /* Cleanup allocated memory */
8790 free_job_info_2(info_2); /* Also frees devmode */
8796 /****************************************************************************
8797 ****************************************************************************/
8799 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8801 POLICY_HND *handle = &q_u->handle;
8802 uint32 jobid = q_u->jobid;
8803 uint32 level = q_u->level;
8804 RPC_BUFFER *buffer = NULL;
8805 uint32 offered = q_u->offered;
8806 uint32 *needed = &r_u->needed;
8807 WERROR wstatus = WERR_OK;
8808 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8811 print_queue_struct *queue = NULL;
8812 print_status_struct prt_status;
8814 /* that's an [in out] buffer */
8816 if (!q_u->buffer && (offered!=0)) {
8817 return WERR_INVALID_PARAM;
8820 rpcbuf_move(q_u->buffer, &r_u->buffer);
8821 buffer = r_u->buffer;
8823 DEBUG(5,("spoolss_getjob\n"));
8827 if (!get_printer_snum(p, handle, &snum))
8830 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8831 if ( !W_ERROR_IS_OK(wstatus) )
8834 count = print_queue_status(snum, &queue, &prt_status);
8836 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8837 count, prt_status.status, prt_status.message));
8841 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8842 buffer, offered, needed);
8845 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8846 buffer, offered, needed);
8849 wstatus = WERR_UNKNOWN_LEVEL;
8854 free_a_printer( &ntprinter, 2 );
8859 /********************************************************************
8860 spoolss_getprinterdataex
8862 From MSDN documentation of GetPrinterDataEx: pass request
8863 to GetPrinterData if key is "PrinterDriverData".
8864 ********************************************************************/
8866 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8868 POLICY_HND *handle = &q_u->handle;
8869 uint32 in_size = q_u->size;
8870 uint32 *type = &r_u->type;
8871 uint32 *out_size = &r_u->size;
8872 uint8 **data = &r_u->data;
8873 uint32 *needed = &r_u->needed;
8874 fstring keyname, valuename;
8876 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8878 NT_PRINTER_INFO_LEVEL *printer = NULL;
8880 WERROR status = WERR_OK;
8882 DEBUG(4,("_spoolss_getprinterdataex\n"));
8884 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8885 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8887 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8888 keyname, valuename));
8890 /* in case of problem, return some default values */
8894 *out_size = in_size;
8897 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8898 status = WERR_BADFID;
8902 /* Is the handle to a printer or to the server? */
8904 if (Printer->printer_type == SPLHND_SERVER) {
8905 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8906 status = WERR_INVALID_PARAM;
8910 if ( !get_printer_snum(p,handle, &snum) )
8913 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8914 if ( !W_ERROR_IS_OK(status) )
8917 /* check to see if the keyname is valid */
8918 if ( !strlen(keyname) ) {
8919 status = WERR_INVALID_PARAM;
8923 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8924 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8925 free_a_printer( &printer, 2 );
8926 status = WERR_BADFILE;
8930 /* When given a new keyname, we should just create it */
8932 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8934 if (*needed > *out_size)
8935 status = WERR_MORE_DATA;
8938 if ( !W_ERROR_IS_OK(status) )
8940 DEBUG(5, ("error: allocating %d\n", *out_size));
8942 /* reply this param doesn't exist */
8946 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8947 status = WERR_NOMEM;
8957 free_a_printer( &printer, 2 );
8962 /********************************************************************
8963 * spoolss_setprinterdataex
8964 ********************************************************************/
8966 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8968 POLICY_HND *handle = &q_u->handle;
8969 uint32 type = q_u->type;
8970 uint8 *data = q_u->data;
8971 uint32 real_len = q_u->real_len;
8973 NT_PRINTER_INFO_LEVEL *printer = NULL;
8975 WERROR status = WERR_OK;
8976 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8981 DEBUG(4,("_spoolss_setprinterdataex\n"));
8983 /* From MSDN documentation of SetPrinterDataEx: pass request to
8984 SetPrinterData if key is "PrinterDriverData" */
8987 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8991 if ( Printer->printer_type == SPLHND_SERVER ) {
8992 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8993 return WERR_INVALID_PARAM;
8996 if ( !get_printer_snum(p,handle, &snum) )
9000 * Access check : NT returns "access denied" if you make a
9001 * SetPrinterData call without the necessary privildge.
9002 * we were originally returning OK if nothing changed
9003 * which made Win2k issue **a lot** of SetPrinterData
9004 * when connecting to a printer --jerry
9007 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9009 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9010 return WERR_ACCESS_DENIED;
9013 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9014 if (!W_ERROR_IS_OK(status))
9017 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9018 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9020 /* check for OID in valuename */
9022 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9028 /* save the registry data */
9030 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9032 if ( W_ERROR_IS_OK(status) )
9034 /* save the OID if one was specified */
9036 fstrcat( keyname, "\\" );
9037 fstrcat( keyname, SPOOL_OID_KEY );
9040 * I'm not checking the status here on purpose. Don't know
9041 * if this is right, but I'm returning the status from the
9042 * previous set_printer_dataex() call. I have no idea if
9043 * this is right. --jerry
9046 set_printer_dataex( printer, keyname, valuename,
9047 REG_SZ, (uint8 *)oid_string,
9048 strlen(oid_string)+1 );
9051 status = mod_a_printer(printer, 2);
9054 free_a_printer(&printer, 2);
9060 /********************************************************************
9061 * spoolss_deleteprinterdataex
9062 ********************************************************************/
9064 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9066 POLICY_HND *handle = &q_u->handle;
9067 UNISTR2 *value = &q_u->valuename;
9068 UNISTR2 *key = &q_u->keyname;
9070 NT_PRINTER_INFO_LEVEL *printer = NULL;
9072 WERROR status = WERR_OK;
9073 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9074 pstring valuename, keyname;
9076 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9079 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9083 if (!get_printer_snum(p, handle, &snum))
9086 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9087 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9088 return WERR_ACCESS_DENIED;
9091 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9092 if (!W_ERROR_IS_OK(status))
9095 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9096 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9098 status = delete_printer_dataex( printer, keyname, valuename );
9100 if ( W_ERROR_IS_OK(status) )
9101 mod_a_printer( printer, 2 );
9103 free_a_printer(&printer, 2);
9108 /********************************************************************
9109 * spoolss_enumprinterkey
9110 ********************************************************************/
9113 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9116 fstring *keynames = NULL;
9117 uint16 *enumkeys = NULL;
9120 POLICY_HND *handle = &q_u->handle;
9121 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9122 NT_PRINTER_DATA *data;
9123 NT_PRINTER_INFO_LEVEL *printer = NULL;
9125 WERROR status = WERR_BADFILE;
9128 DEBUG(4,("_spoolss_enumprinterkey\n"));
9131 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9135 if ( !get_printer_snum(p,handle, &snum) )
9138 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9139 if (!W_ERROR_IS_OK(status))
9142 /* get the list of subkey names */
9144 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9145 data = printer->info_2->data;
9147 num_keys = get_printer_subkeys( data, key, &keynames );
9149 if ( num_keys == -1 ) {
9150 status = WERR_BADFILE;
9154 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9156 r_u->needed = printerkey_len*2;
9158 if ( q_u->size < r_u->needed ) {
9159 status = WERR_MORE_DATA;
9163 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9164 status = WERR_NOMEM;
9170 if ( q_u->size < r_u->needed )
9171 status = WERR_MORE_DATA;
9174 free_a_printer( &printer, 2 );
9175 SAFE_FREE( keynames );
9180 /********************************************************************
9181 * spoolss_deleteprinterkey
9182 ********************************************************************/
9184 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9186 POLICY_HND *handle = &q_u->handle;
9187 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9189 NT_PRINTER_INFO_LEVEL *printer = NULL;
9193 DEBUG(5,("spoolss_deleteprinterkey\n"));
9196 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9200 /* if keyname == NULL, return error */
9202 if ( !q_u->keyname.buffer )
9203 return WERR_INVALID_PARAM;
9205 if (!get_printer_snum(p, handle, &snum))
9208 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9209 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9210 return WERR_ACCESS_DENIED;
9213 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9214 if (!W_ERROR_IS_OK(status))
9217 /* delete the key and all subneys */
9219 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9221 status = delete_all_printer_data( printer->info_2, key );
9223 if ( W_ERROR_IS_OK(status) )
9224 status = mod_a_printer(printer, 2);
9226 free_a_printer( &printer, 2 );
9232 /********************************************************************
9233 * spoolss_enumprinterdataex
9234 ********************************************************************/
9236 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9238 POLICY_HND *handle = &q_u->handle;
9239 uint32 in_size = q_u->size;
9242 NT_PRINTER_INFO_LEVEL *printer = NULL;
9243 PRINTER_ENUM_VALUES *enum_values = NULL;
9244 NT_PRINTER_DATA *p_data;
9246 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9251 REGISTRY_VALUE *val;
9256 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9259 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9264 * first check for a keyname of NULL or "". Win2k seems to send
9265 * this a lot and we should send back WERR_INVALID_PARAM
9266 * no need to spend time looking up the printer in this case.
9270 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9271 if ( !strlen(key) ) {
9272 result = WERR_INVALID_PARAM;
9276 /* get the printer off of disk */
9278 if (!get_printer_snum(p,handle, &snum))
9281 ZERO_STRUCT(printer);
9282 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9283 if (!W_ERROR_IS_OK(result))
9286 /* now look for a match on the key name */
9288 p_data = printer->info_2->data;
9290 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9291 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9293 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9294 result = WERR_INVALID_PARAM;
9301 /* allocate the memory for the array of pointers -- if necessary */
9303 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9306 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9308 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9309 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9310 result = WERR_NOMEM;
9314 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9318 * loop through all params and build the array to pass
9319 * back to the client
9322 for ( i=0; i<num_entries; i++ )
9324 /* lookup the registry value */
9326 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9327 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9331 value_name = regval_name( val );
9332 init_unistr( &enum_values[i].valuename, value_name );
9333 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9334 enum_values[i].type = regval_type( val );
9336 data_len = regval_size( val );
9338 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9340 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9342 result = WERR_NOMEM;
9346 enum_values[i].data_len = data_len;
9348 /* keep track of the size of the array in bytes */
9350 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9353 /* housekeeping information in the reply */
9355 r_u->needed = needed;
9356 r_u->returned = num_entries;
9358 if (needed > in_size) {
9359 result = WERR_MORE_DATA;
9363 /* copy data into the reply */
9365 r_u->ctr.size = r_u->needed;
9366 r_u->ctr.size_of_array = r_u->returned;
9367 r_u->ctr.values = enum_values;
9373 free_a_printer(&printer, 2);
9378 /****************************************************************************
9379 ****************************************************************************/
9381 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9383 init_unistr(&info->name, name);
9386 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9387 UNISTR2 *environment,
9394 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9395 WERROR result = WERR_OK;
9397 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9399 if (!get_short_archi(long_archi))
9400 return WERR_INVALID_ENVIRONMENT;
9402 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9405 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9407 fill_printprocessordirectory_1(info, path);
9409 *needed += spoolss_size_printprocessordirectory_info_1(info);
9411 if (*needed > offered) {
9412 result = WERR_INSUFFICIENT_BUFFER;
9416 if (!rpcbuf_alloc_size(buffer, *needed)) {
9417 result = WERR_INSUFFICIENT_BUFFER;
9421 smb_io_printprocessordirectory_1("", buffer, info, 0);
9429 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9431 uint32 level = q_u->level;
9432 RPC_BUFFER *buffer = NULL;
9433 uint32 offered = q_u->offered;
9434 uint32 *needed = &r_u->needed;
9437 /* that's an [in out] buffer */
9439 if (!q_u->buffer && (offered!=0)) {
9440 return WERR_INVALID_PARAM;
9443 rpcbuf_move(q_u->buffer, &r_u->buffer);
9444 buffer = r_u->buffer;
9446 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9452 result = getprintprocessordirectory_level_1
9453 (&q_u->name, &q_u->environment, buffer, offered, needed);
9456 result = WERR_UNKNOWN_LEVEL;
9462 /*******************************************************************
9463 Streams the monitor UI DLL name in UNICODE
9464 *******************************************************************/
9466 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9467 RPC_BUFFER *out, uint32 *needed )
9469 const char *dllname = "tcpmonui.dll";
9471 *needed = (strlen(dllname)+1) * 2;
9473 if ( rpcbuf_get_size(out) < *needed ) {
9474 return WERR_INSUFFICIENT_BUFFER;
9477 if ( !make_monitorui_buf( out, dllname ) ) {
9484 /*******************************************************************
9485 Create a new TCP/IP port
9486 *******************************************************************/
9488 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9489 RPC_BUFFER *out, uint32 *needed )
9491 NT_PORT_DATA_1 port1;
9494 ZERO_STRUCT( port1 );
9496 /* convert to our internal port data structure */
9498 if ( !convert_port_data_1( &port1, in ) ) {
9502 /* create the device URI and call the add_port_hook() */
9504 switch ( port1.protocol ) {
9505 case PORT_PROTOCOL_DIRECT:
9506 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9509 case PORT_PROTOCOL_LPR:
9510 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9514 return WERR_UNKNOWN_PORT;
9517 return add_port_hook( token, port1.name, device_uri );
9520 /*******************************************************************
9521 *******************************************************************/
9523 struct xcv_api_table xcvtcp_cmds[] = {
9524 { "MonitorUI", xcvtcp_monitorui },
9525 { "AddPort", xcvtcp_addport},
9529 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9530 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9535 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9537 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9538 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9539 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9542 return WERR_BADFUNC;
9545 /*******************************************************************
9546 *******************************************************************/
9547 #if 0 /* don't support management using the "Local Port" monitor */
9549 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9550 RPC_BUFFER *out, uint32 *needed )
9552 const char *dllname = "localui.dll";
9554 *needed = (strlen(dllname)+1) * 2;
9556 if ( rpcbuf_get_size(out) < *needed ) {
9557 return WERR_INSUFFICIENT_BUFFER;
9560 if ( !make_monitorui_buf( out, dllname )) {
9567 /*******************************************************************
9568 *******************************************************************/
9570 struct xcv_api_table xcvlocal_cmds[] = {
9571 { "MonitorUI", xcvlocal_monitorui },
9575 struct xcv_api_table xcvlocal_cmds[] = {
9582 /*******************************************************************
9583 *******************************************************************/
9585 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9586 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9591 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9593 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9594 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9595 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9597 return WERR_BADFUNC;
9600 /*******************************************************************
9601 *******************************************************************/
9603 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9605 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9609 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9613 /* Has to be a handle to the TCP/IP port monitor */
9615 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9616 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9620 /* requires administrative access to the server */
9622 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9623 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9624 return WERR_ACCESS_DENIED;
9627 /* Get the command name. There's numerous commands supported by the
9628 TCPMON interface. */
9630 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9631 q_u->dataname.uni_str_len*2, 0);
9633 /* Allocate the outgoing buffer */
9635 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9637 switch ( Printer->printer_type ) {
9638 case SPLHND_PORTMON_TCP:
9639 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9640 &q_u->indata, &r_u->outdata, &r_u->needed );
9641 case SPLHND_PORTMON_LOCAL:
9642 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9643 &q_u->indata, &r_u->outdata, &r_u->needed );
9646 return WERR_INVALID_PRINT_MONITOR;