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 /* Table to map the driver version */
46 static const char * drv_ver_to_os[] = {
47 "WIN9X", /* driver version/cversion 0 */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
53 static const char *get_drv_ver_to_os(int ver)
55 if (ver < 0 || ver > 3)
57 return drv_ver_to_os[ver];
61 const char *long_archi;
62 const char *short_archi;
66 static Printer_entry *printers_list;
68 typedef struct _counter_printer_0 {
69 struct _counter_printer_0 *next;
70 struct _counter_printer_0 *prev;
76 static counter_printer_0 *counter_list;
78 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
79 static uint32 smb_connections=0;
82 /* in printing/nt_printing.c */
84 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
86 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
87 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
90 /* API table for Xcv Monitor functions */
92 struct xcv_api_table {
94 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
98 /* translate between internal status numbers and NT status numbers */
99 static int nt_printj_status(int v)
105 return JOB_STATUS_PAUSED;
107 return JOB_STATUS_SPOOLING;
109 return JOB_STATUS_PRINTING;
111 return JOB_STATUS_ERROR;
113 return JOB_STATUS_DELETING;
115 return JOB_STATUS_OFFLINE;
117 return JOB_STATUS_PAPEROUT;
119 return JOB_STATUS_PRINTED;
121 return JOB_STATUS_DELETED;
123 return JOB_STATUS_BLOCKED;
124 case LPQ_USER_INTERVENTION:
125 return JOB_STATUS_USER_INTERVENTION;
130 static int nt_printq_status(int v)
134 return PRINTER_STATUS_PAUSED;
143 /****************************************************************************
144 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
145 ****************************************************************************/
147 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
152 SAFE_FREE((*pp)->ctr.type);
156 /***************************************************************************
157 Disconnect from the client
158 ****************************************************************************/
160 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
165 * Tell the specific printing tdb we no longer want messages for this printer
166 * by deregistering our PID.
169 if (!print_notify_deregister_pid(snum))
170 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
172 /* weird if the test succeds !!! */
173 if (smb_connections==0) {
174 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
178 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
180 if (!W_ERROR_IS_OK(result))
181 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
182 dos_errstr(result)));
184 /* if it's the last connection, deconnect the IPC$ share */
185 if (smb_connections==1) {
187 cli_shutdown( notify_cli_pipe->cli );
188 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
190 message_deregister(MSG_PRINTER_NOTIFY2);
192 /* Tell the connections db we're no longer interested in
193 * printer notify messages. */
195 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
201 /****************************************************************************
202 Functions to free a printer entry datastruct.
203 ****************************************************************************/
205 static void free_printer_entry(void *ptr)
207 Printer_entry *Printer = (Printer_entry *)ptr;
209 if (Printer->notify.client_connected==True) {
212 if ( Printer->printer_type == SPLHND_SERVER) {
214 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
215 } else if (Printer->printer_type == SPLHND_PRINTER) {
216 snum = print_queue_snum(Printer->sharename);
218 srv_spoolss_replycloseprinter(snum,
219 &Printer->notify.client_hnd);
223 Printer->notify.flags=0;
224 Printer->notify.options=0;
225 Printer->notify.localmachine[0]='\0';
226 Printer->notify.printerlocal=0;
227 free_spool_notify_option(&Printer->notify.option);
228 Printer->notify.option=NULL;
229 Printer->notify.client_connected=False;
231 free_nt_devicemode( &Printer->nt_devmode );
232 free_a_printer( &Printer->printer_info, 2 );
234 talloc_destroy( Printer->ctx );
236 /* Remove from the internal list. */
237 DLIST_REMOVE(printers_list, Printer);
242 /****************************************************************************
243 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
244 ****************************************************************************/
246 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
248 SPOOL_NOTIFY_OPTION *new_sp = NULL;
253 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
260 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
262 if (!new_sp->ctr.type) {
271 /****************************************************************************
272 find printer index by handle
273 ****************************************************************************/
275 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
277 Printer_entry *find_printer = NULL;
279 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
280 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
287 /****************************************************************************
288 Close printer index by handle.
289 ****************************************************************************/
291 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
293 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
296 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
300 close_policy_hnd(p, hnd);
305 /****************************************************************************
306 Delete a printer given a handle.
307 ****************************************************************************/
308 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
310 char *cmd = lp_deleteprinter_cmd();
313 SE_PRIV se_printop = SE_PRINT_OPERATOR;
314 BOOL is_print_op = False;
316 /* can't fail if we don't try */
321 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
324 is_print_op = user_has_privileges( token, &se_printop );
326 DEBUG(10,("Running [%s]\n", command));
328 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
333 if ( (ret = smbrun(command, NULL)) == 0 ) {
334 /* Tell everyone we updated smb.conf. */
335 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
341 /********** END SePrintOperatorPrivlege BLOCK **********/
343 DEBUGADD(10,("returned [%d]\n", ret));
346 return WERR_BADFID; /* What to return here? */
348 /* go ahead and re-read the services immediately */
349 reload_services( False );
351 if ( lp_servicenumber( sharename ) < 0 )
352 return WERR_ACCESS_DENIED;
357 /****************************************************************************
358 Delete a printer given a handle.
359 ****************************************************************************/
361 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
363 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
366 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
371 * It turns out that Windows allows delete printer on a handle
372 * opened by an admin user, then used on a pipe handle created
373 * by an anonymous user..... but they're working on security.... riiight !
377 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
378 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
379 return WERR_ACCESS_DENIED;
382 /* this does not need a become root since the access check has been
383 done on the handle already */
385 if (del_a_printer( Printer->sharename ) != 0) {
386 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
390 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
393 /****************************************************************************
394 Return the snum of a printer corresponding to an handle.
395 ****************************************************************************/
397 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
399 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
402 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
406 switch (Printer->printer_type) {
408 DEBUG(4,("short name:%s\n", Printer->sharename));
409 *number = print_queue_snum(Printer->sharename);
410 return (*number != -1);
418 /****************************************************************************
419 Set printer handle type.
420 Check if it's \\server or \\server\printer
421 ****************************************************************************/
423 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
425 DEBUG(3,("Setting printer type=%s\n", handlename));
427 if ( strlen(handlename) < 3 ) {
428 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
432 /* it's a print server */
433 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
434 DEBUGADD(4,("Printer is a print server\n"));
435 Printer->printer_type = SPLHND_SERVER;
437 /* it's a printer (set_printer_hnd_name() will handle port monitors */
439 DEBUGADD(4,("Printer is a printer\n"));
440 Printer->printer_type = SPLHND_PRINTER;
446 /****************************************************************************
447 Set printer handle name.. Accept names like \\server, \\server\printer,
448 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
449 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
450 XcvDataPort() interface.
451 ****************************************************************************/
453 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
456 int n_services=lp_numservices();
457 char *aprinter, *printername;
458 const char *servername;
461 NT_PRINTER_INFO_LEVEL *printer;
464 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
466 aprinter = handlename;
467 if ( *handlename == '\\' ) {
468 servername = handlename + 2;
469 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
478 /* save the servername to fill in replies on this handle */
480 if ( !is_myname_or_ipaddr( servername ) )
483 fstrcpy( Printer->servername, servername );
485 if ( Printer->printer_type == SPLHND_SERVER )
488 if ( Printer->printer_type != SPLHND_PRINTER )
491 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
493 /* check for the Port Monitor Interface */
495 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
496 Printer->printer_type = SPLHND_PORTMON_TCP;
497 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
500 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
501 Printer->printer_type = SPLHND_PORTMON_LOCAL;
502 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
506 /* Search all sharenames first as this is easier than pulling
507 the printer_info_2 off of disk. Don't use find_service() since
508 that calls out to map_username() */
510 /* do another loop to look for printernames */
512 for (snum=0; !found && snum<n_services; snum++) {
514 /* no point going on if this is not a printer */
516 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
519 fstrcpy(sname, lp_servicename(snum));
520 if ( strequal( aprinter, sname ) ) {
525 /* no point looking up the printer object if
526 we aren't allowing printername != sharename */
528 if ( lp_force_printername(snum) )
531 fstrcpy(sname, lp_servicename(snum));
534 result = get_a_printer( NULL, &printer, 2, sname );
535 if ( !W_ERROR_IS_OK(result) ) {
536 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
537 sname, dos_errstr(result)));
541 /* printername is always returned as \\server\printername */
542 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
543 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
544 printer->info_2->printername));
545 free_a_printer( &printer, 2);
551 if ( strequal(printername, aprinter) ) {
556 DEBUGADD(10, ("printername: %s\n", printername));
558 free_a_printer( &printer, 2);
562 DEBUGADD(4,("Printer not found\n"));
566 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
568 fstrcpy(Printer->sharename, sname);
573 /****************************************************************************
574 Find first available printer slot. creates a printer handle for you.
575 ****************************************************************************/
577 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
579 Printer_entry *new_printer;
581 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
583 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
586 ZERO_STRUCTP(new_printer);
588 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
589 SAFE_FREE(new_printer);
593 /* Add to the internal list. */
594 DLIST_ADD(printers_list, new_printer);
596 new_printer->notify.option=NULL;
598 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
599 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
600 close_printer_handle(p, hnd);
604 if (!set_printer_hnd_printertype(new_printer, name)) {
605 close_printer_handle(p, hnd);
609 if (!set_printer_hnd_name(new_printer, name)) {
610 close_printer_handle(p, hnd);
614 new_printer->access_granted = access_granted;
616 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
621 /***************************************************************************
622 check to see if the client motify handle is monitoring the notification
623 given by (notify_type, notify_field).
624 **************************************************************************/
626 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
632 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
635 SPOOL_NOTIFY_OPTION *option = p->notify.option;
639 * Flags should always be zero when the change notify
640 * is registered by the client's spooler. A user Win32 app
641 * might use the flags though instead of the NOTIFY_OPTION_INFO
650 return is_monitoring_event_flags(
651 p->notify.flags, notify_type, notify_field);
653 for (i = 0; i < option->count; i++) {
655 /* Check match for notify_type */
657 if (option->ctr.type[i].type != notify_type)
660 /* Check match for field */
662 for (j = 0; j < option->ctr.type[i].count; j++) {
663 if (option->ctr.type[i].fields[j] == notify_field) {
669 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
670 p->servername, p->sharename, notify_type, notify_field));
675 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
677 static void notify_one_value(struct spoolss_notify_msg *msg,
678 SPOOL_NOTIFY_INFO_DATA *data,
681 data->notify_data.value[0] = msg->notify.value[0];
682 data->notify_data.value[1] = 0;
685 static void notify_string(struct spoolss_notify_msg *msg,
686 SPOOL_NOTIFY_INFO_DATA *data,
691 /* The length of the message includes the trailing \0 */
693 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
695 data->notify_data.data.length = msg->len * 2;
696 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
698 if (!data->notify_data.data.string) {
699 data->notify_data.data.length = 0;
703 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
706 static void notify_system_time(struct spoolss_notify_msg *msg,
707 SPOOL_NOTIFY_INFO_DATA *data,
713 if (msg->len != sizeof(time_t)) {
714 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
719 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
720 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
724 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
725 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
729 if (!spoolss_io_system_time("", &ps, 0, &systime))
732 data->notify_data.data.length = prs_offset(&ps);
733 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
735 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
740 struct notify2_message_table {
742 void (*fn)(struct spoolss_notify_msg *msg,
743 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
746 static struct notify2_message_table printer_notify_table[] = {
747 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
748 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
749 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
750 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
751 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
752 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
753 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
754 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
755 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
756 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
757 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
758 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
759 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
760 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
761 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
762 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
763 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
764 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
765 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
768 static struct notify2_message_table job_notify_table[] = {
769 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
770 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
771 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
772 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
773 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
774 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
775 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
776 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
777 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
778 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
779 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
780 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
781 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
782 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
783 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
784 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
785 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
786 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
787 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
788 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
789 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
790 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
791 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
792 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
796 /***********************************************************************
797 Allocate talloc context for container object
798 **********************************************************************/
800 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
805 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
810 /***********************************************************************
811 release all allocated memory and zero out structure
812 **********************************************************************/
814 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
820 talloc_destroy(ctr->ctx);
827 /***********************************************************************
828 **********************************************************************/
830 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
838 /***********************************************************************
839 **********************************************************************/
841 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
843 if ( !ctr || !ctr->msg_groups )
846 if ( idx >= ctr->num_groups )
849 return &ctr->msg_groups[idx];
853 /***********************************************************************
854 How many groups of change messages do we have ?
855 **********************************************************************/
857 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
862 return ctr->num_groups;
865 /***********************************************************************
866 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
867 **********************************************************************/
869 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
871 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
872 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
873 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
879 /* loop over all groups looking for a matching printer name */
881 for ( i=0; i<ctr->num_groups; i++ ) {
882 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
886 /* add a new group? */
888 if ( i == ctr->num_groups ) {
891 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
892 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
895 ctr->msg_groups = groups;
897 /* clear the new entry and set the printer name */
899 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
900 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
903 /* add the change messages; 'i' is the correct index now regardless */
905 msg_grp = &ctr->msg_groups[i];
909 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
910 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
913 msg_grp->msgs = msg_list;
915 new_slot = msg_grp->num_msgs-1;
916 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
918 /* need to allocate own copy of data */
921 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
923 return ctr->num_groups;
926 /***********************************************************************
927 Send a change notication message on all handles which have a call
929 **********************************************************************/
931 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
934 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
935 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
936 SPOOLSS_NOTIFY_MSG *messages;
937 int sending_msg_count;
940 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
944 messages = msg_group->msgs;
947 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
951 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
953 /* loop over all printers */
955 for (p = printers_list; p; p = p->next) {
956 SPOOL_NOTIFY_INFO_DATA *data;
961 /* Is there notification on this handle? */
963 if ( !p->notify.client_connected )
966 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
968 /* For this printer? Print servers always receive
971 if ( ( p->printer_type == SPLHND_PRINTER ) &&
972 ( !strequal(msg_group->printername, p->sharename) ) )
975 DEBUG(10,("Our printer\n"));
977 /* allocate the max entries possible */
979 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
982 /* build the array of change notifications */
984 sending_msg_count = 0;
986 for ( i=0; i<msg_group->num_msgs; i++ ) {
987 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
989 /* Are we monitoring this event? */
991 if (!is_monitoring_event(p, msg->type, msg->field))
997 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
998 msg->type, msg->field, p->sharename));
1001 * if the is a printer notification handle and not a job notification
1002 * type, then set the id to 0. Other wise just use what was specified
1005 * When registering change notification on a print server handle
1006 * we always need to send back the id (snum) matching the printer
1007 * for which the change took place. For change notify registered
1008 * on a printer handle, this does not matter and the id should be 0.
1013 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1019 /* Convert unix jobid to smb jobid */
1021 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1022 id = sysjob_to_jobid(msg->id);
1025 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1030 construct_info_data( &data[data_len], msg->type, msg->field, id );
1033 case PRINTER_NOTIFY_TYPE:
1034 if ( printer_notify_table[msg->field].fn )
1035 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1038 case JOB_NOTIFY_TYPE:
1039 if ( job_notify_table[msg->field].fn )
1040 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1044 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1051 if ( sending_msg_count ) {
1052 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1053 data_len, data, p->notify.change, 0 );
1058 DEBUG(8,("send_notify2_changes: Exit...\n"));
1062 /***********************************************************************
1063 **********************************************************************/
1065 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1068 uint32 tv_sec, tv_usec;
1071 /* Unpack message */
1073 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1076 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1078 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1081 tdb_unpack((char *)buf + offset, len - offset, "dd",
1082 &msg->notify.value[0], &msg->notify.value[1]);
1084 tdb_unpack((char *)buf + offset, len - offset, "B",
1085 &msg->len, &msg->notify.data);
1087 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1088 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1090 tv->tv_sec = tv_sec;
1091 tv->tv_usec = tv_usec;
1094 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1095 msg->notify.value[1]));
1097 dump_data(3, msg->notify.data, msg->len);
1102 /********************************************************************
1103 Receive a notify2 message list
1104 ********************************************************************/
1106 static void receive_notify2_message_list(int msg_type, struct process_id src,
1107 void *msg, size_t len)
1109 size_t msg_count, i;
1110 char *buf = (char *)msg;
1113 SPOOLSS_NOTIFY_MSG notify;
1114 SPOOLSS_NOTIFY_MSG_CTR messages;
1118 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1122 msg_count = IVAL(buf, 0);
1125 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1127 if (msg_count == 0) {
1128 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1132 /* initialize the container */
1134 ZERO_STRUCT( messages );
1135 notify_msg_ctr_init( &messages );
1138 * build message groups for each printer identified
1139 * in a change_notify msg. Remember that a PCN message
1140 * includes the handle returned for the srv_spoolss_replyopenprinter()
1141 * call. Therefore messages are grouped according to printer handle.
1144 for ( i=0; i<msg_count; i++ ) {
1145 struct timeval msg_tv;
1147 if (msg_ptr + 4 - buf > len) {
1148 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1152 msg_len = IVAL(msg_ptr,0);
1155 if (msg_ptr + msg_len - buf > len) {
1156 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1160 /* unpack messages */
1162 ZERO_STRUCT( notify );
1163 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1166 /* add to correct list in container */
1168 notify_msg_ctr_addmsg( &messages, ¬ify );
1170 /* free memory that might have been allocated by notify2_unpack_msg() */
1172 if ( notify.len != 0 )
1173 SAFE_FREE( notify.notify.data );
1176 /* process each group of messages */
1178 num_groups = notify_msg_ctr_numgroups( &messages );
1179 for ( i=0; i<num_groups; i++ )
1180 send_notify2_changes( &messages, i );
1185 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1187 notify_msg_ctr_destroy( &messages );
1192 /********************************************************************
1193 Send a message to ourself about new driver being installed
1194 so we can upgrade the information for each printer bound to this
1196 ********************************************************************/
1198 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1200 int len = strlen(drivername);
1205 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1208 message_send_pid(pid_to_procid(sys_getpid()),
1209 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1214 /**********************************************************************
1215 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1216 over all printers, upgrading ones as necessary
1217 **********************************************************************/
1219 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1223 int n_services = lp_numservices();
1225 len = MIN(len,sizeof(drivername)-1);
1226 strncpy(drivername, buf, len);
1228 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1230 /* Iterate the printer list */
1232 for (snum=0; snum<n_services; snum++)
1234 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1237 NT_PRINTER_INFO_LEVEL *printer = NULL;
1239 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1240 if (!W_ERROR_IS_OK(result))
1243 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1245 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1247 /* all we care about currently is the change_id */
1249 result = mod_a_printer(printer, 2);
1250 if (!W_ERROR_IS_OK(result)) {
1251 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1252 dos_errstr(result)));
1256 free_a_printer(&printer, 2);
1263 /********************************************************************
1264 Update the cache for all printq's with a registered client
1266 ********************************************************************/
1268 void update_monitored_printq_cache( void )
1270 Printer_entry *printer = printers_list;
1273 /* loop through all printers and update the cache where
1274 client_connected == True */
1277 if ( (printer->printer_type == SPLHND_PRINTER)
1278 && printer->notify.client_connected )
1280 snum = print_queue_snum(printer->sharename);
1281 print_queue_status( snum, NULL, NULL );
1284 printer = printer->next;
1289 /********************************************************************
1290 Send a message to ourself about new driver being installed
1291 so we can upgrade the information for each printer bound to this
1293 ********************************************************************/
1295 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1297 int len = strlen(drivername);
1302 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1305 message_send_pid(pid_to_procid(sys_getpid()),
1306 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1311 /**********************************************************************
1312 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1313 over all printers, resetting printer data as neessary
1314 **********************************************************************/
1316 void reset_all_printerdata(int msg_type, struct process_id src,
1317 void *buf, size_t len)
1321 int n_services = lp_numservices();
1323 len = MIN( len, sizeof(drivername)-1 );
1324 strncpy( drivername, buf, len );
1326 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1328 /* Iterate the printer list */
1330 for ( snum=0; snum<n_services; snum++ )
1332 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1335 NT_PRINTER_INFO_LEVEL *printer = NULL;
1337 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1338 if ( !W_ERROR_IS_OK(result) )
1342 * if the printer is bound to the driver,
1343 * then reset to the new driver initdata
1346 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1348 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1350 if ( !set_driver_init(printer, 2) ) {
1351 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1352 printer->info_2->printername, printer->info_2->drivername));
1355 result = mod_a_printer( printer, 2 );
1356 if ( !W_ERROR_IS_OK(result) ) {
1357 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1358 get_dos_error_msg(result)));
1362 free_a_printer( &printer, 2 );
1371 /********************************************************************
1372 Copy routines used by convert_to_openprinterex()
1373 *******************************************************************/
1375 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1383 DEBUG (8,("dup_devmode\n"));
1385 /* bulk copy first */
1387 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1391 /* dup the pointer members separately */
1393 len = unistrlen(devmode->devicename.buffer);
1395 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1396 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1401 len = unistrlen(devmode->formname.buffer);
1403 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1404 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1408 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1413 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1415 if (!new_ctr || !ctr)
1418 DEBUG(8,("copy_devmode_ctr\n"));
1420 new_ctr->size = ctr->size;
1421 new_ctr->devmode_ptr = ctr->devmode_ptr;
1423 if(ctr->devmode_ptr)
1424 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1427 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1429 if (!new_def || !def)
1432 DEBUG(8,("copy_printer_defaults\n"));
1434 new_def->datatype_ptr = def->datatype_ptr;
1436 if (def->datatype_ptr)
1437 copy_unistr2(&new_def->datatype, &def->datatype);
1439 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1441 new_def->access_required = def->access_required;
1444 /********************************************************************
1445 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1446 * SPOOL_Q_OPEN_PRINTER_EX structure
1447 ********************************************************************/
1449 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1451 if (!q_u_ex || !q_u)
1454 DEBUG(8,("convert_to_openprinterex\n"));
1456 if ( q_u->printername ) {
1457 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1458 if (q_u_ex->printername == NULL)
1460 copy_unistr2(q_u_ex->printername, q_u->printername);
1463 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1468 /********************************************************************
1469 * spoolss_open_printer
1471 * called from the spoolss dispatcher
1472 ********************************************************************/
1474 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1476 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1477 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1482 ZERO_STRUCT(q_u_ex);
1483 ZERO_STRUCT(r_u_ex);
1485 /* convert the OpenPrinter() call to OpenPrinterEx() */
1487 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1488 if (!W_ERROR_IS_OK(r_u_ex.status))
1489 return r_u_ex.status;
1491 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1493 /* convert back to OpenPrinter() */
1495 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1500 /********************************************************************
1501 ********************************************************************/
1503 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1505 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1506 POLICY_HND *handle = &r_u->handle;
1510 struct current_user user;
1511 Printer_entry *Printer=NULL;
1513 if ( !q_u->printername )
1514 return WERR_INVALID_PRINTER_NAME;
1516 /* some sanity check because you can open a printer or a print server */
1517 /* aka: \\server\printer or \\server */
1519 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1521 DEBUGADD(3,("checking name: %s\n",name));
1523 if (!open_printer_hnd(p, handle, name, 0))
1524 return WERR_INVALID_PRINTER_NAME;
1526 Printer=find_printer_index_by_hnd(p, handle);
1528 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1529 "handle we created for printer %s\n", name ));
1530 close_printer_handle(p,handle);
1531 return WERR_INVALID_PRINTER_NAME;
1534 get_current_user(&user, p);
1537 * First case: the user is opening the print server:
1539 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1540 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1542 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1543 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1544 * or if the user is listed in the smb.conf printer admin parameter.
1546 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1547 * client view printer folder, but does not show the MSAPW.
1549 * Note: this test needs code to check access rights here too. Jeremy
1550 * could you look at this?
1552 * Second case: the user is opening a printer:
1553 * NT doesn't let us connect to a printer if the connecting user
1554 * doesn't have print permission.
1556 * Third case: user is opening a Port Monitor
1557 * access checks same as opening a handle to the print server.
1560 switch (Printer->printer_type )
1563 case SPLHND_PORTMON_TCP:
1564 case SPLHND_PORTMON_LOCAL:
1565 /* Printserver handles use global struct... */
1569 /* Map standard access rights to object specific access rights */
1571 se_map_standard(&printer_default->access_required,
1572 &printserver_std_mapping);
1574 /* Deny any object specific bits that don't apply to print
1575 servers (i.e printer and job specific bits) */
1577 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1579 if (printer_default->access_required &
1580 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1581 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1582 close_printer_handle(p, handle);
1583 return WERR_ACCESS_DENIED;
1586 /* Allow admin access */
1588 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1590 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1592 if (!lp_ms_add_printer_wizard()) {
1593 close_printer_handle(p, handle);
1594 return WERR_ACCESS_DENIED;
1597 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1598 and not a printer admin, then fail */
1600 if ((user.ut.uid != 0) &&
1601 !user_has_privileges(user.nt_user_token,
1603 !token_contains_name_in_list(
1604 uidtoname(user.ut.uid), NULL,
1606 lp_printer_admin(snum))) {
1607 close_printer_handle(p, handle);
1608 return WERR_ACCESS_DENIED;
1611 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1615 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1618 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1619 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1621 /* We fall through to return WERR_OK */
1624 case SPLHND_PRINTER:
1625 /* NT doesn't let us connect to a printer if the connecting user
1626 doesn't have print permission. */
1628 if (!get_printer_snum(p, handle, &snum)) {
1629 close_printer_handle(p, handle);
1633 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1635 /* map an empty access mask to the minimum access mask */
1636 if (printer_default->access_required == 0x0)
1637 printer_default->access_required = PRINTER_ACCESS_USE;
1640 * If we are not serving the printer driver for this printer,
1641 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1642 * will keep NT clients happy --jerry
1645 if (lp_use_client_driver(snum)
1646 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1648 printer_default->access_required = PRINTER_ACCESS_USE;
1651 /* check smb.conf parameters and the the sec_desc */
1653 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1654 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1655 return WERR_ACCESS_DENIED;
1658 if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
1660 !print_access_check(&user, snum,
1661 printer_default->access_required)) {
1662 DEBUG(3, ("access DENIED for printer open\n"));
1663 close_printer_handle(p, handle);
1664 return WERR_ACCESS_DENIED;
1667 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1668 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1669 close_printer_handle(p, handle);
1670 return WERR_ACCESS_DENIED;
1673 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1674 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1676 printer_default->access_required = PRINTER_ACCESS_USE;
1678 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1679 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1684 /* sanity check to prevent programmer error */
1688 Printer->access_granted = printer_default->access_required;
1691 * If the client sent a devmode in the OpenPrinter() call, then
1692 * save it here in case we get a job submission on this handle
1695 if ( (Printer->printer_type != SPLHND_SERVER)
1696 && q_u->printer_default.devmode_cont.devmode_ptr )
1698 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1699 &Printer->nt_devmode );
1702 #if 0 /* JERRY -- I'm doubtful this is really effective */
1703 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1704 optimization in Windows 2000 clients --jerry */
1706 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1707 && (RA_WIN2K == get_remote_arch()) )
1709 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1710 sys_usleep( 500000 );
1717 /****************************************************************************
1718 ****************************************************************************/
1720 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1721 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1727 /* allocate memory if needed. Messy because
1728 convert_printer_info is used to update an existing
1729 printer or build a new one */
1731 if ( !printer->info_2 ) {
1732 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1733 if ( !printer->info_2 ) {
1734 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1739 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1740 printer->info_2->setuptime = time(NULL);
1748 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1749 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1755 printer->info_3=NULL;
1756 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1760 printer->info_6=NULL;
1761 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1771 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1772 NT_DEVICEMODE **pp_nt_devmode)
1774 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1777 * Ensure nt_devmode is a valid pointer
1778 * as we will be overwriting it.
1781 if (nt_devmode == NULL) {
1782 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1783 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1787 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1788 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1790 nt_devmode->specversion=devmode->specversion;
1791 nt_devmode->driverversion=devmode->driverversion;
1792 nt_devmode->size=devmode->size;
1793 nt_devmode->fields=devmode->fields;
1794 nt_devmode->orientation=devmode->orientation;
1795 nt_devmode->papersize=devmode->papersize;
1796 nt_devmode->paperlength=devmode->paperlength;
1797 nt_devmode->paperwidth=devmode->paperwidth;
1798 nt_devmode->scale=devmode->scale;
1799 nt_devmode->copies=devmode->copies;
1800 nt_devmode->defaultsource=devmode->defaultsource;
1801 nt_devmode->printquality=devmode->printquality;
1802 nt_devmode->color=devmode->color;
1803 nt_devmode->duplex=devmode->duplex;
1804 nt_devmode->yresolution=devmode->yresolution;
1805 nt_devmode->ttoption=devmode->ttoption;
1806 nt_devmode->collate=devmode->collate;
1808 nt_devmode->logpixels=devmode->logpixels;
1809 nt_devmode->bitsperpel=devmode->bitsperpel;
1810 nt_devmode->pelswidth=devmode->pelswidth;
1811 nt_devmode->pelsheight=devmode->pelsheight;
1812 nt_devmode->displayflags=devmode->displayflags;
1813 nt_devmode->displayfrequency=devmode->displayfrequency;
1814 nt_devmode->icmmethod=devmode->icmmethod;
1815 nt_devmode->icmintent=devmode->icmintent;
1816 nt_devmode->mediatype=devmode->mediatype;
1817 nt_devmode->dithertype=devmode->dithertype;
1818 nt_devmode->reserved1=devmode->reserved1;
1819 nt_devmode->reserved2=devmode->reserved2;
1820 nt_devmode->panningwidth=devmode->panningwidth;
1821 nt_devmode->panningheight=devmode->panningheight;
1824 * Only change private and driverextra if the incoming devmode
1825 * has a new one. JRA.
1828 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1829 SAFE_FREE(nt_devmode->nt_dev_private);
1830 nt_devmode->driverextra=devmode->driverextra;
1831 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1833 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1836 *pp_nt_devmode = nt_devmode;
1841 /********************************************************************
1842 * _spoolss_enddocprinter_internal.
1843 ********************************************************************/
1845 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1847 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1851 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1855 if (!get_printer_snum(p, handle, &snum))
1858 Printer->document_started=False;
1859 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1860 /* error codes unhandled so far ... */
1865 /********************************************************************
1866 * api_spoolss_closeprinter
1867 ********************************************************************/
1869 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1871 POLICY_HND *handle = &q_u->handle;
1873 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1875 if (Printer && Printer->document_started)
1876 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1878 if (!close_printer_handle(p, handle))
1881 /* clear the returned printer handle. Observed behavior
1882 from Win2k server. Don't think this really matters.
1883 Previous code just copied the value of the closed
1886 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1891 /********************************************************************
1892 * api_spoolss_deleteprinter
1894 ********************************************************************/
1896 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1898 POLICY_HND *handle = &q_u->handle;
1899 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1902 if (Printer && Printer->document_started)
1903 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1905 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1907 result = delete_printer_handle(p, handle);
1909 update_c_setprinter(False);
1914 /*******************************************************************
1915 * static function to lookup the version id corresponding to an
1916 * long architecture string
1917 ******************************************************************/
1919 static int get_version_id (char * arch)
1922 struct table_node archi_table[]= {
1924 {"Windows 4.0", "WIN40", 0 },
1925 {"Windows NT x86", "W32X86", 2 },
1926 {"Windows NT R4000", "W32MIPS", 2 },
1927 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1928 {"Windows NT PowerPC", "W32PPC", 2 },
1929 {"Windows IA64", "IA64", 3 },
1930 {"Windows x64", "x64", 3 },
1934 for (i=0; archi_table[i].long_archi != NULL; i++)
1936 if (strcmp(arch, archi_table[i].long_archi) == 0)
1937 return (archi_table[i].version);
1943 /********************************************************************
1944 * _spoolss_deleteprinterdriver
1945 ********************************************************************/
1947 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1951 NT_PRINTER_DRIVER_INFO_LEVEL info;
1952 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1954 struct current_user user;
1956 WERROR status_win2k = WERR_ACCESS_DENIED;
1957 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1959 get_current_user(&user, p);
1961 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1962 and not a printer admin, then fail */
1964 if ( (user.ut.uid != 0)
1965 && !user_has_privileges(user.nt_user_token, &se_printop )
1966 && !token_contains_name_in_list( uidtoname(user.ut.uid),
1967 NULL, user.nt_user_token, lp_printer_admin(-1)) )
1969 return WERR_ACCESS_DENIED;
1972 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1973 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1975 /* check that we have a valid driver name first */
1977 if ((version=get_version_id(arch)) == -1)
1978 return WERR_INVALID_ENVIRONMENT;
1981 ZERO_STRUCT(info_win2k);
1983 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1985 /* try for Win2k driver if "Windows NT x86" */
1987 if ( version == 2 ) {
1989 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1990 status = WERR_UNKNOWN_PRINTER_DRIVER;
1994 /* otherwise it was a failure */
1996 status = WERR_UNKNOWN_PRINTER_DRIVER;
2002 if (printer_driver_in_use(info.info_3)) {
2003 status = WERR_PRINTER_DRIVER_IN_USE;
2009 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2011 /* if we get to here, we now have 2 driver info structures to remove */
2012 /* remove the Win2k driver first*/
2014 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2015 free_a_printer_driver( info_win2k, 3 );
2017 /* this should not have failed---if it did, report to client */
2018 if ( !W_ERROR_IS_OK(status_win2k) )
2020 status = status_win2k;
2026 status = delete_printer_driver(info.info_3, &user, version, False);
2028 /* if at least one of the deletes succeeded return OK */
2030 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2034 free_a_printer_driver( info, 3 );
2039 /********************************************************************
2040 * spoolss_deleteprinterdriverex
2041 ********************************************************************/
2043 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2047 NT_PRINTER_DRIVER_INFO_LEVEL info;
2048 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2050 uint32 flags = q_u->delete_flags;
2052 struct current_user user;
2054 WERROR status_win2k = WERR_ACCESS_DENIED;
2055 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2057 get_current_user(&user, p);
2059 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2060 and not a printer admin, then fail */
2062 if ( (user.ut.uid != 0)
2063 && !user_has_privileges(user.nt_user_token, &se_printop )
2064 && !token_contains_name_in_list( uidtoname(user.ut.uid),
2065 NULL, user.nt_user_token, lp_printer_admin(-1)) )
2067 return WERR_ACCESS_DENIED;
2070 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2071 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2073 /* check that we have a valid driver name first */
2074 if ((version=get_version_id(arch)) == -1) {
2075 /* this is what NT returns */
2076 return WERR_INVALID_ENVIRONMENT;
2079 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2080 version = q_u->version;
2083 ZERO_STRUCT(info_win2k);
2085 status = get_a_printer_driver(&info, 3, driver, arch, version);
2087 if ( !W_ERROR_IS_OK(status) )
2090 * if the client asked for a specific version,
2091 * or this is something other than Windows NT x86,
2095 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2098 /* try for Win2k driver if "Windows NT x86" */
2101 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2102 status = WERR_UNKNOWN_PRINTER_DRIVER;
2107 if ( printer_driver_in_use(info.info_3) ) {
2108 status = WERR_PRINTER_DRIVER_IN_USE;
2113 * we have a couple of cases to consider.
2114 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2115 * then the delete should fail if **any** files overlap with
2117 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2118 * non-overlapping files
2119 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2120 * is set, the do not delete any files
2121 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2124 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2126 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2128 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2129 /* no idea of the correct error here */
2130 status = WERR_ACCESS_DENIED;
2135 /* also check for W32X86/3 if necessary; maybe we already have? */
2137 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2138 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2141 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2142 /* no idea of the correct error here */
2143 free_a_printer_driver( info_win2k, 3 );
2144 status = WERR_ACCESS_DENIED;
2148 /* if we get to here, we now have 2 driver info structures to remove */
2149 /* remove the Win2k driver first*/
2151 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2152 free_a_printer_driver( info_win2k, 3 );
2154 /* this should not have failed---if it did, report to client */
2156 if ( !W_ERROR_IS_OK(status_win2k) )
2161 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2163 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2166 free_a_printer_driver( info, 3 );
2172 /****************************************************************************
2173 Internal routine for retreiving printerdata
2174 ***************************************************************************/
2176 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2177 const char *key, const char *value, uint32 *type, uint8 **data,
2178 uint32 *needed, uint32 in_size )
2180 REGISTRY_VALUE *val;
2184 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2185 return WERR_BADFILE;
2187 *type = regval_type( val );
2189 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2191 size = regval_size( val );
2193 /* copy the min(in_size, len) */
2196 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2198 /* special case for 0 length values */
2200 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2204 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2213 DEBUG(5,("get_printer_dataex: copy done\n"));
2218 /****************************************************************************
2219 Internal routine for removing printerdata
2220 ***************************************************************************/
2222 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2224 return delete_printer_data( printer->info_2, key, value );
2227 /****************************************************************************
2228 Internal routine for storing printerdata
2229 ***************************************************************************/
2231 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2232 uint32 type, uint8 *data, int real_len )
2234 /* the registry objects enforce uniqueness based on value name */
2236 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2239 /********************************************************************
2240 GetPrinterData on a printer server Handle.
2241 ********************************************************************/
2243 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2247 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2249 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2251 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2257 if (!StrCaseCmp(value, "BeepEnabled")) {
2259 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2261 SIVAL(*data, 0, 0x00);
2266 if (!StrCaseCmp(value, "EventLog")) {
2268 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2270 /* formally was 0x1b */
2271 SIVAL(*data, 0, 0x0);
2276 if (!StrCaseCmp(value, "NetPopup")) {
2278 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2280 SIVAL(*data, 0, 0x00);
2285 if (!StrCaseCmp(value, "MajorVersion")) {
2287 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2290 /* Windows NT 4.0 seems to not allow uploading of drivers
2291 to a server that reports 0x3 as the MajorVersion.
2292 need to investigate more how Win2k gets around this .
2295 if ( RA_WINNT == get_remote_arch() )
2304 if (!StrCaseCmp(value, "MinorVersion")) {
2306 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2314 * uint32 size = 0x114
2316 * uint32 minor = [0|1]
2317 * uint32 build = [2195|2600]
2318 * extra unicode string = e.g. "Service Pack 3"
2320 if (!StrCaseCmp(value, "OSVersion")) {
2324 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2327 SIVAL(*data, 0, *needed); /* size */
2328 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2330 SIVAL(*data, 12, 2195); /* build */
2332 /* leave extra string empty */
2338 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2339 const char *string="C:\\PRINTERS";
2341 *needed = 2*(strlen(string)+1);
2342 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2344 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2346 /* it's done by hand ready to go on the wire */
2347 for (i=0; i<strlen(string); i++) {
2348 (*data)[2*i]=string[i];
2349 (*data)[2*i+1]='\0';
2354 if (!StrCaseCmp(value, "Architecture")) {
2355 const char *string="Windows NT x86";
2357 *needed = 2*(strlen(string)+1);
2358 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2360 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2361 for (i=0; i<strlen(string); i++) {
2362 (*data)[2*i]=string[i];
2363 (*data)[2*i+1]='\0';
2368 if (!StrCaseCmp(value, "DsPresent")) {
2370 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2373 /* only show the publish check box if we are a
2374 memeber of a AD domain */
2376 if ( lp_security() == SEC_ADS )
2377 SIVAL(*data, 0, 0x01);
2379 SIVAL(*data, 0, 0x00);
2385 if (!StrCaseCmp(value, "DNSMachineName")) {
2388 if (!get_mydnsfullname(hostname))
2389 return WERR_BADFILE;
2391 *needed = 2*(strlen(hostname)+1);
2392 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2394 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2395 for (i=0; i<strlen(hostname); i++) {
2396 (*data)[2*i]=hostname[i];
2397 (*data)[2*i+1]='\0';
2403 return WERR_BADFILE;
2406 /********************************************************************
2407 * spoolss_getprinterdata
2408 ********************************************************************/
2410 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2412 POLICY_HND *handle = &q_u->handle;
2413 UNISTR2 *valuename = &q_u->valuename;
2414 uint32 in_size = q_u->size;
2415 uint32 *type = &r_u->type;
2416 uint32 *out_size = &r_u->size;
2417 uint8 **data = &r_u->data;
2418 uint32 *needed = &r_u->needed;
2421 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2422 NT_PRINTER_INFO_LEVEL *printer = NULL;
2426 * Reminder: when it's a string, the length is in BYTES
2427 * even if UNICODE is negociated.
2432 *out_size = in_size;
2434 /* in case of problem, return some default values */
2439 DEBUG(4,("_spoolss_getprinterdata\n"));
2442 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2443 status = WERR_BADFID;
2447 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2449 if ( Printer->printer_type == SPLHND_SERVER )
2450 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2453 if ( !get_printer_snum(p,handle, &snum) ) {
2454 status = WERR_BADFID;
2458 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2459 if ( !W_ERROR_IS_OK(status) )
2462 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2464 if ( strequal(value, "ChangeId") ) {
2466 *needed = sizeof(uint32);
2467 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2468 status = WERR_NOMEM;
2471 SIVAL( *data, 0, printer->info_2->changeid );
2475 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2478 if (*needed > *out_size)
2479 status = WERR_MORE_DATA;
2482 if ( !W_ERROR_IS_OK(status) )
2484 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2486 /* reply this param doesn't exist */
2489 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2491 free_a_printer( &printer, 2 );
2500 /* cleanup & exit */
2503 free_a_printer( &printer, 2 );
2508 /*********************************************************
2509 Connect to the client machine.
2510 **********************************************************/
2512 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2513 struct in_addr *client_ip, const char *remote_machine)
2516 struct cli_state *the_cli;
2517 struct in_addr rm_addr;
2519 if ( is_zero_ip(*client_ip) ) {
2520 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2521 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2525 if ( ismyip( rm_addr )) {
2526 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2530 rm_addr.s_addr = client_ip->s_addr;
2531 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2532 inet_ntoa(*client_ip) ));
2535 /* setup the connection */
2537 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2538 &rm_addr, 0, "IPC$", "IPC",
2542 0, lp_client_signing(), NULL );
2544 if ( !NT_STATUS_IS_OK( ret ) ) {
2545 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2550 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2551 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2552 cli_shutdown(the_cli);
2557 * Ok - we have an anonymous connection to the IPC$ share.
2558 * Now start the NT Domain stuff :-).
2561 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2562 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2563 remote_machine, nt_errstr(ret)));
2564 cli_shutdown(the_cli);
2568 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2570 (*pp_pipe)->cli = the_cli;
2575 /***************************************************************************
2576 Connect to the client.
2577 ****************************************************************************/
2579 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2580 uint32 localprinter, uint32 type,
2581 POLICY_HND *handle, struct in_addr *client_ip)
2586 * If it's the first connection, contact the client
2587 * and connect to the IPC$ share anonymously
2589 if (smb_connections==0) {
2590 fstring unix_printer;
2592 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2594 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2597 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2598 /* Tell the connections db we're now interested in printer
2599 * notify messages. */
2600 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2604 * Tell the specific printing tdb we want messages for this printer
2605 * by registering our PID.
2608 if (!print_notify_register_pid(snum))
2609 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2613 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2616 if (!W_ERROR_IS_OK(result))
2617 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2618 dos_errstr(result)));
2620 return (W_ERROR_IS_OK(result));
2623 /********************************************************************
2625 * ReplyFindFirstPrinterChangeNotifyEx
2627 * before replying OK: status=0 a rpc call is made to the workstation
2628 * asking ReplyOpenPrinter
2630 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2631 * called from api_spoolss_rffpcnex
2632 ********************************************************************/
2634 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2636 POLICY_HND *handle = &q_u->handle;
2637 uint32 flags = q_u->flags;
2638 uint32 options = q_u->options;
2639 UNISTR2 *localmachine = &q_u->localmachine;
2640 uint32 printerlocal = q_u->printerlocal;
2642 SPOOL_NOTIFY_OPTION *option = q_u->option;
2643 struct in_addr client_ip;
2645 /* store the notify value in the printer struct */
2647 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2650 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2654 Printer->notify.flags=flags;
2655 Printer->notify.options=options;
2656 Printer->notify.printerlocal=printerlocal;
2658 if (Printer->notify.option)
2659 free_spool_notify_option(&Printer->notify.option);
2661 Printer->notify.option=dup_spool_notify_option(option);
2663 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2664 sizeof(Printer->notify.localmachine)-1);
2666 /* Connect to the client machine and send a ReplyOpenPrinter */
2668 if ( Printer->printer_type == SPLHND_SERVER)
2670 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2671 !get_printer_snum(p, handle, &snum) )
2674 client_ip.s_addr = inet_addr(p->conn->client_address);
2676 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2677 Printer->notify.printerlocal, 1,
2678 &Printer->notify.client_hnd, &client_ip))
2679 return WERR_SERVER_UNAVAILABLE;
2681 Printer->notify.client_connected=True;
2686 /*******************************************************************
2687 * fill a notify_info_data with the servername
2688 ********************************************************************/
2690 void spoolss_notify_server_name(int snum,
2691 SPOOL_NOTIFY_INFO_DATA *data,
2692 print_queue_struct *queue,
2693 NT_PRINTER_INFO_LEVEL *printer,
2694 TALLOC_CTX *mem_ctx)
2699 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2701 data->notify_data.data.length = len;
2702 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2704 if (!data->notify_data.data.string) {
2705 data->notify_data.data.length = 0;
2709 memcpy(data->notify_data.data.string, temp, len);
2712 /*******************************************************************
2713 * fill a notify_info_data with the printername (not including the servername).
2714 ********************************************************************/
2716 void spoolss_notify_printer_name(int snum,
2717 SPOOL_NOTIFY_INFO_DATA *data,
2718 print_queue_struct *queue,
2719 NT_PRINTER_INFO_LEVEL *printer,
2720 TALLOC_CTX *mem_ctx)
2725 /* the notify name should not contain the \\server\ part */
2726 char *p = strrchr(printer->info_2->printername, '\\');
2729 p = printer->info_2->printername;
2734 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2736 data->notify_data.data.length = len;
2737 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2739 if (!data->notify_data.data.string) {
2740 data->notify_data.data.length = 0;
2744 memcpy(data->notify_data.data.string, temp, len);
2747 /*******************************************************************
2748 * fill a notify_info_data with the servicename
2749 ********************************************************************/
2751 void spoolss_notify_share_name(int snum,
2752 SPOOL_NOTIFY_INFO_DATA *data,
2753 print_queue_struct *queue,
2754 NT_PRINTER_INFO_LEVEL *printer,
2755 TALLOC_CTX *mem_ctx)
2760 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2762 data->notify_data.data.length = len;
2763 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2765 if (!data->notify_data.data.string) {
2766 data->notify_data.data.length = 0;
2770 memcpy(data->notify_data.data.string, temp, len);
2773 /*******************************************************************
2774 * fill a notify_info_data with the port name
2775 ********************************************************************/
2777 void spoolss_notify_port_name(int snum,
2778 SPOOL_NOTIFY_INFO_DATA *data,
2779 print_queue_struct *queue,
2780 NT_PRINTER_INFO_LEVEL *printer,
2781 TALLOC_CTX *mem_ctx)
2786 /* even if it's strange, that's consistant in all the code */
2788 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2790 data->notify_data.data.length = len;
2791 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2793 if (!data->notify_data.data.string) {
2794 data->notify_data.data.length = 0;
2798 memcpy(data->notify_data.data.string, temp, len);
2801 /*******************************************************************
2802 * fill a notify_info_data with the printername
2803 * but it doesn't exist, have to see what to do
2804 ********************************************************************/
2806 void spoolss_notify_driver_name(int snum,
2807 SPOOL_NOTIFY_INFO_DATA *data,
2808 print_queue_struct *queue,
2809 NT_PRINTER_INFO_LEVEL *printer,
2810 TALLOC_CTX *mem_ctx)
2815 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2817 data->notify_data.data.length = len;
2818 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2820 if (!data->notify_data.data.string) {
2821 data->notify_data.data.length = 0;
2825 memcpy(data->notify_data.data.string, temp, len);
2828 /*******************************************************************
2829 * fill a notify_info_data with the comment
2830 ********************************************************************/
2832 void spoolss_notify_comment(int snum,
2833 SPOOL_NOTIFY_INFO_DATA *data,
2834 print_queue_struct *queue,
2835 NT_PRINTER_INFO_LEVEL *printer,
2836 TALLOC_CTX *mem_ctx)
2841 if (*printer->info_2->comment == '\0')
2842 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2844 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2846 data->notify_data.data.length = len;
2847 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2849 if (!data->notify_data.data.string) {
2850 data->notify_data.data.length = 0;
2854 memcpy(data->notify_data.data.string, temp, len);
2857 /*******************************************************************
2858 * fill a notify_info_data with the comment
2859 * location = "Room 1, floor 2, building 3"
2860 ********************************************************************/
2862 void spoolss_notify_location(int snum,
2863 SPOOL_NOTIFY_INFO_DATA *data,
2864 print_queue_struct *queue,
2865 NT_PRINTER_INFO_LEVEL *printer,
2866 TALLOC_CTX *mem_ctx)
2871 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2873 data->notify_data.data.length = len;
2874 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2876 if (!data->notify_data.data.string) {
2877 data->notify_data.data.length = 0;
2881 memcpy(data->notify_data.data.string, temp, len);
2884 /*******************************************************************
2885 * fill a notify_info_data with the device mode
2886 * jfm:xxxx don't to it for know but that's a real problem !!!
2887 ********************************************************************/
2889 static void spoolss_notify_devmode(int snum,
2890 SPOOL_NOTIFY_INFO_DATA *data,
2891 print_queue_struct *queue,
2892 NT_PRINTER_INFO_LEVEL *printer,
2893 TALLOC_CTX *mem_ctx)
2897 /*******************************************************************
2898 * fill a notify_info_data with the separator file name
2899 ********************************************************************/
2901 void spoolss_notify_sepfile(int snum,
2902 SPOOL_NOTIFY_INFO_DATA *data,
2903 print_queue_struct *queue,
2904 NT_PRINTER_INFO_LEVEL *printer,
2905 TALLOC_CTX *mem_ctx)
2910 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2912 data->notify_data.data.length = len;
2913 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2915 if (!data->notify_data.data.string) {
2916 data->notify_data.data.length = 0;
2920 memcpy(data->notify_data.data.string, temp, len);
2923 /*******************************************************************
2924 * fill a notify_info_data with the print processor
2925 * jfm:xxxx return always winprint to indicate we don't do anything to it
2926 ********************************************************************/
2928 void spoolss_notify_print_processor(int snum,
2929 SPOOL_NOTIFY_INFO_DATA *data,
2930 print_queue_struct *queue,
2931 NT_PRINTER_INFO_LEVEL *printer,
2932 TALLOC_CTX *mem_ctx)
2937 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2939 data->notify_data.data.length = len;
2940 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2942 if (!data->notify_data.data.string) {
2943 data->notify_data.data.length = 0;
2947 memcpy(data->notify_data.data.string, temp, len);
2950 /*******************************************************************
2951 * fill a notify_info_data with the print processor options
2952 * jfm:xxxx send an empty string
2953 ********************************************************************/
2955 void spoolss_notify_parameters(int snum,
2956 SPOOL_NOTIFY_INFO_DATA *data,
2957 print_queue_struct *queue,
2958 NT_PRINTER_INFO_LEVEL *printer,
2959 TALLOC_CTX *mem_ctx)
2964 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2966 data->notify_data.data.length = len;
2967 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2969 if (!data->notify_data.data.string) {
2970 data->notify_data.data.length = 0;
2974 memcpy(data->notify_data.data.string, temp, len);
2977 /*******************************************************************
2978 * fill a notify_info_data with the data type
2979 * jfm:xxxx always send RAW as data type
2980 ********************************************************************/
2982 void spoolss_notify_datatype(int snum,
2983 SPOOL_NOTIFY_INFO_DATA *data,
2984 print_queue_struct *queue,
2985 NT_PRINTER_INFO_LEVEL *printer,
2986 TALLOC_CTX *mem_ctx)
2991 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2993 data->notify_data.data.length = len;
2994 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2996 if (!data->notify_data.data.string) {
2997 data->notify_data.data.length = 0;
3001 memcpy(data->notify_data.data.string, temp, len);
3004 /*******************************************************************
3005 * fill a notify_info_data with the security descriptor
3006 * jfm:xxxx send an null pointer to say no security desc
3007 * have to implement security before !
3008 ********************************************************************/
3010 static void spoolss_notify_security_desc(int snum,
3011 SPOOL_NOTIFY_INFO_DATA *data,
3012 print_queue_struct *queue,
3013 NT_PRINTER_INFO_LEVEL *printer,
3014 TALLOC_CTX *mem_ctx)
3016 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3017 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3020 /*******************************************************************
3021 * fill a notify_info_data with the attributes
3022 * jfm:xxxx a samba printer is always shared
3023 ********************************************************************/
3025 void spoolss_notify_attributes(int snum,
3026 SPOOL_NOTIFY_INFO_DATA *data,
3027 print_queue_struct *queue,
3028 NT_PRINTER_INFO_LEVEL *printer,
3029 TALLOC_CTX *mem_ctx)
3031 data->notify_data.value[0] = printer->info_2->attributes;
3032 data->notify_data.value[1] = 0;
3035 /*******************************************************************
3036 * fill a notify_info_data with the priority
3037 ********************************************************************/
3039 static void spoolss_notify_priority(int snum,
3040 SPOOL_NOTIFY_INFO_DATA *data,
3041 print_queue_struct *queue,
3042 NT_PRINTER_INFO_LEVEL *printer,
3043 TALLOC_CTX *mem_ctx)
3045 data->notify_data.value[0] = printer->info_2->priority;
3046 data->notify_data.value[1] = 0;
3049 /*******************************************************************
3050 * fill a notify_info_data with the default priority
3051 ********************************************************************/
3053 static void spoolss_notify_default_priority(int snum,
3054 SPOOL_NOTIFY_INFO_DATA *data,
3055 print_queue_struct *queue,
3056 NT_PRINTER_INFO_LEVEL *printer,
3057 TALLOC_CTX *mem_ctx)
3059 data->notify_data.value[0] = printer->info_2->default_priority;
3060 data->notify_data.value[1] = 0;
3063 /*******************************************************************
3064 * fill a notify_info_data with the start time
3065 ********************************************************************/
3067 static void spoolss_notify_start_time(int snum,
3068 SPOOL_NOTIFY_INFO_DATA *data,
3069 print_queue_struct *queue,
3070 NT_PRINTER_INFO_LEVEL *printer,
3071 TALLOC_CTX *mem_ctx)
3073 data->notify_data.value[0] = printer->info_2->starttime;
3074 data->notify_data.value[1] = 0;
3077 /*******************************************************************
3078 * fill a notify_info_data with the until time
3079 ********************************************************************/
3081 static void spoolss_notify_until_time(int snum,
3082 SPOOL_NOTIFY_INFO_DATA *data,
3083 print_queue_struct *queue,
3084 NT_PRINTER_INFO_LEVEL *printer,
3085 TALLOC_CTX *mem_ctx)
3087 data->notify_data.value[0] = printer->info_2->untiltime;
3088 data->notify_data.value[1] = 0;
3091 /*******************************************************************
3092 * fill a notify_info_data with the status
3093 ********************************************************************/
3095 static void spoolss_notify_status(int snum,
3096 SPOOL_NOTIFY_INFO_DATA *data,
3097 print_queue_struct *queue,
3098 NT_PRINTER_INFO_LEVEL *printer,
3099 TALLOC_CTX *mem_ctx)
3101 print_status_struct status;
3103 print_queue_length(snum, &status);
3104 data->notify_data.value[0]=(uint32) status.status;
3105 data->notify_data.value[1] = 0;
3108 /*******************************************************************
3109 * fill a notify_info_data with the number of jobs queued
3110 ********************************************************************/
3112 void spoolss_notify_cjobs(int snum,
3113 SPOOL_NOTIFY_INFO_DATA *data,
3114 print_queue_struct *queue,
3115 NT_PRINTER_INFO_LEVEL *printer,
3116 TALLOC_CTX *mem_ctx)
3118 data->notify_data.value[0] = print_queue_length(snum, NULL);
3119 data->notify_data.value[1] = 0;
3122 /*******************************************************************
3123 * fill a notify_info_data with the average ppm
3124 ********************************************************************/
3126 static void spoolss_notify_average_ppm(int snum,
3127 SPOOL_NOTIFY_INFO_DATA *data,
3128 print_queue_struct *queue,
3129 NT_PRINTER_INFO_LEVEL *printer,
3130 TALLOC_CTX *mem_ctx)
3132 /* always respond 8 pages per minutes */
3133 /* a little hard ! */
3134 data->notify_data.value[0] = printer->info_2->averageppm;
3135 data->notify_data.value[1] = 0;
3138 /*******************************************************************
3139 * fill a notify_info_data with username
3140 ********************************************************************/
3142 static void spoolss_notify_username(int snum,
3143 SPOOL_NOTIFY_INFO_DATA *data,
3144 print_queue_struct *queue,
3145 NT_PRINTER_INFO_LEVEL *printer,
3146 TALLOC_CTX *mem_ctx)
3151 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3153 data->notify_data.data.length = len;
3154 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3156 if (!data->notify_data.data.string) {
3157 data->notify_data.data.length = 0;
3161 memcpy(data->notify_data.data.string, temp, len);
3164 /*******************************************************************
3165 * fill a notify_info_data with job status
3166 ********************************************************************/
3168 static void spoolss_notify_job_status(int snum,
3169 SPOOL_NOTIFY_INFO_DATA *data,
3170 print_queue_struct *queue,
3171 NT_PRINTER_INFO_LEVEL *printer,
3172 TALLOC_CTX *mem_ctx)
3174 data->notify_data.value[0]=nt_printj_status(queue->status);
3175 data->notify_data.value[1] = 0;
3178 /*******************************************************************
3179 * fill a notify_info_data with job name
3180 ********************************************************************/
3182 static void spoolss_notify_job_name(int snum,
3183 SPOOL_NOTIFY_INFO_DATA *data,
3184 print_queue_struct *queue,
3185 NT_PRINTER_INFO_LEVEL *printer,
3186 TALLOC_CTX *mem_ctx)
3191 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3193 data->notify_data.data.length = len;
3194 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3196 if (!data->notify_data.data.string) {
3197 data->notify_data.data.length = 0;
3201 memcpy(data->notify_data.data.string, temp, len);
3204 /*******************************************************************
3205 * fill a notify_info_data with job status
3206 ********************************************************************/
3208 static void spoolss_notify_job_status_string(int snum,
3209 SPOOL_NOTIFY_INFO_DATA *data,
3210 print_queue_struct *queue,
3211 NT_PRINTER_INFO_LEVEL *printer,
3212 TALLOC_CTX *mem_ctx)
3215 * Now we're returning job status codes we just return a "" here. JRA.
3222 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3225 switch (queue->status) {
3230 p = ""; /* NT provides the paused string */
3239 #endif /* NO LONGER NEEDED. */
3241 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3243 data->notify_data.data.length = len;
3244 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3246 if (!data->notify_data.data.string) {
3247 data->notify_data.data.length = 0;
3251 memcpy(data->notify_data.data.string, temp, len);
3254 /*******************************************************************
3255 * fill a notify_info_data with job time
3256 ********************************************************************/
3258 static void spoolss_notify_job_time(int snum,
3259 SPOOL_NOTIFY_INFO_DATA *data,
3260 print_queue_struct *queue,
3261 NT_PRINTER_INFO_LEVEL *printer,
3262 TALLOC_CTX *mem_ctx)
3264 data->notify_data.value[0]=0x0;
3265 data->notify_data.value[1]=0;
3268 /*******************************************************************
3269 * fill a notify_info_data with job size
3270 ********************************************************************/
3272 static void spoolss_notify_job_size(int snum,
3273 SPOOL_NOTIFY_INFO_DATA *data,
3274 print_queue_struct *queue,
3275 NT_PRINTER_INFO_LEVEL *printer,
3276 TALLOC_CTX *mem_ctx)
3278 data->notify_data.value[0]=queue->size;
3279 data->notify_data.value[1]=0;
3282 /*******************************************************************
3283 * fill a notify_info_data with page info
3284 ********************************************************************/
3285 static void spoolss_notify_total_pages(int snum,
3286 SPOOL_NOTIFY_INFO_DATA *data,
3287 print_queue_struct *queue,
3288 NT_PRINTER_INFO_LEVEL *printer,
3289 TALLOC_CTX *mem_ctx)
3291 data->notify_data.value[0]=queue->page_count;
3292 data->notify_data.value[1]=0;
3295 /*******************************************************************
3296 * fill a notify_info_data with pages printed info.
3297 ********************************************************************/
3298 static void spoolss_notify_pages_printed(int snum,
3299 SPOOL_NOTIFY_INFO_DATA *data,
3300 print_queue_struct *queue,
3301 NT_PRINTER_INFO_LEVEL *printer,
3302 TALLOC_CTX *mem_ctx)
3304 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3305 data->notify_data.value[1]=0;
3308 /*******************************************************************
3309 Fill a notify_info_data with job position.
3310 ********************************************************************/
3312 static void spoolss_notify_job_position(int snum,
3313 SPOOL_NOTIFY_INFO_DATA *data,
3314 print_queue_struct *queue,
3315 NT_PRINTER_INFO_LEVEL *printer,
3316 TALLOC_CTX *mem_ctx)
3318 data->notify_data.value[0]=queue->job;
3319 data->notify_data.value[1]=0;
3322 /*******************************************************************
3323 Fill a notify_info_data with submitted time.
3324 ********************************************************************/
3326 static void spoolss_notify_submitted_time(int snum,
3327 SPOOL_NOTIFY_INFO_DATA *data,
3328 print_queue_struct *queue,
3329 NT_PRINTER_INFO_LEVEL *printer,
3330 TALLOC_CTX *mem_ctx)
3337 t=gmtime(&queue->time);
3339 len = sizeof(SYSTEMTIME);
3341 data->notify_data.data.length = len;
3342 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3344 if (!data->notify_data.data.string) {
3345 data->notify_data.data.length = 0;
3349 make_systemtime(&st, t);
3352 * Systemtime must be linearized as a set of UINT16's.
3353 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3356 p = (char *)data->notify_data.data.string;
3357 SSVAL(p, 0, st.year);
3358 SSVAL(p, 2, st.month);
3359 SSVAL(p, 4, st.dayofweek);
3360 SSVAL(p, 6, st.day);
3361 SSVAL(p, 8, st.hour);
3362 SSVAL(p, 10, st.minute);
3363 SSVAL(p, 12, st.second);
3364 SSVAL(p, 14, st.milliseconds);
3367 struct s_notify_info_data_table
3373 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3374 print_queue_struct *queue,
3375 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3378 /* A table describing the various print notification constants and
3379 whether the notification data is a pointer to a variable sized
3380 buffer, a one value uint32 or a two value uint32. */
3382 static const struct s_notify_info_data_table notify_info_data_table[] =
3384 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3385 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3386 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3387 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3388 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3389 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3410 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3411 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3412 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3413 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3414 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3415 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3433 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3436 /*******************************************************************
3437 Return the size of info_data structure.
3438 ********************************************************************/
3440 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3444 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3445 if ( (notify_info_data_table[i].type == type)
3446 && (notify_info_data_table[i].field == field) ) {
3447 switch(notify_info_data_table[i].size) {
3448 case NOTIFY_ONE_VALUE:
3449 case NOTIFY_TWO_VALUE:
3454 /* The only pointer notify data I have seen on
3455 the wire is the submitted time and this has
3456 the notify size set to 4. -tpot */
3458 case NOTIFY_POINTER:
3461 case NOTIFY_SECDESC:
3467 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3472 /*******************************************************************
3473 Return the type of notify_info_data.
3474 ********************************************************************/
3476 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3480 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3481 if (notify_info_data_table[i].type == type &&
3482 notify_info_data_table[i].field == field)
3483 return notify_info_data_table[i].size;
3489 /****************************************************************************
3490 ****************************************************************************/
3492 static BOOL search_notify(uint16 type, uint16 field, int *value)
3496 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3497 if (notify_info_data_table[i].type == type &&
3498 notify_info_data_table[i].field == field &&
3499 notify_info_data_table[i].fn != NULL) {
3508 /****************************************************************************
3509 ****************************************************************************/
3511 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3513 info_data->type = type;
3514 info_data->field = field;
3515 info_data->reserved = 0;
3517 info_data->size = size_of_notify_info_data(type, field);
3518 info_data->enc_type = type_of_notify_info_data(type, field);
3523 /*******************************************************************
3525 * fill a notify_info struct with info asked
3527 ********************************************************************/
3529 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3530 snum, SPOOL_NOTIFY_OPTION_TYPE
3531 *option_type, uint32 id,
3532 TALLOC_CTX *mem_ctx)
3538 SPOOL_NOTIFY_INFO_DATA *current_data;
3539 NT_PRINTER_INFO_LEVEL *printer = NULL;
3540 print_queue_struct *queue=NULL;
3542 type=option_type->type;
3544 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3545 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3546 option_type->count, lp_servicename(snum)));
3548 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3551 for(field_num=0; field_num<option_type->count; field_num++) {
3552 field = option_type->fields[field_num];
3554 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3556 if (!search_notify(type, field, &j) )
3559 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3560 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3564 current_data = &info->data[info->count];
3566 construct_info_data(current_data, type, field, id);
3568 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3569 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3571 notify_info_data_table[j].fn(snum, current_data, queue,
3577 free_a_printer(&printer, 2);
3581 /*******************************************************************
3583 * fill a notify_info struct with info asked
3585 ********************************************************************/
3587 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3588 SPOOL_NOTIFY_INFO *info,
3589 NT_PRINTER_INFO_LEVEL *printer,
3590 int snum, SPOOL_NOTIFY_OPTION_TYPE
3591 *option_type, uint32 id,
3592 TALLOC_CTX *mem_ctx)
3598 SPOOL_NOTIFY_INFO_DATA *current_data;
3600 DEBUG(4,("construct_notify_jobs_info\n"));
3602 type = option_type->type;
3604 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3605 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3606 option_type->count));
3608 for(field_num=0; field_num<option_type->count; field_num++) {
3609 field = option_type->fields[field_num];
3611 if (!search_notify(type, field, &j) )
3614 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3615 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3619 current_data=&(info->data[info->count]);
3621 construct_info_data(current_data, type, field, id);
3622 notify_info_data_table[j].fn(snum, current_data, queue,
3631 * JFM: The enumeration is not that simple, it's even non obvious.
3633 * let's take an example: I want to monitor the PRINTER SERVER for
3634 * the printer's name and the number of jobs currently queued.
3635 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3636 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3638 * I have 3 printers on the back of my server.
3640 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3643 * 1 printer 1 name 1
3644 * 2 printer 1 cjob 1
3645 * 3 printer 2 name 2
3646 * 4 printer 2 cjob 2
3647 * 5 printer 3 name 3
3648 * 6 printer 3 name 3
3650 * that's the print server case, the printer case is even worse.
3653 /*******************************************************************
3655 * enumerate all printers on the printserver
3656 * fill a notify_info struct with info asked
3658 ********************************************************************/
3660 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3661 SPOOL_NOTIFY_INFO *info,
3662 TALLOC_CTX *mem_ctx)
3665 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3666 int n_services=lp_numservices();
3668 SPOOL_NOTIFY_OPTION *option;
3669 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3671 DEBUG(4,("printserver_notify_info\n"));
3676 option=Printer->notify.option;
3681 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3682 sending a ffpcn() request first */
3687 for (i=0; i<option->count; i++) {
3688 option_type=&(option->ctr.type[i]);
3690 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3693 for (snum=0; snum<n_services; snum++)
3695 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3696 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3702 * Debugging information, don't delete.
3705 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3706 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3707 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3709 for (i=0; i<info->count; i++) {
3710 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3711 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3712 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3719 /*******************************************************************
3721 * fill a notify_info struct with info asked
3723 ********************************************************************/
3725 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3726 TALLOC_CTX *mem_ctx)
3729 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3732 SPOOL_NOTIFY_OPTION *option;
3733 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3735 print_queue_struct *queue=NULL;
3736 print_status_struct status;
3738 DEBUG(4,("printer_notify_info\n"));
3743 option=Printer->notify.option;
3749 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3750 sending a ffpcn() request first */
3755 get_printer_snum(p, hnd, &snum);
3757 for (i=0; i<option->count; i++) {
3758 option_type=&option->ctr.type[i];
3760 switch ( option_type->type ) {
3761 case PRINTER_NOTIFY_TYPE:
3762 if(construct_notify_printer_info(Printer, info, snum,
3768 case JOB_NOTIFY_TYPE: {
3769 NT_PRINTER_INFO_LEVEL *printer = NULL;
3771 count = print_queue_status(snum, &queue, &status);
3773 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3776 for (j=0; j<count; j++) {
3777 construct_notify_jobs_info(&queue[j], info,
3784 free_a_printer(&printer, 2);
3794 * Debugging information, don't delete.
3797 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3798 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3799 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3801 for (i=0; i<info->count; i++) {
3802 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3803 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3804 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3810 /********************************************************************
3812 ********************************************************************/
3814 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3816 POLICY_HND *handle = &q_u->handle;
3817 SPOOL_NOTIFY_INFO *info = &r_u->info;
3819 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3820 WERROR result = WERR_BADFID;
3822 /* we always have a NOTIFY_INFO struct */
3826 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3827 OUR_HANDLE(handle)));
3831 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3834 * We are now using the change value, and
3835 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3836 * I don't have a global notification system, I'm sending back all the
3837 * informations even when _NOTHING_ has changed.
3840 /* We need to keep track of the change value to send back in
3841 RRPCN replies otherwise our updates are ignored. */
3843 Printer->notify.fnpcn = True;
3845 if (Printer->notify.client_connected) {
3846 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3847 Printer->notify.change = q_u->change;
3850 /* just ignore the SPOOL_NOTIFY_OPTION */
3852 switch (Printer->printer_type) {
3854 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3857 case SPLHND_PRINTER:
3858 result = printer_notify_info(p, handle, info, p->mem_ctx);
3862 Printer->notify.fnpcn = False;
3868 /********************************************************************
3869 * construct_printer_info_0
3870 * fill a printer_info_0 struct
3871 ********************************************************************/
3873 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3877 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3878 counter_printer_0 *session_counter;
3879 uint32 global_counter;
3882 print_status_struct status;
3884 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3887 count = print_queue_length(snum, &status);
3889 /* check if we already have a counter for this printer */
3890 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3891 if (session_counter->snum == snum)
3895 /* it's the first time, add it to the list */
3896 if (session_counter==NULL) {
3897 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3898 free_a_printer(&ntprinter, 2);
3901 ZERO_STRUCTP(session_counter);
3902 session_counter->snum=snum;
3903 session_counter->counter=0;
3904 DLIST_ADD(counter_list, session_counter);
3908 session_counter->counter++;
3911 * the global_counter should be stored in a TDB as it's common to all the clients
3912 * and should be zeroed on samba startup
3914 global_counter=session_counter->counter;
3916 pstrcpy(chaine,ntprinter->info_2->printername);
3918 init_unistr(&printer->printername, chaine);
3920 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3921 init_unistr(&printer->servername, chaine);
3923 printer->cjobs = count;
3924 printer->total_jobs = 0;
3925 printer->total_bytes = 0;
3927 setuptime = (time_t)ntprinter->info_2->setuptime;
3928 t=gmtime(&setuptime);
3930 printer->year = t->tm_year+1900;
3931 printer->month = t->tm_mon+1;
3932 printer->dayofweek = t->tm_wday;
3933 printer->day = t->tm_mday;
3934 printer->hour = t->tm_hour;
3935 printer->minute = t->tm_min;
3936 printer->second = t->tm_sec;
3937 printer->milliseconds = 0;
3939 printer->global_counter = global_counter;
3940 printer->total_pages = 0;
3942 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3943 printer->major_version = 0x0005; /* NT 5 */
3944 printer->build_version = 0x0893; /* build 2195 */
3946 printer->unknown7 = 0x1;
3947 printer->unknown8 = 0x0;
3948 printer->unknown9 = 0x0;
3949 printer->session_counter = session_counter->counter;
3950 printer->unknown11 = 0x0;
3951 printer->printer_errors = 0x0; /* number of print failure */
3952 printer->unknown13 = 0x0;
3953 printer->unknown14 = 0x1;
3954 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3955 printer->unknown16 = 0x0;
3956 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3957 printer->unknown18 = 0x0;
3958 printer->status = nt_printq_status(status.status);
3959 printer->unknown20 = 0x0;
3960 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3961 printer->unknown22 = 0x0;
3962 printer->unknown23 = 0x6; /* 6 ???*/
3963 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3964 printer->unknown25 = 0;
3965 printer->unknown26 = 0;
3966 printer->unknown27 = 0;
3967 printer->unknown28 = 0;
3968 printer->unknown29 = 0;
3970 free_a_printer(&ntprinter,2);
3974 /********************************************************************
3975 * construct_printer_info_1
3976 * fill a printer_info_1 struct
3977 ********************************************************************/
3978 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3982 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3984 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3987 printer->flags=flags;
3989 if (*ntprinter->info_2->comment == '\0') {
3990 init_unistr(&printer->comment, lp_comment(snum));
3991 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3992 ntprinter->info_2->drivername, lp_comment(snum));
3995 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3996 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3997 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4000 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4002 init_unistr(&printer->description, chaine);
4003 init_unistr(&printer->name, chaine2);
4005 free_a_printer(&ntprinter,2);
4010 /****************************************************************************
4011 Free a DEVMODE struct.
4012 ****************************************************************************/
4014 static void free_dev_mode(DEVICEMODE *dev)
4019 SAFE_FREE(dev->dev_private);
4024 /****************************************************************************
4025 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4026 should be valid upon entry
4027 ****************************************************************************/
4029 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4031 if ( !devmode || !ntdevmode )
4034 init_unistr(&devmode->devicename, ntdevmode->devicename);
4036 init_unistr(&devmode->formname, ntdevmode->formname);
4038 devmode->specversion = ntdevmode->specversion;
4039 devmode->driverversion = ntdevmode->driverversion;
4040 devmode->size = ntdevmode->size;
4041 devmode->driverextra = ntdevmode->driverextra;
4042 devmode->fields = ntdevmode->fields;
4044 devmode->orientation = ntdevmode->orientation;
4045 devmode->papersize = ntdevmode->papersize;
4046 devmode->paperlength = ntdevmode->paperlength;
4047 devmode->paperwidth = ntdevmode->paperwidth;
4048 devmode->scale = ntdevmode->scale;
4049 devmode->copies = ntdevmode->copies;
4050 devmode->defaultsource = ntdevmode->defaultsource;
4051 devmode->printquality = ntdevmode->printquality;
4052 devmode->color = ntdevmode->color;
4053 devmode->duplex = ntdevmode->duplex;
4054 devmode->yresolution = ntdevmode->yresolution;
4055 devmode->ttoption = ntdevmode->ttoption;
4056 devmode->collate = ntdevmode->collate;
4057 devmode->icmmethod = ntdevmode->icmmethod;
4058 devmode->icmintent = ntdevmode->icmintent;
4059 devmode->mediatype = ntdevmode->mediatype;
4060 devmode->dithertype = ntdevmode->dithertype;
4062 if (ntdevmode->nt_dev_private != NULL) {
4063 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4070 /****************************************************************************
4071 Create a DEVMODE struct. Returns malloced memory.
4072 ****************************************************************************/
4074 DEVICEMODE *construct_dev_mode(int snum)
4076 NT_PRINTER_INFO_LEVEL *printer = NULL;
4077 DEVICEMODE *devmode = NULL;
4079 DEBUG(7,("construct_dev_mode\n"));
4081 DEBUGADD(8,("getting printer characteristics\n"));
4083 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4086 if ( !printer->info_2->devmode ) {
4087 DEBUG(5, ("BONG! There was no device mode!\n"));
4091 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4092 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4096 ZERO_STRUCTP(devmode);
4098 DEBUGADD(8,("loading DEVICEMODE\n"));
4100 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4101 free_dev_mode( devmode );
4106 free_a_printer(&printer,2);
4111 /********************************************************************
4112 * construct_printer_info_2
4113 * fill a printer_info_2 struct
4114 ********************************************************************/
4116 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4119 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4121 print_status_struct status;
4123 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4126 count = print_queue_length(snum, &status);
4128 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4129 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4130 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4131 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4132 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4134 if (*ntprinter->info_2->comment == '\0')
4135 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4137 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4139 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4140 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4141 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4142 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4143 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4145 printer->attributes = ntprinter->info_2->attributes;
4147 printer->priority = ntprinter->info_2->priority; /* priority */
4148 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4149 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4150 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4151 printer->status = nt_printq_status(status.status); /* status */
4152 printer->cjobs = count; /* jobs */
4153 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4155 if ( !(printer->devmode = construct_dev_mode(snum)) )
4156 DEBUG(8, ("Returning NULL Devicemode!\n"));
4158 printer->secdesc = NULL;
4160 if ( ntprinter->info_2->secdesc_buf
4161 && ntprinter->info_2->secdesc_buf->len != 0 )
4163 /* don't use talloc_steal() here unless you do a deep steal of all
4164 the SEC_DESC members */
4166 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4167 ntprinter->info_2->secdesc_buf->sec );
4170 free_a_printer(&ntprinter, 2);
4175 /********************************************************************
4176 * construct_printer_info_3
4177 * fill a printer_info_3 struct
4178 ********************************************************************/
4180 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4182 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4183 PRINTER_INFO_3 *printer = NULL;
4185 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4189 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4190 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4194 ZERO_STRUCTP(printer);
4196 /* These are the components of the SD we are returning. */
4198 printer->flags = 0x4;
4200 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4201 /* don't use talloc_steal() here unless you do a deep steal of all
4202 the SEC_DESC members */
4204 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4205 ntprinter->info_2->secdesc_buf->sec );
4208 free_a_printer(&ntprinter, 2);
4210 *pp_printer = printer;
4214 /********************************************************************
4215 * construct_printer_info_4
4216 * fill a printer_info_4 struct
4217 ********************************************************************/
4219 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4221 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4223 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4226 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4227 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4228 printer->attributes = ntprinter->info_2->attributes;
4230 free_a_printer(&ntprinter, 2);
4234 /********************************************************************
4235 * construct_printer_info_5
4236 * fill a printer_info_5 struct
4237 ********************************************************************/
4239 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4241 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4243 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4246 init_unistr(&printer->printername, ntprinter->info_2->printername);
4247 init_unistr(&printer->portname, ntprinter->info_2->portname);
4248 printer->attributes = ntprinter->info_2->attributes;
4250 /* these two are not used by NT+ according to MSDN */
4252 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4253 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4255 free_a_printer(&ntprinter, 2);
4260 /********************************************************************
4261 * construct_printer_info_7
4262 * fill a printer_info_7 struct
4263 ********************************************************************/
4265 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4267 char *guid_str = NULL;
4270 if (is_printer_published(print_hnd, snum, &guid)) {
4271 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4272 strupper_m(guid_str);
4273 init_unistr(&printer->guid, guid_str);
4274 printer->action = SPOOL_DS_PUBLISH;
4276 init_unistr(&printer->guid, "");
4277 printer->action = SPOOL_DS_UNPUBLISH;
4283 /********************************************************************
4284 Spoolss_enumprinters.
4285 ********************************************************************/
4287 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4291 int n_services=lp_numservices();
4292 PRINTER_INFO_1 *printers=NULL;
4293 PRINTER_INFO_1 current_prt;
4294 WERROR result = WERR_OK;
4296 DEBUG(4,("enum_all_printers_info_1\n"));
4298 for (snum=0; snum<n_services; snum++) {
4299 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4300 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4302 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4303 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4304 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4308 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4310 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4316 /* check the required size. */
4317 for (i=0; i<*returned; i++)
4318 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4320 if (*needed > offered) {
4321 result = WERR_INSUFFICIENT_BUFFER;
4325 if (!rpcbuf_alloc_size(buffer, *needed)) {
4326 result = WERR_NOMEM;
4330 /* fill the buffer with the structures */
4331 for (i=0; i<*returned; i++)
4332 smb_io_printer_info_1("", buffer, &printers[i], 0);
4337 SAFE_FREE(printers);
4339 if ( !W_ERROR_IS_OK(result) )
4345 /********************************************************************
4346 enum_all_printers_info_1_local.
4347 *********************************************************************/
4349 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4351 DEBUG(4,("enum_all_printers_info_1_local\n"));
4353 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4356 /********************************************************************
4357 enum_all_printers_info_1_name.
4358 *********************************************************************/
4360 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4364 DEBUG(4,("enum_all_printers_info_1_name\n"));
4366 if ((name[0] == '\\') && (name[1] == '\\'))
4369 if (is_myname_or_ipaddr(s)) {
4370 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4373 return WERR_INVALID_NAME;
4376 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4377 /********************************************************************
4378 enum_all_printers_info_1_remote.
4379 *********************************************************************/
4381 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4383 PRINTER_INFO_1 *printer;
4384 fstring printername;
4387 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4388 WERROR result = WERR_OK;
4390 /* JFM: currently it's more a place holder than anything else.
4391 * In the spooler world there is a notion of server registration.
4392 * the print servers are registered on the PDC (in the same domain)
4394 * We should have a TDB here. The registration is done thru an
4395 * undocumented RPC call.
4398 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4403 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4404 slprintf(desc, sizeof(desc)-1,"%s", name);
4405 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4407 init_unistr(&printer->description, desc);
4408 init_unistr(&printer->name, printername);
4409 init_unistr(&printer->comment, comment);
4410 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4412 /* check the required size. */
4413 *needed += spoolss_size_printer_info_1(printer);
4415 if (*needed > offered) {
4416 result = WERR_INSUFFICIENT_BUFFER;
4420 if (!rpcbuf_alloc_size(buffer, *needed)) {
4421 result = WERR_NOMEM;
4425 /* fill the buffer with the structures */
4426 smb_io_printer_info_1("", buffer, printer, 0);
4432 if ( !W_ERROR_IS_OK(result) )
4440 /********************************************************************
4441 enum_all_printers_info_1_network.
4442 *********************************************************************/
4444 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4448 DEBUG(4,("enum_all_printers_info_1_network\n"));
4450 /* If we respond to a enum_printers level 1 on our name with flags
4451 set to PRINTER_ENUM_REMOTE with a list of printers then these
4452 printers incorrectly appear in the APW browse list.
4453 Specifically the printers for the server appear at the workgroup
4454 level where all the other servers in the domain are
4455 listed. Windows responds to this call with a
4456 WERR_CAN_NOT_COMPLETE so we should do the same. */
4458 if (name[0] == '\\' && name[1] == '\\')
4461 if (is_myname_or_ipaddr(s))
4462 return WERR_CAN_NOT_COMPLETE;
4464 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4467 /********************************************************************
4468 * api_spoolss_enumprinters
4470 * called from api_spoolss_enumprinters (see this to understand)
4471 ********************************************************************/
4473 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4477 int n_services=lp_numservices();
4478 PRINTER_INFO_2 *printers=NULL;
4479 PRINTER_INFO_2 current_prt;
4480 WERROR result = WERR_OK;
4484 for (snum=0; snum<n_services; snum++) {
4485 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4486 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4488 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4489 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4490 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4495 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4497 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4504 /* check the required size. */
4505 for (i=0; i<*returned; i++)
4506 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4508 if (*needed > offered) {
4509 result = WERR_INSUFFICIENT_BUFFER;
4513 if (!rpcbuf_alloc_size(buffer, *needed)) {
4514 result = WERR_NOMEM;
4518 /* fill the buffer with the structures */
4519 for (i=0; i<*returned; i++)
4520 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4525 for (i=0; i<*returned; i++)
4526 free_devmode(printers[i].devmode);
4528 SAFE_FREE(printers);
4530 if ( !W_ERROR_IS_OK(result) )
4536 /********************************************************************
4537 * handle enumeration of printers at level 1
4538 ********************************************************************/
4540 static WERROR enumprinters_level1( uint32 flags, fstring name,
4541 RPC_BUFFER *buffer, uint32 offered,
4542 uint32 *needed, uint32 *returned)
4544 /* Not all the flags are equals */
4546 if (flags & PRINTER_ENUM_LOCAL)
4547 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4549 if (flags & PRINTER_ENUM_NAME)
4550 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4552 #if 0 /* JERRY - disabled for now */
4553 if (flags & PRINTER_ENUM_REMOTE)
4554 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4557 if (flags & PRINTER_ENUM_NETWORK)
4558 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4560 return WERR_OK; /* NT4sp5 does that */
4563 /********************************************************************
4564 * handle enumeration of printers at level 2
4565 ********************************************************************/
4567 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4568 RPC_BUFFER *buffer, uint32 offered,
4569 uint32 *needed, uint32 *returned)
4571 char *s = servername;
4573 if (flags & PRINTER_ENUM_LOCAL) {
4574 return enum_all_printers_info_2(buffer, offered, needed, returned);
4577 if (flags & PRINTER_ENUM_NAME) {
4578 if ((servername[0] == '\\') && (servername[1] == '\\'))
4580 if (is_myname_or_ipaddr(s))
4581 return enum_all_printers_info_2(buffer, offered, needed, returned);
4583 return WERR_INVALID_NAME;
4586 if (flags & PRINTER_ENUM_REMOTE)
4587 return WERR_UNKNOWN_LEVEL;
4592 /********************************************************************
4593 * handle enumeration of printers at level 5
4594 ********************************************************************/
4596 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4597 RPC_BUFFER *buffer, uint32 offered,
4598 uint32 *needed, uint32 *returned)
4600 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4604 /********************************************************************
4605 * api_spoolss_enumprinters
4607 * called from api_spoolss_enumprinters (see this to understand)
4608 ********************************************************************/
4610 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4612 uint32 flags = q_u->flags;
4613 UNISTR2 *servername = &q_u->servername;
4614 uint32 level = q_u->level;
4615 RPC_BUFFER *buffer = NULL;
4616 uint32 offered = q_u->offered;
4617 uint32 *needed = &r_u->needed;
4618 uint32 *returned = &r_u->returned;
4622 /* that's an [in out] buffer */
4624 if (!q_u->buffer && (offered!=0)) {
4625 return WERR_INVALID_PARAM;
4628 rpcbuf_move(q_u->buffer, &r_u->buffer);
4629 buffer = r_u->buffer;
4631 DEBUG(4,("_spoolss_enumprinters\n"));
4638 * flags==PRINTER_ENUM_NAME
4639 * if name=="" then enumerates all printers
4640 * if name!="" then enumerate the printer
4641 * flags==PRINTER_ENUM_REMOTE
4642 * name is NULL, enumerate printers
4643 * Level 2: name!="" enumerates printers, name can't be NULL
4644 * Level 3: doesn't exist
4645 * Level 4: does a local registry lookup
4646 * Level 5: same as Level 2
4649 unistr2_to_ascii(name, servername, sizeof(name)-1);
4654 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4656 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4658 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4663 return WERR_UNKNOWN_LEVEL;
4666 /****************************************************************************
4667 ****************************************************************************/
4669 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4671 PRINTER_INFO_0 *printer=NULL;
4672 WERROR result = WERR_OK;
4674 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4677 construct_printer_info_0(print_hnd, printer, snum);
4679 /* check the required size. */
4680 *needed += spoolss_size_printer_info_0(printer);
4682 if (*needed > offered) {
4683 result = WERR_INSUFFICIENT_BUFFER;
4687 if (!rpcbuf_alloc_size(buffer, *needed)) {
4688 result = WERR_NOMEM;
4692 /* fill the buffer with the structures */
4693 smb_io_printer_info_0("", buffer, printer, 0);
4703 /****************************************************************************
4704 ****************************************************************************/
4706 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4708 PRINTER_INFO_1 *printer=NULL;
4709 WERROR result = WERR_OK;
4711 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4714 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4716 /* check the required size. */
4717 *needed += spoolss_size_printer_info_1(printer);
4719 if (*needed > offered) {
4720 result = WERR_INSUFFICIENT_BUFFER;
4724 if (!rpcbuf_alloc_size(buffer, *needed)) {
4725 result = WERR_NOMEM;
4729 /* fill the buffer with the structures */
4730 smb_io_printer_info_1("", buffer, printer, 0);
4739 /****************************************************************************
4740 ****************************************************************************/
4742 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4744 PRINTER_INFO_2 *printer=NULL;
4745 WERROR result = WERR_OK;
4747 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4750 construct_printer_info_2(print_hnd, printer, snum);
4752 /* check the required size. */
4753 *needed += spoolss_size_printer_info_2(printer);
4755 if (*needed > offered) {
4756 result = WERR_INSUFFICIENT_BUFFER;
4760 if (!rpcbuf_alloc_size(buffer, *needed)) {
4761 result = WERR_NOMEM;
4765 /* fill the buffer with the structures */
4766 if (!smb_io_printer_info_2("", buffer, printer, 0))
4767 result = WERR_NOMEM;
4771 free_printer_info_2(printer);
4776 /****************************************************************************
4777 ****************************************************************************/
4779 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4781 PRINTER_INFO_3 *printer=NULL;
4782 WERROR result = WERR_OK;
4784 if (!construct_printer_info_3(print_hnd, &printer, snum))
4787 /* check the required size. */
4788 *needed += spoolss_size_printer_info_3(printer);
4790 if (*needed > offered) {
4791 result = WERR_INSUFFICIENT_BUFFER;
4795 if (!rpcbuf_alloc_size(buffer, *needed)) {
4796 result = WERR_NOMEM;
4800 /* fill the buffer with the structures */
4801 smb_io_printer_info_3("", buffer, printer, 0);
4805 free_printer_info_3(printer);
4810 /****************************************************************************
4811 ****************************************************************************/
4813 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4815 PRINTER_INFO_4 *printer=NULL;
4816 WERROR result = WERR_OK;
4818 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4821 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4826 /* check the required size. */
4827 *needed += spoolss_size_printer_info_4(printer);
4829 if (*needed > offered) {
4830 result = WERR_INSUFFICIENT_BUFFER;
4834 if (!rpcbuf_alloc_size(buffer, *needed)) {
4835 result = WERR_NOMEM;
4839 /* fill the buffer with the structures */
4840 smb_io_printer_info_4("", buffer, printer, 0);
4844 free_printer_info_4(printer);
4849 /****************************************************************************
4850 ****************************************************************************/
4852 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4854 PRINTER_INFO_5 *printer=NULL;
4855 WERROR result = WERR_OK;
4857 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4860 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4861 free_printer_info_5(printer);
4865 /* check the required size. */
4866 *needed += spoolss_size_printer_info_5(printer);
4868 if (*needed > offered) {
4869 result = WERR_INSUFFICIENT_BUFFER;
4873 if (!rpcbuf_alloc_size(buffer, *needed)) {
4874 result = WERR_NOMEM;
4878 /* fill the buffer with the structures */
4879 smb_io_printer_info_5("", buffer, printer, 0);
4883 free_printer_info_5(printer);
4888 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4890 PRINTER_INFO_7 *printer=NULL;
4891 WERROR result = WERR_OK;
4893 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4896 if (!construct_printer_info_7(print_hnd, printer, snum))
4899 /* check the required size. */
4900 *needed += spoolss_size_printer_info_7(printer);
4902 if (*needed > offered) {
4903 result = WERR_INSUFFICIENT_BUFFER;
4907 if (!rpcbuf_alloc_size(buffer, *needed)) {
4908 result = WERR_NOMEM;
4913 /* fill the buffer with the structures */
4914 smb_io_printer_info_7("", buffer, printer, 0);
4918 free_printer_info_7(printer);
4923 /****************************************************************************
4924 ****************************************************************************/
4926 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4928 POLICY_HND *handle = &q_u->handle;
4929 uint32 level = q_u->level;
4930 RPC_BUFFER *buffer = NULL;
4931 uint32 offered = q_u->offered;
4932 uint32 *needed = &r_u->needed;
4933 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4937 /* that's an [in out] buffer */
4939 if (!q_u->buffer && (offered!=0)) {
4940 return WERR_INVALID_PARAM;
4943 rpcbuf_move(q_u->buffer, &r_u->buffer);
4944 buffer = r_u->buffer;
4948 if (!get_printer_snum(p, handle, &snum))
4953 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4955 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4957 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4959 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4961 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4963 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4965 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4967 return WERR_UNKNOWN_LEVEL;
4970 /********************************************************************
4971 * fill a DRIVER_INFO_1 struct
4972 ********************************************************************/
4974 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4976 init_unistr( &info->name, driver.info_3->name);
4979 /********************************************************************
4980 * construct_printer_driver_info_1
4981 ********************************************************************/
4983 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4985 NT_PRINTER_INFO_LEVEL *printer = NULL;
4986 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4988 ZERO_STRUCT(driver);
4990 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4991 return WERR_INVALID_PRINTER_NAME;
4993 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4994 return WERR_UNKNOWN_PRINTER_DRIVER;
4996 fill_printer_driver_info_1(info, driver, servername, architecture);
4998 free_a_printer(&printer,2);
5003 /********************************************************************
5004 * construct_printer_driver_info_2
5005 * fill a printer_info_2 struct
5006 ********************************************************************/
5008 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5012 info->version=driver.info_3->cversion;
5014 init_unistr( &info->name, driver.info_3->name );
5015 init_unistr( &info->architecture, driver.info_3->environment );
5018 if (strlen(driver.info_3->driverpath)) {
5019 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5020 init_unistr( &info->driverpath, temp );
5022 init_unistr( &info->driverpath, "" );
5024 if (strlen(driver.info_3->datafile)) {
5025 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5026 init_unistr( &info->datafile, temp );
5028 init_unistr( &info->datafile, "" );
5030 if (strlen(driver.info_3->configfile)) {
5031 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5032 init_unistr( &info->configfile, temp );
5034 init_unistr( &info->configfile, "" );
5037 /********************************************************************
5038 * construct_printer_driver_info_2
5039 * fill a printer_info_2 struct
5040 ********************************************************************/
5042 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5044 NT_PRINTER_INFO_LEVEL *printer = NULL;
5045 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5047 ZERO_STRUCT(printer);
5048 ZERO_STRUCT(driver);
5050 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5051 return WERR_INVALID_PRINTER_NAME;
5053 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5054 return WERR_UNKNOWN_PRINTER_DRIVER;
5056 fill_printer_driver_info_2(info, driver, servername);
5058 free_a_printer(&printer,2);
5063 /********************************************************************
5064 * copy a strings array and convert to UNICODE
5066 * convert an array of ascii string to a UNICODE string
5067 ********************************************************************/
5069 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5076 DEBUG(6,("init_unistr_array\n"));
5087 v = ""; /* hack to handle null lists */
5090 /* hack to allow this to be used in places other than when generating
5091 the list of dependent files */
5094 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5098 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5100 /* add one extra unit16 for the second terminating NULL */
5102 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5103 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5110 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5115 /* special case for ""; we need to add both NULL's here */
5117 (*uni_array)[j++]=0x0000;
5118 (*uni_array)[j]=0x0000;
5121 DEBUGADD(6,("last one:done\n"));
5123 /* return size of array in uint16's */
5128 /********************************************************************
5129 * construct_printer_info_3
5130 * fill a printer_info_3 struct
5131 ********************************************************************/
5133 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5139 info->version=driver.info_3->cversion;
5141 init_unistr( &info->name, driver.info_3->name );
5142 init_unistr( &info->architecture, driver.info_3->environment );
5144 if (strlen(driver.info_3->driverpath)) {
5145 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5146 init_unistr( &info->driverpath, temp );
5148 init_unistr( &info->driverpath, "" );
5150 if (strlen(driver.info_3->datafile)) {
5151 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5152 init_unistr( &info->datafile, temp );
5154 init_unistr( &info->datafile, "" );
5156 if (strlen(driver.info_3->configfile)) {
5157 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5158 init_unistr( &info->configfile, temp );
5160 init_unistr( &info->configfile, "" );
5162 if (strlen(driver.info_3->helpfile)) {
5163 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5164 init_unistr( &info->helpfile, temp );
5166 init_unistr( &info->helpfile, "" );
5168 init_unistr( &info->monitorname, driver.info_3->monitorname );
5169 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5171 info->dependentfiles=NULL;
5172 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5175 /********************************************************************
5176 * construct_printer_info_3
5177 * fill a printer_info_3 struct
5178 ********************************************************************/
5180 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5182 NT_PRINTER_INFO_LEVEL *printer = NULL;
5183 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5185 ZERO_STRUCT(driver);
5187 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5188 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5189 if (!W_ERROR_IS_OK(status))
5190 return WERR_INVALID_PRINTER_NAME;
5192 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5193 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5198 * I put this code in during testing. Helpful when commenting out the
5199 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5200 * as win2k always queries the driver using an infor level of 6.
5201 * I've left it in (but ifdef'd out) because I'll probably
5202 * use it in experimentation again in the future. --jerry 22/01/2002
5205 if (!W_ERROR_IS_OK(status)) {
5207 * Is this a W2k client ?
5210 /* Yes - try again with a WinNT driver. */
5212 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5213 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5217 if (!W_ERROR_IS_OK(status)) {
5218 free_a_printer(&printer,2);
5219 return WERR_UNKNOWN_PRINTER_DRIVER;
5227 fill_printer_driver_info_3(info, driver, servername);
5229 free_a_printer(&printer,2);
5234 /********************************************************************
5235 * construct_printer_info_6
5236 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5237 ********************************************************************/
5239 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5245 memset(&nullstr, '\0', sizeof(fstring));
5247 info->version=driver.info_3->cversion;
5249 init_unistr( &info->name, driver.info_3->name );
5250 init_unistr( &info->architecture, driver.info_3->environment );
5252 if (strlen(driver.info_3->driverpath)) {
5253 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5254 init_unistr( &info->driverpath, temp );
5256 init_unistr( &info->driverpath, "" );
5258 if (strlen(driver.info_3->datafile)) {
5259 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5260 init_unistr( &info->datafile, temp );
5262 init_unistr( &info->datafile, "" );
5264 if (strlen(driver.info_3->configfile)) {
5265 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5266 init_unistr( &info->configfile, temp );
5268 init_unistr( &info->configfile, "" );
5270 if (strlen(driver.info_3->helpfile)) {
5271 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5272 init_unistr( &info->helpfile, temp );
5274 init_unistr( &info->helpfile, "" );
5276 init_unistr( &info->monitorname, driver.info_3->monitorname );
5277 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5279 info->dependentfiles = NULL;
5280 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5282 info->previousdrivernames=NULL;
5283 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5285 info->driver_date.low=0;
5286 info->driver_date.high=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);
5641 struct current_user user;
5644 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5648 get_current_user(&user, p);
5651 * a nice thing with NT is it doesn't listen to what you tell it.
5652 * when asked to send _only_ RAW datas, it tries to send datas
5655 * So I add checks like in NT Server ...
5658 if (info_1->p_datatype != 0) {
5659 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5660 if (strcmp(datatype, "RAW") != 0) {
5662 return WERR_INVALID_DATATYPE;
5666 /* get the share number of the printer */
5667 if (!get_printer_snum(p, handle, &snum)) {
5671 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5673 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5675 /* An error occured in print_job_start() so return an appropriate
5678 if (Printer->jobid == -1) {
5679 return map_werror_from_unix(errno);
5682 Printer->document_started=True;
5683 (*jobid) = Printer->jobid;
5688 /********************************************************************
5689 * api_spoolss_getprinter
5690 * called from the spoolss dispatcher
5692 ********************************************************************/
5694 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5696 POLICY_HND *handle = &q_u->handle;
5698 return _spoolss_enddocprinter_internal(p, handle);
5701 /****************************************************************************
5702 ****************************************************************************/
5704 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5706 POLICY_HND *handle = &q_u->handle;
5707 uint32 buffer_size = q_u->buffer_size;
5708 uint8 *buffer = q_u->buffer;
5709 uint32 *buffer_written = &q_u->buffer_size2;
5711 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5714 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5715 r_u->buffer_written = q_u->buffer_size2;
5719 if (!get_printer_snum(p, handle, &snum))
5722 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5723 (SMB_OFF_T)-1, (size_t)buffer_size);
5724 if (*buffer_written == (uint32)-1) {
5725 r_u->buffer_written = 0;
5726 if (errno == ENOSPC)
5727 return WERR_NO_SPOOL_SPACE;
5729 return WERR_ACCESS_DENIED;
5732 r_u->buffer_written = q_u->buffer_size2;
5737 /********************************************************************
5738 * api_spoolss_getprinter
5739 * called from the spoolss dispatcher
5741 ********************************************************************/
5743 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5746 struct current_user user;
5748 WERROR errcode = WERR_BADFUNC;
5749 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5751 get_current_user(&user, p);
5754 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5758 if (!get_printer_snum(p, handle, &snum))
5762 case PRINTER_CONTROL_PAUSE:
5763 if (print_queue_pause(&user, snum, &errcode)) {
5767 case PRINTER_CONTROL_RESUME:
5768 case PRINTER_CONTROL_UNPAUSE:
5769 if (print_queue_resume(&user, snum, &errcode)) {
5773 case PRINTER_CONTROL_PURGE:
5774 if (print_queue_purge(&user, snum, &errcode)) {
5779 return WERR_UNKNOWN_LEVEL;
5785 /********************************************************************
5786 * api_spoolss_abortprinter
5787 * From MSDN: "Deletes printer's spool file if printer is configured
5789 ********************************************************************/
5791 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5793 POLICY_HND *handle = &q_u->handle;
5794 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5796 struct current_user user;
5797 WERROR errcode = WERR_OK;
5800 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5804 if (!get_printer_snum(p, handle, &snum))
5807 get_current_user( &user, p );
5809 print_job_delete( &user, snum, Printer->jobid, &errcode );
5814 /********************************************************************
5815 * called by spoolss_api_setprinter
5816 * when updating a printer description
5817 ********************************************************************/
5819 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5820 const SPOOL_PRINTER_INFO_LEVEL *info,
5821 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5823 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5827 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5829 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5830 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5831 OUR_HANDLE(handle)));
5833 result = WERR_BADFID;
5837 /* Check the user has permissions to change the security
5838 descriptor. By experimentation with two NT machines, the user
5839 requires Full Access to the printer to change security
5842 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5843 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5844 result = WERR_ACCESS_DENIED;
5848 /* NT seems to like setting the security descriptor even though
5849 nothing may have actually changed. */
5851 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5853 if (DEBUGLEVEL >= 10) {
5857 the_acl = old_secdesc_ctr->sec->dacl;
5858 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5859 PRINTERNAME(snum), the_acl->num_aces));
5861 for (i = 0; i < the_acl->num_aces; i++) {
5864 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5866 DEBUG(10, ("%s 0x%08x\n", sid_str,
5867 the_acl->ace[i].info.mask));
5870 the_acl = secdesc_ctr->sec->dacl;
5873 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5874 PRINTERNAME(snum), the_acl->num_aces));
5876 for (i = 0; i < the_acl->num_aces; i++) {
5879 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5881 DEBUG(10, ("%s 0x%08x\n", sid_str,
5882 the_acl->ace[i].info.mask));
5885 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5889 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5891 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5896 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5903 /********************************************************************
5904 Canonicalize printer info from a client
5906 ATTN: It does not matter what we set the servername to hear
5907 since we do the necessary work in get_a_printer() to set it to
5908 the correct value based on what the client sent in the
5909 _spoolss_open_printer_ex().
5910 ********************************************************************/
5912 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5914 fstring printername;
5917 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5918 "portname=%s drivername=%s comment=%s location=%s\n",
5919 info->servername, info->printername, info->sharename,
5920 info->portname, info->drivername, info->comment, info->location));
5922 /* we force some elements to "correct" values */
5923 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5924 fstrcpy(info->sharename, lp_servicename(snum));
5926 /* check to see if we allow printername != sharename */
5928 if ( lp_force_printername(snum) ) {
5929 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5930 global_myname(), info->sharename );
5933 /* make sure printername is in \\server\printername format */
5935 fstrcpy( printername, info->printername );
5937 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5938 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5942 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5943 global_myname(), p );
5946 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5947 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5954 /****************************************************************************
5955 ****************************************************************************/
5957 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
5959 char *cmd = lp_addport_cmd();
5963 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5964 BOOL is_print_op = False;
5967 return WERR_ACCESS_DENIED;
5970 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
5973 is_print_op = user_has_privileges( token, &se_printop );
5975 DEBUG(10,("Running [%s]\n", command));
5977 /********* BEGIN SePrintOperatorPrivilege **********/
5982 ret = smbrun(command, &fd);
5987 /********* END SePrintOperatorPrivilege **********/
5989 DEBUGADD(10,("returned [%d]\n", ret));
5994 return WERR_ACCESS_DENIED;
6000 /****************************************************************************
6001 ****************************************************************************/
6003 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6005 char *cmd = lp_addprinter_cmd();
6011 fstring remote_machine = "%m";
6012 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6013 BOOL is_print_op = False;
6015 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6017 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6018 cmd, printer->info_2->printername, printer->info_2->sharename,
6019 printer->info_2->portname, printer->info_2->drivername,
6020 printer->info_2->location, printer->info_2->comment, remote_machine);
6023 is_print_op = user_has_privileges( token, &se_printop );
6025 DEBUG(10,("Running [%s]\n", command));
6027 /********* BEGIN SePrintOperatorPrivilege **********/
6032 if ( (ret = smbrun(command, &fd)) == 0 ) {
6033 /* Tell everyone we updated smb.conf. */
6034 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6040 /********* END SePrintOperatorPrivilege **********/
6042 DEBUGADD(10,("returned [%d]\n", ret));
6050 /* reload our services immediately */
6051 reload_services( False );
6054 /* Get lines and convert them back to dos-codepage */
6055 qlines = fd_lines_load(fd, &numlines, 0);
6056 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6059 /* Set the portname to what the script says the portname should be. */
6060 /* but don't require anything to be return from the script exit a good error code */
6063 /* Set the portname to what the script says the portname should be. */
6064 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6065 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6068 file_lines_free(qlines);
6073 /********************************************************************
6074 * Called by spoolss_api_setprinter
6075 * when updating a printer description.
6076 ********************************************************************/
6078 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6079 const SPOOL_PRINTER_INFO_LEVEL *info,
6080 DEVICEMODE *devmode)
6083 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6084 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6089 DEBUG(8,("update_printer\n"));
6094 result = WERR_BADFID;
6098 if (!get_printer_snum(p, handle, &snum)) {
6099 result = WERR_BADFID;
6103 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6104 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6105 result = WERR_BADFID;
6109 DEBUGADD(8,("Converting info_2 struct\n"));
6112 * convert_printer_info converts the incoming
6113 * info from the client and overwrites the info
6114 * just read from the tdb in the pointer 'printer'.
6117 if (!convert_printer_info(info, printer, level)) {
6118 result = WERR_NOMEM;
6123 /* we have a valid devmode
6124 convert it and link it*/
6126 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6127 if (!convert_devicemode(printer->info_2->printername, devmode,
6128 &printer->info_2->devmode)) {
6129 result = WERR_NOMEM;
6134 /* Do sanity check on the requested changes for Samba */
6136 if (!check_printer_ok(printer->info_2, snum)) {
6137 result = WERR_INVALID_PARAM;
6141 /* FIXME!!! If the driver has changed we really should verify that
6142 it is installed before doing much else --jerry */
6144 /* Check calling user has permission to update printer description */
6146 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6147 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6148 result = WERR_ACCESS_DENIED;
6152 /* Call addprinter hook */
6153 /* Check changes to see if this is really needed */
6155 if ( *lp_addprinter_cmd()
6156 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6157 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6158 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6159 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6161 /* add_printer_hook() will call reload_services() */
6163 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6164 result = WERR_ACCESS_DENIED;
6170 * When a *new* driver is bound to a printer, the drivername is used to
6171 * lookup previously saved driver initialization info, which is then
6172 * bound to the printer, simulating what happens in the Windows arch.
6174 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6176 if (!set_driver_init(printer, 2))
6178 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6179 printer->info_2->drivername));
6182 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6183 printer->info_2->drivername));
6185 notify_printer_driver(snum, printer->info_2->drivername);
6189 * flag which changes actually occured. This is a small subset of
6190 * all the possible changes. We also have to update things in the
6194 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6195 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6196 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6197 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6199 notify_printer_comment(snum, printer->info_2->comment);
6202 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6203 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6204 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6205 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6207 notify_printer_sharename(snum, printer->info_2->sharename);
6210 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6213 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6216 pname = printer->info_2->printername;
6219 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6220 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6221 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6223 notify_printer_printername( snum, pname );
6226 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6227 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6228 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6229 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6231 notify_printer_port(snum, printer->info_2->portname);
6234 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6235 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6236 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6237 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6239 notify_printer_location(snum, printer->info_2->location);
6242 /* here we need to update some more DsSpooler keys */
6243 /* uNCName, serverName, shortServerName */
6245 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6246 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6247 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6248 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6249 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6251 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6252 global_myname(), printer->info_2->sharename );
6253 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6254 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6255 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6257 /* Update printer info */
6258 result = mod_a_printer(printer, 2);
6261 free_a_printer(&printer, 2);
6262 free_a_printer(&old_printer, 2);
6268 /****************************************************************************
6269 ****************************************************************************/
6270 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6271 const SPOOL_PRINTER_INFO_LEVEL *info)
6274 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6276 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6278 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6283 if (!get_printer_snum(p, handle, &snum))
6286 nt_printer_publish(Printer, snum, info7->action);
6290 return WERR_UNKNOWN_LEVEL;
6293 /****************************************************************************
6294 ****************************************************************************/
6296 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6298 POLICY_HND *handle = &q_u->handle;
6299 uint32 level = q_u->level;
6300 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6301 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6302 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6303 uint32 command = q_u->command;
6306 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6309 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6313 /* check the level */
6316 return control_printer(handle, command, p);
6318 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6319 if (!W_ERROR_IS_OK(result))
6322 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6325 return update_printer_sec(handle, level, info, p,
6328 return publish_or_unpublish_printer(p, handle, info);
6330 return WERR_UNKNOWN_LEVEL;
6334 /****************************************************************************
6335 ****************************************************************************/
6337 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6339 POLICY_HND *handle = &q_u->handle;
6340 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6343 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6347 if (Printer->notify.client_connected==True) {
6350 if ( Printer->printer_type == SPLHND_SERVER)
6352 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6353 !get_printer_snum(p, handle, &snum) )
6356 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6359 Printer->notify.flags=0;
6360 Printer->notify.options=0;
6361 Printer->notify.localmachine[0]='\0';
6362 Printer->notify.printerlocal=0;
6363 if (Printer->notify.option)
6364 free_spool_notify_option(&Printer->notify.option);
6365 Printer->notify.client_connected=False;
6370 /****************************************************************************
6371 ****************************************************************************/
6373 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6375 /* that's an [in out] buffer */
6377 if (!q_u->buffer && (q_u->offered!=0)) {
6378 return WERR_INVALID_PARAM;
6381 rpcbuf_move(q_u->buffer, &r_u->buffer);
6384 return WERR_INVALID_PARAM; /* this is what a NT server
6385 returns for AddJob. AddJob
6386 must fail on non-local
6390 /****************************************************************************
6391 ****************************************************************************/
6393 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6394 int position, int snum,
6395 NT_PRINTER_INFO_LEVEL *ntprinter)
6399 t=gmtime(&queue->time);
6401 job_info->jobid=queue->job;
6402 init_unistr(&job_info->printername, lp_servicename(snum));
6403 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6404 init_unistr(&job_info->username, queue->fs_user);
6405 init_unistr(&job_info->document, queue->fs_file);
6406 init_unistr(&job_info->datatype, "RAW");
6407 init_unistr(&job_info->text_status, "");
6408 job_info->status=nt_printj_status(queue->status);
6409 job_info->priority=queue->priority;
6410 job_info->position=position;
6411 job_info->totalpages=queue->page_count;
6412 job_info->pagesprinted=0;
6414 make_systemtime(&job_info->submitted, t);
6417 /****************************************************************************
6418 ****************************************************************************/
6420 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6421 int position, int snum,
6422 NT_PRINTER_INFO_LEVEL *ntprinter,
6423 DEVICEMODE *devmode)
6427 t=gmtime(&queue->time);
6429 job_info->jobid=queue->job;
6431 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6433 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6434 init_unistr(&job_info->username, queue->fs_user);
6435 init_unistr(&job_info->document, queue->fs_file);
6436 init_unistr(&job_info->notifyname, queue->fs_user);
6437 init_unistr(&job_info->datatype, "RAW");
6438 init_unistr(&job_info->printprocessor, "winprint");
6439 init_unistr(&job_info->parameters, "");
6440 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6441 init_unistr(&job_info->text_status, "");
6443 /* and here the security descriptor */
6445 job_info->status=nt_printj_status(queue->status);
6446 job_info->priority=queue->priority;
6447 job_info->position=position;
6448 job_info->starttime=0;
6449 job_info->untiltime=0;
6450 job_info->totalpages=queue->page_count;
6451 job_info->size=queue->size;
6452 make_systemtime(&(job_info->submitted), t);
6453 job_info->timeelapsed=0;
6454 job_info->pagesprinted=0;
6456 job_info->devmode = devmode;
6461 /****************************************************************************
6462 Enumjobs at level 1.
6463 ****************************************************************************/
6465 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6466 NT_PRINTER_INFO_LEVEL *ntprinter,
6467 RPC_BUFFER *buffer, uint32 offered,
6468 uint32 *needed, uint32 *returned)
6472 WERROR result = WERR_OK;
6474 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6481 for (i=0; i<*returned; i++)
6482 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(print_queue_struct *queue, int snum,
6519 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(snum);
6537 for (i=0; i<*returned; i++)
6538 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6540 free_a_printer(&ntprinter, 2);
6543 /* check the required size. */
6544 for (i=0; i<*returned; i++)
6545 (*needed) += spoolss_size_job_info_2(&info[i]);
6547 if (*needed > offered) {
6548 result = WERR_INSUFFICIENT_BUFFER;
6552 if (!rpcbuf_alloc_size(buffer, *needed)) {
6553 result = WERR_NOMEM;
6557 /* fill the buffer with the structures */
6558 for (i=0; i<*returned; i++)
6559 smb_io_job_info_2("", buffer, &info[i], 0);
6562 free_devmode(devmode);
6565 if ( !W_ERROR_IS_OK(result) )
6572 /****************************************************************************
6574 ****************************************************************************/
6576 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6578 POLICY_HND *handle = &q_u->handle;
6579 uint32 level = q_u->level;
6580 RPC_BUFFER *buffer = NULL;
6581 uint32 offered = q_u->offered;
6582 uint32 *needed = &r_u->needed;
6583 uint32 *returned = &r_u->returned;
6585 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6587 print_status_struct prt_status;
6588 print_queue_struct *queue=NULL;
6590 /* that's an [in out] buffer */
6592 if (!q_u->buffer && (offered!=0)) {
6593 return WERR_INVALID_PARAM;
6596 rpcbuf_move(q_u->buffer, &r_u->buffer);
6597 buffer = r_u->buffer;
6599 DEBUG(4,("_spoolss_enumjobs\n"));
6604 /* lookup the printer snum and tdb entry */
6606 if (!get_printer_snum(p, handle, &snum))
6609 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6610 if ( !W_ERROR_IS_OK(wret) )
6613 *returned = print_queue_status(snum, &queue, &prt_status);
6614 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6616 if (*returned == 0) {
6623 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6626 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6631 wret = WERR_UNKNOWN_LEVEL;
6634 free_a_printer( &ntprinter, 2 );
6638 /****************************************************************************
6639 ****************************************************************************/
6641 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6646 /****************************************************************************
6647 ****************************************************************************/
6649 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6651 POLICY_HND *handle = &q_u->handle;
6652 uint32 jobid = q_u->jobid;
6653 uint32 command = q_u->command;
6655 struct current_user user;
6657 WERROR errcode = WERR_BADFUNC;
6659 if (!get_printer_snum(p, handle, &snum)) {
6663 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6664 return WERR_INVALID_PRINTER_NAME;
6667 get_current_user(&user, p);
6670 case JOB_CONTROL_CANCEL:
6671 case JOB_CONTROL_DELETE:
6672 if (print_job_delete(&user, snum, jobid, &errcode)) {
6676 case JOB_CONTROL_PAUSE:
6677 if (print_job_pause(&user, snum, jobid, &errcode)) {
6681 case JOB_CONTROL_RESTART:
6682 case JOB_CONTROL_RESUME:
6683 if (print_job_resume(&user, snum, jobid, &errcode)) {
6688 return WERR_UNKNOWN_LEVEL;
6694 /****************************************************************************
6695 Enumerates all printer drivers at level 1.
6696 ****************************************************************************/
6698 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6703 fstring *list = NULL;
6704 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6705 DRIVER_INFO_1 *driver_info_1=NULL;
6706 WERROR result = WERR_OK;
6710 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6712 ndrivers=get_ntdrivers(&list, architecture, version);
6713 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6715 if(ndrivers == -1) {
6716 SAFE_FREE(driver_info_1);
6721 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6722 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6728 for (i=0; i<ndrivers; i++) {
6730 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6731 ZERO_STRUCT(driver);
6732 status = get_a_printer_driver(&driver, 3, list[i],
6733 architecture, version);
6734 if (!W_ERROR_IS_OK(status)) {
6736 SAFE_FREE(driver_info_1);
6739 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6740 free_a_printer_driver(driver, 3);
6743 *returned+=ndrivers;
6747 /* check the required size. */
6748 for (i=0; i<*returned; i++) {
6749 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6750 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6753 if (*needed > offered) {
6754 result = WERR_INSUFFICIENT_BUFFER;
6758 if (!rpcbuf_alloc_size(buffer, *needed)) {
6759 result = WERR_NOMEM;
6763 /* fill the buffer with the driver structures */
6764 for (i=0; i<*returned; i++) {
6765 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6766 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6770 SAFE_FREE(driver_info_1);
6772 if ( !W_ERROR_IS_OK(result) )
6778 /****************************************************************************
6779 Enumerates all printer drivers at level 2.
6780 ****************************************************************************/
6782 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6787 fstring *list = NULL;
6788 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6789 DRIVER_INFO_2 *driver_info_2=NULL;
6790 WERROR result = WERR_OK;
6794 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6796 ndrivers=get_ntdrivers(&list, architecture, version);
6797 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6799 if(ndrivers == -1) {
6800 SAFE_FREE(driver_info_2);
6805 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6806 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6812 for (i=0; i<ndrivers; i++) {
6815 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6816 ZERO_STRUCT(driver);
6817 status = get_a_printer_driver(&driver, 3, list[i],
6818 architecture, version);
6819 if (!W_ERROR_IS_OK(status)) {
6821 SAFE_FREE(driver_info_2);
6824 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6825 free_a_printer_driver(driver, 3);
6828 *returned+=ndrivers;
6832 /* check the required size. */
6833 for (i=0; i<*returned; i++) {
6834 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6835 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6838 if (*needed > offered) {
6839 result = WERR_INSUFFICIENT_BUFFER;
6843 if (!rpcbuf_alloc_size(buffer, *needed)) {
6844 result = WERR_NOMEM;
6848 /* fill the buffer with the form structures */
6849 for (i=0; i<*returned; i++) {
6850 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6851 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6855 SAFE_FREE(driver_info_2);
6857 if ( !W_ERROR_IS_OK(result) )
6863 /****************************************************************************
6864 Enumerates all printer drivers at level 3.
6865 ****************************************************************************/
6867 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6872 fstring *list = NULL;
6873 DRIVER_INFO_3 *driver_info_3=NULL;
6874 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6875 WERROR result = WERR_OK;
6879 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6881 ndrivers=get_ntdrivers(&list, architecture, version);
6882 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6884 if(ndrivers == -1) {
6885 SAFE_FREE(driver_info_3);
6890 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6891 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6897 for (i=0; i<ndrivers; i++) {
6900 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6901 ZERO_STRUCT(driver);
6902 status = get_a_printer_driver(&driver, 3, list[i],
6903 architecture, version);
6904 if (!W_ERROR_IS_OK(status)) {
6906 SAFE_FREE(driver_info_3);
6909 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6910 free_a_printer_driver(driver, 3);
6913 *returned+=ndrivers;
6917 /* check the required size. */
6918 for (i=0; i<*returned; i++) {
6919 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6920 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6923 if (*needed > offered) {
6924 result = WERR_INSUFFICIENT_BUFFER;
6928 if (!rpcbuf_alloc_size(buffer, *needed)) {
6929 result = WERR_NOMEM;
6933 /* fill the buffer with the driver structures */
6934 for (i=0; i<*returned; i++) {
6935 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6936 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6940 for (i=0; i<*returned; i++) {
6941 SAFE_FREE(driver_info_3[i].dependentfiles);
6944 SAFE_FREE(driver_info_3);
6946 if ( !W_ERROR_IS_OK(result) )
6952 /****************************************************************************
6953 Enumerates all printer drivers.
6954 ****************************************************************************/
6956 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6958 uint32 level = q_u->level;
6959 RPC_BUFFER *buffer = NULL;
6960 uint32 offered = q_u->offered;
6961 uint32 *needed = &r_u->needed;
6962 uint32 *returned = &r_u->returned;
6965 fstring architecture;
6967 /* that's an [in out] buffer */
6969 if (!q_u->buffer && (offered!=0)) {
6970 return WERR_INVALID_PARAM;
6973 rpcbuf_move(q_u->buffer, &r_u->buffer);
6974 buffer = r_u->buffer;
6976 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6981 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6982 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6984 if ( !is_myname_or_ipaddr( servername ) )
6985 return WERR_UNKNOWN_PRINTER_DRIVER;
6989 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6991 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6993 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6995 return WERR_UNKNOWN_LEVEL;
6999 /****************************************************************************
7000 ****************************************************************************/
7002 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7004 form->flag=list->flag;
7005 init_unistr(&form->name, list->name);
7006 form->width=list->width;
7007 form->length=list->length;
7008 form->left=list->left;
7009 form->top=list->top;
7010 form->right=list->right;
7011 form->bottom=list->bottom;
7014 /****************************************************************************
7015 ****************************************************************************/
7017 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7019 uint32 level = q_u->level;
7020 RPC_BUFFER *buffer = NULL;
7021 uint32 offered = q_u->offered;
7022 uint32 *needed = &r_u->needed;
7023 uint32 *numofforms = &r_u->numofforms;
7024 uint32 numbuiltinforms;
7026 nt_forms_struct *list=NULL;
7027 nt_forms_struct *builtinlist=NULL;
7032 /* that's an [in out] buffer */
7034 if (!q_u->buffer && (offered!=0) ) {
7035 return WERR_INVALID_PARAM;
7038 rpcbuf_move(q_u->buffer, &r_u->buffer);
7039 buffer = r_u->buffer;
7041 DEBUG(4,("_spoolss_enumforms\n"));
7042 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7043 DEBUGADD(5,("Info level [%d]\n", level));
7045 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7046 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7047 *numofforms = get_ntforms(&list);
7048 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7049 *numofforms += numbuiltinforms;
7051 if (*numofforms == 0) {
7052 SAFE_FREE(builtinlist);
7054 return WERR_NO_MORE_ITEMS;
7059 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7060 SAFE_FREE(builtinlist);
7066 /* construct the list of form structures */
7067 for (i=0; i<numbuiltinforms; i++) {
7068 DEBUGADD(6,("Filling form number [%d]\n",i));
7069 fill_form_1(&forms_1[i], &builtinlist[i]);
7072 SAFE_FREE(builtinlist);
7074 for (; i<*numofforms; i++) {
7075 DEBUGADD(6,("Filling form number [%d]\n",i));
7076 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7081 /* check the required size. */
7082 for (i=0; i<numbuiltinforms; i++) {
7083 DEBUGADD(6,("adding form [%d]'s size\n",i));
7084 buffer_size += spoolss_size_form_1(&forms_1[i]);
7086 for (; i<*numofforms; i++) {
7087 DEBUGADD(6,("adding form [%d]'s size\n",i));
7088 buffer_size += spoolss_size_form_1(&forms_1[i]);
7091 *needed=buffer_size;
7093 if (*needed > offered) {
7096 return WERR_INSUFFICIENT_BUFFER;
7099 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7105 /* fill the buffer with the form structures */
7106 for (i=0; i<numbuiltinforms; i++) {
7107 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7108 smb_io_form_1("", buffer, &forms_1[i], 0);
7110 for (; i<*numofforms; i++) {
7111 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7112 smb_io_form_1("", buffer, &forms_1[i], 0);
7121 SAFE_FREE(builtinlist);
7122 return WERR_UNKNOWN_LEVEL;
7126 /****************************************************************************
7127 ****************************************************************************/
7129 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7131 uint32 level = q_u->level;
7132 UNISTR2 *uni_formname = &q_u->formname;
7133 RPC_BUFFER *buffer = NULL;
7134 uint32 offered = q_u->offered;
7135 uint32 *needed = &r_u->needed;
7137 nt_forms_struct *list=NULL;
7138 nt_forms_struct builtin_form;
7143 int numofforms=0, i=0;
7145 /* that's an [in out] buffer */
7147 if (!q_u->buffer && (offered!=0)) {
7148 return WERR_INVALID_PARAM;
7151 rpcbuf_move(q_u->buffer, &r_u->buffer);
7152 buffer = r_u->buffer;
7154 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7156 DEBUG(4,("_spoolss_getform\n"));
7157 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7158 DEBUGADD(5,("Info level [%d]\n", level));
7160 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7161 if (!foundBuiltin) {
7162 numofforms = get_ntforms(&list);
7163 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7165 if (numofforms == 0)
7172 fill_form_1(&form_1, &builtin_form);
7175 /* Check if the requested name is in the list of form structures */
7176 for (i=0; i<numofforms; i++) {
7178 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7180 if (strequal(form_name, list[i].name)) {
7181 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7182 fill_form_1(&form_1, &list[i]);
7188 if (i == numofforms) {
7192 /* check the required size. */
7194 *needed=spoolss_size_form_1(&form_1);
7196 if (*needed > offered)
7197 return WERR_INSUFFICIENT_BUFFER;
7199 if (!rpcbuf_alloc_size(buffer, buffer_size))
7202 /* fill the buffer with the form structures */
7203 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7204 smb_io_form_1("", buffer, &form_1, 0);
7210 return WERR_UNKNOWN_LEVEL;
7214 /****************************************************************************
7215 ****************************************************************************/
7217 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7219 init_unistr(&port->port_name, name);
7222 /****************************************************************************
7223 TODO: This probably needs distinguish between TCP/IP and Local ports
7225 ****************************************************************************/
7227 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7229 init_unistr(&port->port_name, name);
7230 init_unistr(&port->monitor_name, "Local Monitor");
7231 init_unistr(&port->description, SPL_LOCAL_PORT );
7232 port->port_type=PORT_TYPE_WRITE;
7237 /****************************************************************************
7238 wrapper around the enumer ports command
7239 ****************************************************************************/
7241 WERROR enumports_hook( int *count, char ***lines )
7243 char *cmd = lp_enumports_cmd();
7253 /* if no hook then just fill in the default port */
7256 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7257 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7262 /* we have a valid enumport command */
7264 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7266 DEBUG(10,("Running [%s]\n", command));
7267 ret = smbrun(command, &fd);
7268 DEBUG(10,("Returned [%d]\n", ret));
7273 return WERR_ACCESS_DENIED;
7277 qlines = fd_lines_load(fd, &numlines, 0);
7278 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7288 /****************************************************************************
7290 ****************************************************************************/
7292 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7294 PORT_INFO_1 *ports=NULL;
7296 WERROR result = WERR_OK;
7297 char **qlines = NULL;
7300 result = enumports_hook( &numlines, &qlines );
7301 if (!W_ERROR_IS_OK(result)) {
7302 file_lines_free(qlines);
7307 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7308 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7309 dos_errstr(WERR_NOMEM)));
7310 file_lines_free(qlines);
7314 for (i=0; i<numlines; i++) {
7315 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7316 fill_port_1(&ports[i], qlines[i]);
7319 file_lines_free(qlines);
7321 *returned = numlines;
7323 /* check the required size. */
7324 for (i=0; i<*returned; i++) {
7325 DEBUGADD(6,("adding port [%d]'s size\n", i));
7326 *needed += spoolss_size_port_info_1(&ports[i]);
7329 if (*needed > offered) {
7330 result = WERR_INSUFFICIENT_BUFFER;
7334 if (!rpcbuf_alloc_size(buffer, *needed)) {
7335 result = WERR_NOMEM;
7339 /* fill the buffer with the ports structures */
7340 for (i=0; i<*returned; i++) {
7341 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7342 smb_io_port_1("", buffer, &ports[i], 0);
7348 if ( !W_ERROR_IS_OK(result) )
7354 /****************************************************************************
7356 ****************************************************************************/
7358 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7360 PORT_INFO_2 *ports=NULL;
7362 WERROR result = WERR_OK;
7363 char **qlines = NULL;
7366 result = enumports_hook( &numlines, &qlines );
7367 if ( !W_ERROR_IS_OK(result)) {
7368 file_lines_free(qlines);
7373 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7374 file_lines_free(qlines);
7378 for (i=0; i<numlines; i++) {
7379 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7380 fill_port_2(&(ports[i]), qlines[i]);
7384 file_lines_free(qlines);
7386 *returned = numlines;
7388 /* check the required size. */
7389 for (i=0; i<*returned; i++) {
7390 DEBUGADD(6,("adding port [%d]'s size\n", i));
7391 *needed += spoolss_size_port_info_2(&ports[i]);
7394 if (*needed > offered) {
7395 result = WERR_INSUFFICIENT_BUFFER;
7399 if (!rpcbuf_alloc_size(buffer, *needed)) {
7400 result = WERR_NOMEM;
7404 /* fill the buffer with the ports structures */
7405 for (i=0; i<*returned; i++) {
7406 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7407 smb_io_port_2("", buffer, &ports[i], 0);
7413 if ( !W_ERROR_IS_OK(result) )
7419 /****************************************************************************
7421 ****************************************************************************/
7423 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7425 uint32 level = q_u->level;
7426 RPC_BUFFER *buffer = NULL;
7427 uint32 offered = q_u->offered;
7428 uint32 *needed = &r_u->needed;
7429 uint32 *returned = &r_u->returned;
7431 /* that's an [in out] buffer */
7433 if (!q_u->buffer && (offered!=0)) {
7434 return WERR_INVALID_PARAM;
7437 rpcbuf_move(q_u->buffer, &r_u->buffer);
7438 buffer = r_u->buffer;
7440 DEBUG(4,("_spoolss_enumports\n"));
7447 return enumports_level_1(buffer, offered, needed, returned);
7449 return enumports_level_2(buffer, offered, needed, returned);
7451 return WERR_UNKNOWN_LEVEL;
7455 /****************************************************************************
7456 ****************************************************************************/
7458 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7459 const SPOOL_PRINTER_INFO_LEVEL *info,
7460 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7461 uint32 user_switch, const SPOOL_USER_CTR *user,
7464 NT_PRINTER_INFO_LEVEL *printer = NULL;
7467 WERROR err = WERR_OK;
7469 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7470 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7474 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7475 if (!convert_printer_info(info, printer, 2)) {
7476 free_a_printer(&printer, 2);
7480 /* check to see if the printer already exists */
7482 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7483 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7484 printer->info_2->sharename));
7485 free_a_printer(&printer, 2);
7486 return WERR_PRINTER_ALREADY_EXISTS;
7489 /* FIXME!!! smbd should check to see if the driver is installed before
7490 trying to add a printer like this --jerry */
7492 if (*lp_addprinter_cmd() ) {
7493 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7494 free_a_printer(&printer,2);
7495 return WERR_ACCESS_DENIED;
7498 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7499 "smb.conf parameter \"addprinter command\" is defined. This"
7500 "parameter must exist for this call to succeed\n",
7501 printer->info_2->sharename ));
7504 /* use our primary netbios name since get_a_printer() will convert
7505 it to what the client expects on a case by case basis */
7507 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7508 printer->info_2->sharename);
7511 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7512 free_a_printer(&printer,2);
7513 return WERR_ACCESS_DENIED;
7516 /* you must be a printer admin to add a new printer */
7517 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7518 free_a_printer(&printer,2);
7519 return WERR_ACCESS_DENIED;
7523 * Do sanity check on the requested changes for Samba.
7526 if (!check_printer_ok(printer->info_2, snum)) {
7527 free_a_printer(&printer,2);
7528 return WERR_INVALID_PARAM;
7532 * When a printer is created, the drivername bound to the printer is used
7533 * to lookup previously saved driver initialization info, which is then
7534 * bound to the new printer, simulating what happens in the Windows arch.
7539 set_driver_init(printer, 2);
7543 /* A valid devmode was included, convert and link it
7545 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7547 if (!convert_devicemode(printer->info_2->printername, devmode,
7548 &printer->info_2->devmode))
7552 /* write the ASCII on disk */
7553 err = mod_a_printer(printer, 2);
7554 if (!W_ERROR_IS_OK(err)) {
7555 free_a_printer(&printer,2);
7559 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7560 /* Handle open failed - remove addition. */
7561 del_a_printer(printer->info_2->sharename);
7562 free_a_printer(&printer,2);
7563 return WERR_ACCESS_DENIED;
7566 update_c_setprinter(False);
7567 free_a_printer(&printer,2);
7572 /****************************************************************************
7573 ****************************************************************************/
7575 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7577 UNISTR2 *uni_srv_name = q_u->server_name;
7578 uint32 level = q_u->level;
7579 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7580 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7581 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7582 uint32 user_switch = q_u->user_switch;
7583 SPOOL_USER_CTR *user = &q_u->user_ctr;
7584 POLICY_HND *handle = &r_u->handle;
7588 /* we don't handle yet */
7589 /* but I know what to do ... */
7590 return WERR_UNKNOWN_LEVEL;
7592 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7594 user_switch, user, handle);
7596 return WERR_UNKNOWN_LEVEL;
7600 /****************************************************************************
7601 ****************************************************************************/
7603 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7605 uint32 level = q_u->level;
7606 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7607 WERROR err = WERR_OK;
7608 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7609 struct current_user user;
7610 fstring driver_name;
7613 ZERO_STRUCT(driver);
7615 get_current_user(&user, p);
7617 if (!convert_printer_driver_info(info, &driver, level)) {
7622 DEBUG(5,("Cleaning driver's information\n"));
7623 err = clean_up_driver_struct(driver, level, &user);
7624 if (!W_ERROR_IS_OK(err))
7627 DEBUG(5,("Moving driver to final destination\n"));
7628 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7632 if (add_a_printer_driver(driver, level)!=0) {
7633 err = WERR_ACCESS_DENIED;
7637 /* BEGIN_ADMIN_LOG */
7640 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7641 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7642 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.ut.uid));
7645 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7646 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7647 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.ut.uid));
7653 * I think this is where he DrvUpgradePrinter() hook would be
7654 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7655 * server. Right now, we just need to send ourselves a message
7656 * to update each printer bound to this driver. --jerry
7659 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7660 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7665 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7666 * decide if the driver init data should be deleted. The rules are:
7667 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7668 * 2) delete init data only if there is no 2k/Xp driver
7669 * 3) always delete init data
7670 * The generalized rule is always use init data from the highest order driver.
7671 * It is necessary to follow the driver install by an initialization step to
7672 * finish off this process.
7675 version = driver.info_3->cversion;
7676 else if (level == 6)
7677 version = driver.info_6->version;
7682 * 9x printer driver - never delete init data
7685 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7690 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7691 * there is no 2k/Xp driver init data for this driver name.
7695 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7697 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7699 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7701 if (!del_driver_init(driver_name))
7702 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7705 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7707 free_a_printer_driver(driver1,3);
7708 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7715 * 2k or Xp printer driver - always delete init data
7718 if (!del_driver_init(driver_name))
7719 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7723 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7729 free_a_printer_driver(driver, level);
7733 /********************************************************************
7734 * spoolss_addprinterdriverex
7735 ********************************************************************/
7737 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7739 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7740 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7743 * we only support the semantics of AddPrinterDriver()
7744 * i.e. only copy files that are newer than existing ones
7747 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7748 return WERR_ACCESS_DENIED;
7750 ZERO_STRUCT(q_u_local);
7751 ZERO_STRUCT(r_u_local);
7753 /* just pass the information off to _spoolss_addprinterdriver() */
7754 q_u_local.server_name_ptr = q_u->server_name_ptr;
7755 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7756 q_u_local.level = q_u->level;
7757 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7759 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7762 /****************************************************************************
7763 ****************************************************************************/
7765 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7767 init_unistr(&info->name, name);
7770 /****************************************************************************
7771 ****************************************************************************/
7773 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7779 const char *short_archi;
7780 DRIVER_DIRECTORY_1 *info=NULL;
7781 WERROR result = WERR_OK;
7783 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7784 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7786 /* check for beginning double '\'s and that the server
7789 pservername = servername;
7790 if ( *pservername == '\\' && strlen(servername)>2 ) {
7794 if ( !is_myname_or_ipaddr( pservername ) )
7795 return WERR_INVALID_PARAM;
7797 if (!(short_archi = get_short_archi(long_archi)))
7798 return WERR_INVALID_ENVIRONMENT;
7800 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7803 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7805 DEBUG(4,("printer driver directory: [%s]\n", path));
7807 fill_driverdir_1(info, path);
7809 *needed += spoolss_size_driverdir_info_1(info);
7811 if (*needed > offered) {
7812 result = WERR_INSUFFICIENT_BUFFER;
7816 if (!rpcbuf_alloc_size(buffer, *needed)) {
7817 result = WERR_NOMEM;
7821 smb_io_driverdir_1("", buffer, info, 0);
7829 /****************************************************************************
7830 ****************************************************************************/
7832 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7834 UNISTR2 *name = &q_u->name;
7835 UNISTR2 *uni_environment = &q_u->environment;
7836 uint32 level = q_u->level;
7837 RPC_BUFFER *buffer = NULL;
7838 uint32 offered = q_u->offered;
7839 uint32 *needed = &r_u->needed;
7841 /* that's an [in out] buffer */
7843 if (!q_u->buffer && (offered!=0)) {
7844 return WERR_INVALID_PARAM;
7847 rpcbuf_move(q_u->buffer, &r_u->buffer);
7848 buffer = r_u->buffer;
7850 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7856 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7858 return WERR_UNKNOWN_LEVEL;
7862 /****************************************************************************
7863 ****************************************************************************/
7865 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7867 POLICY_HND *handle = &q_u->handle;
7868 uint32 idx = q_u->index;
7869 uint32 in_value_len = q_u->valuesize;
7870 uint32 in_data_len = q_u->datasize;
7871 uint32 *out_max_value_len = &r_u->valuesize;
7872 uint16 **out_value = &r_u->value;
7873 uint32 *out_value_len = &r_u->realvaluesize;
7874 uint32 *out_type = &r_u->type;
7875 uint32 *out_max_data_len = &r_u->datasize;
7876 uint8 **data_out = &r_u->data;
7877 uint32 *out_data_len = &r_u->realdatasize;
7879 NT_PRINTER_INFO_LEVEL *printer = NULL;
7881 uint32 biggest_valuesize;
7882 uint32 biggest_datasize;
7884 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7887 REGISTRY_VALUE *val = NULL;
7888 NT_PRINTER_DATA *p_data;
7889 int i, key_index, num_values;
7894 *out_max_data_len = 0;
7898 DEBUG(5,("spoolss_enumprinterdata\n"));
7901 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7905 if (!get_printer_snum(p,handle, &snum))
7908 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7909 if (!W_ERROR_IS_OK(result))
7912 p_data = printer->info_2->data;
7913 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7918 * The NT machine wants to know the biggest size of value and data
7920 * cf: MSDN EnumPrinterData remark section
7923 if ( !in_value_len && !in_data_len && (key_index != -1) )
7925 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7927 biggest_valuesize = 0;
7928 biggest_datasize = 0;
7930 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7932 for ( i=0; i<num_values; i++ )
7934 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7936 name_length = strlen(val->valuename);
7937 if ( strlen(val->valuename) > biggest_valuesize )
7938 biggest_valuesize = name_length;
7940 if ( val->size > biggest_datasize )
7941 biggest_datasize = val->size;
7943 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7947 /* the value is an UNICODE string but real_value_size is the length
7948 in bytes including the trailing 0 */
7950 *out_value_len = 2 * (1+biggest_valuesize);
7951 *out_data_len = biggest_datasize;
7953 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7959 * the value len is wrong in NT sp3
7960 * that's the number of bytes not the number of unicode chars
7963 if ( key_index != -1 )
7964 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7969 /* out_value should default to "" or else NT4 has
7970 problems unmarshalling the response */
7972 *out_max_value_len=(in_value_len/sizeof(uint16));
7974 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7976 result = WERR_NOMEM;
7980 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7982 /* the data is counted in bytes */
7984 *out_max_data_len = in_data_len;
7985 *out_data_len = in_data_len;
7987 /* only allocate when given a non-zero data_len */
7989 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7991 result = WERR_NOMEM;
7995 result = WERR_NO_MORE_ITEMS;
8001 * - counted in bytes in the request
8002 * - counted in UNICODE chars in the max reply
8003 * - counted in bytes in the real size
8005 * take a pause *before* coding not *during* coding
8009 *out_max_value_len=(in_value_len/sizeof(uint16));
8010 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8012 result = WERR_NOMEM;
8016 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8020 *out_type = regval_type( val );
8022 /* data - counted in bytes */
8024 *out_max_data_len = in_data_len;
8025 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8027 result = WERR_NOMEM;
8030 data_len = regval_size(val);
8032 memcpy( *data_out, regval_data_p(val), data_len );
8033 *out_data_len = data_len;
8037 free_a_printer(&printer, 2);
8041 /****************************************************************************
8042 ****************************************************************************/
8044 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8046 POLICY_HND *handle = &q_u->handle;
8047 UNISTR2 *value = &q_u->value;
8048 uint32 type = q_u->type;
8049 uint8 *data = q_u->data;
8050 uint32 real_len = q_u->real_len;
8052 NT_PRINTER_INFO_LEVEL *printer = NULL;
8054 WERROR status = WERR_OK;
8055 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8058 DEBUG(5,("spoolss_setprinterdata\n"));
8061 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8065 if ( Printer->printer_type == SPLHND_SERVER ) {
8066 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8067 return WERR_INVALID_PARAM;
8070 if (!get_printer_snum(p,handle, &snum))
8074 * Access check : NT returns "access denied" if you make a
8075 * SetPrinterData call without the necessary privildge.
8076 * we were originally returning OK if nothing changed
8077 * which made Win2k issue **a lot** of SetPrinterData
8078 * when connecting to a printer --jerry
8081 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8083 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8084 status = WERR_ACCESS_DENIED;
8088 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8089 if (!W_ERROR_IS_OK(status))
8092 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8095 * When client side code sets a magic printer data key, detect it and save
8096 * the current printer data and the magic key's data (its the DEVMODE) for
8097 * future printer/driver initializations.
8099 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8101 /* Set devmode and printer initialization info */
8102 status = save_driver_init( printer, 2, data, real_len );
8104 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8108 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8109 type, data, real_len );
8110 if ( W_ERROR_IS_OK(status) )
8111 status = mod_a_printer(printer, 2);
8115 free_a_printer(&printer, 2);
8120 /****************************************************************************
8121 ****************************************************************************/
8123 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8125 POLICY_HND *handle = &q_u->handle;
8126 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8129 DEBUG(5,("_spoolss_resetprinter\n"));
8132 * All we do is to check to see if the handle and queue is valid.
8133 * This call really doesn't mean anything to us because we only
8134 * support RAW printing. --jerry
8138 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8142 if (!get_printer_snum(p,handle, &snum))
8146 /* blindly return success */
8151 /****************************************************************************
8152 ****************************************************************************/
8154 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8156 POLICY_HND *handle = &q_u->handle;
8157 UNISTR2 *value = &q_u->valuename;
8159 NT_PRINTER_INFO_LEVEL *printer = NULL;
8161 WERROR status = WERR_OK;
8162 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8165 DEBUG(5,("spoolss_deleteprinterdata\n"));
8168 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8172 if (!get_printer_snum(p, handle, &snum))
8175 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8176 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8177 return WERR_ACCESS_DENIED;
8180 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8181 if (!W_ERROR_IS_OK(status))
8184 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8186 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8188 if ( W_ERROR_IS_OK(status) )
8189 mod_a_printer( printer, 2 );
8191 free_a_printer(&printer, 2);
8196 /****************************************************************************
8197 ****************************************************************************/
8199 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8201 POLICY_HND *handle = &q_u->handle;
8202 FORM *form = &q_u->form;
8203 nt_forms_struct tmpForm;
8205 WERROR status = WERR_OK;
8206 NT_PRINTER_INFO_LEVEL *printer = NULL;
8209 nt_forms_struct *list=NULL;
8210 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8212 DEBUG(5,("spoolss_addform\n"));
8215 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8220 /* forms can be added on printer of on the print server handle */
8222 if ( Printer->printer_type == SPLHND_PRINTER )
8224 if (!get_printer_snum(p,handle, &snum))
8227 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8228 if (!W_ERROR_IS_OK(status))
8232 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8233 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8234 status = WERR_ACCESS_DENIED;
8238 /* can't add if builtin */
8240 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8241 status = WERR_ALREADY_EXISTS;
8245 count = get_ntforms(&list);
8247 if(!add_a_form(&list, form, &count)) {
8248 status = WERR_NOMEM;
8252 write_ntforms(&list, count);
8255 * ChangeID must always be set if this is a printer
8258 if ( Printer->printer_type == SPLHND_PRINTER )
8259 status = mod_a_printer(printer, 2);
8263 free_a_printer(&printer, 2);
8269 /****************************************************************************
8270 ****************************************************************************/
8272 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8274 POLICY_HND *handle = &q_u->handle;
8275 UNISTR2 *form_name = &q_u->name;
8276 nt_forms_struct tmpForm;
8278 nt_forms_struct *list=NULL;
8279 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8281 WERROR status = WERR_OK;
8282 NT_PRINTER_INFO_LEVEL *printer = NULL;
8284 DEBUG(5,("spoolss_deleteform\n"));
8287 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8291 /* forms can be deleted on printer of on the print server handle */
8293 if ( Printer->printer_type == SPLHND_PRINTER )
8295 if (!get_printer_snum(p,handle, &snum))
8298 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8299 if (!W_ERROR_IS_OK(status))
8303 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8304 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8305 status = WERR_ACCESS_DENIED;
8309 /* can't delete if builtin */
8311 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8312 status = WERR_INVALID_PARAM;
8316 count = get_ntforms(&list);
8318 if ( !delete_a_form(&list, form_name, &count, &status ))
8322 * ChangeID must always be set if this is a printer
8325 if ( Printer->printer_type == SPLHND_PRINTER )
8326 status = mod_a_printer(printer, 2);
8330 free_a_printer(&printer, 2);
8336 /****************************************************************************
8337 ****************************************************************************/
8339 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8341 POLICY_HND *handle = &q_u->handle;
8342 FORM *form = &q_u->form;
8343 nt_forms_struct tmpForm;
8345 WERROR status = WERR_OK;
8346 NT_PRINTER_INFO_LEVEL *printer = NULL;
8349 nt_forms_struct *list=NULL;
8350 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8352 DEBUG(5,("spoolss_setform\n"));
8355 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8359 /* forms can be modified on printer of on the print server handle */
8361 if ( Printer->printer_type == SPLHND_PRINTER )
8363 if (!get_printer_snum(p,handle, &snum))
8366 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8367 if (!W_ERROR_IS_OK(status))
8371 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8372 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8373 status = WERR_ACCESS_DENIED;
8377 /* can't set if builtin */
8378 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8379 status = WERR_INVALID_PARAM;
8383 count = get_ntforms(&list);
8384 update_a_form(&list, form, count);
8385 write_ntforms(&list, count);
8388 * ChangeID must always be set if this is a printer
8391 if ( Printer->printer_type == SPLHND_PRINTER )
8392 status = mod_a_printer(printer, 2);
8397 free_a_printer(&printer, 2);
8403 /****************************************************************************
8404 enumprintprocessors level 1.
8405 ****************************************************************************/
8407 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8409 PRINTPROCESSOR_1 *info_1=NULL;
8410 WERROR result = WERR_OK;
8412 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8417 init_unistr(&info_1->name, "winprint");
8419 *needed += spoolss_size_printprocessor_info_1(info_1);
8421 if (*needed > offered) {
8422 result = WERR_INSUFFICIENT_BUFFER;
8426 if (!rpcbuf_alloc_size(buffer, *needed)) {
8427 result = WERR_NOMEM;
8431 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8436 if ( !W_ERROR_IS_OK(result) )
8442 /****************************************************************************
8443 ****************************************************************************/
8445 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8447 uint32 level = q_u->level;
8448 RPC_BUFFER *buffer = NULL;
8449 uint32 offered = q_u->offered;
8450 uint32 *needed = &r_u->needed;
8451 uint32 *returned = &r_u->returned;
8453 /* that's an [in out] buffer */
8455 if (!q_u->buffer && (offered!=0)) {
8456 return WERR_INVALID_PARAM;
8459 rpcbuf_move(q_u->buffer, &r_u->buffer);
8460 buffer = r_u->buffer;
8462 DEBUG(5,("spoolss_enumprintprocessors\n"));
8465 * Enumerate the print processors ...
8467 * Just reply with "winprint", to keep NT happy
8468 * and I can use my nice printer checker.
8476 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8478 return WERR_UNKNOWN_LEVEL;
8482 /****************************************************************************
8483 enumprintprocdatatypes level 1.
8484 ****************************************************************************/
8486 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8488 PRINTPROCDATATYPE_1 *info_1=NULL;
8489 WERROR result = WERR_NOMEM;
8491 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8496 init_unistr(&info_1->name, "RAW");
8498 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8500 if (*needed > offered) {
8501 result = WERR_INSUFFICIENT_BUFFER;
8505 if (!rpcbuf_alloc_size(buffer, *needed)) {
8506 result = WERR_NOMEM;
8510 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8515 if ( !W_ERROR_IS_OK(result) )
8521 /****************************************************************************
8522 ****************************************************************************/
8524 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8526 uint32 level = q_u->level;
8527 RPC_BUFFER *buffer = NULL;
8528 uint32 offered = q_u->offered;
8529 uint32 *needed = &r_u->needed;
8530 uint32 *returned = &r_u->returned;
8532 /* that's an [in out] buffer */
8534 if (!q_u->buffer && (offered!=0)) {
8535 return WERR_INVALID_PARAM;
8538 rpcbuf_move(q_u->buffer, &r_u->buffer);
8539 buffer = r_u->buffer;
8541 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8548 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8550 return WERR_UNKNOWN_LEVEL;
8554 /****************************************************************************
8555 enumprintmonitors level 1.
8556 ****************************************************************************/
8558 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8560 PRINTMONITOR_1 *info_1;
8561 WERROR result = WERR_OK;
8564 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8569 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8570 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8572 for ( i=0; i<*returned; i++ ) {
8573 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8576 if (*needed > offered) {
8577 result = WERR_INSUFFICIENT_BUFFER;
8581 if (!rpcbuf_alloc_size(buffer, *needed)) {
8582 result = WERR_NOMEM;
8586 for ( i=0; i<*returned; i++ ) {
8587 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8593 if ( !W_ERROR_IS_OK(result) )
8599 /****************************************************************************
8600 enumprintmonitors level 2.
8601 ****************************************************************************/
8603 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8605 PRINTMONITOR_2 *info_2;
8606 WERROR result = WERR_OK;
8609 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8614 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8615 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8616 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8618 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8619 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8620 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8622 for ( i=0; i<*returned; i++ ) {
8623 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8626 if (*needed > offered) {
8627 result = WERR_INSUFFICIENT_BUFFER;
8631 if (!rpcbuf_alloc_size(buffer, *needed)) {
8632 result = WERR_NOMEM;
8636 for ( i=0; i<*returned; i++ ) {
8637 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8643 if ( !W_ERROR_IS_OK(result) )
8649 /****************************************************************************
8650 ****************************************************************************/
8652 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8654 uint32 level = q_u->level;
8655 RPC_BUFFER *buffer = NULL;
8656 uint32 offered = q_u->offered;
8657 uint32 *needed = &r_u->needed;
8658 uint32 *returned = &r_u->returned;
8660 /* that's an [in out] buffer */
8662 if (!q_u->buffer && (offered!=0)) {
8663 return WERR_INVALID_PARAM;
8666 rpcbuf_move(q_u->buffer, &r_u->buffer);
8667 buffer = r_u->buffer;
8669 DEBUG(5,("spoolss_enumprintmonitors\n"));
8672 * Enumerate the print monitors ...
8674 * Just reply with "Local Port", to keep NT happy
8675 * and I can use my nice printer checker.
8683 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8685 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8687 return WERR_UNKNOWN_LEVEL;
8691 /****************************************************************************
8692 ****************************************************************************/
8694 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8695 NT_PRINTER_INFO_LEVEL *ntprinter,
8696 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8701 JOB_INFO_1 *info_1=NULL;
8702 WERROR result = WERR_OK;
8704 info_1=SMB_MALLOC_P(JOB_INFO_1);
8706 if (info_1 == NULL) {
8710 for (i=0; i<count && found==False; i++) {
8711 if ((*queue)[i].job==(int)jobid)
8717 /* NT treats not found as bad param... yet another bad choice */
8718 return WERR_INVALID_PARAM;
8721 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8723 *needed += spoolss_size_job_info_1(info_1);
8725 if (*needed > offered) {
8726 result = WERR_INSUFFICIENT_BUFFER;
8730 if (!rpcbuf_alloc_size(buffer, *needed)) {
8731 result = WERR_NOMEM;
8735 smb_io_job_info_1("", buffer, info_1, 0);
8743 /****************************************************************************
8744 ****************************************************************************/
8746 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8747 NT_PRINTER_INFO_LEVEL *ntprinter,
8748 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8755 DEVICEMODE *devmode = NULL;
8756 NT_DEVICEMODE *nt_devmode = NULL;
8758 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8761 ZERO_STRUCTP(info_2);
8763 for ( i=0; i<count && found==False; i++ )
8765 if ((*queue)[i].job == (int)jobid)
8770 /* NT treats not found as bad param... yet another bad
8772 result = WERR_INVALID_PARAM;
8777 * if the print job does not have a DEVMODE associated with it,
8778 * just use the one for the printer. A NULL devicemode is not
8779 * a failure condition
8782 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8783 devmode = construct_dev_mode(snum);
8785 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8786 ZERO_STRUCTP( devmode );
8787 convert_nt_devicemode( devmode, nt_devmode );
8791 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8793 *needed += spoolss_size_job_info_2(info_2);
8795 if (*needed > offered) {
8796 result = WERR_INSUFFICIENT_BUFFER;
8800 if (!rpcbuf_alloc_size(buffer, *needed)) {
8801 result = WERR_NOMEM;
8805 smb_io_job_info_2("", buffer, info_2, 0);
8810 /* Cleanup allocated memory */
8812 free_job_info_2(info_2); /* Also frees devmode */
8818 /****************************************************************************
8819 ****************************************************************************/
8821 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8823 POLICY_HND *handle = &q_u->handle;
8824 uint32 jobid = q_u->jobid;
8825 uint32 level = q_u->level;
8826 RPC_BUFFER *buffer = NULL;
8827 uint32 offered = q_u->offered;
8828 uint32 *needed = &r_u->needed;
8829 WERROR wstatus = WERR_OK;
8830 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8833 print_queue_struct *queue = NULL;
8834 print_status_struct prt_status;
8836 /* that's an [in out] buffer */
8838 if (!q_u->buffer && (offered!=0)) {
8839 return WERR_INVALID_PARAM;
8842 rpcbuf_move(q_u->buffer, &r_u->buffer);
8843 buffer = r_u->buffer;
8845 DEBUG(5,("spoolss_getjob\n"));
8849 if (!get_printer_snum(p, handle, &snum))
8852 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8853 if ( !W_ERROR_IS_OK(wstatus) )
8856 count = print_queue_status(snum, &queue, &prt_status);
8858 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8859 count, prt_status.status, prt_status.message));
8863 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8864 buffer, offered, needed);
8867 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8868 buffer, offered, needed);
8871 wstatus = WERR_UNKNOWN_LEVEL;
8876 free_a_printer( &ntprinter, 2 );
8881 /********************************************************************
8882 spoolss_getprinterdataex
8884 From MSDN documentation of GetPrinterDataEx: pass request
8885 to GetPrinterData if key is "PrinterDriverData".
8886 ********************************************************************/
8888 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8890 POLICY_HND *handle = &q_u->handle;
8891 uint32 in_size = q_u->size;
8892 uint32 *type = &r_u->type;
8893 uint32 *out_size = &r_u->size;
8894 uint8 **data = &r_u->data;
8895 uint32 *needed = &r_u->needed;
8896 fstring keyname, valuename;
8898 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8900 NT_PRINTER_INFO_LEVEL *printer = NULL;
8902 WERROR status = WERR_OK;
8904 DEBUG(4,("_spoolss_getprinterdataex\n"));
8906 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8907 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8909 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8910 keyname, valuename));
8912 /* in case of problem, return some default values */
8916 *out_size = in_size;
8919 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8920 status = WERR_BADFID;
8924 /* Is the handle to a printer or to the server? */
8926 if (Printer->printer_type == SPLHND_SERVER) {
8927 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8928 status = WERR_INVALID_PARAM;
8932 if ( !get_printer_snum(p,handle, &snum) )
8935 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8936 if ( !W_ERROR_IS_OK(status) )
8939 /* check to see if the keyname is valid */
8940 if ( !strlen(keyname) ) {
8941 status = WERR_INVALID_PARAM;
8945 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8946 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8947 free_a_printer( &printer, 2 );
8948 status = WERR_BADFILE;
8952 /* When given a new keyname, we should just create it */
8954 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8956 if (*needed > *out_size)
8957 status = WERR_MORE_DATA;
8960 if ( !W_ERROR_IS_OK(status) )
8962 DEBUG(5, ("error: allocating %d\n", *out_size));
8964 /* reply this param doesn't exist */
8968 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8969 status = WERR_NOMEM;
8979 free_a_printer( &printer, 2 );
8984 /********************************************************************
8985 * spoolss_setprinterdataex
8986 ********************************************************************/
8988 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8990 POLICY_HND *handle = &q_u->handle;
8991 uint32 type = q_u->type;
8992 uint8 *data = q_u->data;
8993 uint32 real_len = q_u->real_len;
8995 NT_PRINTER_INFO_LEVEL *printer = NULL;
8997 WERROR status = WERR_OK;
8998 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9003 DEBUG(4,("_spoolss_setprinterdataex\n"));
9005 /* From MSDN documentation of SetPrinterDataEx: pass request to
9006 SetPrinterData if key is "PrinterDriverData" */
9009 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9013 if ( Printer->printer_type == SPLHND_SERVER ) {
9014 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9015 return WERR_INVALID_PARAM;
9018 if ( !get_printer_snum(p,handle, &snum) )
9022 * Access check : NT returns "access denied" if you make a
9023 * SetPrinterData call without the necessary privildge.
9024 * we were originally returning OK if nothing changed
9025 * which made Win2k issue **a lot** of SetPrinterData
9026 * when connecting to a printer --jerry
9029 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9031 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9032 return WERR_ACCESS_DENIED;
9035 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9036 if (!W_ERROR_IS_OK(status))
9039 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9040 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9042 /* check for OID in valuename */
9044 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9050 /* save the registry data */
9052 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9054 if ( W_ERROR_IS_OK(status) )
9056 /* save the OID if one was specified */
9058 fstrcat( keyname, "\\" );
9059 fstrcat( keyname, SPOOL_OID_KEY );
9062 * I'm not checking the status here on purpose. Don't know
9063 * if this is right, but I'm returning the status from the
9064 * previous set_printer_dataex() call. I have no idea if
9065 * this is right. --jerry
9068 set_printer_dataex( printer, keyname, valuename,
9069 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9072 status = mod_a_printer(printer, 2);
9075 free_a_printer(&printer, 2);
9081 /********************************************************************
9082 * spoolss_deleteprinterdataex
9083 ********************************************************************/
9085 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9087 POLICY_HND *handle = &q_u->handle;
9088 UNISTR2 *value = &q_u->valuename;
9089 UNISTR2 *key = &q_u->keyname;
9091 NT_PRINTER_INFO_LEVEL *printer = NULL;
9093 WERROR status = WERR_OK;
9094 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9095 pstring valuename, keyname;
9097 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9100 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9104 if (!get_printer_snum(p, handle, &snum))
9107 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9108 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9109 return WERR_ACCESS_DENIED;
9112 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9113 if (!W_ERROR_IS_OK(status))
9116 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9117 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9119 status = delete_printer_dataex( printer, keyname, valuename );
9121 if ( W_ERROR_IS_OK(status) )
9122 mod_a_printer( printer, 2 );
9124 free_a_printer(&printer, 2);
9129 /********************************************************************
9130 * spoolss_enumprinterkey
9131 ********************************************************************/
9134 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9137 fstring *keynames = NULL;
9138 uint16 *enumkeys = NULL;
9141 POLICY_HND *handle = &q_u->handle;
9142 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9143 NT_PRINTER_DATA *data;
9144 NT_PRINTER_INFO_LEVEL *printer = NULL;
9146 WERROR status = WERR_BADFILE;
9149 DEBUG(4,("_spoolss_enumprinterkey\n"));
9152 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9156 if ( !get_printer_snum(p,handle, &snum) )
9159 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9160 if (!W_ERROR_IS_OK(status))
9163 /* get the list of subkey names */
9165 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9166 data = printer->info_2->data;
9168 num_keys = get_printer_subkeys( data, key, &keynames );
9170 if ( num_keys == -1 ) {
9171 status = WERR_BADFILE;
9175 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9177 r_u->needed = printerkey_len*2;
9179 if ( q_u->size < r_u->needed ) {
9180 status = WERR_MORE_DATA;
9184 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9185 status = WERR_NOMEM;
9191 if ( q_u->size < r_u->needed )
9192 status = WERR_MORE_DATA;
9195 free_a_printer( &printer, 2 );
9196 SAFE_FREE( keynames );
9201 /********************************************************************
9202 * spoolss_deleteprinterkey
9203 ********************************************************************/
9205 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9207 POLICY_HND *handle = &q_u->handle;
9208 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9210 NT_PRINTER_INFO_LEVEL *printer = NULL;
9214 DEBUG(5,("spoolss_deleteprinterkey\n"));
9217 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9221 /* if keyname == NULL, return error */
9223 if ( !q_u->keyname.buffer )
9224 return WERR_INVALID_PARAM;
9226 if (!get_printer_snum(p, handle, &snum))
9229 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9230 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9231 return WERR_ACCESS_DENIED;
9234 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9235 if (!W_ERROR_IS_OK(status))
9238 /* delete the key and all subneys */
9240 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9242 status = delete_all_printer_data( printer->info_2, key );
9244 if ( W_ERROR_IS_OK(status) )
9245 status = mod_a_printer(printer, 2);
9247 free_a_printer( &printer, 2 );
9253 /********************************************************************
9254 * spoolss_enumprinterdataex
9255 ********************************************************************/
9257 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9259 POLICY_HND *handle = &q_u->handle;
9260 uint32 in_size = q_u->size;
9263 NT_PRINTER_INFO_LEVEL *printer = NULL;
9264 PRINTER_ENUM_VALUES *enum_values = NULL;
9265 NT_PRINTER_DATA *p_data;
9267 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9272 REGISTRY_VALUE *val;
9277 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9280 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9285 * first check for a keyname of NULL or "". Win2k seems to send
9286 * this a lot and we should send back WERR_INVALID_PARAM
9287 * no need to spend time looking up the printer in this case.
9291 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9292 if ( !strlen(key) ) {
9293 result = WERR_INVALID_PARAM;
9297 /* get the printer off of disk */
9299 if (!get_printer_snum(p,handle, &snum))
9302 ZERO_STRUCT(printer);
9303 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9304 if (!W_ERROR_IS_OK(result))
9307 /* now look for a match on the key name */
9309 p_data = printer->info_2->data;
9311 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9312 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9314 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9315 result = WERR_INVALID_PARAM;
9322 /* allocate the memory for the array of pointers -- if necessary */
9324 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9327 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9329 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9330 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9331 result = WERR_NOMEM;
9335 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9339 * loop through all params and build the array to pass
9340 * back to the client
9343 for ( i=0; i<num_entries; i++ )
9345 /* lookup the registry value */
9347 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9348 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9352 value_name = regval_name( val );
9353 init_unistr( &enum_values[i].valuename, value_name );
9354 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9355 enum_values[i].type = regval_type( val );
9357 data_len = regval_size( val );
9359 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9361 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9363 result = WERR_NOMEM;
9367 enum_values[i].data_len = data_len;
9369 /* keep track of the size of the array in bytes */
9371 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9374 /* housekeeping information in the reply */
9376 r_u->needed = needed;
9377 r_u->returned = num_entries;
9379 if (needed > in_size) {
9380 result = WERR_MORE_DATA;
9384 /* copy data into the reply */
9386 r_u->ctr.size = r_u->needed;
9387 r_u->ctr.size_of_array = r_u->returned;
9388 r_u->ctr.values = enum_values;
9394 free_a_printer(&printer, 2);
9399 /****************************************************************************
9400 ****************************************************************************/
9402 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9404 init_unistr(&info->name, name);
9407 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9408 UNISTR2 *environment,
9415 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9416 WERROR result = WERR_OK;
9418 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9420 if (!get_short_archi(long_archi))
9421 return WERR_INVALID_ENVIRONMENT;
9423 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9426 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9428 fill_printprocessordirectory_1(info, path);
9430 *needed += spoolss_size_printprocessordirectory_info_1(info);
9432 if (*needed > offered) {
9433 result = WERR_INSUFFICIENT_BUFFER;
9437 if (!rpcbuf_alloc_size(buffer, *needed)) {
9438 result = WERR_INSUFFICIENT_BUFFER;
9442 smb_io_printprocessordirectory_1("", buffer, info, 0);
9450 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9452 uint32 level = q_u->level;
9453 RPC_BUFFER *buffer = NULL;
9454 uint32 offered = q_u->offered;
9455 uint32 *needed = &r_u->needed;
9458 /* that's an [in out] buffer */
9460 if (!q_u->buffer && (offered!=0)) {
9461 return WERR_INVALID_PARAM;
9464 rpcbuf_move(q_u->buffer, &r_u->buffer);
9465 buffer = r_u->buffer;
9467 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9473 result = getprintprocessordirectory_level_1
9474 (&q_u->name, &q_u->environment, buffer, offered, needed);
9477 result = WERR_UNKNOWN_LEVEL;
9483 /*******************************************************************
9484 Streams the monitor UI DLL name in UNICODE
9485 *******************************************************************/
9487 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9488 RPC_BUFFER *out, uint32 *needed )
9490 const char *dllname = "tcpmonui.dll";
9492 *needed = (strlen(dllname)+1) * 2;
9494 if ( rpcbuf_get_size(out) < *needed ) {
9495 return WERR_INSUFFICIENT_BUFFER;
9498 if ( !make_monitorui_buf( out, dllname ) ) {
9505 /*******************************************************************
9506 Create a new TCP/IP port
9507 *******************************************************************/
9509 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9510 RPC_BUFFER *out, uint32 *needed )
9512 NT_PORT_DATA_1 port1;
9515 ZERO_STRUCT( port1 );
9517 /* convert to our internal port data structure */
9519 if ( !convert_port_data_1( &port1, in ) ) {
9523 /* create the device URI and call the add_port_hook() */
9525 switch ( port1.protocol ) {
9526 case PORT_PROTOCOL_DIRECT:
9527 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9530 case PORT_PROTOCOL_LPR:
9531 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9535 return WERR_UNKNOWN_PORT;
9538 return add_port_hook( token, port1.name, device_uri );
9541 /*******************************************************************
9542 *******************************************************************/
9544 struct xcv_api_table xcvtcp_cmds[] = {
9545 { "MonitorUI", xcvtcp_monitorui },
9546 { "AddPort", xcvtcp_addport},
9550 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9551 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9556 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9558 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9559 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9560 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9563 return WERR_BADFUNC;
9566 /*******************************************************************
9567 *******************************************************************/
9568 #if 0 /* don't support management using the "Local Port" monitor */
9570 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9571 RPC_BUFFER *out, uint32 *needed )
9573 const char *dllname = "localui.dll";
9575 *needed = (strlen(dllname)+1) * 2;
9577 if ( rpcbuf_get_size(out) < *needed ) {
9578 return WERR_INSUFFICIENT_BUFFER;
9581 if ( !make_monitorui_buf( out, dllname )) {
9588 /*******************************************************************
9589 *******************************************************************/
9591 struct xcv_api_table xcvlocal_cmds[] = {
9592 { "MonitorUI", xcvlocal_monitorui },
9596 struct xcv_api_table xcvlocal_cmds[] = {
9603 /*******************************************************************
9604 *******************************************************************/
9606 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9607 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9612 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9614 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9615 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9616 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9618 return WERR_BADFUNC;
9621 /*******************************************************************
9622 *******************************************************************/
9624 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9626 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9630 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9634 /* Has to be a handle to the TCP/IP port monitor */
9636 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9637 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9641 /* requires administrative access to the server */
9643 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9644 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9645 return WERR_ACCESS_DENIED;
9648 /* Get the command name. There's numerous commands supported by the
9649 TCPMON interface. */
9651 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9652 q_u->dataname.uni_str_len*2, 0);
9654 /* Allocate the outgoing buffer */
9656 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9658 switch ( Printer->printer_type ) {
9659 case SPLHND_PORTMON_TCP:
9660 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9661 &q_u->indata, &r_u->outdata, &r_u->needed );
9662 case SPLHND_PORTMON_LOCAL:
9663 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9664 &q_u->indata, &r_u->outdata, &r_u->needed );
9667 return WERR_INVALID_PRINT_MONITOR;