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"));
730 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
735 data->notify_data.data.length = prs_offset(&ps);
736 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
737 if (!data->notify_data.data.string) {
742 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
747 struct notify2_message_table {
749 void (*fn)(struct spoolss_notify_msg *msg,
750 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
753 static struct notify2_message_table printer_notify_table[] = {
754 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
755 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
756 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
757 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
758 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
759 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
760 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
761 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
762 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
763 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
764 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
765 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
766 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
767 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
768 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
769 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
770 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
771 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
772 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
775 static struct notify2_message_table job_notify_table[] = {
776 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
777 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
778 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
779 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
780 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
781 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
782 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
783 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
784 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
785 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
786 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
787 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
788 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
789 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
790 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
791 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
792 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
793 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
794 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
795 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
796 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
797 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
798 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
799 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
803 /***********************************************************************
804 Allocate talloc context for container object
805 **********************************************************************/
807 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
812 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
817 /***********************************************************************
818 release all allocated memory and zero out structure
819 **********************************************************************/
821 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
827 talloc_destroy(ctr->ctx);
834 /***********************************************************************
835 **********************************************************************/
837 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
845 /***********************************************************************
846 **********************************************************************/
848 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
850 if ( !ctr || !ctr->msg_groups )
853 if ( idx >= ctr->num_groups )
856 return &ctr->msg_groups[idx];
860 /***********************************************************************
861 How many groups of change messages do we have ?
862 **********************************************************************/
864 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
869 return ctr->num_groups;
872 /***********************************************************************
873 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
874 **********************************************************************/
876 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
878 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
879 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
880 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
886 /* loop over all groups looking for a matching printer name */
888 for ( i=0; i<ctr->num_groups; i++ ) {
889 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
893 /* add a new group? */
895 if ( i == ctr->num_groups ) {
898 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
899 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
902 ctr->msg_groups = groups;
904 /* clear the new entry and set the printer name */
906 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
907 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
910 /* add the change messages; 'i' is the correct index now regardless */
912 msg_grp = &ctr->msg_groups[i];
916 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
917 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
920 msg_grp->msgs = msg_list;
922 new_slot = msg_grp->num_msgs-1;
923 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
925 /* need to allocate own copy of data */
928 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
930 return ctr->num_groups;
933 /***********************************************************************
934 Send a change notication message on all handles which have a call
936 **********************************************************************/
938 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
941 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
942 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
943 SPOOLSS_NOTIFY_MSG *messages;
944 int sending_msg_count;
947 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
951 messages = msg_group->msgs;
954 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
958 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
960 /* loop over all printers */
962 for (p = printers_list; p; p = p->next) {
963 SPOOL_NOTIFY_INFO_DATA *data;
968 /* Is there notification on this handle? */
970 if ( !p->notify.client_connected )
973 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
975 /* For this printer? Print servers always receive
978 if ( ( p->printer_type == SPLHND_PRINTER ) &&
979 ( !strequal(msg_group->printername, p->sharename) ) )
982 DEBUG(10,("Our printer\n"));
984 /* allocate the max entries possible */
986 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
993 /* build the array of change notifications */
995 sending_msg_count = 0;
997 for ( i=0; i<msg_group->num_msgs; i++ ) {
998 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1000 /* Are we monitoring this event? */
1002 if (!is_monitoring_event(p, msg->type, msg->field))
1005 sending_msg_count++;
1008 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1009 msg->type, msg->field, p->sharename));
1012 * if the is a printer notification handle and not a job notification
1013 * type, then set the id to 0. Other wise just use what was specified
1016 * When registering change notification on a print server handle
1017 * we always need to send back the id (snum) matching the printer
1018 * for which the change took place. For change notify registered
1019 * on a printer handle, this does not matter and the id should be 0.
1024 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1030 /* Convert unix jobid to smb jobid */
1032 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1033 id = sysjob_to_jobid(msg->id);
1036 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1041 construct_info_data( &data[data_len], msg->type, msg->field, id );
1044 case PRINTER_NOTIFY_TYPE:
1045 if ( printer_notify_table[msg->field].fn )
1046 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1049 case JOB_NOTIFY_TYPE:
1050 if ( job_notify_table[msg->field].fn )
1051 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1055 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1062 if ( sending_msg_count ) {
1063 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1064 data_len, data, p->notify.change, 0 );
1069 DEBUG(8,("send_notify2_changes: Exit...\n"));
1073 /***********************************************************************
1074 **********************************************************************/
1076 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1079 uint32 tv_sec, tv_usec;
1082 /* Unpack message */
1084 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1087 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1089 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1092 tdb_unpack((char *)buf + offset, len - offset, "dd",
1093 &msg->notify.value[0], &msg->notify.value[1]);
1095 tdb_unpack((char *)buf + offset, len - offset, "B",
1096 &msg->len, &msg->notify.data);
1098 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1099 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1101 tv->tv_sec = tv_sec;
1102 tv->tv_usec = tv_usec;
1105 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1106 msg->notify.value[1]));
1108 dump_data(3, msg->notify.data, msg->len);
1113 /********************************************************************
1114 Receive a notify2 message list
1115 ********************************************************************/
1117 static void receive_notify2_message_list(int msg_type, struct process_id src,
1118 void *msg, size_t len)
1120 size_t msg_count, i;
1121 char *buf = (char *)msg;
1124 SPOOLSS_NOTIFY_MSG notify;
1125 SPOOLSS_NOTIFY_MSG_CTR messages;
1129 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1133 msg_count = IVAL(buf, 0);
1136 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1138 if (msg_count == 0) {
1139 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1143 /* initialize the container */
1145 ZERO_STRUCT( messages );
1146 notify_msg_ctr_init( &messages );
1149 * build message groups for each printer identified
1150 * in a change_notify msg. Remember that a PCN message
1151 * includes the handle returned for the srv_spoolss_replyopenprinter()
1152 * call. Therefore messages are grouped according to printer handle.
1155 for ( i=0; i<msg_count; i++ ) {
1156 struct timeval msg_tv;
1158 if (msg_ptr + 4 - buf > len) {
1159 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1163 msg_len = IVAL(msg_ptr,0);
1166 if (msg_ptr + msg_len - buf > len) {
1167 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1171 /* unpack messages */
1173 ZERO_STRUCT( notify );
1174 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1177 /* add to correct list in container */
1179 notify_msg_ctr_addmsg( &messages, ¬ify );
1181 /* free memory that might have been allocated by notify2_unpack_msg() */
1183 if ( notify.len != 0 )
1184 SAFE_FREE( notify.notify.data );
1187 /* process each group of messages */
1189 num_groups = notify_msg_ctr_numgroups( &messages );
1190 for ( i=0; i<num_groups; i++ )
1191 send_notify2_changes( &messages, i );
1196 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1198 notify_msg_ctr_destroy( &messages );
1203 /********************************************************************
1204 Send a message to ourself about new driver being installed
1205 so we can upgrade the information for each printer bound to this
1207 ********************************************************************/
1209 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1211 int len = strlen(drivername);
1216 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1219 message_send_pid(pid_to_procid(sys_getpid()),
1220 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1225 /**********************************************************************
1226 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1227 over all printers, upgrading ones as necessary
1228 **********************************************************************/
1230 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1234 int n_services = lp_numservices();
1236 len = MIN(len,sizeof(drivername)-1);
1237 strncpy(drivername, buf, len);
1239 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1241 /* Iterate the printer list */
1243 for (snum=0; snum<n_services; snum++)
1245 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1248 NT_PRINTER_INFO_LEVEL *printer = NULL;
1250 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1251 if (!W_ERROR_IS_OK(result))
1254 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1256 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1258 /* all we care about currently is the change_id */
1260 result = mod_a_printer(printer, 2);
1261 if (!W_ERROR_IS_OK(result)) {
1262 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1263 dos_errstr(result)));
1267 free_a_printer(&printer, 2);
1274 /********************************************************************
1275 Update the cache for all printq's with a registered client
1277 ********************************************************************/
1279 void update_monitored_printq_cache( void )
1281 Printer_entry *printer = printers_list;
1284 /* loop through all printers and update the cache where
1285 client_connected == True */
1288 if ( (printer->printer_type == SPLHND_PRINTER)
1289 && printer->notify.client_connected )
1291 snum = print_queue_snum(printer->sharename);
1292 print_queue_status( snum, NULL, NULL );
1295 printer = printer->next;
1300 /********************************************************************
1301 Send a message to ourself about new driver being installed
1302 so we can upgrade the information for each printer bound to this
1304 ********************************************************************/
1306 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1308 int len = strlen(drivername);
1313 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1316 message_send_pid(pid_to_procid(sys_getpid()),
1317 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1322 /**********************************************************************
1323 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1324 over all printers, resetting printer data as neessary
1325 **********************************************************************/
1327 void reset_all_printerdata(int msg_type, struct process_id src,
1328 void *buf, size_t len)
1332 int n_services = lp_numservices();
1334 len = MIN( len, sizeof(drivername)-1 );
1335 strncpy( drivername, buf, len );
1337 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1339 /* Iterate the printer list */
1341 for ( snum=0; snum<n_services; snum++ )
1343 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1346 NT_PRINTER_INFO_LEVEL *printer = NULL;
1348 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1349 if ( !W_ERROR_IS_OK(result) )
1353 * if the printer is bound to the driver,
1354 * then reset to the new driver initdata
1357 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1359 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1361 if ( !set_driver_init(printer, 2) ) {
1362 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1363 printer->info_2->printername, printer->info_2->drivername));
1366 result = mod_a_printer( printer, 2 );
1367 if ( !W_ERROR_IS_OK(result) ) {
1368 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1369 get_dos_error_msg(result)));
1373 free_a_printer( &printer, 2 );
1382 /********************************************************************
1383 Copy routines used by convert_to_openprinterex()
1384 *******************************************************************/
1386 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1394 DEBUG (8,("dup_devmode\n"));
1396 /* bulk copy first */
1398 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1402 /* dup the pointer members separately */
1404 len = unistrlen(devmode->devicename.buffer);
1406 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1407 if (!d->devicename.buffer) {
1410 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1415 len = unistrlen(devmode->formname.buffer);
1417 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1418 if (!d->devicename.buffer) {
1421 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1425 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1426 if (!d->dev_private) {
1432 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1434 if (!new_ctr || !ctr)
1437 DEBUG(8,("copy_devmode_ctr\n"));
1439 new_ctr->size = ctr->size;
1440 new_ctr->devmode_ptr = ctr->devmode_ptr;
1442 if(ctr->devmode_ptr)
1443 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1446 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1448 if (!new_def || !def)
1451 DEBUG(8,("copy_printer_defaults\n"));
1453 new_def->datatype_ptr = def->datatype_ptr;
1455 if (def->datatype_ptr)
1456 copy_unistr2(&new_def->datatype, &def->datatype);
1458 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1460 new_def->access_required = def->access_required;
1463 /********************************************************************
1464 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1465 * SPOOL_Q_OPEN_PRINTER_EX structure
1466 ********************************************************************/
1468 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1470 if (!q_u_ex || !q_u)
1473 DEBUG(8,("convert_to_openprinterex\n"));
1475 if ( q_u->printername ) {
1476 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1477 if (q_u_ex->printername == NULL)
1479 copy_unistr2(q_u_ex->printername, q_u->printername);
1482 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1487 /********************************************************************
1488 * spoolss_open_printer
1490 * called from the spoolss dispatcher
1491 ********************************************************************/
1493 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1495 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1496 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1501 ZERO_STRUCT(q_u_ex);
1502 ZERO_STRUCT(r_u_ex);
1504 /* convert the OpenPrinter() call to OpenPrinterEx() */
1506 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1507 if (!W_ERROR_IS_OK(r_u_ex.status))
1508 return r_u_ex.status;
1510 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1512 /* convert back to OpenPrinter() */
1514 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1519 /********************************************************************
1520 ********************************************************************/
1522 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1524 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1525 POLICY_HND *handle = &r_u->handle;
1529 struct current_user user;
1530 Printer_entry *Printer=NULL;
1532 if ( !q_u->printername )
1533 return WERR_INVALID_PRINTER_NAME;
1535 /* some sanity check because you can open a printer or a print server */
1536 /* aka: \\server\printer or \\server */
1538 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1540 DEBUGADD(3,("checking name: %s\n",name));
1542 if (!open_printer_hnd(p, handle, name, 0))
1543 return WERR_INVALID_PRINTER_NAME;
1545 Printer=find_printer_index_by_hnd(p, handle);
1547 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1548 "handle we created for printer %s\n", name ));
1549 close_printer_handle(p,handle);
1550 return WERR_INVALID_PRINTER_NAME;
1553 get_current_user(&user, p);
1556 * First case: the user is opening the print server:
1558 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1559 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1561 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1562 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1563 * or if the user is listed in the smb.conf printer admin parameter.
1565 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1566 * client view printer folder, but does not show the MSAPW.
1568 * Note: this test needs code to check access rights here too. Jeremy
1569 * could you look at this?
1571 * Second case: the user is opening a printer:
1572 * NT doesn't let us connect to a printer if the connecting user
1573 * doesn't have print permission.
1575 * Third case: user is opening a Port Monitor
1576 * access checks same as opening a handle to the print server.
1579 switch (Printer->printer_type )
1582 case SPLHND_PORTMON_TCP:
1583 case SPLHND_PORTMON_LOCAL:
1584 /* Printserver handles use global struct... */
1588 /* Map standard access rights to object specific access rights */
1590 se_map_standard(&printer_default->access_required,
1591 &printserver_std_mapping);
1593 /* Deny any object specific bits that don't apply to print
1594 servers (i.e printer and job specific bits) */
1596 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1598 if (printer_default->access_required &
1599 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1600 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1601 close_printer_handle(p, handle);
1602 return WERR_ACCESS_DENIED;
1605 /* Allow admin access */
1607 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1609 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1611 if (!lp_ms_add_printer_wizard()) {
1612 close_printer_handle(p, handle);
1613 return WERR_ACCESS_DENIED;
1616 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1617 and not a printer admin, then fail */
1619 if ((user.ut.uid != 0) &&
1620 !user_has_privileges(user.nt_user_token,
1622 !token_contains_name_in_list(
1623 uidtoname(user.ut.uid), NULL,
1625 lp_printer_admin(snum))) {
1626 close_printer_handle(p, handle);
1627 return WERR_ACCESS_DENIED;
1630 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1634 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1637 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1638 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1640 /* We fall through to return WERR_OK */
1643 case SPLHND_PRINTER:
1644 /* NT doesn't let us connect to a printer if the connecting user
1645 doesn't have print permission. */
1647 if (!get_printer_snum(p, handle, &snum)) {
1648 close_printer_handle(p, handle);
1652 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1654 /* map an empty access mask to the minimum access mask */
1655 if (printer_default->access_required == 0x0)
1656 printer_default->access_required = PRINTER_ACCESS_USE;
1659 * If we are not serving the printer driver for this printer,
1660 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1661 * will keep NT clients happy --jerry
1664 if (lp_use_client_driver(snum)
1665 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1667 printer_default->access_required = PRINTER_ACCESS_USE;
1670 /* check smb.conf parameters and the the sec_desc */
1672 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1673 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1674 return WERR_ACCESS_DENIED;
1677 if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
1679 !print_access_check(&user, snum,
1680 printer_default->access_required)) {
1681 DEBUG(3, ("access DENIED for printer open\n"));
1682 close_printer_handle(p, handle);
1683 return WERR_ACCESS_DENIED;
1686 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1687 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1688 close_printer_handle(p, handle);
1689 return WERR_ACCESS_DENIED;
1692 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1693 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1695 printer_default->access_required = PRINTER_ACCESS_USE;
1697 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1698 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1703 /* sanity check to prevent programmer error */
1707 Printer->access_granted = printer_default->access_required;
1710 * If the client sent a devmode in the OpenPrinter() call, then
1711 * save it here in case we get a job submission on this handle
1714 if ( (Printer->printer_type != SPLHND_SERVER)
1715 && q_u->printer_default.devmode_cont.devmode_ptr )
1717 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1718 &Printer->nt_devmode );
1721 #if 0 /* JERRY -- I'm doubtful this is really effective */
1722 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1723 optimization in Windows 2000 clients --jerry */
1725 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1726 && (RA_WIN2K == get_remote_arch()) )
1728 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1729 sys_usleep( 500000 );
1736 /****************************************************************************
1737 ****************************************************************************/
1739 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1740 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1746 /* allocate memory if needed. Messy because
1747 convert_printer_info is used to update an existing
1748 printer or build a new one */
1750 if ( !printer->info_2 ) {
1751 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1752 if ( !printer->info_2 ) {
1753 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1758 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1759 printer->info_2->setuptime = time(NULL);
1767 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1768 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1774 printer->info_3=NULL;
1775 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1779 printer->info_6=NULL;
1780 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1790 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1791 NT_DEVICEMODE **pp_nt_devmode)
1793 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1796 * Ensure nt_devmode is a valid pointer
1797 * as we will be overwriting it.
1800 if (nt_devmode == NULL) {
1801 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1802 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1806 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1807 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1809 nt_devmode->specversion=devmode->specversion;
1810 nt_devmode->driverversion=devmode->driverversion;
1811 nt_devmode->size=devmode->size;
1812 nt_devmode->fields=devmode->fields;
1813 nt_devmode->orientation=devmode->orientation;
1814 nt_devmode->papersize=devmode->papersize;
1815 nt_devmode->paperlength=devmode->paperlength;
1816 nt_devmode->paperwidth=devmode->paperwidth;
1817 nt_devmode->scale=devmode->scale;
1818 nt_devmode->copies=devmode->copies;
1819 nt_devmode->defaultsource=devmode->defaultsource;
1820 nt_devmode->printquality=devmode->printquality;
1821 nt_devmode->color=devmode->color;
1822 nt_devmode->duplex=devmode->duplex;
1823 nt_devmode->yresolution=devmode->yresolution;
1824 nt_devmode->ttoption=devmode->ttoption;
1825 nt_devmode->collate=devmode->collate;
1827 nt_devmode->logpixels=devmode->logpixels;
1828 nt_devmode->bitsperpel=devmode->bitsperpel;
1829 nt_devmode->pelswidth=devmode->pelswidth;
1830 nt_devmode->pelsheight=devmode->pelsheight;
1831 nt_devmode->displayflags=devmode->displayflags;
1832 nt_devmode->displayfrequency=devmode->displayfrequency;
1833 nt_devmode->icmmethod=devmode->icmmethod;
1834 nt_devmode->icmintent=devmode->icmintent;
1835 nt_devmode->mediatype=devmode->mediatype;
1836 nt_devmode->dithertype=devmode->dithertype;
1837 nt_devmode->reserved1=devmode->reserved1;
1838 nt_devmode->reserved2=devmode->reserved2;
1839 nt_devmode->panningwidth=devmode->panningwidth;
1840 nt_devmode->panningheight=devmode->panningheight;
1843 * Only change private and driverextra if the incoming devmode
1844 * has a new one. JRA.
1847 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1848 SAFE_FREE(nt_devmode->nt_dev_private);
1849 nt_devmode->driverextra=devmode->driverextra;
1850 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1852 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1855 *pp_nt_devmode = nt_devmode;
1860 /********************************************************************
1861 * _spoolss_enddocprinter_internal.
1862 ********************************************************************/
1864 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1866 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1870 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1874 if (!get_printer_snum(p, handle, &snum))
1877 Printer->document_started=False;
1878 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1879 /* error codes unhandled so far ... */
1884 /********************************************************************
1885 * api_spoolss_closeprinter
1886 ********************************************************************/
1888 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1890 POLICY_HND *handle = &q_u->handle;
1892 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1894 if (Printer && Printer->document_started)
1895 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1897 if (!close_printer_handle(p, handle))
1900 /* clear the returned printer handle. Observed behavior
1901 from Win2k server. Don't think this really matters.
1902 Previous code just copied the value of the closed
1905 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1910 /********************************************************************
1911 * api_spoolss_deleteprinter
1913 ********************************************************************/
1915 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1917 POLICY_HND *handle = &q_u->handle;
1918 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1921 if (Printer && Printer->document_started)
1922 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1924 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1926 result = delete_printer_handle(p, handle);
1928 update_c_setprinter(False);
1933 /*******************************************************************
1934 * static function to lookup the version id corresponding to an
1935 * long architecture string
1936 ******************************************************************/
1938 static int get_version_id (char * arch)
1941 struct table_node archi_table[]= {
1943 {"Windows 4.0", "WIN40", 0 },
1944 {"Windows NT x86", "W32X86", 2 },
1945 {"Windows NT R4000", "W32MIPS", 2 },
1946 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1947 {"Windows NT PowerPC", "W32PPC", 2 },
1948 {"Windows IA64", "IA64", 3 },
1949 {"Windows x64", "x64", 3 },
1953 for (i=0; archi_table[i].long_archi != NULL; i++)
1955 if (strcmp(arch, archi_table[i].long_archi) == 0)
1956 return (archi_table[i].version);
1962 /********************************************************************
1963 * _spoolss_deleteprinterdriver
1964 ********************************************************************/
1966 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1970 NT_PRINTER_DRIVER_INFO_LEVEL info;
1971 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1973 struct current_user user;
1975 WERROR status_win2k = WERR_ACCESS_DENIED;
1976 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1978 get_current_user(&user, p);
1980 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1981 and not a printer admin, then fail */
1983 if ( (user.ut.uid != 0)
1984 && !user_has_privileges(user.nt_user_token, &se_printop )
1985 && !token_contains_name_in_list( uidtoname(user.ut.uid),
1986 NULL, user.nt_user_token, lp_printer_admin(-1)) )
1988 return WERR_ACCESS_DENIED;
1991 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1992 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1994 /* check that we have a valid driver name first */
1996 if ((version=get_version_id(arch)) == -1)
1997 return WERR_INVALID_ENVIRONMENT;
2000 ZERO_STRUCT(info_win2k);
2002 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2004 /* try for Win2k driver if "Windows NT x86" */
2006 if ( version == 2 ) {
2008 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2009 status = WERR_UNKNOWN_PRINTER_DRIVER;
2013 /* otherwise it was a failure */
2015 status = WERR_UNKNOWN_PRINTER_DRIVER;
2021 if (printer_driver_in_use(info.info_3)) {
2022 status = WERR_PRINTER_DRIVER_IN_USE;
2028 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2030 /* if we get to here, we now have 2 driver info structures to remove */
2031 /* remove the Win2k driver first*/
2033 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2034 free_a_printer_driver( info_win2k, 3 );
2036 /* this should not have failed---if it did, report to client */
2037 if ( !W_ERROR_IS_OK(status_win2k) )
2039 status = status_win2k;
2045 status = delete_printer_driver(info.info_3, &user, version, False);
2047 /* if at least one of the deletes succeeded return OK */
2049 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2053 free_a_printer_driver( info, 3 );
2058 /********************************************************************
2059 * spoolss_deleteprinterdriverex
2060 ********************************************************************/
2062 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2066 NT_PRINTER_DRIVER_INFO_LEVEL info;
2067 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2069 uint32 flags = q_u->delete_flags;
2071 struct current_user user;
2073 WERROR status_win2k = WERR_ACCESS_DENIED;
2074 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2076 get_current_user(&user, p);
2078 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2079 and not a printer admin, then fail */
2081 if ( (user.ut.uid != 0)
2082 && !user_has_privileges(user.nt_user_token, &se_printop )
2083 && !token_contains_name_in_list( uidtoname(user.ut.uid),
2084 NULL, user.nt_user_token, lp_printer_admin(-1)) )
2086 return WERR_ACCESS_DENIED;
2089 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2090 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2092 /* check that we have a valid driver name first */
2093 if ((version=get_version_id(arch)) == -1) {
2094 /* this is what NT returns */
2095 return WERR_INVALID_ENVIRONMENT;
2098 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2099 version = q_u->version;
2102 ZERO_STRUCT(info_win2k);
2104 status = get_a_printer_driver(&info, 3, driver, arch, version);
2106 if ( !W_ERROR_IS_OK(status) )
2109 * if the client asked for a specific version,
2110 * or this is something other than Windows NT x86,
2114 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2117 /* try for Win2k driver if "Windows NT x86" */
2120 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2121 status = WERR_UNKNOWN_PRINTER_DRIVER;
2126 if ( printer_driver_in_use(info.info_3) ) {
2127 status = WERR_PRINTER_DRIVER_IN_USE;
2132 * we have a couple of cases to consider.
2133 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2134 * then the delete should fail if **any** files overlap with
2136 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2137 * non-overlapping files
2138 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2139 * is set, the do not delete any files
2140 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2143 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2145 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2147 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2148 /* no idea of the correct error here */
2149 status = WERR_ACCESS_DENIED;
2154 /* also check for W32X86/3 if necessary; maybe we already have? */
2156 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2157 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2160 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2161 /* no idea of the correct error here */
2162 free_a_printer_driver( info_win2k, 3 );
2163 status = WERR_ACCESS_DENIED;
2167 /* if we get to here, we now have 2 driver info structures to remove */
2168 /* remove the Win2k driver first*/
2170 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2171 free_a_printer_driver( info_win2k, 3 );
2173 /* this should not have failed---if it did, report to client */
2175 if ( !W_ERROR_IS_OK(status_win2k) )
2180 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2182 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2185 free_a_printer_driver( info, 3 );
2191 /****************************************************************************
2192 Internal routine for retreiving printerdata
2193 ***************************************************************************/
2195 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2196 const char *key, const char *value, uint32 *type, uint8 **data,
2197 uint32 *needed, uint32 in_size )
2199 REGISTRY_VALUE *val;
2203 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2204 return WERR_BADFILE;
2206 *type = regval_type( val );
2208 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2210 size = regval_size( val );
2212 /* copy the min(in_size, len) */
2215 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2217 /* special case for 0 length values */
2219 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2223 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2232 DEBUG(5,("get_printer_dataex: copy done\n"));
2237 /****************************************************************************
2238 Internal routine for removing printerdata
2239 ***************************************************************************/
2241 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2243 return delete_printer_data( printer->info_2, key, value );
2246 /****************************************************************************
2247 Internal routine for storing printerdata
2248 ***************************************************************************/
2250 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2251 uint32 type, uint8 *data, int real_len )
2253 /* the registry objects enforce uniqueness based on value name */
2255 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2258 /********************************************************************
2259 GetPrinterData on a printer server Handle.
2260 ********************************************************************/
2262 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2266 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2268 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2270 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2276 if (!StrCaseCmp(value, "BeepEnabled")) {
2278 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2280 SIVAL(*data, 0, 0x00);
2285 if (!StrCaseCmp(value, "EventLog")) {
2287 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2289 /* formally was 0x1b */
2290 SIVAL(*data, 0, 0x0);
2295 if (!StrCaseCmp(value, "NetPopup")) {
2297 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2299 SIVAL(*data, 0, 0x00);
2304 if (!StrCaseCmp(value, "MajorVersion")) {
2306 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2309 /* Windows NT 4.0 seems to not allow uploading of drivers
2310 to a server that reports 0x3 as the MajorVersion.
2311 need to investigate more how Win2k gets around this .
2314 if ( RA_WINNT == get_remote_arch() )
2323 if (!StrCaseCmp(value, "MinorVersion")) {
2325 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2333 * uint32 size = 0x114
2335 * uint32 minor = [0|1]
2336 * uint32 build = [2195|2600]
2337 * extra unicode string = e.g. "Service Pack 3"
2339 if (!StrCaseCmp(value, "OSVersion")) {
2343 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2346 SIVAL(*data, 0, *needed); /* size */
2347 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2349 SIVAL(*data, 12, 2195); /* build */
2351 /* leave extra string empty */
2357 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2358 const char *string="C:\\PRINTERS";
2360 *needed = 2*(strlen(string)+1);
2361 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2363 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2365 /* it's done by hand ready to go on the wire */
2366 for (i=0; i<strlen(string); i++) {
2367 (*data)[2*i]=string[i];
2368 (*data)[2*i+1]='\0';
2373 if (!StrCaseCmp(value, "Architecture")) {
2374 const char *string="Windows NT x86";
2376 *needed = 2*(strlen(string)+1);
2377 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2379 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2380 for (i=0; i<strlen(string); i++) {
2381 (*data)[2*i]=string[i];
2382 (*data)[2*i+1]='\0';
2387 if (!StrCaseCmp(value, "DsPresent")) {
2389 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2392 /* only show the publish check box if we are a
2393 memeber of a AD domain */
2395 if ( lp_security() == SEC_ADS )
2396 SIVAL(*data, 0, 0x01);
2398 SIVAL(*data, 0, 0x00);
2404 if (!StrCaseCmp(value, "DNSMachineName")) {
2407 if (!get_mydnsfullname(hostname))
2408 return WERR_BADFILE;
2410 *needed = 2*(strlen(hostname)+1);
2411 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2413 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2414 for (i=0; i<strlen(hostname); i++) {
2415 (*data)[2*i]=hostname[i];
2416 (*data)[2*i+1]='\0';
2422 return WERR_BADFILE;
2425 /********************************************************************
2426 * spoolss_getprinterdata
2427 ********************************************************************/
2429 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2431 POLICY_HND *handle = &q_u->handle;
2432 UNISTR2 *valuename = &q_u->valuename;
2433 uint32 in_size = q_u->size;
2434 uint32 *type = &r_u->type;
2435 uint32 *out_size = &r_u->size;
2436 uint8 **data = &r_u->data;
2437 uint32 *needed = &r_u->needed;
2440 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2441 NT_PRINTER_INFO_LEVEL *printer = NULL;
2445 * Reminder: when it's a string, the length is in BYTES
2446 * even if UNICODE is negociated.
2451 *out_size = in_size;
2453 /* in case of problem, return some default values */
2458 DEBUG(4,("_spoolss_getprinterdata\n"));
2461 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2462 status = WERR_BADFID;
2466 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2468 if ( Printer->printer_type == SPLHND_SERVER )
2469 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2472 if ( !get_printer_snum(p,handle, &snum) ) {
2473 status = WERR_BADFID;
2477 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2478 if ( !W_ERROR_IS_OK(status) )
2481 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2483 if ( strequal(value, "ChangeId") ) {
2485 *needed = sizeof(uint32);
2486 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2487 status = WERR_NOMEM;
2490 SIVAL( *data, 0, printer->info_2->changeid );
2494 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2497 if (*needed > *out_size)
2498 status = WERR_MORE_DATA;
2501 if ( !W_ERROR_IS_OK(status) )
2503 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2505 /* reply this param doesn't exist */
2508 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2510 free_a_printer( &printer, 2 );
2519 /* cleanup & exit */
2522 free_a_printer( &printer, 2 );
2527 /*********************************************************
2528 Connect to the client machine.
2529 **********************************************************/
2531 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2532 struct in_addr *client_ip, const char *remote_machine)
2535 struct cli_state *the_cli;
2536 struct in_addr rm_addr;
2538 if ( is_zero_ip(*client_ip) ) {
2539 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2540 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2544 if ( ismyip( rm_addr )) {
2545 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2549 rm_addr.s_addr = client_ip->s_addr;
2550 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2551 inet_ntoa(*client_ip) ));
2554 /* setup the connection */
2556 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2557 &rm_addr, 0, "IPC$", "IPC",
2561 0, lp_client_signing(), NULL );
2563 if ( !NT_STATUS_IS_OK( ret ) ) {
2564 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2569 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2570 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2571 cli_shutdown(the_cli);
2576 * Ok - we have an anonymous connection to the IPC$ share.
2577 * Now start the NT Domain stuff :-).
2580 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2581 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2582 remote_machine, nt_errstr(ret)));
2583 cli_shutdown(the_cli);
2587 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2589 (*pp_pipe)->cli = the_cli;
2594 /***************************************************************************
2595 Connect to the client.
2596 ****************************************************************************/
2598 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2599 uint32 localprinter, uint32 type,
2600 POLICY_HND *handle, struct in_addr *client_ip)
2605 * If it's the first connection, contact the client
2606 * and connect to the IPC$ share anonymously
2608 if (smb_connections==0) {
2609 fstring unix_printer;
2611 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2613 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2616 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2617 /* Tell the connections db we're now interested in printer
2618 * notify messages. */
2619 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2623 * Tell the specific printing tdb we want messages for this printer
2624 * by registering our PID.
2627 if (!print_notify_register_pid(snum))
2628 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2632 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2635 if (!W_ERROR_IS_OK(result))
2636 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2637 dos_errstr(result)));
2639 return (W_ERROR_IS_OK(result));
2642 /********************************************************************
2644 * ReplyFindFirstPrinterChangeNotifyEx
2646 * before replying OK: status=0 a rpc call is made to the workstation
2647 * asking ReplyOpenPrinter
2649 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2650 * called from api_spoolss_rffpcnex
2651 ********************************************************************/
2653 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2655 POLICY_HND *handle = &q_u->handle;
2656 uint32 flags = q_u->flags;
2657 uint32 options = q_u->options;
2658 UNISTR2 *localmachine = &q_u->localmachine;
2659 uint32 printerlocal = q_u->printerlocal;
2661 SPOOL_NOTIFY_OPTION *option = q_u->option;
2662 struct in_addr client_ip;
2664 /* store the notify value in the printer struct */
2666 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2669 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2673 Printer->notify.flags=flags;
2674 Printer->notify.options=options;
2675 Printer->notify.printerlocal=printerlocal;
2677 if (Printer->notify.option)
2678 free_spool_notify_option(&Printer->notify.option);
2680 Printer->notify.option=dup_spool_notify_option(option);
2682 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2683 sizeof(Printer->notify.localmachine)-1);
2685 /* Connect to the client machine and send a ReplyOpenPrinter */
2687 if ( Printer->printer_type == SPLHND_SERVER)
2689 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2690 !get_printer_snum(p, handle, &snum) )
2693 client_ip.s_addr = inet_addr(p->conn->client_address);
2695 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2696 Printer->notify.printerlocal, 1,
2697 &Printer->notify.client_hnd, &client_ip))
2698 return WERR_SERVER_UNAVAILABLE;
2700 Printer->notify.client_connected=True;
2705 /*******************************************************************
2706 * fill a notify_info_data with the servername
2707 ********************************************************************/
2709 void spoolss_notify_server_name(int snum,
2710 SPOOL_NOTIFY_INFO_DATA *data,
2711 print_queue_struct *queue,
2712 NT_PRINTER_INFO_LEVEL *printer,
2713 TALLOC_CTX *mem_ctx)
2718 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2720 data->notify_data.data.length = len;
2721 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2723 if (!data->notify_data.data.string) {
2724 data->notify_data.data.length = 0;
2728 memcpy(data->notify_data.data.string, temp, len);
2731 /*******************************************************************
2732 * fill a notify_info_data with the printername (not including the servername).
2733 ********************************************************************/
2735 void spoolss_notify_printer_name(int snum,
2736 SPOOL_NOTIFY_INFO_DATA *data,
2737 print_queue_struct *queue,
2738 NT_PRINTER_INFO_LEVEL *printer,
2739 TALLOC_CTX *mem_ctx)
2744 /* the notify name should not contain the \\server\ part */
2745 char *p = strrchr(printer->info_2->printername, '\\');
2748 p = printer->info_2->printername;
2753 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2755 data->notify_data.data.length = len;
2756 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2758 if (!data->notify_data.data.string) {
2759 data->notify_data.data.length = 0;
2763 memcpy(data->notify_data.data.string, temp, len);
2766 /*******************************************************************
2767 * fill a notify_info_data with the servicename
2768 ********************************************************************/
2770 void spoolss_notify_share_name(int snum,
2771 SPOOL_NOTIFY_INFO_DATA *data,
2772 print_queue_struct *queue,
2773 NT_PRINTER_INFO_LEVEL *printer,
2774 TALLOC_CTX *mem_ctx)
2779 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2781 data->notify_data.data.length = len;
2782 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2784 if (!data->notify_data.data.string) {
2785 data->notify_data.data.length = 0;
2789 memcpy(data->notify_data.data.string, temp, len);
2792 /*******************************************************************
2793 * fill a notify_info_data with the port name
2794 ********************************************************************/
2796 void spoolss_notify_port_name(int snum,
2797 SPOOL_NOTIFY_INFO_DATA *data,
2798 print_queue_struct *queue,
2799 NT_PRINTER_INFO_LEVEL *printer,
2800 TALLOC_CTX *mem_ctx)
2805 /* even if it's strange, that's consistant in all the code */
2807 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2809 data->notify_data.data.length = len;
2810 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2812 if (!data->notify_data.data.string) {
2813 data->notify_data.data.length = 0;
2817 memcpy(data->notify_data.data.string, temp, len);
2820 /*******************************************************************
2821 * fill a notify_info_data with the printername
2822 * but it doesn't exist, have to see what to do
2823 ********************************************************************/
2825 void spoolss_notify_driver_name(int snum,
2826 SPOOL_NOTIFY_INFO_DATA *data,
2827 print_queue_struct *queue,
2828 NT_PRINTER_INFO_LEVEL *printer,
2829 TALLOC_CTX *mem_ctx)
2834 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2836 data->notify_data.data.length = len;
2837 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2839 if (!data->notify_data.data.string) {
2840 data->notify_data.data.length = 0;
2844 memcpy(data->notify_data.data.string, temp, len);
2847 /*******************************************************************
2848 * fill a notify_info_data with the comment
2849 ********************************************************************/
2851 void spoolss_notify_comment(int snum,
2852 SPOOL_NOTIFY_INFO_DATA *data,
2853 print_queue_struct *queue,
2854 NT_PRINTER_INFO_LEVEL *printer,
2855 TALLOC_CTX *mem_ctx)
2860 if (*printer->info_2->comment == '\0')
2861 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2863 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2865 data->notify_data.data.length = len;
2866 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2868 if (!data->notify_data.data.string) {
2869 data->notify_data.data.length = 0;
2873 memcpy(data->notify_data.data.string, temp, len);
2876 /*******************************************************************
2877 * fill a notify_info_data with the comment
2878 * location = "Room 1, floor 2, building 3"
2879 ********************************************************************/
2881 void spoolss_notify_location(int snum,
2882 SPOOL_NOTIFY_INFO_DATA *data,
2883 print_queue_struct *queue,
2884 NT_PRINTER_INFO_LEVEL *printer,
2885 TALLOC_CTX *mem_ctx)
2890 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2892 data->notify_data.data.length = len;
2893 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2895 if (!data->notify_data.data.string) {
2896 data->notify_data.data.length = 0;
2900 memcpy(data->notify_data.data.string, temp, len);
2903 /*******************************************************************
2904 * fill a notify_info_data with the device mode
2905 * jfm:xxxx don't to it for know but that's a real problem !!!
2906 ********************************************************************/
2908 static void spoolss_notify_devmode(int snum,
2909 SPOOL_NOTIFY_INFO_DATA *data,
2910 print_queue_struct *queue,
2911 NT_PRINTER_INFO_LEVEL *printer,
2912 TALLOC_CTX *mem_ctx)
2916 /*******************************************************************
2917 * fill a notify_info_data with the separator file name
2918 ********************************************************************/
2920 void spoolss_notify_sepfile(int snum,
2921 SPOOL_NOTIFY_INFO_DATA *data,
2922 print_queue_struct *queue,
2923 NT_PRINTER_INFO_LEVEL *printer,
2924 TALLOC_CTX *mem_ctx)
2929 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2931 data->notify_data.data.length = len;
2932 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2934 if (!data->notify_data.data.string) {
2935 data->notify_data.data.length = 0;
2939 memcpy(data->notify_data.data.string, temp, len);
2942 /*******************************************************************
2943 * fill a notify_info_data with the print processor
2944 * jfm:xxxx return always winprint to indicate we don't do anything to it
2945 ********************************************************************/
2947 void spoolss_notify_print_processor(int snum,
2948 SPOOL_NOTIFY_INFO_DATA *data,
2949 print_queue_struct *queue,
2950 NT_PRINTER_INFO_LEVEL *printer,
2951 TALLOC_CTX *mem_ctx)
2956 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2958 data->notify_data.data.length = len;
2959 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2961 if (!data->notify_data.data.string) {
2962 data->notify_data.data.length = 0;
2966 memcpy(data->notify_data.data.string, temp, len);
2969 /*******************************************************************
2970 * fill a notify_info_data with the print processor options
2971 * jfm:xxxx send an empty string
2972 ********************************************************************/
2974 void spoolss_notify_parameters(int snum,
2975 SPOOL_NOTIFY_INFO_DATA *data,
2976 print_queue_struct *queue,
2977 NT_PRINTER_INFO_LEVEL *printer,
2978 TALLOC_CTX *mem_ctx)
2983 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2985 data->notify_data.data.length = len;
2986 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2988 if (!data->notify_data.data.string) {
2989 data->notify_data.data.length = 0;
2993 memcpy(data->notify_data.data.string, temp, len);
2996 /*******************************************************************
2997 * fill a notify_info_data with the data type
2998 * jfm:xxxx always send RAW as data type
2999 ********************************************************************/
3001 void spoolss_notify_datatype(int snum,
3002 SPOOL_NOTIFY_INFO_DATA *data,
3003 print_queue_struct *queue,
3004 NT_PRINTER_INFO_LEVEL *printer,
3005 TALLOC_CTX *mem_ctx)
3010 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3012 data->notify_data.data.length = len;
3013 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3015 if (!data->notify_data.data.string) {
3016 data->notify_data.data.length = 0;
3020 memcpy(data->notify_data.data.string, temp, len);
3023 /*******************************************************************
3024 * fill a notify_info_data with the security descriptor
3025 * jfm:xxxx send an null pointer to say no security desc
3026 * have to implement security before !
3027 ********************************************************************/
3029 static void spoolss_notify_security_desc(int snum,
3030 SPOOL_NOTIFY_INFO_DATA *data,
3031 print_queue_struct *queue,
3032 NT_PRINTER_INFO_LEVEL *printer,
3033 TALLOC_CTX *mem_ctx)
3035 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3036 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3039 /*******************************************************************
3040 * fill a notify_info_data with the attributes
3041 * jfm:xxxx a samba printer is always shared
3042 ********************************************************************/
3044 void spoolss_notify_attributes(int snum,
3045 SPOOL_NOTIFY_INFO_DATA *data,
3046 print_queue_struct *queue,
3047 NT_PRINTER_INFO_LEVEL *printer,
3048 TALLOC_CTX *mem_ctx)
3050 data->notify_data.value[0] = printer->info_2->attributes;
3051 data->notify_data.value[1] = 0;
3054 /*******************************************************************
3055 * fill a notify_info_data with the priority
3056 ********************************************************************/
3058 static void spoolss_notify_priority(int snum,
3059 SPOOL_NOTIFY_INFO_DATA *data,
3060 print_queue_struct *queue,
3061 NT_PRINTER_INFO_LEVEL *printer,
3062 TALLOC_CTX *mem_ctx)
3064 data->notify_data.value[0] = printer->info_2->priority;
3065 data->notify_data.value[1] = 0;
3068 /*******************************************************************
3069 * fill a notify_info_data with the default priority
3070 ********************************************************************/
3072 static void spoolss_notify_default_priority(int snum,
3073 SPOOL_NOTIFY_INFO_DATA *data,
3074 print_queue_struct *queue,
3075 NT_PRINTER_INFO_LEVEL *printer,
3076 TALLOC_CTX *mem_ctx)
3078 data->notify_data.value[0] = printer->info_2->default_priority;
3079 data->notify_data.value[1] = 0;
3082 /*******************************************************************
3083 * fill a notify_info_data with the start time
3084 ********************************************************************/
3086 static void spoolss_notify_start_time(int snum,
3087 SPOOL_NOTIFY_INFO_DATA *data,
3088 print_queue_struct *queue,
3089 NT_PRINTER_INFO_LEVEL *printer,
3090 TALLOC_CTX *mem_ctx)
3092 data->notify_data.value[0] = printer->info_2->starttime;
3093 data->notify_data.value[1] = 0;
3096 /*******************************************************************
3097 * fill a notify_info_data with the until time
3098 ********************************************************************/
3100 static void spoolss_notify_until_time(int snum,
3101 SPOOL_NOTIFY_INFO_DATA *data,
3102 print_queue_struct *queue,
3103 NT_PRINTER_INFO_LEVEL *printer,
3104 TALLOC_CTX *mem_ctx)
3106 data->notify_data.value[0] = printer->info_2->untiltime;
3107 data->notify_data.value[1] = 0;
3110 /*******************************************************************
3111 * fill a notify_info_data with the status
3112 ********************************************************************/
3114 static void spoolss_notify_status(int snum,
3115 SPOOL_NOTIFY_INFO_DATA *data,
3116 print_queue_struct *queue,
3117 NT_PRINTER_INFO_LEVEL *printer,
3118 TALLOC_CTX *mem_ctx)
3120 print_status_struct status;
3122 print_queue_length(snum, &status);
3123 data->notify_data.value[0]=(uint32) status.status;
3124 data->notify_data.value[1] = 0;
3127 /*******************************************************************
3128 * fill a notify_info_data with the number of jobs queued
3129 ********************************************************************/
3131 void spoolss_notify_cjobs(int snum,
3132 SPOOL_NOTIFY_INFO_DATA *data,
3133 print_queue_struct *queue,
3134 NT_PRINTER_INFO_LEVEL *printer,
3135 TALLOC_CTX *mem_ctx)
3137 data->notify_data.value[0] = print_queue_length(snum, NULL);
3138 data->notify_data.value[1] = 0;
3141 /*******************************************************************
3142 * fill a notify_info_data with the average ppm
3143 ********************************************************************/
3145 static void spoolss_notify_average_ppm(int snum,
3146 SPOOL_NOTIFY_INFO_DATA *data,
3147 print_queue_struct *queue,
3148 NT_PRINTER_INFO_LEVEL *printer,
3149 TALLOC_CTX *mem_ctx)
3151 /* always respond 8 pages per minutes */
3152 /* a little hard ! */
3153 data->notify_data.value[0] = printer->info_2->averageppm;
3154 data->notify_data.value[1] = 0;
3157 /*******************************************************************
3158 * fill a notify_info_data with username
3159 ********************************************************************/
3161 static void spoolss_notify_username(int snum,
3162 SPOOL_NOTIFY_INFO_DATA *data,
3163 print_queue_struct *queue,
3164 NT_PRINTER_INFO_LEVEL *printer,
3165 TALLOC_CTX *mem_ctx)
3170 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3172 data->notify_data.data.length = len;
3173 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3175 if (!data->notify_data.data.string) {
3176 data->notify_data.data.length = 0;
3180 memcpy(data->notify_data.data.string, temp, len);
3183 /*******************************************************************
3184 * fill a notify_info_data with job status
3185 ********************************************************************/
3187 static void spoolss_notify_job_status(int snum,
3188 SPOOL_NOTIFY_INFO_DATA *data,
3189 print_queue_struct *queue,
3190 NT_PRINTER_INFO_LEVEL *printer,
3191 TALLOC_CTX *mem_ctx)
3193 data->notify_data.value[0]=nt_printj_status(queue->status);
3194 data->notify_data.value[1] = 0;
3197 /*******************************************************************
3198 * fill a notify_info_data with job name
3199 ********************************************************************/
3201 static void spoolss_notify_job_name(int snum,
3202 SPOOL_NOTIFY_INFO_DATA *data,
3203 print_queue_struct *queue,
3204 NT_PRINTER_INFO_LEVEL *printer,
3205 TALLOC_CTX *mem_ctx)
3210 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3212 data->notify_data.data.length = len;
3213 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3215 if (!data->notify_data.data.string) {
3216 data->notify_data.data.length = 0;
3220 memcpy(data->notify_data.data.string, temp, len);
3223 /*******************************************************************
3224 * fill a notify_info_data with job status
3225 ********************************************************************/
3227 static void spoolss_notify_job_status_string(int snum,
3228 SPOOL_NOTIFY_INFO_DATA *data,
3229 print_queue_struct *queue,
3230 NT_PRINTER_INFO_LEVEL *printer,
3231 TALLOC_CTX *mem_ctx)
3234 * Now we're returning job status codes we just return a "" here. JRA.
3241 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3244 switch (queue->status) {
3249 p = ""; /* NT provides the paused string */
3258 #endif /* NO LONGER NEEDED. */
3260 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3262 data->notify_data.data.length = len;
3263 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3265 if (!data->notify_data.data.string) {
3266 data->notify_data.data.length = 0;
3270 memcpy(data->notify_data.data.string, temp, len);
3273 /*******************************************************************
3274 * fill a notify_info_data with job time
3275 ********************************************************************/
3277 static void spoolss_notify_job_time(int snum,
3278 SPOOL_NOTIFY_INFO_DATA *data,
3279 print_queue_struct *queue,
3280 NT_PRINTER_INFO_LEVEL *printer,
3281 TALLOC_CTX *mem_ctx)
3283 data->notify_data.value[0]=0x0;
3284 data->notify_data.value[1]=0;
3287 /*******************************************************************
3288 * fill a notify_info_data with job size
3289 ********************************************************************/
3291 static void spoolss_notify_job_size(int snum,
3292 SPOOL_NOTIFY_INFO_DATA *data,
3293 print_queue_struct *queue,
3294 NT_PRINTER_INFO_LEVEL *printer,
3295 TALLOC_CTX *mem_ctx)
3297 data->notify_data.value[0]=queue->size;
3298 data->notify_data.value[1]=0;
3301 /*******************************************************************
3302 * fill a notify_info_data with page info
3303 ********************************************************************/
3304 static void spoolss_notify_total_pages(int snum,
3305 SPOOL_NOTIFY_INFO_DATA *data,
3306 print_queue_struct *queue,
3307 NT_PRINTER_INFO_LEVEL *printer,
3308 TALLOC_CTX *mem_ctx)
3310 data->notify_data.value[0]=queue->page_count;
3311 data->notify_data.value[1]=0;
3314 /*******************************************************************
3315 * fill a notify_info_data with pages printed info.
3316 ********************************************************************/
3317 static void spoolss_notify_pages_printed(int snum,
3318 SPOOL_NOTIFY_INFO_DATA *data,
3319 print_queue_struct *queue,
3320 NT_PRINTER_INFO_LEVEL *printer,
3321 TALLOC_CTX *mem_ctx)
3323 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3324 data->notify_data.value[1]=0;
3327 /*******************************************************************
3328 Fill a notify_info_data with job position.
3329 ********************************************************************/
3331 static void spoolss_notify_job_position(int snum,
3332 SPOOL_NOTIFY_INFO_DATA *data,
3333 print_queue_struct *queue,
3334 NT_PRINTER_INFO_LEVEL *printer,
3335 TALLOC_CTX *mem_ctx)
3337 data->notify_data.value[0]=queue->job;
3338 data->notify_data.value[1]=0;
3341 /*******************************************************************
3342 Fill a notify_info_data with submitted time.
3343 ********************************************************************/
3345 static void spoolss_notify_submitted_time(int snum,
3346 SPOOL_NOTIFY_INFO_DATA *data,
3347 print_queue_struct *queue,
3348 NT_PRINTER_INFO_LEVEL *printer,
3349 TALLOC_CTX *mem_ctx)
3356 t=gmtime(&queue->time);
3358 len = sizeof(SYSTEMTIME);
3360 data->notify_data.data.length = len;
3361 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3363 if (!data->notify_data.data.string) {
3364 data->notify_data.data.length = 0;
3368 make_systemtime(&st, t);
3371 * Systemtime must be linearized as a set of UINT16's.
3372 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3375 p = (char *)data->notify_data.data.string;
3376 SSVAL(p, 0, st.year);
3377 SSVAL(p, 2, st.month);
3378 SSVAL(p, 4, st.dayofweek);
3379 SSVAL(p, 6, st.day);
3380 SSVAL(p, 8, st.hour);
3381 SSVAL(p, 10, st.minute);
3382 SSVAL(p, 12, st.second);
3383 SSVAL(p, 14, st.milliseconds);
3386 struct s_notify_info_data_table
3392 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3393 print_queue_struct *queue,
3394 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3397 /* A table describing the various print notification constants and
3398 whether the notification data is a pointer to a variable sized
3399 buffer, a one value uint32 or a two value uint32. */
3401 static const struct s_notify_info_data_table notify_info_data_table[] =
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3422 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3423 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3424 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3440 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3442 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3443 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3444 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3445 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3446 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3447 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3448 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3449 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3450 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3451 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3452 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3455 /*******************************************************************
3456 Return the size of info_data structure.
3457 ********************************************************************/
3459 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3463 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3464 if ( (notify_info_data_table[i].type == type)
3465 && (notify_info_data_table[i].field == field) ) {
3466 switch(notify_info_data_table[i].size) {
3467 case NOTIFY_ONE_VALUE:
3468 case NOTIFY_TWO_VALUE:
3473 /* The only pointer notify data I have seen on
3474 the wire is the submitted time and this has
3475 the notify size set to 4. -tpot */
3477 case NOTIFY_POINTER:
3480 case NOTIFY_SECDESC:
3486 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3491 /*******************************************************************
3492 Return the type of notify_info_data.
3493 ********************************************************************/
3495 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3499 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3500 if (notify_info_data_table[i].type == type &&
3501 notify_info_data_table[i].field == field)
3502 return notify_info_data_table[i].size;
3508 /****************************************************************************
3509 ****************************************************************************/
3511 static BOOL search_notify(uint16 type, uint16 field, int *value)
3515 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3516 if (notify_info_data_table[i].type == type &&
3517 notify_info_data_table[i].field == field &&
3518 notify_info_data_table[i].fn != NULL) {
3527 /****************************************************************************
3528 ****************************************************************************/
3530 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3532 info_data->type = type;
3533 info_data->field = field;
3534 info_data->reserved = 0;
3536 info_data->size = size_of_notify_info_data(type, field);
3537 info_data->enc_type = type_of_notify_info_data(type, field);
3542 /*******************************************************************
3544 * fill a notify_info struct with info asked
3546 ********************************************************************/
3548 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3549 snum, SPOOL_NOTIFY_OPTION_TYPE
3550 *option_type, uint32 id,
3551 TALLOC_CTX *mem_ctx)
3557 SPOOL_NOTIFY_INFO_DATA *current_data;
3558 NT_PRINTER_INFO_LEVEL *printer = NULL;
3559 print_queue_struct *queue=NULL;
3561 type=option_type->type;
3563 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3564 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3565 option_type->count, lp_servicename(snum)));
3567 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3570 for(field_num=0; field_num<option_type->count; field_num++) {
3571 field = option_type->fields[field_num];
3573 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3575 if (!search_notify(type, field, &j) )
3578 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3579 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3583 current_data = &info->data[info->count];
3585 construct_info_data(current_data, type, field, id);
3587 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3588 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3590 notify_info_data_table[j].fn(snum, current_data, queue,
3596 free_a_printer(&printer, 2);
3600 /*******************************************************************
3602 * fill a notify_info struct with info asked
3604 ********************************************************************/
3606 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3607 SPOOL_NOTIFY_INFO *info,
3608 NT_PRINTER_INFO_LEVEL *printer,
3609 int snum, SPOOL_NOTIFY_OPTION_TYPE
3610 *option_type, uint32 id,
3611 TALLOC_CTX *mem_ctx)
3617 SPOOL_NOTIFY_INFO_DATA *current_data;
3619 DEBUG(4,("construct_notify_jobs_info\n"));
3621 type = option_type->type;
3623 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3624 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3625 option_type->count));
3627 for(field_num=0; field_num<option_type->count; field_num++) {
3628 field = option_type->fields[field_num];
3630 if (!search_notify(type, field, &j) )
3633 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3634 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3638 current_data=&(info->data[info->count]);
3640 construct_info_data(current_data, type, field, id);
3641 notify_info_data_table[j].fn(snum, current_data, queue,
3650 * JFM: The enumeration is not that simple, it's even non obvious.
3652 * let's take an example: I want to monitor the PRINTER SERVER for
3653 * the printer's name and the number of jobs currently queued.
3654 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3655 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3657 * I have 3 printers on the back of my server.
3659 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3662 * 1 printer 1 name 1
3663 * 2 printer 1 cjob 1
3664 * 3 printer 2 name 2
3665 * 4 printer 2 cjob 2
3666 * 5 printer 3 name 3
3667 * 6 printer 3 name 3
3669 * that's the print server case, the printer case is even worse.
3672 /*******************************************************************
3674 * enumerate all printers on the printserver
3675 * fill a notify_info struct with info asked
3677 ********************************************************************/
3679 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3680 SPOOL_NOTIFY_INFO *info,
3681 TALLOC_CTX *mem_ctx)
3684 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3685 int n_services=lp_numservices();
3687 SPOOL_NOTIFY_OPTION *option;
3688 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3690 DEBUG(4,("printserver_notify_info\n"));
3695 option=Printer->notify.option;
3700 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3701 sending a ffpcn() request first */
3706 for (i=0; i<option->count; i++) {
3707 option_type=&(option->ctr.type[i]);
3709 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3712 for (snum=0; snum<n_services; snum++)
3714 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3715 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3721 * Debugging information, don't delete.
3724 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3725 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3726 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3728 for (i=0; i<info->count; i++) {
3729 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3730 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3731 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3738 /*******************************************************************
3740 * fill a notify_info struct with info asked
3742 ********************************************************************/
3744 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3745 TALLOC_CTX *mem_ctx)
3748 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3751 SPOOL_NOTIFY_OPTION *option;
3752 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3754 print_queue_struct *queue=NULL;
3755 print_status_struct status;
3757 DEBUG(4,("printer_notify_info\n"));
3762 option=Printer->notify.option;
3768 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3769 sending a ffpcn() request first */
3774 get_printer_snum(p, hnd, &snum);
3776 for (i=0; i<option->count; i++) {
3777 option_type=&option->ctr.type[i];
3779 switch ( option_type->type ) {
3780 case PRINTER_NOTIFY_TYPE:
3781 if(construct_notify_printer_info(Printer, info, snum,
3787 case JOB_NOTIFY_TYPE: {
3788 NT_PRINTER_INFO_LEVEL *printer = NULL;
3790 count = print_queue_status(snum, &queue, &status);
3792 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3795 for (j=0; j<count; j++) {
3796 construct_notify_jobs_info(&queue[j], info,
3803 free_a_printer(&printer, 2);
3813 * Debugging information, don't delete.
3816 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3817 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3818 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3820 for (i=0; i<info->count; i++) {
3821 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3822 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3823 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3829 /********************************************************************
3831 ********************************************************************/
3833 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3835 POLICY_HND *handle = &q_u->handle;
3836 SPOOL_NOTIFY_INFO *info = &r_u->info;
3838 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3839 WERROR result = WERR_BADFID;
3841 /* we always have a NOTIFY_INFO struct */
3845 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3846 OUR_HANDLE(handle)));
3850 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3853 * We are now using the change value, and
3854 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3855 * I don't have a global notification system, I'm sending back all the
3856 * informations even when _NOTHING_ has changed.
3859 /* We need to keep track of the change value to send back in
3860 RRPCN replies otherwise our updates are ignored. */
3862 Printer->notify.fnpcn = True;
3864 if (Printer->notify.client_connected) {
3865 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3866 Printer->notify.change = q_u->change;
3869 /* just ignore the SPOOL_NOTIFY_OPTION */
3871 switch (Printer->printer_type) {
3873 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3876 case SPLHND_PRINTER:
3877 result = printer_notify_info(p, handle, info, p->mem_ctx);
3881 Printer->notify.fnpcn = False;
3887 /********************************************************************
3888 * construct_printer_info_0
3889 * fill a printer_info_0 struct
3890 ********************************************************************/
3892 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3896 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3897 counter_printer_0 *session_counter;
3898 uint32 global_counter;
3901 print_status_struct status;
3903 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3906 count = print_queue_length(snum, &status);
3908 /* check if we already have a counter for this printer */
3909 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3910 if (session_counter->snum == snum)
3914 /* it's the first time, add it to the list */
3915 if (session_counter==NULL) {
3916 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3917 free_a_printer(&ntprinter, 2);
3920 ZERO_STRUCTP(session_counter);
3921 session_counter->snum=snum;
3922 session_counter->counter=0;
3923 DLIST_ADD(counter_list, session_counter);
3927 session_counter->counter++;
3930 * the global_counter should be stored in a TDB as it's common to all the clients
3931 * and should be zeroed on samba startup
3933 global_counter=session_counter->counter;
3935 pstrcpy(chaine,ntprinter->info_2->printername);
3937 init_unistr(&printer->printername, chaine);
3939 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3940 init_unistr(&printer->servername, chaine);
3942 printer->cjobs = count;
3943 printer->total_jobs = 0;
3944 printer->total_bytes = 0;
3946 setuptime = (time_t)ntprinter->info_2->setuptime;
3947 t=gmtime(&setuptime);
3949 printer->year = t->tm_year+1900;
3950 printer->month = t->tm_mon+1;
3951 printer->dayofweek = t->tm_wday;
3952 printer->day = t->tm_mday;
3953 printer->hour = t->tm_hour;
3954 printer->minute = t->tm_min;
3955 printer->second = t->tm_sec;
3956 printer->milliseconds = 0;
3958 printer->global_counter = global_counter;
3959 printer->total_pages = 0;
3961 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3962 printer->major_version = 0x0005; /* NT 5 */
3963 printer->build_version = 0x0893; /* build 2195 */
3965 printer->unknown7 = 0x1;
3966 printer->unknown8 = 0x0;
3967 printer->unknown9 = 0x0;
3968 printer->session_counter = session_counter->counter;
3969 printer->unknown11 = 0x0;
3970 printer->printer_errors = 0x0; /* number of print failure */
3971 printer->unknown13 = 0x0;
3972 printer->unknown14 = 0x1;
3973 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3974 printer->unknown16 = 0x0;
3975 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3976 printer->unknown18 = 0x0;
3977 printer->status = nt_printq_status(status.status);
3978 printer->unknown20 = 0x0;
3979 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3980 printer->unknown22 = 0x0;
3981 printer->unknown23 = 0x6; /* 6 ???*/
3982 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3983 printer->unknown25 = 0;
3984 printer->unknown26 = 0;
3985 printer->unknown27 = 0;
3986 printer->unknown28 = 0;
3987 printer->unknown29 = 0;
3989 free_a_printer(&ntprinter,2);
3993 /********************************************************************
3994 * construct_printer_info_1
3995 * fill a printer_info_1 struct
3996 ********************************************************************/
3997 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4001 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4003 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4006 printer->flags=flags;
4008 if (*ntprinter->info_2->comment == '\0') {
4009 init_unistr(&printer->comment, lp_comment(snum));
4010 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4011 ntprinter->info_2->drivername, lp_comment(snum));
4014 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4015 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4016 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4019 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4021 init_unistr(&printer->description, chaine);
4022 init_unistr(&printer->name, chaine2);
4024 free_a_printer(&ntprinter,2);
4029 /****************************************************************************
4030 Free a DEVMODE struct.
4031 ****************************************************************************/
4033 static void free_dev_mode(DEVICEMODE *dev)
4038 SAFE_FREE(dev->dev_private);
4043 /****************************************************************************
4044 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4045 should be valid upon entry
4046 ****************************************************************************/
4048 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4050 if ( !devmode || !ntdevmode )
4053 init_unistr(&devmode->devicename, ntdevmode->devicename);
4055 init_unistr(&devmode->formname, ntdevmode->formname);
4057 devmode->specversion = ntdevmode->specversion;
4058 devmode->driverversion = ntdevmode->driverversion;
4059 devmode->size = ntdevmode->size;
4060 devmode->driverextra = ntdevmode->driverextra;
4061 devmode->fields = ntdevmode->fields;
4063 devmode->orientation = ntdevmode->orientation;
4064 devmode->papersize = ntdevmode->papersize;
4065 devmode->paperlength = ntdevmode->paperlength;
4066 devmode->paperwidth = ntdevmode->paperwidth;
4067 devmode->scale = ntdevmode->scale;
4068 devmode->copies = ntdevmode->copies;
4069 devmode->defaultsource = ntdevmode->defaultsource;
4070 devmode->printquality = ntdevmode->printquality;
4071 devmode->color = ntdevmode->color;
4072 devmode->duplex = ntdevmode->duplex;
4073 devmode->yresolution = ntdevmode->yresolution;
4074 devmode->ttoption = ntdevmode->ttoption;
4075 devmode->collate = ntdevmode->collate;
4076 devmode->icmmethod = ntdevmode->icmmethod;
4077 devmode->icmintent = ntdevmode->icmintent;
4078 devmode->mediatype = ntdevmode->mediatype;
4079 devmode->dithertype = ntdevmode->dithertype;
4081 if (ntdevmode->nt_dev_private != NULL) {
4082 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4089 /****************************************************************************
4090 Create a DEVMODE struct. Returns malloced memory.
4091 ****************************************************************************/
4093 DEVICEMODE *construct_dev_mode(int snum)
4095 NT_PRINTER_INFO_LEVEL *printer = NULL;
4096 DEVICEMODE *devmode = NULL;
4098 DEBUG(7,("construct_dev_mode\n"));
4100 DEBUGADD(8,("getting printer characteristics\n"));
4102 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4105 if ( !printer->info_2->devmode ) {
4106 DEBUG(5, ("BONG! There was no device mode!\n"));
4110 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4111 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4115 ZERO_STRUCTP(devmode);
4117 DEBUGADD(8,("loading DEVICEMODE\n"));
4119 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4120 free_dev_mode( devmode );
4125 free_a_printer(&printer,2);
4130 /********************************************************************
4131 * construct_printer_info_2
4132 * fill a printer_info_2 struct
4133 ********************************************************************/
4135 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4138 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4140 print_status_struct status;
4142 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4145 count = print_queue_length(snum, &status);
4147 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4148 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4149 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4150 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4151 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4153 if (*ntprinter->info_2->comment == '\0')
4154 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4156 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4158 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4159 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4160 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4161 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4162 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4164 printer->attributes = ntprinter->info_2->attributes;
4166 printer->priority = ntprinter->info_2->priority; /* priority */
4167 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4168 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4169 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4170 printer->status = nt_printq_status(status.status); /* status */
4171 printer->cjobs = count; /* jobs */
4172 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4174 if ( !(printer->devmode = construct_dev_mode(snum)) )
4175 DEBUG(8, ("Returning NULL Devicemode!\n"));
4177 printer->secdesc = NULL;
4179 if ( ntprinter->info_2->secdesc_buf
4180 && ntprinter->info_2->secdesc_buf->len != 0 )
4182 /* don't use talloc_steal() here unless you do a deep steal of all
4183 the SEC_DESC members */
4185 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4186 ntprinter->info_2->secdesc_buf->sec );
4189 free_a_printer(&ntprinter, 2);
4194 /********************************************************************
4195 * construct_printer_info_3
4196 * fill a printer_info_3 struct
4197 ********************************************************************/
4199 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4201 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4202 PRINTER_INFO_3 *printer = NULL;
4204 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4208 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4209 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4213 ZERO_STRUCTP(printer);
4215 /* These are the components of the SD we are returning. */
4217 printer->flags = 0x4;
4219 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4220 /* don't use talloc_steal() here unless you do a deep steal of all
4221 the SEC_DESC members */
4223 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4224 ntprinter->info_2->secdesc_buf->sec );
4227 free_a_printer(&ntprinter, 2);
4229 *pp_printer = printer;
4233 /********************************************************************
4234 * construct_printer_info_4
4235 * fill a printer_info_4 struct
4236 ********************************************************************/
4238 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4240 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4242 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4245 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4246 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4247 printer->attributes = ntprinter->info_2->attributes;
4249 free_a_printer(&ntprinter, 2);
4253 /********************************************************************
4254 * construct_printer_info_5
4255 * fill a printer_info_5 struct
4256 ********************************************************************/
4258 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4260 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4262 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4265 init_unistr(&printer->printername, ntprinter->info_2->printername);
4266 init_unistr(&printer->portname, ntprinter->info_2->portname);
4267 printer->attributes = ntprinter->info_2->attributes;
4269 /* these two are not used by NT+ according to MSDN */
4271 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4272 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4274 free_a_printer(&ntprinter, 2);
4279 /********************************************************************
4280 * construct_printer_info_7
4281 * fill a printer_info_7 struct
4282 ********************************************************************/
4284 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4286 char *guid_str = NULL;
4289 if (is_printer_published(print_hnd, snum, &guid)) {
4290 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4291 strupper_m(guid_str);
4292 init_unistr(&printer->guid, guid_str);
4293 printer->action = SPOOL_DS_PUBLISH;
4295 init_unistr(&printer->guid, "");
4296 printer->action = SPOOL_DS_UNPUBLISH;
4302 /********************************************************************
4303 Spoolss_enumprinters.
4304 ********************************************************************/
4306 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4310 int n_services=lp_numservices();
4311 PRINTER_INFO_1 *printers=NULL;
4312 PRINTER_INFO_1 current_prt;
4313 WERROR result = WERR_OK;
4315 DEBUG(4,("enum_all_printers_info_1\n"));
4317 for (snum=0; snum<n_services; snum++) {
4318 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4319 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4321 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4322 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4323 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4327 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4329 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4335 /* check the required size. */
4336 for (i=0; i<*returned; i++)
4337 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4339 if (*needed > offered) {
4340 result = WERR_INSUFFICIENT_BUFFER;
4344 if (!rpcbuf_alloc_size(buffer, *needed)) {
4345 result = WERR_NOMEM;
4349 /* fill the buffer with the structures */
4350 for (i=0; i<*returned; i++)
4351 smb_io_printer_info_1("", buffer, &printers[i], 0);
4356 SAFE_FREE(printers);
4358 if ( !W_ERROR_IS_OK(result) )
4364 /********************************************************************
4365 enum_all_printers_info_1_local.
4366 *********************************************************************/
4368 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4370 DEBUG(4,("enum_all_printers_info_1_local\n"));
4372 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4375 /********************************************************************
4376 enum_all_printers_info_1_name.
4377 *********************************************************************/
4379 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4383 DEBUG(4,("enum_all_printers_info_1_name\n"));
4385 if ((name[0] == '\\') && (name[1] == '\\'))
4388 if (is_myname_or_ipaddr(s)) {
4389 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4392 return WERR_INVALID_NAME;
4395 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4396 /********************************************************************
4397 enum_all_printers_info_1_remote.
4398 *********************************************************************/
4400 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4402 PRINTER_INFO_1 *printer;
4403 fstring printername;
4406 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4407 WERROR result = WERR_OK;
4409 /* JFM: currently it's more a place holder than anything else.
4410 * In the spooler world there is a notion of server registration.
4411 * the print servers are registered on the PDC (in the same domain)
4413 * We should have a TDB here. The registration is done thru an
4414 * undocumented RPC call.
4417 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4422 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4423 slprintf(desc, sizeof(desc)-1,"%s", name);
4424 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4426 init_unistr(&printer->description, desc);
4427 init_unistr(&printer->name, printername);
4428 init_unistr(&printer->comment, comment);
4429 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4431 /* check the required size. */
4432 *needed += spoolss_size_printer_info_1(printer);
4434 if (*needed > offered) {
4435 result = WERR_INSUFFICIENT_BUFFER;
4439 if (!rpcbuf_alloc_size(buffer, *needed)) {
4440 result = WERR_NOMEM;
4444 /* fill the buffer with the structures */
4445 smb_io_printer_info_1("", buffer, printer, 0);
4451 if ( !W_ERROR_IS_OK(result) )
4459 /********************************************************************
4460 enum_all_printers_info_1_network.
4461 *********************************************************************/
4463 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4467 DEBUG(4,("enum_all_printers_info_1_network\n"));
4469 /* If we respond to a enum_printers level 1 on our name with flags
4470 set to PRINTER_ENUM_REMOTE with a list of printers then these
4471 printers incorrectly appear in the APW browse list.
4472 Specifically the printers for the server appear at the workgroup
4473 level where all the other servers in the domain are
4474 listed. Windows responds to this call with a
4475 WERR_CAN_NOT_COMPLETE so we should do the same. */
4477 if (name[0] == '\\' && name[1] == '\\')
4480 if (is_myname_or_ipaddr(s))
4481 return WERR_CAN_NOT_COMPLETE;
4483 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4486 /********************************************************************
4487 * api_spoolss_enumprinters
4489 * called from api_spoolss_enumprinters (see this to understand)
4490 ********************************************************************/
4492 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4496 int n_services=lp_numservices();
4497 PRINTER_INFO_2 *printers=NULL;
4498 PRINTER_INFO_2 current_prt;
4499 WERROR result = WERR_OK;
4503 for (snum=0; snum<n_services; snum++) {
4504 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4505 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4507 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4508 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4509 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4514 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4516 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4523 /* check the required size. */
4524 for (i=0; i<*returned; i++)
4525 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4527 if (*needed > offered) {
4528 result = WERR_INSUFFICIENT_BUFFER;
4532 if (!rpcbuf_alloc_size(buffer, *needed)) {
4533 result = WERR_NOMEM;
4537 /* fill the buffer with the structures */
4538 for (i=0; i<*returned; i++)
4539 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4544 for (i=0; i<*returned; i++)
4545 free_devmode(printers[i].devmode);
4547 SAFE_FREE(printers);
4549 if ( !W_ERROR_IS_OK(result) )
4555 /********************************************************************
4556 * handle enumeration of printers at level 1
4557 ********************************************************************/
4559 static WERROR enumprinters_level1( uint32 flags, fstring name,
4560 RPC_BUFFER *buffer, uint32 offered,
4561 uint32 *needed, uint32 *returned)
4563 /* Not all the flags are equals */
4565 if (flags & PRINTER_ENUM_LOCAL)
4566 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4568 if (flags & PRINTER_ENUM_NAME)
4569 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4571 #if 0 /* JERRY - disabled for now */
4572 if (flags & PRINTER_ENUM_REMOTE)
4573 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4576 if (flags & PRINTER_ENUM_NETWORK)
4577 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4579 return WERR_OK; /* NT4sp5 does that */
4582 /********************************************************************
4583 * handle enumeration of printers at level 2
4584 ********************************************************************/
4586 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4587 RPC_BUFFER *buffer, uint32 offered,
4588 uint32 *needed, uint32 *returned)
4590 char *s = servername;
4592 if (flags & PRINTER_ENUM_LOCAL) {
4593 return enum_all_printers_info_2(buffer, offered, needed, returned);
4596 if (flags & PRINTER_ENUM_NAME) {
4597 if ((servername[0] == '\\') && (servername[1] == '\\'))
4599 if (is_myname_or_ipaddr(s))
4600 return enum_all_printers_info_2(buffer, offered, needed, returned);
4602 return WERR_INVALID_NAME;
4605 if (flags & PRINTER_ENUM_REMOTE)
4606 return WERR_UNKNOWN_LEVEL;
4611 /********************************************************************
4612 * handle enumeration of printers at level 5
4613 ********************************************************************/
4615 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4616 RPC_BUFFER *buffer, uint32 offered,
4617 uint32 *needed, uint32 *returned)
4619 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4623 /********************************************************************
4624 * api_spoolss_enumprinters
4626 * called from api_spoolss_enumprinters (see this to understand)
4627 ********************************************************************/
4629 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4631 uint32 flags = q_u->flags;
4632 UNISTR2 *servername = &q_u->servername;
4633 uint32 level = q_u->level;
4634 RPC_BUFFER *buffer = NULL;
4635 uint32 offered = q_u->offered;
4636 uint32 *needed = &r_u->needed;
4637 uint32 *returned = &r_u->returned;
4641 /* that's an [in out] buffer */
4643 if (!q_u->buffer && (offered!=0)) {
4644 return WERR_INVALID_PARAM;
4647 rpcbuf_move(q_u->buffer, &r_u->buffer);
4648 buffer = r_u->buffer;
4650 DEBUG(4,("_spoolss_enumprinters\n"));
4657 * flags==PRINTER_ENUM_NAME
4658 * if name=="" then enumerates all printers
4659 * if name!="" then enumerate the printer
4660 * flags==PRINTER_ENUM_REMOTE
4661 * name is NULL, enumerate printers
4662 * Level 2: name!="" enumerates printers, name can't be NULL
4663 * Level 3: doesn't exist
4664 * Level 4: does a local registry lookup
4665 * Level 5: same as Level 2
4668 unistr2_to_ascii(name, servername, sizeof(name)-1);
4673 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4675 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4677 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4682 return WERR_UNKNOWN_LEVEL;
4685 /****************************************************************************
4686 ****************************************************************************/
4688 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4690 PRINTER_INFO_0 *printer=NULL;
4691 WERROR result = WERR_OK;
4693 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4696 construct_printer_info_0(print_hnd, printer, snum);
4698 /* check the required size. */
4699 *needed += spoolss_size_printer_info_0(printer);
4701 if (*needed > offered) {
4702 result = WERR_INSUFFICIENT_BUFFER;
4706 if (!rpcbuf_alloc_size(buffer, *needed)) {
4707 result = WERR_NOMEM;
4711 /* fill the buffer with the structures */
4712 smb_io_printer_info_0("", buffer, printer, 0);
4722 /****************************************************************************
4723 ****************************************************************************/
4725 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4727 PRINTER_INFO_1 *printer=NULL;
4728 WERROR result = WERR_OK;
4730 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4733 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4735 /* check the required size. */
4736 *needed += spoolss_size_printer_info_1(printer);
4738 if (*needed > offered) {
4739 result = WERR_INSUFFICIENT_BUFFER;
4743 if (!rpcbuf_alloc_size(buffer, *needed)) {
4744 result = WERR_NOMEM;
4748 /* fill the buffer with the structures */
4749 smb_io_printer_info_1("", buffer, printer, 0);
4758 /****************************************************************************
4759 ****************************************************************************/
4761 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4763 PRINTER_INFO_2 *printer=NULL;
4764 WERROR result = WERR_OK;
4766 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4769 construct_printer_info_2(print_hnd, printer, snum);
4771 /* check the required size. */
4772 *needed += spoolss_size_printer_info_2(printer);
4774 if (*needed > offered) {
4775 result = WERR_INSUFFICIENT_BUFFER;
4779 if (!rpcbuf_alloc_size(buffer, *needed)) {
4780 result = WERR_NOMEM;
4784 /* fill the buffer with the structures */
4785 if (!smb_io_printer_info_2("", buffer, printer, 0))
4786 result = WERR_NOMEM;
4790 free_printer_info_2(printer);
4795 /****************************************************************************
4796 ****************************************************************************/
4798 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4800 PRINTER_INFO_3 *printer=NULL;
4801 WERROR result = WERR_OK;
4803 if (!construct_printer_info_3(print_hnd, &printer, snum))
4806 /* check the required size. */
4807 *needed += spoolss_size_printer_info_3(printer);
4809 if (*needed > offered) {
4810 result = WERR_INSUFFICIENT_BUFFER;
4814 if (!rpcbuf_alloc_size(buffer, *needed)) {
4815 result = WERR_NOMEM;
4819 /* fill the buffer with the structures */
4820 smb_io_printer_info_3("", buffer, printer, 0);
4824 free_printer_info_3(printer);
4829 /****************************************************************************
4830 ****************************************************************************/
4832 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4834 PRINTER_INFO_4 *printer=NULL;
4835 WERROR result = WERR_OK;
4837 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4840 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4845 /* check the required size. */
4846 *needed += spoolss_size_printer_info_4(printer);
4848 if (*needed > offered) {
4849 result = WERR_INSUFFICIENT_BUFFER;
4853 if (!rpcbuf_alloc_size(buffer, *needed)) {
4854 result = WERR_NOMEM;
4858 /* fill the buffer with the structures */
4859 smb_io_printer_info_4("", buffer, printer, 0);
4863 free_printer_info_4(printer);
4868 /****************************************************************************
4869 ****************************************************************************/
4871 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4873 PRINTER_INFO_5 *printer=NULL;
4874 WERROR result = WERR_OK;
4876 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4879 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4880 free_printer_info_5(printer);
4884 /* check the required size. */
4885 *needed += spoolss_size_printer_info_5(printer);
4887 if (*needed > offered) {
4888 result = WERR_INSUFFICIENT_BUFFER;
4892 if (!rpcbuf_alloc_size(buffer, *needed)) {
4893 result = WERR_NOMEM;
4897 /* fill the buffer with the structures */
4898 smb_io_printer_info_5("", buffer, printer, 0);
4902 free_printer_info_5(printer);
4907 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4909 PRINTER_INFO_7 *printer=NULL;
4910 WERROR result = WERR_OK;
4912 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4915 if (!construct_printer_info_7(print_hnd, printer, snum))
4918 /* check the required size. */
4919 *needed += spoolss_size_printer_info_7(printer);
4921 if (*needed > offered) {
4922 result = WERR_INSUFFICIENT_BUFFER;
4926 if (!rpcbuf_alloc_size(buffer, *needed)) {
4927 result = WERR_NOMEM;
4932 /* fill the buffer with the structures */
4933 smb_io_printer_info_7("", buffer, printer, 0);
4937 free_printer_info_7(printer);
4942 /****************************************************************************
4943 ****************************************************************************/
4945 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4947 POLICY_HND *handle = &q_u->handle;
4948 uint32 level = q_u->level;
4949 RPC_BUFFER *buffer = NULL;
4950 uint32 offered = q_u->offered;
4951 uint32 *needed = &r_u->needed;
4952 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4956 /* that's an [in out] buffer */
4958 if (!q_u->buffer && (offered!=0)) {
4959 return WERR_INVALID_PARAM;
4962 rpcbuf_move(q_u->buffer, &r_u->buffer);
4963 buffer = r_u->buffer;
4967 if (!get_printer_snum(p, handle, &snum))
4972 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4974 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4976 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4978 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4980 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4982 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4984 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4986 return WERR_UNKNOWN_LEVEL;
4989 /********************************************************************
4990 * fill a DRIVER_INFO_1 struct
4991 ********************************************************************/
4993 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4995 init_unistr( &info->name, driver.info_3->name);
4998 /********************************************************************
4999 * construct_printer_driver_info_1
5000 ********************************************************************/
5002 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5004 NT_PRINTER_INFO_LEVEL *printer = NULL;
5005 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5007 ZERO_STRUCT(driver);
5009 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5010 return WERR_INVALID_PRINTER_NAME;
5012 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5013 return WERR_UNKNOWN_PRINTER_DRIVER;
5015 fill_printer_driver_info_1(info, driver, servername, architecture);
5017 free_a_printer(&printer,2);
5022 /********************************************************************
5023 * construct_printer_driver_info_2
5024 * fill a printer_info_2 struct
5025 ********************************************************************/
5027 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5031 info->version=driver.info_3->cversion;
5033 init_unistr( &info->name, driver.info_3->name );
5034 init_unistr( &info->architecture, driver.info_3->environment );
5037 if (strlen(driver.info_3->driverpath)) {
5038 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5039 init_unistr( &info->driverpath, temp );
5041 init_unistr( &info->driverpath, "" );
5043 if (strlen(driver.info_3->datafile)) {
5044 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5045 init_unistr( &info->datafile, temp );
5047 init_unistr( &info->datafile, "" );
5049 if (strlen(driver.info_3->configfile)) {
5050 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5051 init_unistr( &info->configfile, temp );
5053 init_unistr( &info->configfile, "" );
5056 /********************************************************************
5057 * construct_printer_driver_info_2
5058 * fill a printer_info_2 struct
5059 ********************************************************************/
5061 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5063 NT_PRINTER_INFO_LEVEL *printer = NULL;
5064 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5066 ZERO_STRUCT(printer);
5067 ZERO_STRUCT(driver);
5069 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5070 return WERR_INVALID_PRINTER_NAME;
5072 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5073 return WERR_UNKNOWN_PRINTER_DRIVER;
5075 fill_printer_driver_info_2(info, driver, servername);
5077 free_a_printer(&printer,2);
5082 /********************************************************************
5083 * copy a strings array and convert to UNICODE
5085 * convert an array of ascii string to a UNICODE string
5086 ********************************************************************/
5088 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5095 DEBUG(6,("init_unistr_array\n"));
5106 v = ""; /* hack to handle null lists */
5109 /* hack to allow this to be used in places other than when generating
5110 the list of dependent files */
5113 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5117 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5119 /* add one extra unit16 for the second terminating NULL */
5121 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5122 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5129 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5134 /* special case for ""; we need to add both NULL's here */
5136 (*uni_array)[j++]=0x0000;
5137 (*uni_array)[j]=0x0000;
5140 DEBUGADD(6,("last one:done\n"));
5142 /* return size of array in uint16's */
5147 /********************************************************************
5148 * construct_printer_info_3
5149 * fill a printer_info_3 struct
5150 ********************************************************************/
5152 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5158 info->version=driver.info_3->cversion;
5160 init_unistr( &info->name, driver.info_3->name );
5161 init_unistr( &info->architecture, driver.info_3->environment );
5163 if (strlen(driver.info_3->driverpath)) {
5164 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5165 init_unistr( &info->driverpath, temp );
5167 init_unistr( &info->driverpath, "" );
5169 if (strlen(driver.info_3->datafile)) {
5170 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5171 init_unistr( &info->datafile, temp );
5173 init_unistr( &info->datafile, "" );
5175 if (strlen(driver.info_3->configfile)) {
5176 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5177 init_unistr( &info->configfile, temp );
5179 init_unistr( &info->configfile, "" );
5181 if (strlen(driver.info_3->helpfile)) {
5182 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5183 init_unistr( &info->helpfile, temp );
5185 init_unistr( &info->helpfile, "" );
5187 init_unistr( &info->monitorname, driver.info_3->monitorname );
5188 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5190 info->dependentfiles=NULL;
5191 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5194 /********************************************************************
5195 * construct_printer_info_3
5196 * fill a printer_info_3 struct
5197 ********************************************************************/
5199 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5201 NT_PRINTER_INFO_LEVEL *printer = NULL;
5202 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5204 ZERO_STRUCT(driver);
5206 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5207 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5208 if (!W_ERROR_IS_OK(status))
5209 return WERR_INVALID_PRINTER_NAME;
5211 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5212 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5217 * I put this code in during testing. Helpful when commenting out the
5218 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5219 * as win2k always queries the driver using an infor level of 6.
5220 * I've left it in (but ifdef'd out) because I'll probably
5221 * use it in experimentation again in the future. --jerry 22/01/2002
5224 if (!W_ERROR_IS_OK(status)) {
5226 * Is this a W2k client ?
5229 /* Yes - try again with a WinNT driver. */
5231 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5232 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5236 if (!W_ERROR_IS_OK(status)) {
5237 free_a_printer(&printer,2);
5238 return WERR_UNKNOWN_PRINTER_DRIVER;
5246 fill_printer_driver_info_3(info, driver, servername);
5248 free_a_printer(&printer,2);
5253 /********************************************************************
5254 * construct_printer_info_6
5255 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5256 ********************************************************************/
5258 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5264 memset(&nullstr, '\0', sizeof(fstring));
5266 info->version=driver.info_3->cversion;
5268 init_unistr( &info->name, driver.info_3->name );
5269 init_unistr( &info->architecture, driver.info_3->environment );
5271 if (strlen(driver.info_3->driverpath)) {
5272 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5273 init_unistr( &info->driverpath, temp );
5275 init_unistr( &info->driverpath, "" );
5277 if (strlen(driver.info_3->datafile)) {
5278 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5279 init_unistr( &info->datafile, temp );
5281 init_unistr( &info->datafile, "" );
5283 if (strlen(driver.info_3->configfile)) {
5284 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5285 init_unistr( &info->configfile, temp );
5287 init_unistr( &info->configfile, "" );
5289 if (strlen(driver.info_3->helpfile)) {
5290 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5291 init_unistr( &info->helpfile, temp );
5293 init_unistr( &info->helpfile, "" );
5295 init_unistr( &info->monitorname, driver.info_3->monitorname );
5296 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5298 info->dependentfiles = NULL;
5299 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5301 info->previousdrivernames=NULL;
5302 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5304 info->driver_date.low=0;
5305 info->driver_date.high=0;
5308 info->driver_version_low=0;
5309 info->driver_version_high=0;
5311 init_unistr( &info->mfgname, "");
5312 init_unistr( &info->oem_url, "");
5313 init_unistr( &info->hardware_id, "");
5314 init_unistr( &info->provider, "");
5317 /********************************************************************
5318 * construct_printer_info_6
5319 * fill a printer_info_6 struct
5320 ********************************************************************/
5322 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5323 fstring servername, fstring architecture, uint32 version)
5325 NT_PRINTER_INFO_LEVEL *printer = NULL;
5326 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5329 ZERO_STRUCT(driver);
5331 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5333 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5335 if (!W_ERROR_IS_OK(status))
5336 return WERR_INVALID_PRINTER_NAME;
5338 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5340 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5342 if (!W_ERROR_IS_OK(status))
5345 * Is this a W2k client ?
5349 free_a_printer(&printer,2);
5350 return WERR_UNKNOWN_PRINTER_DRIVER;
5353 /* Yes - try again with a WinNT driver. */
5355 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5356 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5357 if (!W_ERROR_IS_OK(status)) {
5358 free_a_printer(&printer,2);
5359 return WERR_UNKNOWN_PRINTER_DRIVER;
5363 fill_printer_driver_info_6(info, driver, servername);
5365 free_a_printer(&printer,2);
5366 free_a_printer_driver(driver, 3);
5371 /****************************************************************************
5372 ****************************************************************************/
5374 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5376 SAFE_FREE(info->dependentfiles);
5379 /****************************************************************************
5380 ****************************************************************************/
5382 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5384 SAFE_FREE(info->dependentfiles);
5387 /****************************************************************************
5388 ****************************************************************************/
5390 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5392 DRIVER_INFO_1 *info=NULL;
5395 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5398 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5399 if (!W_ERROR_IS_OK(result))
5402 /* check the required size. */
5403 *needed += spoolss_size_printer_driver_info_1(info);
5405 if (*needed > offered) {
5406 result = WERR_INSUFFICIENT_BUFFER;
5410 if (!rpcbuf_alloc_size(buffer, *needed)) {
5411 result = WERR_NOMEM;
5415 /* fill the buffer with the structures */
5416 smb_io_printer_driver_info_1("", buffer, info, 0);
5425 /****************************************************************************
5426 ****************************************************************************/
5428 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5430 DRIVER_INFO_2 *info=NULL;
5433 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5436 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5437 if (!W_ERROR_IS_OK(result))
5440 /* check the required size. */
5441 *needed += spoolss_size_printer_driver_info_2(info);
5443 if (*needed > offered) {
5444 result = WERR_INSUFFICIENT_BUFFER;
5448 if (!rpcbuf_alloc_size(buffer, *needed)) {
5449 result = WERR_NOMEM;
5453 /* fill the buffer with the structures */
5454 smb_io_printer_driver_info_2("", buffer, info, 0);
5463 /****************************************************************************
5464 ****************************************************************************/
5466 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5473 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5474 if (!W_ERROR_IS_OK(result))
5477 /* check the required size. */
5478 *needed += spoolss_size_printer_driver_info_3(&info);
5480 if (*needed > offered) {
5481 result = WERR_INSUFFICIENT_BUFFER;
5485 if (!rpcbuf_alloc_size(buffer, *needed)) {
5486 result = WERR_NOMEM;
5490 /* fill the buffer with the structures */
5491 smb_io_printer_driver_info_3("", buffer, &info, 0);
5494 free_printer_driver_info_3(&info);
5499 /****************************************************************************
5500 ****************************************************************************/
5502 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5509 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5510 if (!W_ERROR_IS_OK(result))
5513 /* check the required size. */
5514 *needed += spoolss_size_printer_driver_info_6(&info);
5516 if (*needed > offered) {
5517 result = WERR_INSUFFICIENT_BUFFER;
5521 if (!rpcbuf_alloc_size(buffer, *needed)) {
5522 result = WERR_NOMEM;
5526 /* fill the buffer with the structures */
5527 smb_io_printer_driver_info_6("", buffer, &info, 0);
5530 free_printer_driver_info_6(&info);
5535 /****************************************************************************
5536 ****************************************************************************/
5538 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5540 POLICY_HND *handle = &q_u->handle;
5541 UNISTR2 *uni_arch = &q_u->architecture;
5542 uint32 level = q_u->level;
5543 uint32 clientmajorversion = q_u->clientmajorversion;
5544 RPC_BUFFER *buffer = NULL;
5545 uint32 offered = q_u->offered;
5546 uint32 *needed = &r_u->needed;
5547 uint32 *servermajorversion = &r_u->servermajorversion;
5548 uint32 *serverminorversion = &r_u->serverminorversion;
5549 Printer_entry *printer;
5552 fstring architecture;
5555 /* that's an [in out] buffer */
5557 if (!q_u->buffer && (offered!=0)) {
5558 return WERR_INVALID_PARAM;
5561 rpcbuf_move(q_u->buffer, &r_u->buffer);
5562 buffer = r_u->buffer;
5564 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5566 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5567 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5568 return WERR_INVALID_PRINTER_NAME;
5572 *servermajorversion = 0;
5573 *serverminorversion = 0;
5575 fstrcpy(servername, get_server_name( printer ));
5576 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5578 if (!get_printer_snum(p, handle, &snum))
5583 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5585 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5587 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5589 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5592 /* apparently this call is the equivalent of
5593 EnumPrinterDataEx() for the DsDriver key */
5598 return WERR_UNKNOWN_LEVEL;
5601 /****************************************************************************
5602 ****************************************************************************/
5604 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5606 POLICY_HND *handle = &q_u->handle;
5608 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5611 DEBUG(3,("Error in startpageprinter printer handle\n"));
5615 Printer->page_started=True;
5619 /****************************************************************************
5620 ****************************************************************************/
5622 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5624 POLICY_HND *handle = &q_u->handle;
5627 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5630 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5634 if (!get_printer_snum(p, handle, &snum))
5637 Printer->page_started=False;
5638 print_job_endpage(snum, Printer->jobid);
5643 /********************************************************************
5644 * api_spoolss_getprinter
5645 * called from the spoolss dispatcher
5647 ********************************************************************/
5649 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5651 POLICY_HND *handle = &q_u->handle;
5652 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5653 uint32 *jobid = &r_u->jobid;
5655 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5659 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5660 struct current_user user;
5663 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5667 get_current_user(&user, p);
5670 * a nice thing with NT is it doesn't listen to what you tell it.
5671 * when asked to send _only_ RAW datas, it tries to send datas
5674 * So I add checks like in NT Server ...
5677 if (info_1->p_datatype != 0) {
5678 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5679 if (strcmp(datatype, "RAW") != 0) {
5681 return WERR_INVALID_DATATYPE;
5685 /* get the share number of the printer */
5686 if (!get_printer_snum(p, handle, &snum)) {
5690 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5692 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5694 /* An error occured in print_job_start() so return an appropriate
5697 if (Printer->jobid == -1) {
5698 return map_werror_from_unix(errno);
5701 Printer->document_started=True;
5702 (*jobid) = Printer->jobid;
5707 /********************************************************************
5708 * api_spoolss_getprinter
5709 * called from the spoolss dispatcher
5711 ********************************************************************/
5713 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5715 POLICY_HND *handle = &q_u->handle;
5717 return _spoolss_enddocprinter_internal(p, handle);
5720 /****************************************************************************
5721 ****************************************************************************/
5723 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5725 POLICY_HND *handle = &q_u->handle;
5726 uint32 buffer_size = q_u->buffer_size;
5727 uint8 *buffer = q_u->buffer;
5728 uint32 *buffer_written = &q_u->buffer_size2;
5730 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5733 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5734 r_u->buffer_written = q_u->buffer_size2;
5738 if (!get_printer_snum(p, handle, &snum))
5741 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5742 (SMB_OFF_T)-1, (size_t)buffer_size);
5743 if (*buffer_written == (uint32)-1) {
5744 r_u->buffer_written = 0;
5745 if (errno == ENOSPC)
5746 return WERR_NO_SPOOL_SPACE;
5748 return WERR_ACCESS_DENIED;
5751 r_u->buffer_written = q_u->buffer_size2;
5756 /********************************************************************
5757 * api_spoolss_getprinter
5758 * called from the spoolss dispatcher
5760 ********************************************************************/
5762 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5765 struct current_user user;
5767 WERROR errcode = WERR_BADFUNC;
5768 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5770 get_current_user(&user, p);
5773 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5777 if (!get_printer_snum(p, handle, &snum))
5781 case PRINTER_CONTROL_PAUSE:
5782 if (print_queue_pause(&user, snum, &errcode)) {
5786 case PRINTER_CONTROL_RESUME:
5787 case PRINTER_CONTROL_UNPAUSE:
5788 if (print_queue_resume(&user, snum, &errcode)) {
5792 case PRINTER_CONTROL_PURGE:
5793 if (print_queue_purge(&user, snum, &errcode)) {
5798 return WERR_UNKNOWN_LEVEL;
5804 /********************************************************************
5805 * api_spoolss_abortprinter
5806 * From MSDN: "Deletes printer's spool file if printer is configured
5808 ********************************************************************/
5810 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5812 POLICY_HND *handle = &q_u->handle;
5813 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5815 struct current_user user;
5816 WERROR errcode = WERR_OK;
5819 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5823 if (!get_printer_snum(p, handle, &snum))
5826 get_current_user( &user, p );
5828 print_job_delete( &user, snum, Printer->jobid, &errcode );
5833 /********************************************************************
5834 * called by spoolss_api_setprinter
5835 * when updating a printer description
5836 ********************************************************************/
5838 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5839 const SPOOL_PRINTER_INFO_LEVEL *info,
5840 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5842 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5846 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5848 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5849 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5850 OUR_HANDLE(handle)));
5852 result = WERR_BADFID;
5856 /* Check the user has permissions to change the security
5857 descriptor. By experimentation with two NT machines, the user
5858 requires Full Access to the printer to change security
5861 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5862 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5863 result = WERR_ACCESS_DENIED;
5867 /* NT seems to like setting the security descriptor even though
5868 nothing may have actually changed. */
5870 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5872 if (DEBUGLEVEL >= 10) {
5876 the_acl = old_secdesc_ctr->sec->dacl;
5877 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5878 PRINTERNAME(snum), the_acl->num_aces));
5880 for (i = 0; i < the_acl->num_aces; i++) {
5883 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5885 DEBUG(10, ("%s 0x%08x\n", sid_str,
5886 the_acl->ace[i].info.mask));
5889 the_acl = secdesc_ctr->sec->dacl;
5892 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5893 PRINTERNAME(snum), the_acl->num_aces));
5895 for (i = 0; i < the_acl->num_aces; i++) {
5898 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5900 DEBUG(10, ("%s 0x%08x\n", sid_str,
5901 the_acl->ace[i].info.mask));
5904 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5908 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5909 if (!new_secdesc_ctr) {
5910 result = WERR_NOMEM;
5914 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5919 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5926 /********************************************************************
5927 Canonicalize printer info from a client
5929 ATTN: It does not matter what we set the servername to hear
5930 since we do the necessary work in get_a_printer() to set it to
5931 the correct value based on what the client sent in the
5932 _spoolss_open_printer_ex().
5933 ********************************************************************/
5935 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5937 fstring printername;
5940 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5941 "portname=%s drivername=%s comment=%s location=%s\n",
5942 info->servername, info->printername, info->sharename,
5943 info->portname, info->drivername, info->comment, info->location));
5945 /* we force some elements to "correct" values */
5946 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5947 fstrcpy(info->sharename, lp_servicename(snum));
5949 /* check to see if we allow printername != sharename */
5951 if ( lp_force_printername(snum) ) {
5952 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5953 global_myname(), info->sharename );
5956 /* make sure printername is in \\server\printername format */
5958 fstrcpy( printername, info->printername );
5960 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5961 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5965 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5966 global_myname(), p );
5969 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5970 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5977 /****************************************************************************
5978 ****************************************************************************/
5980 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
5982 char *cmd = lp_addport_cmd();
5986 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5987 BOOL is_print_op = False;
5990 return WERR_ACCESS_DENIED;
5993 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
5996 is_print_op = user_has_privileges( token, &se_printop );
5998 DEBUG(10,("Running [%s]\n", command));
6000 /********* BEGIN SePrintOperatorPrivilege **********/
6005 ret = smbrun(command, &fd);
6010 /********* END SePrintOperatorPrivilege **********/
6012 DEBUGADD(10,("returned [%d]\n", ret));
6017 return WERR_ACCESS_DENIED;
6023 /****************************************************************************
6024 ****************************************************************************/
6026 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6028 char *cmd = lp_addprinter_cmd();
6034 fstring remote_machine = "%m";
6035 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6036 BOOL is_print_op = False;
6038 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6040 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6041 cmd, printer->info_2->printername, printer->info_2->sharename,
6042 printer->info_2->portname, printer->info_2->drivername,
6043 printer->info_2->location, printer->info_2->comment, remote_machine);
6046 is_print_op = user_has_privileges( token, &se_printop );
6048 DEBUG(10,("Running [%s]\n", command));
6050 /********* BEGIN SePrintOperatorPrivilege **********/
6055 if ( (ret = smbrun(command, &fd)) == 0 ) {
6056 /* Tell everyone we updated smb.conf. */
6057 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6063 /********* END SePrintOperatorPrivilege **********/
6065 DEBUGADD(10,("returned [%d]\n", ret));
6073 /* reload our services immediately */
6074 reload_services( False );
6077 /* Get lines and convert them back to dos-codepage */
6078 qlines = fd_lines_load(fd, &numlines, 0);
6079 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6082 /* Set the portname to what the script says the portname should be. */
6083 /* but don't require anything to be return from the script exit a good error code */
6086 /* Set the portname to what the script says the portname should be. */
6087 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6088 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6091 file_lines_free(qlines);
6096 /********************************************************************
6097 * Called by spoolss_api_setprinter
6098 * when updating a printer description.
6099 ********************************************************************/
6101 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6102 const SPOOL_PRINTER_INFO_LEVEL *info,
6103 DEVICEMODE *devmode)
6106 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6107 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6112 DEBUG(8,("update_printer\n"));
6117 result = WERR_BADFID;
6121 if (!get_printer_snum(p, handle, &snum)) {
6122 result = WERR_BADFID;
6126 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6127 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6128 result = WERR_BADFID;
6132 DEBUGADD(8,("Converting info_2 struct\n"));
6135 * convert_printer_info converts the incoming
6136 * info from the client and overwrites the info
6137 * just read from the tdb in the pointer 'printer'.
6140 if (!convert_printer_info(info, printer, level)) {
6141 result = WERR_NOMEM;
6146 /* we have a valid devmode
6147 convert it and link it*/
6149 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6150 if (!convert_devicemode(printer->info_2->printername, devmode,
6151 &printer->info_2->devmode)) {
6152 result = WERR_NOMEM;
6157 /* Do sanity check on the requested changes for Samba */
6159 if (!check_printer_ok(printer->info_2, snum)) {
6160 result = WERR_INVALID_PARAM;
6164 /* FIXME!!! If the driver has changed we really should verify that
6165 it is installed before doing much else --jerry */
6167 /* Check calling user has permission to update printer description */
6169 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6170 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6171 result = WERR_ACCESS_DENIED;
6175 /* Call addprinter hook */
6176 /* Check changes to see if this is really needed */
6178 if ( *lp_addprinter_cmd()
6179 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6180 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6181 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6182 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6184 /* add_printer_hook() will call reload_services() */
6186 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6187 result = WERR_ACCESS_DENIED;
6193 * When a *new* driver is bound to a printer, the drivername is used to
6194 * lookup previously saved driver initialization info, which is then
6195 * bound to the printer, simulating what happens in the Windows arch.
6197 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6199 if (!set_driver_init(printer, 2))
6201 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6202 printer->info_2->drivername));
6205 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6206 printer->info_2->drivername));
6208 notify_printer_driver(snum, printer->info_2->drivername);
6212 * flag which changes actually occured. This is a small subset of
6213 * all the possible changes. We also have to update things in the
6217 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6218 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6219 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6220 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6222 notify_printer_comment(snum, printer->info_2->comment);
6225 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6226 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6227 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6228 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6230 notify_printer_sharename(snum, printer->info_2->sharename);
6233 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6236 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6239 pname = printer->info_2->printername;
6242 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6243 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6244 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6246 notify_printer_printername( snum, pname );
6249 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6250 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6251 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6252 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6254 notify_printer_port(snum, printer->info_2->portname);
6257 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6258 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6259 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6260 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6262 notify_printer_location(snum, printer->info_2->location);
6265 /* here we need to update some more DsSpooler keys */
6266 /* uNCName, serverName, shortServerName */
6268 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6269 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6270 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6271 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6272 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6274 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6275 global_myname(), printer->info_2->sharename );
6276 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6277 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6278 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6280 /* Update printer info */
6281 result = mod_a_printer(printer, 2);
6284 free_a_printer(&printer, 2);
6285 free_a_printer(&old_printer, 2);
6291 /****************************************************************************
6292 ****************************************************************************/
6293 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6294 const SPOOL_PRINTER_INFO_LEVEL *info)
6297 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6299 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6301 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6306 if (!get_printer_snum(p, handle, &snum))
6309 nt_printer_publish(Printer, snum, info7->action);
6313 return WERR_UNKNOWN_LEVEL;
6316 /****************************************************************************
6317 ****************************************************************************/
6319 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6321 POLICY_HND *handle = &q_u->handle;
6322 uint32 level = q_u->level;
6323 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6324 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6325 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6326 uint32 command = q_u->command;
6329 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6332 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6336 /* check the level */
6339 return control_printer(handle, command, p);
6341 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6342 if (!W_ERROR_IS_OK(result))
6345 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6348 return update_printer_sec(handle, level, info, p,
6351 return publish_or_unpublish_printer(p, handle, info);
6353 return WERR_UNKNOWN_LEVEL;
6357 /****************************************************************************
6358 ****************************************************************************/
6360 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6362 POLICY_HND *handle = &q_u->handle;
6363 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6366 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6370 if (Printer->notify.client_connected==True) {
6373 if ( Printer->printer_type == SPLHND_SERVER)
6375 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6376 !get_printer_snum(p, handle, &snum) )
6379 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6382 Printer->notify.flags=0;
6383 Printer->notify.options=0;
6384 Printer->notify.localmachine[0]='\0';
6385 Printer->notify.printerlocal=0;
6386 if (Printer->notify.option)
6387 free_spool_notify_option(&Printer->notify.option);
6388 Printer->notify.client_connected=False;
6393 /****************************************************************************
6394 ****************************************************************************/
6396 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6398 /* that's an [in out] buffer */
6400 if (!q_u->buffer && (q_u->offered!=0)) {
6401 return WERR_INVALID_PARAM;
6404 rpcbuf_move(q_u->buffer, &r_u->buffer);
6407 return WERR_INVALID_PARAM; /* this is what a NT server
6408 returns for AddJob. AddJob
6409 must fail on non-local
6413 /****************************************************************************
6414 ****************************************************************************/
6416 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6417 int position, int snum,
6418 NT_PRINTER_INFO_LEVEL *ntprinter)
6422 t=gmtime(&queue->time);
6424 job_info->jobid=queue->job;
6425 init_unistr(&job_info->printername, lp_servicename(snum));
6426 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6427 init_unistr(&job_info->username, queue->fs_user);
6428 init_unistr(&job_info->document, queue->fs_file);
6429 init_unistr(&job_info->datatype, "RAW");
6430 init_unistr(&job_info->text_status, "");
6431 job_info->status=nt_printj_status(queue->status);
6432 job_info->priority=queue->priority;
6433 job_info->position=position;
6434 job_info->totalpages=queue->page_count;
6435 job_info->pagesprinted=0;
6437 make_systemtime(&job_info->submitted, t);
6440 /****************************************************************************
6441 ****************************************************************************/
6443 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6444 int position, int snum,
6445 NT_PRINTER_INFO_LEVEL *ntprinter,
6446 DEVICEMODE *devmode)
6450 t=gmtime(&queue->time);
6452 job_info->jobid=queue->job;
6454 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6456 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6457 init_unistr(&job_info->username, queue->fs_user);
6458 init_unistr(&job_info->document, queue->fs_file);
6459 init_unistr(&job_info->notifyname, queue->fs_user);
6460 init_unistr(&job_info->datatype, "RAW");
6461 init_unistr(&job_info->printprocessor, "winprint");
6462 init_unistr(&job_info->parameters, "");
6463 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6464 init_unistr(&job_info->text_status, "");
6466 /* and here the security descriptor */
6468 job_info->status=nt_printj_status(queue->status);
6469 job_info->priority=queue->priority;
6470 job_info->position=position;
6471 job_info->starttime=0;
6472 job_info->untiltime=0;
6473 job_info->totalpages=queue->page_count;
6474 job_info->size=queue->size;
6475 make_systemtime(&(job_info->submitted), t);
6476 job_info->timeelapsed=0;
6477 job_info->pagesprinted=0;
6479 job_info->devmode = devmode;
6484 /****************************************************************************
6485 Enumjobs at level 1.
6486 ****************************************************************************/
6488 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6489 NT_PRINTER_INFO_LEVEL *ntprinter,
6490 RPC_BUFFER *buffer, uint32 offered,
6491 uint32 *needed, uint32 *returned)
6495 WERROR result = WERR_OK;
6497 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6504 for (i=0; i<*returned; i++)
6505 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6509 /* check the required size. */
6510 for (i=0; i<*returned; i++)
6511 (*needed) += spoolss_size_job_info_1(&info[i]);
6513 if (*needed > offered) {
6514 result = WERR_INSUFFICIENT_BUFFER;
6518 if (!rpcbuf_alloc_size(buffer, *needed)) {
6519 result = WERR_NOMEM;
6523 /* fill the buffer with the structures */
6524 for (i=0; i<*returned; i++)
6525 smb_io_job_info_1("", buffer, &info[i], 0);
6531 if ( !W_ERROR_IS_OK(result) )
6537 /****************************************************************************
6538 Enumjobs at level 2.
6539 ****************************************************************************/
6541 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6542 NT_PRINTER_INFO_LEVEL *ntprinter,
6543 RPC_BUFFER *buffer, uint32 offered,
6544 uint32 *needed, uint32 *returned)
6546 JOB_INFO_2 *info = NULL;
6548 WERROR result = WERR_OK;
6549 DEVICEMODE *devmode = NULL;
6551 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6556 /* this should not be a failure condition if the devmode is NULL */
6558 devmode = construct_dev_mode(snum);
6560 for (i=0; i<*returned; i++)
6561 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6563 free_a_printer(&ntprinter, 2);
6566 /* check the required size. */
6567 for (i=0; i<*returned; i++)
6568 (*needed) += spoolss_size_job_info_2(&info[i]);
6570 if (*needed > offered) {
6571 result = WERR_INSUFFICIENT_BUFFER;
6575 if (!rpcbuf_alloc_size(buffer, *needed)) {
6576 result = WERR_NOMEM;
6580 /* fill the buffer with the structures */
6581 for (i=0; i<*returned; i++)
6582 smb_io_job_info_2("", buffer, &info[i], 0);
6585 free_devmode(devmode);
6588 if ( !W_ERROR_IS_OK(result) )
6595 /****************************************************************************
6597 ****************************************************************************/
6599 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6601 POLICY_HND *handle = &q_u->handle;
6602 uint32 level = q_u->level;
6603 RPC_BUFFER *buffer = NULL;
6604 uint32 offered = q_u->offered;
6605 uint32 *needed = &r_u->needed;
6606 uint32 *returned = &r_u->returned;
6608 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6610 print_status_struct prt_status;
6611 print_queue_struct *queue=NULL;
6613 /* that's an [in out] buffer */
6615 if (!q_u->buffer && (offered!=0)) {
6616 return WERR_INVALID_PARAM;
6619 rpcbuf_move(q_u->buffer, &r_u->buffer);
6620 buffer = r_u->buffer;
6622 DEBUG(4,("_spoolss_enumjobs\n"));
6627 /* lookup the printer snum and tdb entry */
6629 if (!get_printer_snum(p, handle, &snum))
6632 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6633 if ( !W_ERROR_IS_OK(wret) )
6636 *returned = print_queue_status(snum, &queue, &prt_status);
6637 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6639 if (*returned == 0) {
6646 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6649 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6654 wret = WERR_UNKNOWN_LEVEL;
6657 free_a_printer( &ntprinter, 2 );
6661 /****************************************************************************
6662 ****************************************************************************/
6664 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6669 /****************************************************************************
6670 ****************************************************************************/
6672 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6674 POLICY_HND *handle = &q_u->handle;
6675 uint32 jobid = q_u->jobid;
6676 uint32 command = q_u->command;
6678 struct current_user user;
6680 WERROR errcode = WERR_BADFUNC;
6682 if (!get_printer_snum(p, handle, &snum)) {
6686 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6687 return WERR_INVALID_PRINTER_NAME;
6690 get_current_user(&user, p);
6693 case JOB_CONTROL_CANCEL:
6694 case JOB_CONTROL_DELETE:
6695 if (print_job_delete(&user, snum, jobid, &errcode)) {
6699 case JOB_CONTROL_PAUSE:
6700 if (print_job_pause(&user, snum, jobid, &errcode)) {
6704 case JOB_CONTROL_RESTART:
6705 case JOB_CONTROL_RESUME:
6706 if (print_job_resume(&user, snum, jobid, &errcode)) {
6711 return WERR_UNKNOWN_LEVEL;
6717 /****************************************************************************
6718 Enumerates all printer drivers at level 1.
6719 ****************************************************************************/
6721 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6726 fstring *list = NULL;
6727 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6728 DRIVER_INFO_1 *driver_info_1=NULL;
6729 WERROR result = WERR_OK;
6733 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6735 ndrivers=get_ntdrivers(&list, architecture, version);
6736 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6738 if(ndrivers == -1) {
6739 SAFE_FREE(driver_info_1);
6744 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6745 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6751 for (i=0; i<ndrivers; i++) {
6753 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6754 ZERO_STRUCT(driver);
6755 status = get_a_printer_driver(&driver, 3, list[i],
6756 architecture, version);
6757 if (!W_ERROR_IS_OK(status)) {
6759 SAFE_FREE(driver_info_1);
6762 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6763 free_a_printer_driver(driver, 3);
6766 *returned+=ndrivers;
6770 /* check the required size. */
6771 for (i=0; i<*returned; i++) {
6772 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6773 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6776 if (*needed > offered) {
6777 result = WERR_INSUFFICIENT_BUFFER;
6781 if (!rpcbuf_alloc_size(buffer, *needed)) {
6782 result = WERR_NOMEM;
6786 /* fill the buffer with the driver structures */
6787 for (i=0; i<*returned; i++) {
6788 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6789 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6793 SAFE_FREE(driver_info_1);
6795 if ( !W_ERROR_IS_OK(result) )
6801 /****************************************************************************
6802 Enumerates all printer drivers at level 2.
6803 ****************************************************************************/
6805 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6810 fstring *list = NULL;
6811 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6812 DRIVER_INFO_2 *driver_info_2=NULL;
6813 WERROR result = WERR_OK;
6817 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6819 ndrivers=get_ntdrivers(&list, architecture, version);
6820 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6822 if(ndrivers == -1) {
6823 SAFE_FREE(driver_info_2);
6828 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6829 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6835 for (i=0; i<ndrivers; i++) {
6838 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6839 ZERO_STRUCT(driver);
6840 status = get_a_printer_driver(&driver, 3, list[i],
6841 architecture, version);
6842 if (!W_ERROR_IS_OK(status)) {
6844 SAFE_FREE(driver_info_2);
6847 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6848 free_a_printer_driver(driver, 3);
6851 *returned+=ndrivers;
6855 /* check the required size. */
6856 for (i=0; i<*returned; i++) {
6857 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6858 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6861 if (*needed > offered) {
6862 result = WERR_INSUFFICIENT_BUFFER;
6866 if (!rpcbuf_alloc_size(buffer, *needed)) {
6867 result = WERR_NOMEM;
6871 /* fill the buffer with the form structures */
6872 for (i=0; i<*returned; i++) {
6873 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6874 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6878 SAFE_FREE(driver_info_2);
6880 if ( !W_ERROR_IS_OK(result) )
6886 /****************************************************************************
6887 Enumerates all printer drivers at level 3.
6888 ****************************************************************************/
6890 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6895 fstring *list = NULL;
6896 DRIVER_INFO_3 *driver_info_3=NULL;
6897 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6898 WERROR result = WERR_OK;
6902 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6904 ndrivers=get_ntdrivers(&list, architecture, version);
6905 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6907 if(ndrivers == -1) {
6908 SAFE_FREE(driver_info_3);
6913 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6914 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6920 for (i=0; i<ndrivers; i++) {
6923 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6924 ZERO_STRUCT(driver);
6925 status = get_a_printer_driver(&driver, 3, list[i],
6926 architecture, version);
6927 if (!W_ERROR_IS_OK(status)) {
6929 SAFE_FREE(driver_info_3);
6932 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6933 free_a_printer_driver(driver, 3);
6936 *returned+=ndrivers;
6940 /* check the required size. */
6941 for (i=0; i<*returned; i++) {
6942 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6943 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6946 if (*needed > offered) {
6947 result = WERR_INSUFFICIENT_BUFFER;
6951 if (!rpcbuf_alloc_size(buffer, *needed)) {
6952 result = WERR_NOMEM;
6956 /* fill the buffer with the driver structures */
6957 for (i=0; i<*returned; i++) {
6958 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6959 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6963 for (i=0; i<*returned; i++) {
6964 SAFE_FREE(driver_info_3[i].dependentfiles);
6967 SAFE_FREE(driver_info_3);
6969 if ( !W_ERROR_IS_OK(result) )
6975 /****************************************************************************
6976 Enumerates all printer drivers.
6977 ****************************************************************************/
6979 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6981 uint32 level = q_u->level;
6982 RPC_BUFFER *buffer = NULL;
6983 uint32 offered = q_u->offered;
6984 uint32 *needed = &r_u->needed;
6985 uint32 *returned = &r_u->returned;
6988 fstring architecture;
6990 /* that's an [in out] buffer */
6992 if (!q_u->buffer && (offered!=0)) {
6993 return WERR_INVALID_PARAM;
6996 rpcbuf_move(q_u->buffer, &r_u->buffer);
6997 buffer = r_u->buffer;
6999 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7004 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7005 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7007 if ( !is_myname_or_ipaddr( servername ) )
7008 return WERR_UNKNOWN_PRINTER_DRIVER;
7012 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7014 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7016 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7018 return WERR_UNKNOWN_LEVEL;
7022 /****************************************************************************
7023 ****************************************************************************/
7025 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7027 form->flag=list->flag;
7028 init_unistr(&form->name, list->name);
7029 form->width=list->width;
7030 form->length=list->length;
7031 form->left=list->left;
7032 form->top=list->top;
7033 form->right=list->right;
7034 form->bottom=list->bottom;
7037 /****************************************************************************
7038 ****************************************************************************/
7040 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7042 uint32 level = q_u->level;
7043 RPC_BUFFER *buffer = NULL;
7044 uint32 offered = q_u->offered;
7045 uint32 *needed = &r_u->needed;
7046 uint32 *numofforms = &r_u->numofforms;
7047 uint32 numbuiltinforms;
7049 nt_forms_struct *list=NULL;
7050 nt_forms_struct *builtinlist=NULL;
7055 /* that's an [in out] buffer */
7057 if (!q_u->buffer && (offered!=0) ) {
7058 return WERR_INVALID_PARAM;
7061 rpcbuf_move(q_u->buffer, &r_u->buffer);
7062 buffer = r_u->buffer;
7064 DEBUG(4,("_spoolss_enumforms\n"));
7065 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7066 DEBUGADD(5,("Info level [%d]\n", level));
7068 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7069 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7070 *numofforms = get_ntforms(&list);
7071 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7072 *numofforms += numbuiltinforms;
7074 if (*numofforms == 0) {
7075 SAFE_FREE(builtinlist);
7077 return WERR_NO_MORE_ITEMS;
7082 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7083 SAFE_FREE(builtinlist);
7089 /* construct the list of form structures */
7090 for (i=0; i<numbuiltinforms; i++) {
7091 DEBUGADD(6,("Filling form number [%d]\n",i));
7092 fill_form_1(&forms_1[i], &builtinlist[i]);
7095 SAFE_FREE(builtinlist);
7097 for (; i<*numofforms; i++) {
7098 DEBUGADD(6,("Filling form number [%d]\n",i));
7099 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7104 /* check the required size. */
7105 for (i=0; i<numbuiltinforms; i++) {
7106 DEBUGADD(6,("adding form [%d]'s size\n",i));
7107 buffer_size += spoolss_size_form_1(&forms_1[i]);
7109 for (; i<*numofforms; i++) {
7110 DEBUGADD(6,("adding form [%d]'s size\n",i));
7111 buffer_size += spoolss_size_form_1(&forms_1[i]);
7114 *needed=buffer_size;
7116 if (*needed > offered) {
7119 return WERR_INSUFFICIENT_BUFFER;
7122 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7128 /* fill the buffer with the form structures */
7129 for (i=0; i<numbuiltinforms; i++) {
7130 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7131 smb_io_form_1("", buffer, &forms_1[i], 0);
7133 for (; i<*numofforms; i++) {
7134 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7135 smb_io_form_1("", buffer, &forms_1[i], 0);
7144 SAFE_FREE(builtinlist);
7145 return WERR_UNKNOWN_LEVEL;
7149 /****************************************************************************
7150 ****************************************************************************/
7152 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7154 uint32 level = q_u->level;
7155 UNISTR2 *uni_formname = &q_u->formname;
7156 RPC_BUFFER *buffer = NULL;
7157 uint32 offered = q_u->offered;
7158 uint32 *needed = &r_u->needed;
7160 nt_forms_struct *list=NULL;
7161 nt_forms_struct builtin_form;
7166 int numofforms=0, i=0;
7168 /* that's an [in out] buffer */
7170 if (!q_u->buffer && (offered!=0)) {
7171 return WERR_INVALID_PARAM;
7174 rpcbuf_move(q_u->buffer, &r_u->buffer);
7175 buffer = r_u->buffer;
7177 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7179 DEBUG(4,("_spoolss_getform\n"));
7180 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7181 DEBUGADD(5,("Info level [%d]\n", level));
7183 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7184 if (!foundBuiltin) {
7185 numofforms = get_ntforms(&list);
7186 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7188 if (numofforms == 0)
7195 fill_form_1(&form_1, &builtin_form);
7198 /* Check if the requested name is in the list of form structures */
7199 for (i=0; i<numofforms; i++) {
7201 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7203 if (strequal(form_name, list[i].name)) {
7204 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7205 fill_form_1(&form_1, &list[i]);
7211 if (i == numofforms) {
7215 /* check the required size. */
7217 *needed=spoolss_size_form_1(&form_1);
7219 if (*needed > offered)
7220 return WERR_INSUFFICIENT_BUFFER;
7222 if (!rpcbuf_alloc_size(buffer, buffer_size))
7225 /* fill the buffer with the form structures */
7226 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7227 smb_io_form_1("", buffer, &form_1, 0);
7233 return WERR_UNKNOWN_LEVEL;
7237 /****************************************************************************
7238 ****************************************************************************/
7240 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7242 init_unistr(&port->port_name, name);
7245 /****************************************************************************
7246 TODO: This probably needs distinguish between TCP/IP and Local ports
7248 ****************************************************************************/
7250 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7252 init_unistr(&port->port_name, name);
7253 init_unistr(&port->monitor_name, "Local Monitor");
7254 init_unistr(&port->description, SPL_LOCAL_PORT );
7255 port->port_type=PORT_TYPE_WRITE;
7260 /****************************************************************************
7261 wrapper around the enumer ports command
7262 ****************************************************************************/
7264 WERROR enumports_hook( int *count, char ***lines )
7266 char *cmd = lp_enumports_cmd();
7276 /* if no hook then just fill in the default port */
7279 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7280 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7285 /* we have a valid enumport command */
7287 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7289 DEBUG(10,("Running [%s]\n", command));
7290 ret = smbrun(command, &fd);
7291 DEBUG(10,("Returned [%d]\n", ret));
7296 return WERR_ACCESS_DENIED;
7300 qlines = fd_lines_load(fd, &numlines, 0);
7301 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7311 /****************************************************************************
7313 ****************************************************************************/
7315 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7317 PORT_INFO_1 *ports=NULL;
7319 WERROR result = WERR_OK;
7320 char **qlines = NULL;
7323 result = enumports_hook( &numlines, &qlines );
7324 if (!W_ERROR_IS_OK(result)) {
7325 file_lines_free(qlines);
7330 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7331 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7332 dos_errstr(WERR_NOMEM)));
7333 file_lines_free(qlines);
7337 for (i=0; i<numlines; i++) {
7338 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7339 fill_port_1(&ports[i], qlines[i]);
7342 file_lines_free(qlines);
7344 *returned = numlines;
7346 /* check the required size. */
7347 for (i=0; i<*returned; i++) {
7348 DEBUGADD(6,("adding port [%d]'s size\n", i));
7349 *needed += spoolss_size_port_info_1(&ports[i]);
7352 if (*needed > offered) {
7353 result = WERR_INSUFFICIENT_BUFFER;
7357 if (!rpcbuf_alloc_size(buffer, *needed)) {
7358 result = WERR_NOMEM;
7362 /* fill the buffer with the ports structures */
7363 for (i=0; i<*returned; i++) {
7364 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7365 smb_io_port_1("", buffer, &ports[i], 0);
7371 if ( !W_ERROR_IS_OK(result) )
7377 /****************************************************************************
7379 ****************************************************************************/
7381 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7383 PORT_INFO_2 *ports=NULL;
7385 WERROR result = WERR_OK;
7386 char **qlines = NULL;
7389 result = enumports_hook( &numlines, &qlines );
7390 if ( !W_ERROR_IS_OK(result)) {
7391 file_lines_free(qlines);
7396 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7397 file_lines_free(qlines);
7401 for (i=0; i<numlines; i++) {
7402 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7403 fill_port_2(&(ports[i]), qlines[i]);
7407 file_lines_free(qlines);
7409 *returned = numlines;
7411 /* check the required size. */
7412 for (i=0; i<*returned; i++) {
7413 DEBUGADD(6,("adding port [%d]'s size\n", i));
7414 *needed += spoolss_size_port_info_2(&ports[i]);
7417 if (*needed > offered) {
7418 result = WERR_INSUFFICIENT_BUFFER;
7422 if (!rpcbuf_alloc_size(buffer, *needed)) {
7423 result = WERR_NOMEM;
7427 /* fill the buffer with the ports structures */
7428 for (i=0; i<*returned; i++) {
7429 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7430 smb_io_port_2("", buffer, &ports[i], 0);
7436 if ( !W_ERROR_IS_OK(result) )
7442 /****************************************************************************
7444 ****************************************************************************/
7446 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7448 uint32 level = q_u->level;
7449 RPC_BUFFER *buffer = NULL;
7450 uint32 offered = q_u->offered;
7451 uint32 *needed = &r_u->needed;
7452 uint32 *returned = &r_u->returned;
7454 /* that's an [in out] buffer */
7456 if (!q_u->buffer && (offered!=0)) {
7457 return WERR_INVALID_PARAM;
7460 rpcbuf_move(q_u->buffer, &r_u->buffer);
7461 buffer = r_u->buffer;
7463 DEBUG(4,("_spoolss_enumports\n"));
7470 return enumports_level_1(buffer, offered, needed, returned);
7472 return enumports_level_2(buffer, offered, needed, returned);
7474 return WERR_UNKNOWN_LEVEL;
7478 /****************************************************************************
7479 ****************************************************************************/
7481 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7482 const SPOOL_PRINTER_INFO_LEVEL *info,
7483 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7484 uint32 user_switch, const SPOOL_USER_CTR *user,
7487 NT_PRINTER_INFO_LEVEL *printer = NULL;
7490 WERROR err = WERR_OK;
7492 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7493 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7497 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7498 if (!convert_printer_info(info, printer, 2)) {
7499 free_a_printer(&printer, 2);
7503 /* check to see if the printer already exists */
7505 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7506 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7507 printer->info_2->sharename));
7508 free_a_printer(&printer, 2);
7509 return WERR_PRINTER_ALREADY_EXISTS;
7512 /* FIXME!!! smbd should check to see if the driver is installed before
7513 trying to add a printer like this --jerry */
7515 if (*lp_addprinter_cmd() ) {
7516 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7517 free_a_printer(&printer,2);
7518 return WERR_ACCESS_DENIED;
7521 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7522 "smb.conf parameter \"addprinter command\" is defined. This"
7523 "parameter must exist for this call to succeed\n",
7524 printer->info_2->sharename ));
7527 /* use our primary netbios name since get_a_printer() will convert
7528 it to what the client expects on a case by case basis */
7530 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7531 printer->info_2->sharename);
7534 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7535 free_a_printer(&printer,2);
7536 return WERR_ACCESS_DENIED;
7539 /* you must be a printer admin to add a new printer */
7540 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7541 free_a_printer(&printer,2);
7542 return WERR_ACCESS_DENIED;
7546 * Do sanity check on the requested changes for Samba.
7549 if (!check_printer_ok(printer->info_2, snum)) {
7550 free_a_printer(&printer,2);
7551 return WERR_INVALID_PARAM;
7555 * When a printer is created, the drivername bound to the printer is used
7556 * to lookup previously saved driver initialization info, which is then
7557 * bound to the new printer, simulating what happens in the Windows arch.
7562 set_driver_init(printer, 2);
7566 /* A valid devmode was included, convert and link it
7568 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7570 if (!convert_devicemode(printer->info_2->printername, devmode,
7571 &printer->info_2->devmode))
7575 /* write the ASCII on disk */
7576 err = mod_a_printer(printer, 2);
7577 if (!W_ERROR_IS_OK(err)) {
7578 free_a_printer(&printer,2);
7582 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7583 /* Handle open failed - remove addition. */
7584 del_a_printer(printer->info_2->sharename);
7585 free_a_printer(&printer,2);
7586 return WERR_ACCESS_DENIED;
7589 update_c_setprinter(False);
7590 free_a_printer(&printer,2);
7595 /****************************************************************************
7596 ****************************************************************************/
7598 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7600 UNISTR2 *uni_srv_name = q_u->server_name;
7601 uint32 level = q_u->level;
7602 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7603 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7604 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7605 uint32 user_switch = q_u->user_switch;
7606 SPOOL_USER_CTR *user = &q_u->user_ctr;
7607 POLICY_HND *handle = &r_u->handle;
7611 /* we don't handle yet */
7612 /* but I know what to do ... */
7613 return WERR_UNKNOWN_LEVEL;
7615 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7617 user_switch, user, handle);
7619 return WERR_UNKNOWN_LEVEL;
7623 /****************************************************************************
7624 ****************************************************************************/
7626 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7628 uint32 level = q_u->level;
7629 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7630 WERROR err = WERR_OK;
7631 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7632 struct current_user user;
7633 fstring driver_name;
7636 ZERO_STRUCT(driver);
7638 get_current_user(&user, p);
7640 if (!convert_printer_driver_info(info, &driver, level)) {
7645 DEBUG(5,("Cleaning driver's information\n"));
7646 err = clean_up_driver_struct(driver, level, &user);
7647 if (!W_ERROR_IS_OK(err))
7650 DEBUG(5,("Moving driver to final destination\n"));
7651 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7655 if (add_a_printer_driver(driver, level)!=0) {
7656 err = WERR_ACCESS_DENIED;
7661 * I think this is where he DrvUpgradePrinter() hook would be
7662 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7663 * server. Right now, we just need to send ourselves a message
7664 * to update each printer bound to this driver. --jerry
7667 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7668 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7673 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7674 * decide if the driver init data should be deleted. The rules are:
7675 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7676 * 2) delete init data only if there is no 2k/Xp driver
7677 * 3) always delete init data
7678 * The generalized rule is always use init data from the highest order driver.
7679 * It is necessary to follow the driver install by an initialization step to
7680 * finish off this process.
7683 version = driver.info_3->cversion;
7684 else if (level == 6)
7685 version = driver.info_6->version;
7690 * 9x printer driver - never delete init data
7693 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7698 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7699 * there is no 2k/Xp driver init data for this driver name.
7703 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7705 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7707 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7709 if (!del_driver_init(driver_name))
7710 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7713 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7715 free_a_printer_driver(driver1,3);
7716 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7723 * 2k or Xp printer driver - always delete init data
7726 if (!del_driver_init(driver_name))
7727 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7731 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7737 free_a_printer_driver(driver, level);
7741 /********************************************************************
7742 * spoolss_addprinterdriverex
7743 ********************************************************************/
7745 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7747 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7748 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7751 * we only support the semantics of AddPrinterDriver()
7752 * i.e. only copy files that are newer than existing ones
7755 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7756 return WERR_ACCESS_DENIED;
7758 ZERO_STRUCT(q_u_local);
7759 ZERO_STRUCT(r_u_local);
7761 /* just pass the information off to _spoolss_addprinterdriver() */
7762 q_u_local.server_name_ptr = q_u->server_name_ptr;
7763 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7764 q_u_local.level = q_u->level;
7765 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7767 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7770 /****************************************************************************
7771 ****************************************************************************/
7773 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7775 init_unistr(&info->name, name);
7778 /****************************************************************************
7779 ****************************************************************************/
7781 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7787 const char *short_archi;
7788 DRIVER_DIRECTORY_1 *info=NULL;
7789 WERROR result = WERR_OK;
7791 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7792 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7794 /* check for beginning double '\'s and that the server
7797 pservername = servername;
7798 if ( *pservername == '\\' && strlen(servername)>2 ) {
7802 if ( !is_myname_or_ipaddr( pservername ) )
7803 return WERR_INVALID_PARAM;
7805 if (!(short_archi = get_short_archi(long_archi)))
7806 return WERR_INVALID_ENVIRONMENT;
7808 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7811 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7813 DEBUG(4,("printer driver directory: [%s]\n", path));
7815 fill_driverdir_1(info, path);
7817 *needed += spoolss_size_driverdir_info_1(info);
7819 if (*needed > offered) {
7820 result = WERR_INSUFFICIENT_BUFFER;
7824 if (!rpcbuf_alloc_size(buffer, *needed)) {
7825 result = WERR_NOMEM;
7829 smb_io_driverdir_1("", buffer, info, 0);
7837 /****************************************************************************
7838 ****************************************************************************/
7840 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7842 UNISTR2 *name = &q_u->name;
7843 UNISTR2 *uni_environment = &q_u->environment;
7844 uint32 level = q_u->level;
7845 RPC_BUFFER *buffer = NULL;
7846 uint32 offered = q_u->offered;
7847 uint32 *needed = &r_u->needed;
7849 /* that's an [in out] buffer */
7851 if (!q_u->buffer && (offered!=0)) {
7852 return WERR_INVALID_PARAM;
7855 rpcbuf_move(q_u->buffer, &r_u->buffer);
7856 buffer = r_u->buffer;
7858 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7864 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7866 return WERR_UNKNOWN_LEVEL;
7870 /****************************************************************************
7871 ****************************************************************************/
7873 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7875 POLICY_HND *handle = &q_u->handle;
7876 uint32 idx = q_u->index;
7877 uint32 in_value_len = q_u->valuesize;
7878 uint32 in_data_len = q_u->datasize;
7879 uint32 *out_max_value_len = &r_u->valuesize;
7880 uint16 **out_value = &r_u->value;
7881 uint32 *out_value_len = &r_u->realvaluesize;
7882 uint32 *out_type = &r_u->type;
7883 uint32 *out_max_data_len = &r_u->datasize;
7884 uint8 **data_out = &r_u->data;
7885 uint32 *out_data_len = &r_u->realdatasize;
7887 NT_PRINTER_INFO_LEVEL *printer = NULL;
7889 uint32 biggest_valuesize;
7890 uint32 biggest_datasize;
7892 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7895 REGISTRY_VALUE *val = NULL;
7896 NT_PRINTER_DATA *p_data;
7897 int i, key_index, num_values;
7902 *out_max_data_len = 0;
7906 DEBUG(5,("spoolss_enumprinterdata\n"));
7909 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7913 if (!get_printer_snum(p,handle, &snum))
7916 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7917 if (!W_ERROR_IS_OK(result))
7920 p_data = printer->info_2->data;
7921 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7926 * The NT machine wants to know the biggest size of value and data
7928 * cf: MSDN EnumPrinterData remark section
7931 if ( !in_value_len && !in_data_len && (key_index != -1) )
7933 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7935 biggest_valuesize = 0;
7936 biggest_datasize = 0;
7938 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7940 for ( i=0; i<num_values; i++ )
7942 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7944 name_length = strlen(val->valuename);
7945 if ( strlen(val->valuename) > biggest_valuesize )
7946 biggest_valuesize = name_length;
7948 if ( val->size > biggest_datasize )
7949 biggest_datasize = val->size;
7951 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7955 /* the value is an UNICODE string but real_value_size is the length
7956 in bytes including the trailing 0 */
7958 *out_value_len = 2 * (1+biggest_valuesize);
7959 *out_data_len = biggest_datasize;
7961 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7967 * the value len is wrong in NT sp3
7968 * that's the number of bytes not the number of unicode chars
7971 if ( key_index != -1 )
7972 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7977 /* out_value should default to "" or else NT4 has
7978 problems unmarshalling the response */
7980 *out_max_value_len=(in_value_len/sizeof(uint16));
7982 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7984 result = WERR_NOMEM;
7988 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7990 /* the data is counted in bytes */
7992 *out_max_data_len = in_data_len;
7993 *out_data_len = in_data_len;
7995 /* only allocate when given a non-zero data_len */
7997 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7999 result = WERR_NOMEM;
8003 result = WERR_NO_MORE_ITEMS;
8009 * - counted in bytes in the request
8010 * - counted in UNICODE chars in the max reply
8011 * - counted in bytes in the real size
8013 * take a pause *before* coding not *during* coding
8017 *out_max_value_len=(in_value_len/sizeof(uint16));
8018 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8020 result = WERR_NOMEM;
8024 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8028 *out_type = regval_type( val );
8030 /* data - counted in bytes */
8032 *out_max_data_len = in_data_len;
8033 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8035 result = WERR_NOMEM;
8038 data_len = regval_size(val);
8040 memcpy( *data_out, regval_data_p(val), data_len );
8041 *out_data_len = data_len;
8045 free_a_printer(&printer, 2);
8049 /****************************************************************************
8050 ****************************************************************************/
8052 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8054 POLICY_HND *handle = &q_u->handle;
8055 UNISTR2 *value = &q_u->value;
8056 uint32 type = q_u->type;
8057 uint8 *data = q_u->data;
8058 uint32 real_len = q_u->real_len;
8060 NT_PRINTER_INFO_LEVEL *printer = NULL;
8062 WERROR status = WERR_OK;
8063 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8066 DEBUG(5,("spoolss_setprinterdata\n"));
8069 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8073 if ( Printer->printer_type == SPLHND_SERVER ) {
8074 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8075 return WERR_INVALID_PARAM;
8078 if (!get_printer_snum(p,handle, &snum))
8082 * Access check : NT returns "access denied" if you make a
8083 * SetPrinterData call without the necessary privildge.
8084 * we were originally returning OK if nothing changed
8085 * which made Win2k issue **a lot** of SetPrinterData
8086 * when connecting to a printer --jerry
8089 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8091 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8092 status = WERR_ACCESS_DENIED;
8096 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8097 if (!W_ERROR_IS_OK(status))
8100 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8103 * When client side code sets a magic printer data key, detect it and save
8104 * the current printer data and the magic key's data (its the DEVMODE) for
8105 * future printer/driver initializations.
8107 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8109 /* Set devmode and printer initialization info */
8110 status = save_driver_init( printer, 2, data, real_len );
8112 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8116 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8117 type, data, real_len );
8118 if ( W_ERROR_IS_OK(status) )
8119 status = mod_a_printer(printer, 2);
8123 free_a_printer(&printer, 2);
8128 /****************************************************************************
8129 ****************************************************************************/
8131 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8133 POLICY_HND *handle = &q_u->handle;
8134 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8137 DEBUG(5,("_spoolss_resetprinter\n"));
8140 * All we do is to check to see if the handle and queue is valid.
8141 * This call really doesn't mean anything to us because we only
8142 * support RAW printing. --jerry
8146 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8150 if (!get_printer_snum(p,handle, &snum))
8154 /* blindly return success */
8159 /****************************************************************************
8160 ****************************************************************************/
8162 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8164 POLICY_HND *handle = &q_u->handle;
8165 UNISTR2 *value = &q_u->valuename;
8167 NT_PRINTER_INFO_LEVEL *printer = NULL;
8169 WERROR status = WERR_OK;
8170 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8173 DEBUG(5,("spoolss_deleteprinterdata\n"));
8176 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8180 if (!get_printer_snum(p, handle, &snum))
8183 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8184 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8185 return WERR_ACCESS_DENIED;
8188 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8189 if (!W_ERROR_IS_OK(status))
8192 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8194 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8196 if ( W_ERROR_IS_OK(status) )
8197 mod_a_printer( printer, 2 );
8199 free_a_printer(&printer, 2);
8204 /****************************************************************************
8205 ****************************************************************************/
8207 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8209 POLICY_HND *handle = &q_u->handle;
8210 FORM *form = &q_u->form;
8211 nt_forms_struct tmpForm;
8213 WERROR status = WERR_OK;
8214 NT_PRINTER_INFO_LEVEL *printer = NULL;
8217 nt_forms_struct *list=NULL;
8218 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8220 DEBUG(5,("spoolss_addform\n"));
8223 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8228 /* forms can be added on printer of on the print server handle */
8230 if ( Printer->printer_type == SPLHND_PRINTER )
8232 if (!get_printer_snum(p,handle, &snum))
8235 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8236 if (!W_ERROR_IS_OK(status))
8240 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8241 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8242 status = WERR_ACCESS_DENIED;
8246 /* can't add if builtin */
8248 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8249 status = WERR_ALREADY_EXISTS;
8253 count = get_ntforms(&list);
8255 if(!add_a_form(&list, form, &count)) {
8256 status = WERR_NOMEM;
8260 write_ntforms(&list, count);
8263 * ChangeID must always be set if this is a printer
8266 if ( Printer->printer_type == SPLHND_PRINTER )
8267 status = mod_a_printer(printer, 2);
8271 free_a_printer(&printer, 2);
8277 /****************************************************************************
8278 ****************************************************************************/
8280 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8282 POLICY_HND *handle = &q_u->handle;
8283 UNISTR2 *form_name = &q_u->name;
8284 nt_forms_struct tmpForm;
8286 nt_forms_struct *list=NULL;
8287 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8289 WERROR status = WERR_OK;
8290 NT_PRINTER_INFO_LEVEL *printer = NULL;
8292 DEBUG(5,("spoolss_deleteform\n"));
8295 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8299 /* forms can be deleted on printer of on the print server handle */
8301 if ( Printer->printer_type == SPLHND_PRINTER )
8303 if (!get_printer_snum(p,handle, &snum))
8306 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8307 if (!W_ERROR_IS_OK(status))
8311 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8312 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8313 status = WERR_ACCESS_DENIED;
8317 /* can't delete if builtin */
8319 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8320 status = WERR_INVALID_PARAM;
8324 count = get_ntforms(&list);
8326 if ( !delete_a_form(&list, form_name, &count, &status ))
8330 * ChangeID must always be set if this is a printer
8333 if ( Printer->printer_type == SPLHND_PRINTER )
8334 status = mod_a_printer(printer, 2);
8338 free_a_printer(&printer, 2);
8344 /****************************************************************************
8345 ****************************************************************************/
8347 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8349 POLICY_HND *handle = &q_u->handle;
8350 FORM *form = &q_u->form;
8351 nt_forms_struct tmpForm;
8353 WERROR status = WERR_OK;
8354 NT_PRINTER_INFO_LEVEL *printer = NULL;
8357 nt_forms_struct *list=NULL;
8358 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8360 DEBUG(5,("spoolss_setform\n"));
8363 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8367 /* forms can be modified on printer of on the print server handle */
8369 if ( Printer->printer_type == SPLHND_PRINTER )
8371 if (!get_printer_snum(p,handle, &snum))
8374 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8375 if (!W_ERROR_IS_OK(status))
8379 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8380 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8381 status = WERR_ACCESS_DENIED;
8385 /* can't set if builtin */
8386 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8387 status = WERR_INVALID_PARAM;
8391 count = get_ntforms(&list);
8392 update_a_form(&list, form, count);
8393 write_ntforms(&list, count);
8396 * ChangeID must always be set if this is a printer
8399 if ( Printer->printer_type == SPLHND_PRINTER )
8400 status = mod_a_printer(printer, 2);
8405 free_a_printer(&printer, 2);
8411 /****************************************************************************
8412 enumprintprocessors level 1.
8413 ****************************************************************************/
8415 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8417 PRINTPROCESSOR_1 *info_1=NULL;
8418 WERROR result = WERR_OK;
8420 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8425 init_unistr(&info_1->name, "winprint");
8427 *needed += spoolss_size_printprocessor_info_1(info_1);
8429 if (*needed > offered) {
8430 result = WERR_INSUFFICIENT_BUFFER;
8434 if (!rpcbuf_alloc_size(buffer, *needed)) {
8435 result = WERR_NOMEM;
8439 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8444 if ( !W_ERROR_IS_OK(result) )
8450 /****************************************************************************
8451 ****************************************************************************/
8453 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8455 uint32 level = q_u->level;
8456 RPC_BUFFER *buffer = NULL;
8457 uint32 offered = q_u->offered;
8458 uint32 *needed = &r_u->needed;
8459 uint32 *returned = &r_u->returned;
8461 /* that's an [in out] buffer */
8463 if (!q_u->buffer && (offered!=0)) {
8464 return WERR_INVALID_PARAM;
8467 rpcbuf_move(q_u->buffer, &r_u->buffer);
8468 buffer = r_u->buffer;
8470 DEBUG(5,("spoolss_enumprintprocessors\n"));
8473 * Enumerate the print processors ...
8475 * Just reply with "winprint", to keep NT happy
8476 * and I can use my nice printer checker.
8484 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8486 return WERR_UNKNOWN_LEVEL;
8490 /****************************************************************************
8491 enumprintprocdatatypes level 1.
8492 ****************************************************************************/
8494 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8496 PRINTPROCDATATYPE_1 *info_1=NULL;
8497 WERROR result = WERR_NOMEM;
8499 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8504 init_unistr(&info_1->name, "RAW");
8506 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8508 if (*needed > offered) {
8509 result = WERR_INSUFFICIENT_BUFFER;
8513 if (!rpcbuf_alloc_size(buffer, *needed)) {
8514 result = WERR_NOMEM;
8518 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8523 if ( !W_ERROR_IS_OK(result) )
8529 /****************************************************************************
8530 ****************************************************************************/
8532 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8534 uint32 level = q_u->level;
8535 RPC_BUFFER *buffer = NULL;
8536 uint32 offered = q_u->offered;
8537 uint32 *needed = &r_u->needed;
8538 uint32 *returned = &r_u->returned;
8540 /* that's an [in out] buffer */
8542 if (!q_u->buffer && (offered!=0)) {
8543 return WERR_INVALID_PARAM;
8546 rpcbuf_move(q_u->buffer, &r_u->buffer);
8547 buffer = r_u->buffer;
8549 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8556 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8558 return WERR_UNKNOWN_LEVEL;
8562 /****************************************************************************
8563 enumprintmonitors level 1.
8564 ****************************************************************************/
8566 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8568 PRINTMONITOR_1 *info_1;
8569 WERROR result = WERR_OK;
8572 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8577 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8578 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8580 for ( i=0; i<*returned; i++ ) {
8581 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8584 if (*needed > offered) {
8585 result = WERR_INSUFFICIENT_BUFFER;
8589 if (!rpcbuf_alloc_size(buffer, *needed)) {
8590 result = WERR_NOMEM;
8594 for ( i=0; i<*returned; i++ ) {
8595 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8601 if ( !W_ERROR_IS_OK(result) )
8607 /****************************************************************************
8608 enumprintmonitors level 2.
8609 ****************************************************************************/
8611 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8613 PRINTMONITOR_2 *info_2;
8614 WERROR result = WERR_OK;
8617 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8622 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8623 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8624 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8626 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8627 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8628 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8630 for ( i=0; i<*returned; i++ ) {
8631 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8634 if (*needed > offered) {
8635 result = WERR_INSUFFICIENT_BUFFER;
8639 if (!rpcbuf_alloc_size(buffer, *needed)) {
8640 result = WERR_NOMEM;
8644 for ( i=0; i<*returned; i++ ) {
8645 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8651 if ( !W_ERROR_IS_OK(result) )
8657 /****************************************************************************
8658 ****************************************************************************/
8660 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8662 uint32 level = q_u->level;
8663 RPC_BUFFER *buffer = NULL;
8664 uint32 offered = q_u->offered;
8665 uint32 *needed = &r_u->needed;
8666 uint32 *returned = &r_u->returned;
8668 /* that's an [in out] buffer */
8670 if (!q_u->buffer && (offered!=0)) {
8671 return WERR_INVALID_PARAM;
8674 rpcbuf_move(q_u->buffer, &r_u->buffer);
8675 buffer = r_u->buffer;
8677 DEBUG(5,("spoolss_enumprintmonitors\n"));
8680 * Enumerate the print monitors ...
8682 * Just reply with "Local Port", to keep NT happy
8683 * and I can use my nice printer checker.
8691 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8693 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8695 return WERR_UNKNOWN_LEVEL;
8699 /****************************************************************************
8700 ****************************************************************************/
8702 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8703 NT_PRINTER_INFO_LEVEL *ntprinter,
8704 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8709 JOB_INFO_1 *info_1=NULL;
8710 WERROR result = WERR_OK;
8712 info_1=SMB_MALLOC_P(JOB_INFO_1);
8714 if (info_1 == NULL) {
8718 for (i=0; i<count && found==False; i++) {
8719 if ((*queue)[i].job==(int)jobid)
8725 /* NT treats not found as bad param... yet another bad choice */
8726 return WERR_INVALID_PARAM;
8729 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8731 *needed += spoolss_size_job_info_1(info_1);
8733 if (*needed > offered) {
8734 result = WERR_INSUFFICIENT_BUFFER;
8738 if (!rpcbuf_alloc_size(buffer, *needed)) {
8739 result = WERR_NOMEM;
8743 smb_io_job_info_1("", buffer, info_1, 0);
8751 /****************************************************************************
8752 ****************************************************************************/
8754 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8755 NT_PRINTER_INFO_LEVEL *ntprinter,
8756 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8763 DEVICEMODE *devmode = NULL;
8764 NT_DEVICEMODE *nt_devmode = NULL;
8766 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8769 ZERO_STRUCTP(info_2);
8771 for ( i=0; i<count && found==False; i++ )
8773 if ((*queue)[i].job == (int)jobid)
8778 /* NT treats not found as bad param... yet another bad
8780 result = WERR_INVALID_PARAM;
8785 * if the print job does not have a DEVMODE associated with it,
8786 * just use the one for the printer. A NULL devicemode is not
8787 * a failure condition
8790 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8791 devmode = construct_dev_mode(snum);
8793 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8794 ZERO_STRUCTP( devmode );
8795 convert_nt_devicemode( devmode, nt_devmode );
8799 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8801 *needed += spoolss_size_job_info_2(info_2);
8803 if (*needed > offered) {
8804 result = WERR_INSUFFICIENT_BUFFER;
8808 if (!rpcbuf_alloc_size(buffer, *needed)) {
8809 result = WERR_NOMEM;
8813 smb_io_job_info_2("", buffer, info_2, 0);
8818 /* Cleanup allocated memory */
8820 free_job_info_2(info_2); /* Also frees devmode */
8826 /****************************************************************************
8827 ****************************************************************************/
8829 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8831 POLICY_HND *handle = &q_u->handle;
8832 uint32 jobid = q_u->jobid;
8833 uint32 level = q_u->level;
8834 RPC_BUFFER *buffer = NULL;
8835 uint32 offered = q_u->offered;
8836 uint32 *needed = &r_u->needed;
8837 WERROR wstatus = WERR_OK;
8838 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8841 print_queue_struct *queue = NULL;
8842 print_status_struct prt_status;
8844 /* that's an [in out] buffer */
8846 if (!q_u->buffer && (offered!=0)) {
8847 return WERR_INVALID_PARAM;
8850 rpcbuf_move(q_u->buffer, &r_u->buffer);
8851 buffer = r_u->buffer;
8853 DEBUG(5,("spoolss_getjob\n"));
8857 if (!get_printer_snum(p, handle, &snum))
8860 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8861 if ( !W_ERROR_IS_OK(wstatus) )
8864 count = print_queue_status(snum, &queue, &prt_status);
8866 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8867 count, prt_status.status, prt_status.message));
8871 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8872 buffer, offered, needed);
8875 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8876 buffer, offered, needed);
8879 wstatus = WERR_UNKNOWN_LEVEL;
8884 free_a_printer( &ntprinter, 2 );
8889 /********************************************************************
8890 spoolss_getprinterdataex
8892 From MSDN documentation of GetPrinterDataEx: pass request
8893 to GetPrinterData if key is "PrinterDriverData".
8894 ********************************************************************/
8896 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8898 POLICY_HND *handle = &q_u->handle;
8899 uint32 in_size = q_u->size;
8900 uint32 *type = &r_u->type;
8901 uint32 *out_size = &r_u->size;
8902 uint8 **data = &r_u->data;
8903 uint32 *needed = &r_u->needed;
8904 fstring keyname, valuename;
8906 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8908 NT_PRINTER_INFO_LEVEL *printer = NULL;
8910 WERROR status = WERR_OK;
8912 DEBUG(4,("_spoolss_getprinterdataex\n"));
8914 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8915 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8917 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8918 keyname, valuename));
8920 /* in case of problem, return some default values */
8924 *out_size = in_size;
8927 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8928 status = WERR_BADFID;
8932 /* Is the handle to a printer or to the server? */
8934 if (Printer->printer_type == SPLHND_SERVER) {
8935 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8936 status = WERR_INVALID_PARAM;
8940 if ( !get_printer_snum(p,handle, &snum) )
8943 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8944 if ( !W_ERROR_IS_OK(status) )
8947 /* check to see if the keyname is valid */
8948 if ( !strlen(keyname) ) {
8949 status = WERR_INVALID_PARAM;
8953 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8954 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8955 free_a_printer( &printer, 2 );
8956 status = WERR_BADFILE;
8960 /* When given a new keyname, we should just create it */
8962 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8964 if (*needed > *out_size)
8965 status = WERR_MORE_DATA;
8968 if ( !W_ERROR_IS_OK(status) )
8970 DEBUG(5, ("error: allocating %d\n", *out_size));
8972 /* reply this param doesn't exist */
8976 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8977 status = WERR_NOMEM;
8987 free_a_printer( &printer, 2 );
8992 /********************************************************************
8993 * spoolss_setprinterdataex
8994 ********************************************************************/
8996 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8998 POLICY_HND *handle = &q_u->handle;
8999 uint32 type = q_u->type;
9000 uint8 *data = q_u->data;
9001 uint32 real_len = q_u->real_len;
9003 NT_PRINTER_INFO_LEVEL *printer = NULL;
9005 WERROR status = WERR_OK;
9006 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9011 DEBUG(4,("_spoolss_setprinterdataex\n"));
9013 /* From MSDN documentation of SetPrinterDataEx: pass request to
9014 SetPrinterData if key is "PrinterDriverData" */
9017 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9021 if ( Printer->printer_type == SPLHND_SERVER ) {
9022 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9023 return WERR_INVALID_PARAM;
9026 if ( !get_printer_snum(p,handle, &snum) )
9030 * Access check : NT returns "access denied" if you make a
9031 * SetPrinterData call without the necessary privildge.
9032 * we were originally returning OK if nothing changed
9033 * which made Win2k issue **a lot** of SetPrinterData
9034 * when connecting to a printer --jerry
9037 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9039 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9040 return WERR_ACCESS_DENIED;
9043 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9044 if (!W_ERROR_IS_OK(status))
9047 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9048 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9050 /* check for OID in valuename */
9052 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9058 /* save the registry data */
9060 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9062 if ( W_ERROR_IS_OK(status) )
9064 /* save the OID if one was specified */
9066 fstrcat( keyname, "\\" );
9067 fstrcat( keyname, SPOOL_OID_KEY );
9070 * I'm not checking the status here on purpose. Don't know
9071 * if this is right, but I'm returning the status from the
9072 * previous set_printer_dataex() call. I have no idea if
9073 * this is right. --jerry
9076 set_printer_dataex( printer, keyname, valuename,
9077 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9080 status = mod_a_printer(printer, 2);
9083 free_a_printer(&printer, 2);
9089 /********************************************************************
9090 * spoolss_deleteprinterdataex
9091 ********************************************************************/
9093 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9095 POLICY_HND *handle = &q_u->handle;
9096 UNISTR2 *value = &q_u->valuename;
9097 UNISTR2 *key = &q_u->keyname;
9099 NT_PRINTER_INFO_LEVEL *printer = NULL;
9101 WERROR status = WERR_OK;
9102 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9103 pstring valuename, keyname;
9105 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9108 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9112 if (!get_printer_snum(p, handle, &snum))
9115 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9116 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9117 return WERR_ACCESS_DENIED;
9120 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9121 if (!W_ERROR_IS_OK(status))
9124 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9125 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9127 status = delete_printer_dataex( printer, keyname, valuename );
9129 if ( W_ERROR_IS_OK(status) )
9130 mod_a_printer( printer, 2 );
9132 free_a_printer(&printer, 2);
9137 /********************************************************************
9138 * spoolss_enumprinterkey
9139 ********************************************************************/
9142 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9145 fstring *keynames = NULL;
9146 uint16 *enumkeys = NULL;
9149 POLICY_HND *handle = &q_u->handle;
9150 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9151 NT_PRINTER_DATA *data;
9152 NT_PRINTER_INFO_LEVEL *printer = NULL;
9154 WERROR status = WERR_BADFILE;
9157 DEBUG(4,("_spoolss_enumprinterkey\n"));
9160 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9164 if ( !get_printer_snum(p,handle, &snum) )
9167 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9168 if (!W_ERROR_IS_OK(status))
9171 /* get the list of subkey names */
9173 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9174 data = printer->info_2->data;
9176 num_keys = get_printer_subkeys( data, key, &keynames );
9178 if ( num_keys == -1 ) {
9179 status = WERR_BADFILE;
9183 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9185 r_u->needed = printerkey_len*2;
9187 if ( q_u->size < r_u->needed ) {
9188 status = WERR_MORE_DATA;
9192 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9193 status = WERR_NOMEM;
9199 if ( q_u->size < r_u->needed )
9200 status = WERR_MORE_DATA;
9203 free_a_printer( &printer, 2 );
9204 SAFE_FREE( keynames );
9209 /********************************************************************
9210 * spoolss_deleteprinterkey
9211 ********************************************************************/
9213 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9215 POLICY_HND *handle = &q_u->handle;
9216 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9218 NT_PRINTER_INFO_LEVEL *printer = NULL;
9222 DEBUG(5,("spoolss_deleteprinterkey\n"));
9225 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9229 /* if keyname == NULL, return error */
9231 if ( !q_u->keyname.buffer )
9232 return WERR_INVALID_PARAM;
9234 if (!get_printer_snum(p, handle, &snum))
9237 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9238 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9239 return WERR_ACCESS_DENIED;
9242 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9243 if (!W_ERROR_IS_OK(status))
9246 /* delete the key and all subneys */
9248 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9250 status = delete_all_printer_data( printer->info_2, key );
9252 if ( W_ERROR_IS_OK(status) )
9253 status = mod_a_printer(printer, 2);
9255 free_a_printer( &printer, 2 );
9261 /********************************************************************
9262 * spoolss_enumprinterdataex
9263 ********************************************************************/
9265 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9267 POLICY_HND *handle = &q_u->handle;
9268 uint32 in_size = q_u->size;
9271 NT_PRINTER_INFO_LEVEL *printer = NULL;
9272 PRINTER_ENUM_VALUES *enum_values = NULL;
9273 NT_PRINTER_DATA *p_data;
9275 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9280 REGISTRY_VALUE *val;
9285 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9288 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9293 * first check for a keyname of NULL or "". Win2k seems to send
9294 * this a lot and we should send back WERR_INVALID_PARAM
9295 * no need to spend time looking up the printer in this case.
9299 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9300 if ( !strlen(key) ) {
9301 result = WERR_INVALID_PARAM;
9305 /* get the printer off of disk */
9307 if (!get_printer_snum(p,handle, &snum))
9310 ZERO_STRUCT(printer);
9311 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9312 if (!W_ERROR_IS_OK(result))
9315 /* now look for a match on the key name */
9317 p_data = printer->info_2->data;
9319 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9320 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9322 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9323 result = WERR_INVALID_PARAM;
9330 /* allocate the memory for the array of pointers -- if necessary */
9332 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9335 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9337 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9338 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9339 result = WERR_NOMEM;
9343 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9347 * loop through all params and build the array to pass
9348 * back to the client
9351 for ( i=0; i<num_entries; i++ )
9353 /* lookup the registry value */
9355 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9356 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9360 value_name = regval_name( val );
9361 init_unistr( &enum_values[i].valuename, value_name );
9362 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9363 enum_values[i].type = regval_type( val );
9365 data_len = regval_size( val );
9367 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9369 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9371 result = WERR_NOMEM;
9375 enum_values[i].data_len = data_len;
9377 /* keep track of the size of the array in bytes */
9379 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9382 /* housekeeping information in the reply */
9384 r_u->needed = needed;
9385 r_u->returned = num_entries;
9387 if (needed > in_size) {
9388 result = WERR_MORE_DATA;
9392 /* copy data into the reply */
9394 r_u->ctr.size = r_u->needed;
9395 r_u->ctr.size_of_array = r_u->returned;
9396 r_u->ctr.values = enum_values;
9402 free_a_printer(&printer, 2);
9407 /****************************************************************************
9408 ****************************************************************************/
9410 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9412 init_unistr(&info->name, name);
9415 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9416 UNISTR2 *environment,
9423 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9424 WERROR result = WERR_OK;
9426 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9428 if (!get_short_archi(long_archi))
9429 return WERR_INVALID_ENVIRONMENT;
9431 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9434 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9436 fill_printprocessordirectory_1(info, path);
9438 *needed += spoolss_size_printprocessordirectory_info_1(info);
9440 if (*needed > offered) {
9441 result = WERR_INSUFFICIENT_BUFFER;
9445 if (!rpcbuf_alloc_size(buffer, *needed)) {
9446 result = WERR_INSUFFICIENT_BUFFER;
9450 smb_io_printprocessordirectory_1("", buffer, info, 0);
9458 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9460 uint32 level = q_u->level;
9461 RPC_BUFFER *buffer = NULL;
9462 uint32 offered = q_u->offered;
9463 uint32 *needed = &r_u->needed;
9466 /* that's an [in out] buffer */
9468 if (!q_u->buffer && (offered!=0)) {
9469 return WERR_INVALID_PARAM;
9472 rpcbuf_move(q_u->buffer, &r_u->buffer);
9473 buffer = r_u->buffer;
9475 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9481 result = getprintprocessordirectory_level_1
9482 (&q_u->name, &q_u->environment, buffer, offered, needed);
9485 result = WERR_UNKNOWN_LEVEL;
9491 /*******************************************************************
9492 Streams the monitor UI DLL name in UNICODE
9493 *******************************************************************/
9495 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9496 RPC_BUFFER *out, uint32 *needed )
9498 const char *dllname = "tcpmonui.dll";
9500 *needed = (strlen(dllname)+1) * 2;
9502 if ( rpcbuf_get_size(out) < *needed ) {
9503 return WERR_INSUFFICIENT_BUFFER;
9506 if ( !make_monitorui_buf( out, dllname ) ) {
9513 /*******************************************************************
9514 Create a new TCP/IP port
9515 *******************************************************************/
9517 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9518 RPC_BUFFER *out, uint32 *needed )
9520 NT_PORT_DATA_1 port1;
9523 ZERO_STRUCT( port1 );
9525 /* convert to our internal port data structure */
9527 if ( !convert_port_data_1( &port1, in ) ) {
9531 /* create the device URI and call the add_port_hook() */
9533 switch ( port1.protocol ) {
9534 case PORT_PROTOCOL_DIRECT:
9535 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9538 case PORT_PROTOCOL_LPR:
9539 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9543 return WERR_UNKNOWN_PORT;
9546 return add_port_hook( token, port1.name, device_uri );
9549 /*******************************************************************
9550 *******************************************************************/
9552 struct xcv_api_table xcvtcp_cmds[] = {
9553 { "MonitorUI", xcvtcp_monitorui },
9554 { "AddPort", xcvtcp_addport},
9558 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9559 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9564 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9566 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9567 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9568 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9571 return WERR_BADFUNC;
9574 /*******************************************************************
9575 *******************************************************************/
9576 #if 0 /* don't support management using the "Local Port" monitor */
9578 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9579 RPC_BUFFER *out, uint32 *needed )
9581 const char *dllname = "localui.dll";
9583 *needed = (strlen(dllname)+1) * 2;
9585 if ( rpcbuf_get_size(out) < *needed ) {
9586 return WERR_INSUFFICIENT_BUFFER;
9589 if ( !make_monitorui_buf( out, dllname )) {
9596 /*******************************************************************
9597 *******************************************************************/
9599 struct xcv_api_table xcvlocal_cmds[] = {
9600 { "MonitorUI", xcvlocal_monitorui },
9604 struct xcv_api_table xcvlocal_cmds[] = {
9611 /*******************************************************************
9612 *******************************************************************/
9614 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9615 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9620 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9622 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9623 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9624 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9626 return WERR_BADFUNC;
9629 /*******************************************************************
9630 *******************************************************************/
9632 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9634 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9638 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9642 /* Has to be a handle to the TCP/IP port monitor */
9644 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9645 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9649 /* requires administrative access to the server */
9651 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9652 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9653 return WERR_ACCESS_DENIED;
9656 /* Get the command name. There's numerous commands supported by the
9657 TCPMON interface. */
9659 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9660 q_u->dataname.uni_str_len*2, 0);
9662 /* Allocate the outgoing buffer */
9664 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9666 switch ( Printer->printer_type ) {
9667 case SPLHND_PORTMON_TCP:
9668 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9669 &q_u->indata, &r_u->outdata, &r_u->needed );
9670 case SPLHND_PORTMON_LOCAL:
9671 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9672 &q_u->indata, &r_u->outdata, &r_u->needed );
9675 return WERR_INVALID_PRINT_MONITOR;