2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 extern userdom_struct current_user_info;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 /* Table to map the driver version */
46 static const char * drv_ver_to_os[] = {
47 "WIN9X", /* driver version/cversion 0 */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
53 static const char *get_drv_ver_to_os(int ver)
55 if (ver < 0 || ver > 3)
57 return drv_ver_to_os[ver];
61 const char *long_archi;
62 const char *short_archi;
66 static Printer_entry *printers_list;
68 typedef struct _counter_printer_0 {
69 struct _counter_printer_0 *next;
70 struct _counter_printer_0 *prev;
76 static counter_printer_0 *counter_list;
78 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
79 static uint32 smb_connections=0;
82 /* in printing/nt_printing.c */
84 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
86 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
87 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
90 /* API table for Xcv Monitor functions */
92 struct xcv_api_table {
94 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
98 /* translate between internal status numbers and NT status numbers */
99 static int nt_printj_status(int v)
105 return JOB_STATUS_PAUSED;
107 return JOB_STATUS_SPOOLING;
109 return JOB_STATUS_PRINTING;
111 return JOB_STATUS_ERROR;
113 return JOB_STATUS_DELETING;
115 return JOB_STATUS_OFFLINE;
117 return JOB_STATUS_PAPEROUT;
119 return JOB_STATUS_PRINTED;
121 return JOB_STATUS_DELETED;
123 return JOB_STATUS_BLOCKED;
124 case LPQ_USER_INTERVENTION:
125 return JOB_STATUS_USER_INTERVENTION;
130 static int nt_printq_status(int v)
134 return PRINTER_STATUS_PAUSED;
143 /****************************************************************************
144 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
145 ****************************************************************************/
147 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
152 SAFE_FREE((*pp)->ctr.type);
156 /***************************************************************************
157 Disconnect from the client
158 ****************************************************************************/
160 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
165 * Tell the specific printing tdb we no longer want messages for this printer
166 * by deregistering our PID.
169 if (!print_notify_deregister_pid(snum))
170 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
172 /* weird if the test succeds !!! */
173 if (smb_connections==0) {
174 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
178 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
180 if (!W_ERROR_IS_OK(result))
181 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
182 dos_errstr(result)));
184 /* if it's the last connection, deconnect the IPC$ share */
185 if (smb_connections==1) {
187 cli_shutdown( notify_cli_pipe->cli );
188 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
190 message_deregister(MSG_PRINTER_NOTIFY2);
192 /* Tell the connections db we're no longer interested in
193 * printer notify messages. */
195 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
201 /****************************************************************************
202 Functions to free a printer entry datastruct.
203 ****************************************************************************/
205 static void free_printer_entry(void *ptr)
207 Printer_entry *Printer = (Printer_entry *)ptr;
209 if (Printer->notify.client_connected==True) {
212 if ( Printer->printer_type == SPLHND_SERVER) {
214 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
215 } else if (Printer->printer_type == SPLHND_PRINTER) {
216 snum = print_queue_snum(Printer->sharename);
218 srv_spoolss_replycloseprinter(snum,
219 &Printer->notify.client_hnd);
223 Printer->notify.flags=0;
224 Printer->notify.options=0;
225 Printer->notify.localmachine[0]='\0';
226 Printer->notify.printerlocal=0;
227 free_spool_notify_option(&Printer->notify.option);
228 Printer->notify.option=NULL;
229 Printer->notify.client_connected=False;
231 free_nt_devicemode( &Printer->nt_devmode );
232 free_a_printer( &Printer->printer_info, 2 );
234 talloc_destroy( Printer->ctx );
236 /* Remove from the internal list. */
237 DLIST_REMOVE(printers_list, Printer);
242 /****************************************************************************
243 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
244 ****************************************************************************/
246 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
248 SPOOL_NOTIFY_OPTION *new_sp = NULL;
253 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
260 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
262 if (!new_sp->ctr.type) {
271 /****************************************************************************
272 find printer index by handle
273 ****************************************************************************/
275 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
277 Printer_entry *find_printer = NULL;
279 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
280 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
287 /****************************************************************************
288 Close printer index by handle.
289 ****************************************************************************/
291 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
293 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
296 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
300 close_policy_hnd(p, hnd);
305 /****************************************************************************
306 Delete a printer given a handle.
307 ****************************************************************************/
308 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
310 char *cmd = lp_deleteprinter_cmd();
313 SE_PRIV se_printop = SE_PRINT_OPERATOR;
314 BOOL is_print_op = False;
316 /* can't fail if we don't try */
321 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
324 is_print_op = user_has_privileges( token, &se_printop );
326 DEBUG(10,("Running [%s]\n", command));
328 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
333 if ( (ret = smbrun(command, NULL)) == 0 ) {
334 /* Tell everyone we updated smb.conf. */
335 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
341 /********** END SePrintOperatorPrivlege BLOCK **********/
343 DEBUGADD(10,("returned [%d]\n", ret));
346 return WERR_BADFID; /* What to return here? */
348 /* go ahead and re-read the services immediately */
349 reload_services( False );
351 if ( lp_servicenumber( sharename ) < 0 )
352 return WERR_ACCESS_DENIED;
357 /****************************************************************************
358 Delete a printer given a handle.
359 ****************************************************************************/
361 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
363 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
366 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
371 * It turns out that Windows allows delete printer on a handle
372 * opened by an admin user, then used on a pipe handle created
373 * by an anonymous user..... but they're working on security.... riiight !
377 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
378 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
379 return WERR_ACCESS_DENIED;
382 /* this does not need a become root since the access check has been
383 done on the handle already */
385 if (del_a_printer( Printer->sharename ) != 0) {
386 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
390 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
393 /****************************************************************************
394 Return the snum of a printer corresponding to an handle.
395 ****************************************************************************/
397 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
399 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
402 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
406 switch (Printer->printer_type) {
408 DEBUG(4,("short name:%s\n", Printer->sharename));
409 *number = print_queue_snum(Printer->sharename);
410 return (*number != -1);
418 /****************************************************************************
419 Set printer handle type.
420 Check if it's \\server or \\server\printer
421 ****************************************************************************/
423 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
425 DEBUG(3,("Setting printer type=%s\n", handlename));
427 if ( strlen(handlename) < 3 ) {
428 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
432 /* it's a print server */
433 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
434 DEBUGADD(4,("Printer is a print server\n"));
435 Printer->printer_type = SPLHND_SERVER;
437 /* it's a printer (set_printer_hnd_name() will handle port monitors */
439 DEBUGADD(4,("Printer is a printer\n"));
440 Printer->printer_type = SPLHND_PRINTER;
446 /****************************************************************************
447 Set printer handle name.. Accept names like \\server, \\server\printer,
448 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
449 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
450 XcvDataPort() interface.
451 ****************************************************************************/
453 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
456 int n_services=lp_numservices();
457 char *aprinter, *printername;
458 const char *servername;
461 NT_PRINTER_INFO_LEVEL *printer;
464 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
466 aprinter = handlename;
467 if ( *handlename == '\\' ) {
468 servername = handlename + 2;
469 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
478 /* save the servername to fill in replies on this handle */
480 if ( !is_myname_or_ipaddr( servername ) )
483 fstrcpy( Printer->servername, servername );
485 if ( Printer->printer_type == SPLHND_SERVER )
488 if ( Printer->printer_type != SPLHND_PRINTER )
491 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
493 /* check for the Port Monitor Interface */
495 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
496 Printer->printer_type = SPLHND_PORTMON_TCP;
497 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
500 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
501 Printer->printer_type = SPLHND_PORTMON_LOCAL;
502 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
506 /* Search all sharenames first as this is easier than pulling
507 the printer_info_2 off of disk. Don't use find_service() since
508 that calls out to map_username() */
510 /* do another loop to look for printernames */
512 for (snum=0; !found && snum<n_services; snum++) {
514 /* no point going on if this is not a printer */
516 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
519 fstrcpy(sname, lp_servicename(snum));
520 if ( strequal( aprinter, sname ) ) {
525 /* no point looking up the printer object if
526 we aren't allowing printername != sharename */
528 if ( lp_force_printername(snum) )
531 fstrcpy(sname, lp_servicename(snum));
534 result = get_a_printer( NULL, &printer, 2, sname );
535 if ( !W_ERROR_IS_OK(result) ) {
536 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
537 sname, dos_errstr(result)));
541 /* printername is always returned as \\server\printername */
542 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
543 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
544 printer->info_2->printername));
545 free_a_printer( &printer, 2);
551 if ( strequal(printername, aprinter) ) {
556 DEBUGADD(10, ("printername: %s\n", printername));
558 free_a_printer( &printer, 2);
562 DEBUGADD(4,("Printer not found\n"));
566 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
568 fstrcpy(Printer->sharename, sname);
573 /****************************************************************************
574 Find first available printer slot. creates a printer handle for you.
575 ****************************************************************************/
577 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
579 Printer_entry *new_printer;
581 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
583 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
586 ZERO_STRUCTP(new_printer);
588 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
589 SAFE_FREE(new_printer);
593 /* Add to the internal list. */
594 DLIST_ADD(printers_list, new_printer);
596 new_printer->notify.option=NULL;
598 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
599 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
600 close_printer_handle(p, hnd);
604 if (!set_printer_hnd_printertype(new_printer, name)) {
605 close_printer_handle(p, hnd);
609 if (!set_printer_hnd_name(new_printer, name)) {
610 close_printer_handle(p, hnd);
614 new_printer->access_granted = access_granted;
616 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
621 /***************************************************************************
622 check to see if the client motify handle is monitoring the notification
623 given by (notify_type, notify_field).
624 **************************************************************************/
626 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
632 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
635 SPOOL_NOTIFY_OPTION *option = p->notify.option;
639 * Flags should always be zero when the change notify
640 * is registered by the client's spooler. A user Win32 app
641 * might use the flags though instead of the NOTIFY_OPTION_INFO
650 return is_monitoring_event_flags(
651 p->notify.flags, notify_type, notify_field);
653 for (i = 0; i < option->count; i++) {
655 /* Check match for notify_type */
657 if (option->ctr.type[i].type != notify_type)
660 /* Check match for field */
662 for (j = 0; j < option->ctr.type[i].count; j++) {
663 if (option->ctr.type[i].fields[j] == notify_field) {
669 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
670 p->servername, p->sharename, notify_type, notify_field));
675 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
677 static void notify_one_value(struct spoolss_notify_msg *msg,
678 SPOOL_NOTIFY_INFO_DATA *data,
681 data->notify_data.value[0] = msg->notify.value[0];
682 data->notify_data.value[1] = 0;
685 static void notify_string(struct spoolss_notify_msg *msg,
686 SPOOL_NOTIFY_INFO_DATA *data,
691 /* The length of the message includes the trailing \0 */
693 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
695 data->notify_data.data.length = msg->len * 2;
696 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
698 if (!data->notify_data.data.string) {
699 data->notify_data.data.length = 0;
703 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
706 static void notify_system_time(struct spoolss_notify_msg *msg,
707 SPOOL_NOTIFY_INFO_DATA *data,
713 if (msg->len != sizeof(time_t)) {
714 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
719 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
720 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
724 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
725 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
729 if (!spoolss_io_system_time("", &ps, 0, &systime))
732 data->notify_data.data.length = prs_offset(&ps);
733 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
735 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
740 struct notify2_message_table {
742 void (*fn)(struct spoolss_notify_msg *msg,
743 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
746 static struct notify2_message_table printer_notify_table[] = {
747 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
748 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
749 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
750 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
751 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
752 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
753 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
754 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
755 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
756 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
757 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
758 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
759 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
760 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
761 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
762 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
763 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
764 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
765 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
768 static struct notify2_message_table job_notify_table[] = {
769 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
770 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
771 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
772 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
773 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
774 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
775 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
776 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
777 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
778 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
779 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
780 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
781 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
782 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
783 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
784 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
785 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
786 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
787 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
788 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
789 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
790 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
791 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
792 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
796 /***********************************************************************
797 Allocate talloc context for container object
798 **********************************************************************/
800 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
805 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
810 /***********************************************************************
811 release all allocated memory and zero out structure
812 **********************************************************************/
814 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
820 talloc_destroy(ctr->ctx);
827 /***********************************************************************
828 **********************************************************************/
830 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
838 /***********************************************************************
839 **********************************************************************/
841 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
843 if ( !ctr || !ctr->msg_groups )
846 if ( idx >= ctr->num_groups )
849 return &ctr->msg_groups[idx];
853 /***********************************************************************
854 How many groups of change messages do we have ?
855 **********************************************************************/
857 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
862 return ctr->num_groups;
865 /***********************************************************************
866 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
867 **********************************************************************/
869 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
871 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
872 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
873 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
879 /* loop over all groups looking for a matching printer name */
881 for ( i=0; i<ctr->num_groups; i++ ) {
882 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
886 /* add a new group? */
888 if ( i == ctr->num_groups ) {
891 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
892 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
895 ctr->msg_groups = groups;
897 /* clear the new entry and set the printer name */
899 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
900 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
903 /* add the change messages; 'i' is the correct index now regardless */
905 msg_grp = &ctr->msg_groups[i];
909 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
910 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
913 msg_grp->msgs = msg_list;
915 new_slot = msg_grp->num_msgs-1;
916 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
918 /* need to allocate own copy of data */
921 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
923 return ctr->num_groups;
926 /***********************************************************************
927 Send a change notication message on all handles which have a call
929 **********************************************************************/
931 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
934 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
935 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
936 SPOOLSS_NOTIFY_MSG *messages;
937 int sending_msg_count;
940 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
944 messages = msg_group->msgs;
947 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
951 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
953 /* loop over all printers */
955 for (p = printers_list; p; p = p->next) {
956 SPOOL_NOTIFY_INFO_DATA *data;
961 /* Is there notification on this handle? */
963 if ( !p->notify.client_connected )
966 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
968 /* For this printer? Print servers always receive
971 if ( ( p->printer_type == SPLHND_PRINTER ) &&
972 ( !strequal(msg_group->printername, p->sharename) ) )
975 DEBUG(10,("Our printer\n"));
977 /* allocate the max entries possible */
979 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
982 /* build the array of change notifications */
984 sending_msg_count = 0;
986 for ( i=0; i<msg_group->num_msgs; i++ ) {
987 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
989 /* Are we monitoring this event? */
991 if (!is_monitoring_event(p, msg->type, msg->field))
997 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
998 msg->type, msg->field, p->sharename));
1001 * if the is a printer notification handle and not a job notification
1002 * type, then set the id to 0. Other wise just use what was specified
1005 * When registering change notification on a print server handle
1006 * we always need to send back the id (snum) matching the printer
1007 * for which the change took place. For change notify registered
1008 * on a printer handle, this does not matter and the id should be 0.
1013 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1019 /* Convert unix jobid to smb jobid */
1021 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1022 id = sysjob_to_jobid(msg->id);
1025 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1030 construct_info_data( &data[data_len], msg->type, msg->field, id );
1033 case PRINTER_NOTIFY_TYPE:
1034 if ( printer_notify_table[msg->field].fn )
1035 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1038 case JOB_NOTIFY_TYPE:
1039 if ( job_notify_table[msg->field].fn )
1040 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1044 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1051 if ( sending_msg_count ) {
1052 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1053 data_len, data, p->notify.change, 0 );
1058 DEBUG(8,("send_notify2_changes: Exit...\n"));
1062 /***********************************************************************
1063 **********************************************************************/
1065 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1068 uint32 tv_sec, tv_usec;
1071 /* Unpack message */
1073 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1076 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1078 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1081 tdb_unpack((char *)buf + offset, len - offset, "dd",
1082 &msg->notify.value[0], &msg->notify.value[1]);
1084 tdb_unpack((char *)buf + offset, len - offset, "B",
1085 &msg->len, &msg->notify.data);
1087 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1088 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1090 tv->tv_sec = tv_sec;
1091 tv->tv_usec = tv_usec;
1094 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1095 msg->notify.value[1]));
1097 dump_data(3, msg->notify.data, msg->len);
1102 /********************************************************************
1103 Receive a notify2 message list
1104 ********************************************************************/
1106 static void receive_notify2_message_list(int msg_type, struct process_id src,
1107 void *msg, size_t len)
1109 size_t msg_count, i;
1110 char *buf = (char *)msg;
1113 SPOOLSS_NOTIFY_MSG notify;
1114 SPOOLSS_NOTIFY_MSG_CTR messages;
1118 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1122 msg_count = IVAL(buf, 0);
1125 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1127 if (msg_count == 0) {
1128 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1132 /* initialize the container */
1134 ZERO_STRUCT( messages );
1135 notify_msg_ctr_init( &messages );
1138 * build message groups for each printer identified
1139 * in a change_notify msg. Remember that a PCN message
1140 * includes the handle returned for the srv_spoolss_replyopenprinter()
1141 * call. Therefore messages are grouped according to printer handle.
1144 for ( i=0; i<msg_count; i++ ) {
1145 struct timeval msg_tv;
1147 if (msg_ptr + 4 - buf > len) {
1148 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1152 msg_len = IVAL(msg_ptr,0);
1155 if (msg_ptr + msg_len - buf > len) {
1156 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1160 /* unpack messages */
1162 ZERO_STRUCT( notify );
1163 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1166 /* add to correct list in container */
1168 notify_msg_ctr_addmsg( &messages, ¬ify );
1170 /* free memory that might have been allocated by notify2_unpack_msg() */
1172 if ( notify.len != 0 )
1173 SAFE_FREE( notify.notify.data );
1176 /* process each group of messages */
1178 num_groups = notify_msg_ctr_numgroups( &messages );
1179 for ( i=0; i<num_groups; i++ )
1180 send_notify2_changes( &messages, i );
1185 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1187 notify_msg_ctr_destroy( &messages );
1192 /********************************************************************
1193 Send a message to ourself about new driver being installed
1194 so we can upgrade the information for each printer bound to this
1196 ********************************************************************/
1198 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1200 int len = strlen(drivername);
1205 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1208 message_send_pid(pid_to_procid(sys_getpid()),
1209 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1214 /**********************************************************************
1215 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1216 over all printers, upgrading ones as necessary
1217 **********************************************************************/
1219 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1223 int n_services = lp_numservices();
1225 len = MIN(len,sizeof(drivername)-1);
1226 strncpy(drivername, buf, len);
1228 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1230 /* Iterate the printer list */
1232 for (snum=0; snum<n_services; snum++)
1234 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1237 NT_PRINTER_INFO_LEVEL *printer = NULL;
1239 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1240 if (!W_ERROR_IS_OK(result))
1243 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1245 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1247 /* all we care about currently is the change_id */
1249 result = mod_a_printer(printer, 2);
1250 if (!W_ERROR_IS_OK(result)) {
1251 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1252 dos_errstr(result)));
1256 free_a_printer(&printer, 2);
1263 /********************************************************************
1264 Update the cache for all printq's with a registered client
1266 ********************************************************************/
1268 void update_monitored_printq_cache( void )
1270 Printer_entry *printer = printers_list;
1273 /* loop through all printers and update the cache where
1274 client_connected == True */
1277 if ( (printer->printer_type == SPLHND_PRINTER)
1278 && printer->notify.client_connected )
1280 snum = print_queue_snum(printer->sharename);
1281 print_queue_status( snum, NULL, NULL );
1284 printer = printer->next;
1289 /********************************************************************
1290 Send a message to ourself about new driver being installed
1291 so we can upgrade the information for each printer bound to this
1293 ********************************************************************/
1295 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1297 int len = strlen(drivername);
1302 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1305 message_send_pid(pid_to_procid(sys_getpid()),
1306 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1311 /**********************************************************************
1312 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1313 over all printers, resetting printer data as neessary
1314 **********************************************************************/
1316 void reset_all_printerdata(int msg_type, struct process_id src,
1317 void *buf, size_t len)
1321 int n_services = lp_numservices();
1323 len = MIN( len, sizeof(drivername)-1 );
1324 strncpy( drivername, buf, len );
1326 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1328 /* Iterate the printer list */
1330 for ( snum=0; snum<n_services; snum++ )
1332 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1335 NT_PRINTER_INFO_LEVEL *printer = NULL;
1337 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1338 if ( !W_ERROR_IS_OK(result) )
1342 * if the printer is bound to the driver,
1343 * then reset to the new driver initdata
1346 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1348 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1350 if ( !set_driver_init(printer, 2) ) {
1351 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1352 printer->info_2->printername, printer->info_2->drivername));
1355 result = mod_a_printer( printer, 2 );
1356 if ( !W_ERROR_IS_OK(result) ) {
1357 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1358 get_dos_error_msg(result)));
1362 free_a_printer( &printer, 2 );
1371 /********************************************************************
1372 Copy routines used by convert_to_openprinterex()
1373 *******************************************************************/
1375 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1383 DEBUG (8,("dup_devmode\n"));
1385 /* bulk copy first */
1387 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1391 /* dup the pointer members separately */
1393 len = unistrlen(devmode->devicename.buffer);
1395 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1396 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1401 len = unistrlen(devmode->formname.buffer);
1403 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1404 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1408 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1413 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1415 if (!new_ctr || !ctr)
1418 DEBUG(8,("copy_devmode_ctr\n"));
1420 new_ctr->size = ctr->size;
1421 new_ctr->devmode_ptr = ctr->devmode_ptr;
1423 if(ctr->devmode_ptr)
1424 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1427 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1429 if (!new_def || !def)
1432 DEBUG(8,("copy_printer_defaults\n"));
1434 new_def->datatype_ptr = def->datatype_ptr;
1436 if (def->datatype_ptr)
1437 copy_unistr2(&new_def->datatype, &def->datatype);
1439 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1441 new_def->access_required = def->access_required;
1444 /********************************************************************
1445 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1446 * SPOOL_Q_OPEN_PRINTER_EX structure
1447 ********************************************************************/
1449 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1451 if (!q_u_ex || !q_u)
1454 DEBUG(8,("convert_to_openprinterex\n"));
1456 if ( q_u->printername ) {
1457 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1458 if (q_u_ex->printername == NULL)
1460 copy_unistr2(q_u_ex->printername, q_u->printername);
1463 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1468 /********************************************************************
1469 * spoolss_open_printer
1471 * called from the spoolss dispatcher
1472 ********************************************************************/
1474 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1476 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1477 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1482 ZERO_STRUCT(q_u_ex);
1483 ZERO_STRUCT(r_u_ex);
1485 /* convert the OpenPrinter() call to OpenPrinterEx() */
1487 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1488 if (!W_ERROR_IS_OK(r_u_ex.status))
1489 return r_u_ex.status;
1491 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1493 /* convert back to OpenPrinter() */
1495 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1500 /********************************************************************
1501 ********************************************************************/
1503 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1505 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1506 POLICY_HND *handle = &r_u->handle;
1510 struct current_user user;
1511 Printer_entry *Printer=NULL;
1513 if ( !q_u->printername )
1514 return WERR_INVALID_PRINTER_NAME;
1516 /* some sanity check because you can open a printer or a print server */
1517 /* aka: \\server\printer or \\server */
1519 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1521 DEBUGADD(3,("checking name: %s\n",name));
1523 if (!open_printer_hnd(p, handle, name, 0))
1524 return WERR_INVALID_PRINTER_NAME;
1526 Printer=find_printer_index_by_hnd(p, handle);
1528 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1529 "handle we created for printer %s\n", name ));
1530 close_printer_handle(p,handle);
1531 return WERR_INVALID_PRINTER_NAME;
1534 get_current_user(&user, p);
1537 * First case: the user is opening the print server:
1539 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1540 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1542 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1543 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1544 * or if the user is listed in the smb.conf printer admin parameter.
1546 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1547 * client view printer folder, but does not show the MSAPW.
1549 * Note: this test needs code to check access rights here too. Jeremy
1550 * could you look at this?
1552 * Second case: the user is opening a printer:
1553 * NT doesn't let us connect to a printer if the connecting user
1554 * doesn't have print permission.
1556 * Third case: user is opening a Port Monitor
1557 * access checks same as opening a handle to the print server.
1560 switch (Printer->printer_type )
1563 case SPLHND_PORTMON_TCP:
1564 case SPLHND_PORTMON_LOCAL:
1565 /* Printserver handles use global struct... */
1569 /* Map standard access rights to object specific access rights */
1571 se_map_standard(&printer_default->access_required,
1572 &printserver_std_mapping);
1574 /* Deny any object specific bits that don't apply to print
1575 servers (i.e printer and job specific bits) */
1577 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1579 if (printer_default->access_required &
1580 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1581 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1582 close_printer_handle(p, handle);
1583 return WERR_ACCESS_DENIED;
1586 /* Allow admin access */
1588 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1590 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1592 if (!lp_ms_add_printer_wizard()) {
1593 close_printer_handle(p, handle);
1594 return WERR_ACCESS_DENIED;
1597 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1598 and not a printer admin, then fail */
1600 if ((user.ut.uid != 0) &&
1601 !user_has_privileges(user.nt_user_token,
1603 !token_contains_name_in_list(
1604 uidtoname(user.ut.uid), NULL,
1606 lp_printer_admin(snum))) {
1607 close_printer_handle(p, handle);
1608 return WERR_ACCESS_DENIED;
1611 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1615 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1618 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1619 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1621 /* We fall through to return WERR_OK */
1624 case SPLHND_PRINTER:
1625 /* NT doesn't let us connect to a printer if the connecting user
1626 doesn't have print permission. */
1628 if (!get_printer_snum(p, handle, &snum)) {
1629 close_printer_handle(p, handle);
1633 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1635 /* map an empty access mask to the minimum access mask */
1636 if (printer_default->access_required == 0x0)
1637 printer_default->access_required = PRINTER_ACCESS_USE;
1640 * If we are not serving the printer driver for this printer,
1641 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1642 * will keep NT clients happy --jerry
1645 if (lp_use_client_driver(snum)
1646 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1648 printer_default->access_required = PRINTER_ACCESS_USE;
1651 /* check smb.conf parameters and the the sec_desc */
1653 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1654 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1655 return WERR_ACCESS_DENIED;
1658 if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
1660 !print_access_check(&user, snum,
1661 printer_default->access_required)) {
1662 DEBUG(3, ("access DENIED for printer open\n"));
1663 close_printer_handle(p, handle);
1664 return WERR_ACCESS_DENIED;
1667 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1668 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1669 close_printer_handle(p, handle);
1670 return WERR_ACCESS_DENIED;
1673 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1674 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1676 printer_default->access_required = PRINTER_ACCESS_USE;
1678 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1679 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1684 /* sanity check to prevent programmer error */
1688 Printer->access_granted = printer_default->access_required;
1691 * If the client sent a devmode in the OpenPrinter() call, then
1692 * save it here in case we get a job submission on this handle
1695 if ( (Printer->printer_type != SPLHND_SERVER)
1696 && q_u->printer_default.devmode_cont.devmode_ptr )
1698 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1699 &Printer->nt_devmode );
1702 #if 0 /* JERRY -- I'm doubtful this is really effective */
1703 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1704 optimization in Windows 2000 clients --jerry */
1706 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1707 && (RA_WIN2K == get_remote_arch()) )
1709 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1710 sys_usleep( 500000 );
1717 /****************************************************************************
1718 ****************************************************************************/
1720 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1721 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1727 /* allocate memory if needed. Messy because
1728 convert_printer_info is used to update an existing
1729 printer or build a new one */
1731 if ( !printer->info_2 ) {
1732 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1733 if ( !printer->info_2 ) {
1734 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1739 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1740 printer->info_2->setuptime = time(NULL);
1748 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1749 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1755 printer->info_3=NULL;
1756 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1760 printer->info_6=NULL;
1761 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1771 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1772 NT_DEVICEMODE **pp_nt_devmode)
1774 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1777 * Ensure nt_devmode is a valid pointer
1778 * as we will be overwriting it.
1781 if (nt_devmode == NULL) {
1782 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1783 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1787 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1788 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1790 nt_devmode->specversion=devmode->specversion;
1791 nt_devmode->driverversion=devmode->driverversion;
1792 nt_devmode->size=devmode->size;
1793 nt_devmode->fields=devmode->fields;
1794 nt_devmode->orientation=devmode->orientation;
1795 nt_devmode->papersize=devmode->papersize;
1796 nt_devmode->paperlength=devmode->paperlength;
1797 nt_devmode->paperwidth=devmode->paperwidth;
1798 nt_devmode->scale=devmode->scale;
1799 nt_devmode->copies=devmode->copies;
1800 nt_devmode->defaultsource=devmode->defaultsource;
1801 nt_devmode->printquality=devmode->printquality;
1802 nt_devmode->color=devmode->color;
1803 nt_devmode->duplex=devmode->duplex;
1804 nt_devmode->yresolution=devmode->yresolution;
1805 nt_devmode->ttoption=devmode->ttoption;
1806 nt_devmode->collate=devmode->collate;
1808 nt_devmode->logpixels=devmode->logpixels;
1809 nt_devmode->bitsperpel=devmode->bitsperpel;
1810 nt_devmode->pelswidth=devmode->pelswidth;
1811 nt_devmode->pelsheight=devmode->pelsheight;
1812 nt_devmode->displayflags=devmode->displayflags;
1813 nt_devmode->displayfrequency=devmode->displayfrequency;
1814 nt_devmode->icmmethod=devmode->icmmethod;
1815 nt_devmode->icmintent=devmode->icmintent;
1816 nt_devmode->mediatype=devmode->mediatype;
1817 nt_devmode->dithertype=devmode->dithertype;
1818 nt_devmode->reserved1=devmode->reserved1;
1819 nt_devmode->reserved2=devmode->reserved2;
1820 nt_devmode->panningwidth=devmode->panningwidth;
1821 nt_devmode->panningheight=devmode->panningheight;
1824 * Only change private and driverextra if the incoming devmode
1825 * has a new one. JRA.
1828 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1829 SAFE_FREE(nt_devmode->nt_dev_private);
1830 nt_devmode->driverextra=devmode->driverextra;
1831 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1833 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1836 *pp_nt_devmode = nt_devmode;
1841 /********************************************************************
1842 * _spoolss_enddocprinter_internal.
1843 ********************************************************************/
1845 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1847 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1851 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1855 if (!get_printer_snum(p, handle, &snum))
1858 Printer->document_started=False;
1859 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1860 /* error codes unhandled so far ... */
1865 /********************************************************************
1866 * api_spoolss_closeprinter
1867 ********************************************************************/
1869 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1871 POLICY_HND *handle = &q_u->handle;
1873 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1875 if (Printer && Printer->document_started)
1876 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1878 if (!close_printer_handle(p, handle))
1881 /* clear the returned printer handle. Observed behavior
1882 from Win2k server. Don't think this really matters.
1883 Previous code just copied the value of the closed
1886 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1891 /********************************************************************
1892 * api_spoolss_deleteprinter
1894 ********************************************************************/
1896 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1898 POLICY_HND *handle = &q_u->handle;
1899 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1902 if (Printer && Printer->document_started)
1903 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1905 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1907 result = delete_printer_handle(p, handle);
1909 update_c_setprinter(False);
1914 /*******************************************************************
1915 * static function to lookup the version id corresponding to an
1916 * long architecture string
1917 ******************************************************************/
1919 static int get_version_id (char * arch)
1922 struct table_node archi_table[]= {
1924 {"Windows 4.0", "WIN40", 0 },
1925 {"Windows NT x86", "W32X86", 2 },
1926 {"Windows NT R4000", "W32MIPS", 2 },
1927 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1928 {"Windows NT PowerPC", "W32PPC", 2 },
1929 {"Windows IA64", "IA64", 3 },
1930 {"Windows x64", "x64", 3 },
1934 for (i=0; archi_table[i].long_archi != NULL; i++)
1936 if (strcmp(arch, archi_table[i].long_archi) == 0)
1937 return (archi_table[i].version);
1943 /********************************************************************
1944 * _spoolss_deleteprinterdriver
1945 ********************************************************************/
1947 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1951 NT_PRINTER_DRIVER_INFO_LEVEL info;
1952 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1954 struct current_user user;
1956 WERROR status_win2k = WERR_ACCESS_DENIED;
1957 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1959 get_current_user(&user, p);
1961 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1962 and not a printer admin, then fail */
1964 if ( (user.ut.uid != 0)
1965 && !user_has_privileges(user.nt_user_token, &se_printop )
1966 && !token_contains_name_in_list( uidtoname(user.ut.uid),
1967 NULL, user.nt_user_token, lp_printer_admin(-1)) )
1969 return WERR_ACCESS_DENIED;
1972 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1973 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1975 /* check that we have a valid driver name first */
1977 if ((version=get_version_id(arch)) == -1)
1978 return WERR_INVALID_ENVIRONMENT;
1981 ZERO_STRUCT(info_win2k);
1983 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1985 /* try for Win2k driver if "Windows NT x86" */
1987 if ( version == 2 ) {
1989 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1990 status = WERR_UNKNOWN_PRINTER_DRIVER;
1994 /* otherwise it was a failure */
1996 status = WERR_UNKNOWN_PRINTER_DRIVER;
2002 if (printer_driver_in_use(info.info_3)) {
2003 status = WERR_PRINTER_DRIVER_IN_USE;
2009 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2011 /* if we get to here, we now have 2 driver info structures to remove */
2012 /* remove the Win2k driver first*/
2014 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2015 free_a_printer_driver( info_win2k, 3 );
2017 /* this should not have failed---if it did, report to client */
2018 if ( !W_ERROR_IS_OK(status_win2k) )
2020 status = status_win2k;
2026 status = delete_printer_driver(info.info_3, &user, version, False);
2028 /* if at least one of the deletes succeeded return OK */
2030 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2034 free_a_printer_driver( info, 3 );
2039 /********************************************************************
2040 * spoolss_deleteprinterdriverex
2041 ********************************************************************/
2043 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2047 NT_PRINTER_DRIVER_INFO_LEVEL info;
2048 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2050 uint32 flags = q_u->delete_flags;
2052 struct current_user user;
2054 WERROR status_win2k = WERR_ACCESS_DENIED;
2055 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2057 get_current_user(&user, p);
2059 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2060 and not a printer admin, then fail */
2062 if ( (user.ut.uid != 0)
2063 && !user_has_privileges(user.nt_user_token, &se_printop )
2064 && !token_contains_name_in_list( uidtoname(user.ut.uid),
2065 NULL, user.nt_user_token, lp_printer_admin(-1)) )
2067 return WERR_ACCESS_DENIED;
2070 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2071 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2073 /* check that we have a valid driver name first */
2074 if ((version=get_version_id(arch)) == -1) {
2075 /* this is what NT returns */
2076 return WERR_INVALID_ENVIRONMENT;
2079 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2080 version = q_u->version;
2083 ZERO_STRUCT(info_win2k);
2085 status = get_a_printer_driver(&info, 3, driver, arch, version);
2087 if ( !W_ERROR_IS_OK(status) )
2090 * if the client asked for a specific version,
2091 * or this is something other than Windows NT x86,
2095 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2098 /* try for Win2k driver if "Windows NT x86" */
2101 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2102 status = WERR_UNKNOWN_PRINTER_DRIVER;
2107 if ( printer_driver_in_use(info.info_3) ) {
2108 status = WERR_PRINTER_DRIVER_IN_USE;
2113 * we have a couple of cases to consider.
2114 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2115 * then the delete should fail if **any** files overlap with
2117 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2118 * non-overlapping files
2119 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2120 * is set, the do not delete any files
2121 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2124 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2126 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2128 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2129 /* no idea of the correct error here */
2130 status = WERR_ACCESS_DENIED;
2135 /* also check for W32X86/3 if necessary; maybe we already have? */
2137 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2138 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2141 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2142 /* no idea of the correct error here */
2143 free_a_printer_driver( info_win2k, 3 );
2144 status = WERR_ACCESS_DENIED;
2148 /* if we get to here, we now have 2 driver info structures to remove */
2149 /* remove the Win2k driver first*/
2151 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2152 free_a_printer_driver( info_win2k, 3 );
2154 /* this should not have failed---if it did, report to client */
2156 if ( !W_ERROR_IS_OK(status_win2k) )
2161 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2163 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2166 free_a_printer_driver( info, 3 );
2172 /****************************************************************************
2173 Internal routine for retreiving printerdata
2174 ***************************************************************************/
2176 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2177 const char *key, const char *value, uint32 *type, uint8 **data,
2178 uint32 *needed, uint32 in_size )
2180 REGISTRY_VALUE *val;
2184 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2185 return WERR_BADFILE;
2187 *type = regval_type( val );
2189 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2191 size = regval_size( val );
2193 /* copy the min(in_size, len) */
2196 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2198 /* special case for 0 length values */
2200 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2204 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2213 DEBUG(5,("get_printer_dataex: copy done\n"));
2218 /****************************************************************************
2219 Internal routine for removing printerdata
2220 ***************************************************************************/
2222 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2224 return delete_printer_data( printer->info_2, key, value );
2227 /****************************************************************************
2228 Internal routine for storing printerdata
2229 ***************************************************************************/
2231 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2232 uint32 type, uint8 *data, int real_len )
2234 /* the registry objects enforce uniqueness based on value name */
2236 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2239 /********************************************************************
2240 GetPrinterData on a printer server Handle.
2241 ********************************************************************/
2243 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2247 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2249 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2251 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2257 if (!StrCaseCmp(value, "BeepEnabled")) {
2259 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2261 SIVAL(*data, 0, 0x00);
2266 if (!StrCaseCmp(value, "EventLog")) {
2268 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2270 /* formally was 0x1b */
2271 SIVAL(*data, 0, 0x0);
2276 if (!StrCaseCmp(value, "NetPopup")) {
2278 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2280 SIVAL(*data, 0, 0x00);
2285 if (!StrCaseCmp(value, "MajorVersion")) {
2287 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2290 /* Windows NT 4.0 seems to not allow uploading of drivers
2291 to a server that reports 0x3 as the MajorVersion.
2292 need to investigate more how Win2k gets around this .
2295 if ( RA_WINNT == get_remote_arch() )
2304 if (!StrCaseCmp(value, "MinorVersion")) {
2306 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2314 * uint32 size = 0x114
2316 * uint32 minor = [0|1]
2317 * uint32 build = [2195|2600]
2318 * extra unicode string = e.g. "Service Pack 3"
2320 if (!StrCaseCmp(value, "OSVersion")) {
2324 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2327 SIVAL(*data, 0, *needed); /* size */
2328 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2330 SIVAL(*data, 12, 2195); /* build */
2332 /* leave extra string empty */
2338 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2339 const char *string="C:\\PRINTERS";
2341 *needed = 2*(strlen(string)+1);
2342 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2344 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2346 /* it's done by hand ready to go on the wire */
2347 for (i=0; i<strlen(string); i++) {
2348 (*data)[2*i]=string[i];
2349 (*data)[2*i+1]='\0';
2354 if (!StrCaseCmp(value, "Architecture")) {
2355 const char *string="Windows NT x86";
2357 *needed = 2*(strlen(string)+1);
2358 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2360 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2361 for (i=0; i<strlen(string); i++) {
2362 (*data)[2*i]=string[i];
2363 (*data)[2*i+1]='\0';
2368 if (!StrCaseCmp(value, "DsPresent")) {
2370 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2373 /* only show the publish check box if we are a
2374 memeber of a AD domain */
2376 if ( lp_security() == SEC_ADS )
2377 SIVAL(*data, 0, 0x01);
2379 SIVAL(*data, 0, 0x00);
2385 if (!StrCaseCmp(value, "DNSMachineName")) {
2388 if (!get_mydnsfullname(hostname))
2389 return WERR_BADFILE;
2391 *needed = 2*(strlen(hostname)+1);
2392 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2394 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2395 for (i=0; i<strlen(hostname); i++) {
2396 (*data)[2*i]=hostname[i];
2397 (*data)[2*i+1]='\0';
2403 return WERR_BADFILE;
2406 /********************************************************************
2407 * spoolss_getprinterdata
2408 ********************************************************************/
2410 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2412 POLICY_HND *handle = &q_u->handle;
2413 UNISTR2 *valuename = &q_u->valuename;
2414 uint32 in_size = q_u->size;
2415 uint32 *type = &r_u->type;
2416 uint32 *out_size = &r_u->size;
2417 uint8 **data = &r_u->data;
2418 uint32 *needed = &r_u->needed;
2421 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2422 NT_PRINTER_INFO_LEVEL *printer = NULL;
2426 * Reminder: when it's a string, the length is in BYTES
2427 * even if UNICODE is negociated.
2432 *out_size = in_size;
2434 /* in case of problem, return some default values */
2439 DEBUG(4,("_spoolss_getprinterdata\n"));
2442 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2443 status = WERR_BADFID;
2447 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2449 if ( Printer->printer_type == SPLHND_SERVER )
2450 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2453 if ( !get_printer_snum(p,handle, &snum) ) {
2454 status = WERR_BADFID;
2458 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2459 if ( !W_ERROR_IS_OK(status) )
2462 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2464 if ( strequal(value, "ChangeId") ) {
2466 *needed = sizeof(uint32);
2467 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2468 status = WERR_NOMEM;
2471 SIVAL( *data, 0, printer->info_2->changeid );
2475 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2478 if (*needed > *out_size)
2479 status = WERR_MORE_DATA;
2482 if ( !W_ERROR_IS_OK(status) )
2484 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2486 /* reply this param doesn't exist */
2489 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2491 free_a_printer( &printer, 2 );
2500 /* cleanup & exit */
2503 free_a_printer( &printer, 2 );
2508 /*********************************************************
2509 Connect to the client machine.
2510 **********************************************************/
2512 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2513 struct in_addr *client_ip, const char *remote_machine)
2516 struct cli_state *the_cli;
2517 struct in_addr rm_addr;
2519 if ( is_zero_ip(*client_ip) ) {
2520 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2521 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2525 if ( ismyip( rm_addr )) {
2526 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2530 rm_addr.s_addr = client_ip->s_addr;
2531 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2532 inet_ntoa(*client_ip) ));
2535 /* setup the connection */
2537 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2538 &rm_addr, 0, "IPC$", "IPC",
2542 0, lp_client_signing(), NULL );
2544 if ( !NT_STATUS_IS_OK( ret ) ) {
2545 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2550 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2551 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2552 cli_shutdown(the_cli);
2557 * Ok - we have an anonymous connection to the IPC$ share.
2558 * Now start the NT Domain stuff :-).
2561 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2562 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2563 remote_machine, nt_errstr(ret)));
2564 cli_shutdown(the_cli);
2568 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2570 (*pp_pipe)->cli = the_cli;
2575 /***************************************************************************
2576 Connect to the client.
2577 ****************************************************************************/
2579 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2580 uint32 localprinter, uint32 type,
2581 POLICY_HND *handle, struct in_addr *client_ip)
2586 * If it's the first connection, contact the client
2587 * and connect to the IPC$ share anonymously
2589 if (smb_connections==0) {
2590 fstring unix_printer;
2592 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2594 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2597 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2598 /* Tell the connections db we're now interested in printer
2599 * notify messages. */
2600 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2604 * Tell the specific printing tdb we want messages for this printer
2605 * by registering our PID.
2608 if (!print_notify_register_pid(snum))
2609 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2613 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2616 if (!W_ERROR_IS_OK(result))
2617 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2618 dos_errstr(result)));
2620 return (W_ERROR_IS_OK(result));
2623 /********************************************************************
2625 * ReplyFindFirstPrinterChangeNotifyEx
2627 * before replying OK: status=0 a rpc call is made to the workstation
2628 * asking ReplyOpenPrinter
2630 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2631 * called from api_spoolss_rffpcnex
2632 ********************************************************************/
2634 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2636 POLICY_HND *handle = &q_u->handle;
2637 uint32 flags = q_u->flags;
2638 uint32 options = q_u->options;
2639 UNISTR2 *localmachine = &q_u->localmachine;
2640 uint32 printerlocal = q_u->printerlocal;
2642 SPOOL_NOTIFY_OPTION *option = q_u->option;
2643 struct in_addr client_ip;
2645 /* store the notify value in the printer struct */
2647 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2650 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2654 Printer->notify.flags=flags;
2655 Printer->notify.options=options;
2656 Printer->notify.printerlocal=printerlocal;
2658 if (Printer->notify.option)
2659 free_spool_notify_option(&Printer->notify.option);
2661 Printer->notify.option=dup_spool_notify_option(option);
2663 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2664 sizeof(Printer->notify.localmachine)-1);
2666 /* Connect to the client machine and send a ReplyOpenPrinter */
2668 if ( Printer->printer_type == SPLHND_SERVER)
2670 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2671 !get_printer_snum(p, handle, &snum) )
2674 client_ip.s_addr = inet_addr(p->conn->client_address);
2676 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2677 Printer->notify.printerlocal, 1,
2678 &Printer->notify.client_hnd, &client_ip))
2679 return WERR_SERVER_UNAVAILABLE;
2681 Printer->notify.client_connected=True;
2686 /*******************************************************************
2687 * fill a notify_info_data with the servername
2688 ********************************************************************/
2690 void spoolss_notify_server_name(int snum,
2691 SPOOL_NOTIFY_INFO_DATA *data,
2692 print_queue_struct *queue,
2693 NT_PRINTER_INFO_LEVEL *printer,
2694 TALLOC_CTX *mem_ctx)
2699 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2701 data->notify_data.data.length = len;
2702 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2704 if (!data->notify_data.data.string) {
2705 data->notify_data.data.length = 0;
2709 memcpy(data->notify_data.data.string, temp, len);
2712 /*******************************************************************
2713 * fill a notify_info_data with the printername (not including the servername).
2714 ********************************************************************/
2716 void spoolss_notify_printer_name(int snum,
2717 SPOOL_NOTIFY_INFO_DATA *data,
2718 print_queue_struct *queue,
2719 NT_PRINTER_INFO_LEVEL *printer,
2720 TALLOC_CTX *mem_ctx)
2725 /* the notify name should not contain the \\server\ part */
2726 char *p = strrchr(printer->info_2->printername, '\\');
2729 p = printer->info_2->printername;
2734 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2736 data->notify_data.data.length = len;
2737 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2739 if (!data->notify_data.data.string) {
2740 data->notify_data.data.length = 0;
2744 memcpy(data->notify_data.data.string, temp, len);
2747 /*******************************************************************
2748 * fill a notify_info_data with the servicename
2749 ********************************************************************/
2751 void spoolss_notify_share_name(int snum,
2752 SPOOL_NOTIFY_INFO_DATA *data,
2753 print_queue_struct *queue,
2754 NT_PRINTER_INFO_LEVEL *printer,
2755 TALLOC_CTX *mem_ctx)
2760 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2762 data->notify_data.data.length = len;
2763 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2765 if (!data->notify_data.data.string) {
2766 data->notify_data.data.length = 0;
2770 memcpy(data->notify_data.data.string, temp, len);
2773 /*******************************************************************
2774 * fill a notify_info_data with the port name
2775 ********************************************************************/
2777 void spoolss_notify_port_name(int snum,
2778 SPOOL_NOTIFY_INFO_DATA *data,
2779 print_queue_struct *queue,
2780 NT_PRINTER_INFO_LEVEL *printer,
2781 TALLOC_CTX *mem_ctx)
2786 /* even if it's strange, that's consistant in all the code */
2788 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2790 data->notify_data.data.length = len;
2791 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2793 if (!data->notify_data.data.string) {
2794 data->notify_data.data.length = 0;
2798 memcpy(data->notify_data.data.string, temp, len);
2801 /*******************************************************************
2802 * fill a notify_info_data with the printername
2803 * but it doesn't exist, have to see what to do
2804 ********************************************************************/
2806 void spoolss_notify_driver_name(int snum,
2807 SPOOL_NOTIFY_INFO_DATA *data,
2808 print_queue_struct *queue,
2809 NT_PRINTER_INFO_LEVEL *printer,
2810 TALLOC_CTX *mem_ctx)
2815 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2817 data->notify_data.data.length = len;
2818 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2820 if (!data->notify_data.data.string) {
2821 data->notify_data.data.length = 0;
2825 memcpy(data->notify_data.data.string, temp, len);
2828 /*******************************************************************
2829 * fill a notify_info_data with the comment
2830 ********************************************************************/
2832 void spoolss_notify_comment(int snum,
2833 SPOOL_NOTIFY_INFO_DATA *data,
2834 print_queue_struct *queue,
2835 NT_PRINTER_INFO_LEVEL *printer,
2836 TALLOC_CTX *mem_ctx)
2841 if (*printer->info_2->comment == '\0')
2842 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2844 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2846 data->notify_data.data.length = len;
2847 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2849 if (!data->notify_data.data.string) {
2850 data->notify_data.data.length = 0;
2854 memcpy(data->notify_data.data.string, temp, len);
2857 /*******************************************************************
2858 * fill a notify_info_data with the comment
2859 * location = "Room 1, floor 2, building 3"
2860 ********************************************************************/
2862 void spoolss_notify_location(int snum,
2863 SPOOL_NOTIFY_INFO_DATA *data,
2864 print_queue_struct *queue,
2865 NT_PRINTER_INFO_LEVEL *printer,
2866 TALLOC_CTX *mem_ctx)
2871 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2873 data->notify_data.data.length = len;
2874 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2876 if (!data->notify_data.data.string) {
2877 data->notify_data.data.length = 0;
2881 memcpy(data->notify_data.data.string, temp, len);
2884 /*******************************************************************
2885 * fill a notify_info_data with the device mode
2886 * jfm:xxxx don't to it for know but that's a real problem !!!
2887 ********************************************************************/
2889 static void spoolss_notify_devmode(int snum,
2890 SPOOL_NOTIFY_INFO_DATA *data,
2891 print_queue_struct *queue,
2892 NT_PRINTER_INFO_LEVEL *printer,
2893 TALLOC_CTX *mem_ctx)
2897 /*******************************************************************
2898 * fill a notify_info_data with the separator file name
2899 ********************************************************************/
2901 void spoolss_notify_sepfile(int snum,
2902 SPOOL_NOTIFY_INFO_DATA *data,
2903 print_queue_struct *queue,
2904 NT_PRINTER_INFO_LEVEL *printer,
2905 TALLOC_CTX *mem_ctx)
2910 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2912 data->notify_data.data.length = len;
2913 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2915 if (!data->notify_data.data.string) {
2916 data->notify_data.data.length = 0;
2920 memcpy(data->notify_data.data.string, temp, len);
2923 /*******************************************************************
2924 * fill a notify_info_data with the print processor
2925 * jfm:xxxx return always winprint to indicate we don't do anything to it
2926 ********************************************************************/
2928 void spoolss_notify_print_processor(int snum,
2929 SPOOL_NOTIFY_INFO_DATA *data,
2930 print_queue_struct *queue,
2931 NT_PRINTER_INFO_LEVEL *printer,
2932 TALLOC_CTX *mem_ctx)
2937 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2939 data->notify_data.data.length = len;
2940 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2942 if (!data->notify_data.data.string) {
2943 data->notify_data.data.length = 0;
2947 memcpy(data->notify_data.data.string, temp, len);
2950 /*******************************************************************
2951 * fill a notify_info_data with the print processor options
2952 * jfm:xxxx send an empty string
2953 ********************************************************************/
2955 void spoolss_notify_parameters(int snum,
2956 SPOOL_NOTIFY_INFO_DATA *data,
2957 print_queue_struct *queue,
2958 NT_PRINTER_INFO_LEVEL *printer,
2959 TALLOC_CTX *mem_ctx)
2964 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2966 data->notify_data.data.length = len;
2967 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2969 if (!data->notify_data.data.string) {
2970 data->notify_data.data.length = 0;
2974 memcpy(data->notify_data.data.string, temp, len);
2977 /*******************************************************************
2978 * fill a notify_info_data with the data type
2979 * jfm:xxxx always send RAW as data type
2980 ********************************************************************/
2982 void spoolss_notify_datatype(int snum,
2983 SPOOL_NOTIFY_INFO_DATA *data,
2984 print_queue_struct *queue,
2985 NT_PRINTER_INFO_LEVEL *printer,
2986 TALLOC_CTX *mem_ctx)
2991 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2993 data->notify_data.data.length = len;
2994 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2996 if (!data->notify_data.data.string) {
2997 data->notify_data.data.length = 0;
3001 memcpy(data->notify_data.data.string, temp, len);
3004 /*******************************************************************
3005 * fill a notify_info_data with the security descriptor
3006 * jfm:xxxx send an null pointer to say no security desc
3007 * have to implement security before !
3008 ********************************************************************/
3010 static void spoolss_notify_security_desc(int snum,
3011 SPOOL_NOTIFY_INFO_DATA *data,
3012 print_queue_struct *queue,
3013 NT_PRINTER_INFO_LEVEL *printer,
3014 TALLOC_CTX *mem_ctx)
3016 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3017 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3020 /*******************************************************************
3021 * fill a notify_info_data with the attributes
3022 * jfm:xxxx a samba printer is always shared
3023 ********************************************************************/
3025 void spoolss_notify_attributes(int snum,
3026 SPOOL_NOTIFY_INFO_DATA *data,
3027 print_queue_struct *queue,
3028 NT_PRINTER_INFO_LEVEL *printer,
3029 TALLOC_CTX *mem_ctx)
3031 data->notify_data.value[0] = printer->info_2->attributes;
3032 data->notify_data.value[1] = 0;
3035 /*******************************************************************
3036 * fill a notify_info_data with the priority
3037 ********************************************************************/
3039 static void spoolss_notify_priority(int snum,
3040 SPOOL_NOTIFY_INFO_DATA *data,
3041 print_queue_struct *queue,
3042 NT_PRINTER_INFO_LEVEL *printer,
3043 TALLOC_CTX *mem_ctx)
3045 data->notify_data.value[0] = printer->info_2->priority;
3046 data->notify_data.value[1] = 0;
3049 /*******************************************************************
3050 * fill a notify_info_data with the default priority
3051 ********************************************************************/
3053 static void spoolss_notify_default_priority(int snum,
3054 SPOOL_NOTIFY_INFO_DATA *data,
3055 print_queue_struct *queue,
3056 NT_PRINTER_INFO_LEVEL *printer,
3057 TALLOC_CTX *mem_ctx)
3059 data->notify_data.value[0] = printer->info_2->default_priority;
3060 data->notify_data.value[1] = 0;
3063 /*******************************************************************
3064 * fill a notify_info_data with the start time
3065 ********************************************************************/
3067 static void spoolss_notify_start_time(int snum,
3068 SPOOL_NOTIFY_INFO_DATA *data,
3069 print_queue_struct *queue,
3070 NT_PRINTER_INFO_LEVEL *printer,
3071 TALLOC_CTX *mem_ctx)
3073 data->notify_data.value[0] = printer->info_2->starttime;
3074 data->notify_data.value[1] = 0;
3077 /*******************************************************************
3078 * fill a notify_info_data with the until time
3079 ********************************************************************/
3081 static void spoolss_notify_until_time(int snum,
3082 SPOOL_NOTIFY_INFO_DATA *data,
3083 print_queue_struct *queue,
3084 NT_PRINTER_INFO_LEVEL *printer,
3085 TALLOC_CTX *mem_ctx)
3087 data->notify_data.value[0] = printer->info_2->untiltime;
3088 data->notify_data.value[1] = 0;
3091 /*******************************************************************
3092 * fill a notify_info_data with the status
3093 ********************************************************************/
3095 static void spoolss_notify_status(int snum,
3096 SPOOL_NOTIFY_INFO_DATA *data,
3097 print_queue_struct *queue,
3098 NT_PRINTER_INFO_LEVEL *printer,
3099 TALLOC_CTX *mem_ctx)
3101 print_status_struct status;
3103 print_queue_length(snum, &status);
3104 data->notify_data.value[0]=(uint32) status.status;
3105 data->notify_data.value[1] = 0;
3108 /*******************************************************************
3109 * fill a notify_info_data with the number of jobs queued
3110 ********************************************************************/
3112 void spoolss_notify_cjobs(int snum,
3113 SPOOL_NOTIFY_INFO_DATA *data,
3114 print_queue_struct *queue,
3115 NT_PRINTER_INFO_LEVEL *printer,
3116 TALLOC_CTX *mem_ctx)
3118 data->notify_data.value[0] = print_queue_length(snum, NULL);
3119 data->notify_data.value[1] = 0;
3122 /*******************************************************************
3123 * fill a notify_info_data with the average ppm
3124 ********************************************************************/
3126 static void spoolss_notify_average_ppm(int snum,
3127 SPOOL_NOTIFY_INFO_DATA *data,
3128 print_queue_struct *queue,
3129 NT_PRINTER_INFO_LEVEL *printer,
3130 TALLOC_CTX *mem_ctx)
3132 /* always respond 8 pages per minutes */
3133 /* a little hard ! */
3134 data->notify_data.value[0] = printer->info_2->averageppm;
3135 data->notify_data.value[1] = 0;
3138 /*******************************************************************
3139 * fill a notify_info_data with username
3140 ********************************************************************/
3142 static void spoolss_notify_username(int snum,
3143 SPOOL_NOTIFY_INFO_DATA *data,
3144 print_queue_struct *queue,
3145 NT_PRINTER_INFO_LEVEL *printer,
3146 TALLOC_CTX *mem_ctx)
3151 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3153 data->notify_data.data.length = len;
3154 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3156 if (!data->notify_data.data.string) {
3157 data->notify_data.data.length = 0;
3161 memcpy(data->notify_data.data.string, temp, len);
3164 /*******************************************************************
3165 * fill a notify_info_data with job status
3166 ********************************************************************/
3168 static void spoolss_notify_job_status(int snum,
3169 SPOOL_NOTIFY_INFO_DATA *data,
3170 print_queue_struct *queue,
3171 NT_PRINTER_INFO_LEVEL *printer,
3172 TALLOC_CTX *mem_ctx)
3174 data->notify_data.value[0]=nt_printj_status(queue->status);
3175 data->notify_data.value[1] = 0;
3178 /*******************************************************************
3179 * fill a notify_info_data with job name
3180 ********************************************************************/
3182 static void spoolss_notify_job_name(int snum,
3183 SPOOL_NOTIFY_INFO_DATA *data,
3184 print_queue_struct *queue,
3185 NT_PRINTER_INFO_LEVEL *printer,
3186 TALLOC_CTX *mem_ctx)
3191 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3193 data->notify_data.data.length = len;
3194 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3196 if (!data->notify_data.data.string) {
3197 data->notify_data.data.length = 0;
3201 memcpy(data->notify_data.data.string, temp, len);
3204 /*******************************************************************
3205 * fill a notify_info_data with job status
3206 ********************************************************************/
3208 static void spoolss_notify_job_status_string(int snum,
3209 SPOOL_NOTIFY_INFO_DATA *data,
3210 print_queue_struct *queue,
3211 NT_PRINTER_INFO_LEVEL *printer,
3212 TALLOC_CTX *mem_ctx)
3215 * Now we're returning job status codes we just return a "" here. JRA.
3222 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3225 switch (queue->status) {
3230 p = ""; /* NT provides the paused string */
3239 #endif /* NO LONGER NEEDED. */
3241 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3243 data->notify_data.data.length = len;
3244 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3246 if (!data->notify_data.data.string) {
3247 data->notify_data.data.length = 0;
3251 memcpy(data->notify_data.data.string, temp, len);
3254 /*******************************************************************
3255 * fill a notify_info_data with job time
3256 ********************************************************************/
3258 static void spoolss_notify_job_time(int snum,
3259 SPOOL_NOTIFY_INFO_DATA *data,
3260 print_queue_struct *queue,
3261 NT_PRINTER_INFO_LEVEL *printer,
3262 TALLOC_CTX *mem_ctx)
3264 data->notify_data.value[0]=0x0;
3265 data->notify_data.value[1]=0;
3268 /*******************************************************************
3269 * fill a notify_info_data with job size
3270 ********************************************************************/
3272 static void spoolss_notify_job_size(int snum,
3273 SPOOL_NOTIFY_INFO_DATA *data,
3274 print_queue_struct *queue,
3275 NT_PRINTER_INFO_LEVEL *printer,
3276 TALLOC_CTX *mem_ctx)
3278 data->notify_data.value[0]=queue->size;
3279 data->notify_data.value[1]=0;
3282 /*******************************************************************
3283 * fill a notify_info_data with page info
3284 ********************************************************************/
3285 static void spoolss_notify_total_pages(int snum,
3286 SPOOL_NOTIFY_INFO_DATA *data,
3287 print_queue_struct *queue,
3288 NT_PRINTER_INFO_LEVEL *printer,
3289 TALLOC_CTX *mem_ctx)
3291 data->notify_data.value[0]=queue->page_count;
3292 data->notify_data.value[1]=0;
3295 /*******************************************************************
3296 * fill a notify_info_data with pages printed info.
3297 ********************************************************************/
3298 static void spoolss_notify_pages_printed(int snum,
3299 SPOOL_NOTIFY_INFO_DATA *data,
3300 print_queue_struct *queue,
3301 NT_PRINTER_INFO_LEVEL *printer,
3302 TALLOC_CTX *mem_ctx)
3304 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3305 data->notify_data.value[1]=0;
3308 /*******************************************************************
3309 Fill a notify_info_data with job position.
3310 ********************************************************************/
3312 static void spoolss_notify_job_position(int snum,
3313 SPOOL_NOTIFY_INFO_DATA *data,
3314 print_queue_struct *queue,
3315 NT_PRINTER_INFO_LEVEL *printer,
3316 TALLOC_CTX *mem_ctx)
3318 data->notify_data.value[0]=queue->job;
3319 data->notify_data.value[1]=0;
3322 /*******************************************************************
3323 Fill a notify_info_data with submitted time.
3324 ********************************************************************/
3326 static void spoolss_notify_submitted_time(int snum,
3327 SPOOL_NOTIFY_INFO_DATA *data,
3328 print_queue_struct *queue,
3329 NT_PRINTER_INFO_LEVEL *printer,
3330 TALLOC_CTX *mem_ctx)
3337 t=gmtime(&queue->time);
3339 len = sizeof(SYSTEMTIME);
3341 data->notify_data.data.length = len;
3342 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3344 if (!data->notify_data.data.string) {
3345 data->notify_data.data.length = 0;
3349 make_systemtime(&st, t);
3352 * Systemtime must be linearized as a set of UINT16's.
3353 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3356 p = (char *)data->notify_data.data.string;
3357 SSVAL(p, 0, st.year);
3358 SSVAL(p, 2, st.month);
3359 SSVAL(p, 4, st.dayofweek);
3360 SSVAL(p, 6, st.day);
3361 SSVAL(p, 8, st.hour);
3362 SSVAL(p, 10, st.minute);
3363 SSVAL(p, 12, st.second);
3364 SSVAL(p, 14, st.milliseconds);
3367 struct s_notify_info_data_table
3373 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3374 print_queue_struct *queue,
3375 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3378 /* A table describing the various print notification constants and
3379 whether the notification data is a pointer to a variable sized
3380 buffer, a one value uint32 or a two value uint32. */
3382 static const struct s_notify_info_data_table notify_info_data_table[] =
3384 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3385 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3386 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3387 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3388 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3389 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3410 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3411 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3412 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3413 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3414 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3415 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3433 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3436 /*******************************************************************
3437 Return the size of info_data structure.
3438 ********************************************************************/
3440 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3444 for (i = 0; i < sizeof(notify_info_data_table); i++)
3446 if ( (notify_info_data_table[i].type == type)
3447 && (notify_info_data_table[i].field == field) )
3449 switch(notify_info_data_table[i].size)
3451 case NOTIFY_ONE_VALUE:
3452 case NOTIFY_TWO_VALUE:
3457 /* The only pointer notify data I have seen on
3458 the wire is the submitted time and this has
3459 the notify size set to 4. -tpot */
3461 case NOTIFY_POINTER:
3464 case NOTIFY_SECDESC:
3470 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3475 /*******************************************************************
3476 Return the type of notify_info_data.
3477 ********************************************************************/
3479 static int type_of_notify_info_data(uint16 type, uint16 field)
3483 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3484 if (notify_info_data_table[i].type == type &&
3485 notify_info_data_table[i].field == field)
3486 return notify_info_data_table[i].size;
3492 /****************************************************************************
3493 ****************************************************************************/
3495 static int search_notify(uint16 type, uint16 field, int *value)
3499 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3500 if (notify_info_data_table[i].type == type &&
3501 notify_info_data_table[i].field == field &&
3502 notify_info_data_table[i].fn != NULL) {
3511 /****************************************************************************
3512 ****************************************************************************/
3514 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3516 info_data->type = type;
3517 info_data->field = field;
3518 info_data->reserved = 0;
3520 info_data->size = size_of_notify_info_data(type, field);
3521 info_data->enc_type = type_of_notify_info_data(type, field);
3528 /*******************************************************************
3530 * fill a notify_info struct with info asked
3532 ********************************************************************/
3534 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3535 snum, SPOOL_NOTIFY_OPTION_TYPE
3536 *option_type, uint32 id,
3537 TALLOC_CTX *mem_ctx)
3543 SPOOL_NOTIFY_INFO_DATA *current_data;
3544 NT_PRINTER_INFO_LEVEL *printer = NULL;
3545 print_queue_struct *queue=NULL;
3547 type=option_type->type;
3549 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3550 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3551 option_type->count, lp_servicename(snum)));
3553 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3556 for(field_num=0; field_num<option_type->count; field_num++) {
3557 field = option_type->fields[field_num];
3559 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3561 if (!search_notify(type, field, &j) )
3564 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3565 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3569 current_data = &info->data[info->count];
3571 construct_info_data(current_data, type, field, id);
3573 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3574 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3576 notify_info_data_table[j].fn(snum, current_data, queue,
3582 free_a_printer(&printer, 2);
3586 /*******************************************************************
3588 * fill a notify_info struct with info asked
3590 ********************************************************************/
3592 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3593 SPOOL_NOTIFY_INFO *info,
3594 NT_PRINTER_INFO_LEVEL *printer,
3595 int snum, SPOOL_NOTIFY_OPTION_TYPE
3596 *option_type, uint32 id,
3597 TALLOC_CTX *mem_ctx)
3603 SPOOL_NOTIFY_INFO_DATA *current_data;
3605 DEBUG(4,("construct_notify_jobs_info\n"));
3607 type = option_type->type;
3609 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3610 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3611 option_type->count));
3613 for(field_num=0; field_num<option_type->count; field_num++) {
3614 field = option_type->fields[field_num];
3616 if (!search_notify(type, field, &j) )
3619 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3620 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3624 current_data=&(info->data[info->count]);
3626 construct_info_data(current_data, type, field, id);
3627 notify_info_data_table[j].fn(snum, current_data, queue,
3636 * JFM: The enumeration is not that simple, it's even non obvious.
3638 * let's take an example: I want to monitor the PRINTER SERVER for
3639 * the printer's name and the number of jobs currently queued.
3640 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3641 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3643 * I have 3 printers on the back of my server.
3645 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3648 * 1 printer 1 name 1
3649 * 2 printer 1 cjob 1
3650 * 3 printer 2 name 2
3651 * 4 printer 2 cjob 2
3652 * 5 printer 3 name 3
3653 * 6 printer 3 name 3
3655 * that's the print server case, the printer case is even worse.
3658 /*******************************************************************
3660 * enumerate all printers on the printserver
3661 * fill a notify_info struct with info asked
3663 ********************************************************************/
3665 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3666 SPOOL_NOTIFY_INFO *info,
3667 TALLOC_CTX *mem_ctx)
3670 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3671 int n_services=lp_numservices();
3673 SPOOL_NOTIFY_OPTION *option;
3674 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3676 DEBUG(4,("printserver_notify_info\n"));
3681 option=Printer->notify.option;
3686 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3687 sending a ffpcn() request first */
3692 for (i=0; i<option->count; i++) {
3693 option_type=&(option->ctr.type[i]);
3695 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3698 for (snum=0; snum<n_services; snum++)
3700 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3701 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3707 * Debugging information, don't delete.
3710 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3711 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3712 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3714 for (i=0; i<info->count; i++) {
3715 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3716 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3717 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3724 /*******************************************************************
3726 * fill a notify_info struct with info asked
3728 ********************************************************************/
3730 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3731 TALLOC_CTX *mem_ctx)
3734 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3737 SPOOL_NOTIFY_OPTION *option;
3738 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3740 print_queue_struct *queue=NULL;
3741 print_status_struct status;
3743 DEBUG(4,("printer_notify_info\n"));
3748 option=Printer->notify.option;
3754 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3755 sending a ffpcn() request first */
3760 get_printer_snum(p, hnd, &snum);
3762 for (i=0; i<option->count; i++) {
3763 option_type=&option->ctr.type[i];
3765 switch ( option_type->type ) {
3766 case PRINTER_NOTIFY_TYPE:
3767 if(construct_notify_printer_info(Printer, info, snum,
3773 case JOB_NOTIFY_TYPE: {
3774 NT_PRINTER_INFO_LEVEL *printer = NULL;
3776 count = print_queue_status(snum, &queue, &status);
3778 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3781 for (j=0; j<count; j++) {
3782 construct_notify_jobs_info(&queue[j], info,
3789 free_a_printer(&printer, 2);
3799 * Debugging information, don't delete.
3802 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3803 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3804 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3806 for (i=0; i<info->count; i++) {
3807 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3808 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3809 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3815 /********************************************************************
3817 ********************************************************************/
3819 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3821 POLICY_HND *handle = &q_u->handle;
3822 SPOOL_NOTIFY_INFO *info = &r_u->info;
3824 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3825 WERROR result = WERR_BADFID;
3827 /* we always have a NOTIFY_INFO struct */
3831 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3832 OUR_HANDLE(handle)));
3836 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3839 * We are now using the change value, and
3840 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3841 * I don't have a global notification system, I'm sending back all the
3842 * informations even when _NOTHING_ has changed.
3845 /* We need to keep track of the change value to send back in
3846 RRPCN replies otherwise our updates are ignored. */
3848 Printer->notify.fnpcn = True;
3850 if (Printer->notify.client_connected) {
3851 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3852 Printer->notify.change = q_u->change;
3855 /* just ignore the SPOOL_NOTIFY_OPTION */
3857 switch (Printer->printer_type) {
3859 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3862 case SPLHND_PRINTER:
3863 result = printer_notify_info(p, handle, info, p->mem_ctx);
3867 Printer->notify.fnpcn = False;
3873 /********************************************************************
3874 * construct_printer_info_0
3875 * fill a printer_info_0 struct
3876 ********************************************************************/
3878 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3882 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3883 counter_printer_0 *session_counter;
3884 uint32 global_counter;
3887 print_status_struct status;
3889 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3892 count = print_queue_length(snum, &status);
3894 /* check if we already have a counter for this printer */
3895 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3896 if (session_counter->snum == snum)
3900 /* it's the first time, add it to the list */
3901 if (session_counter==NULL) {
3902 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3903 free_a_printer(&ntprinter, 2);
3906 ZERO_STRUCTP(session_counter);
3907 session_counter->snum=snum;
3908 session_counter->counter=0;
3909 DLIST_ADD(counter_list, session_counter);
3913 session_counter->counter++;
3916 * the global_counter should be stored in a TDB as it's common to all the clients
3917 * and should be zeroed on samba startup
3919 global_counter=session_counter->counter;
3921 pstrcpy(chaine,ntprinter->info_2->printername);
3923 init_unistr(&printer->printername, chaine);
3925 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3926 init_unistr(&printer->servername, chaine);
3928 printer->cjobs = count;
3929 printer->total_jobs = 0;
3930 printer->total_bytes = 0;
3932 setuptime = (time_t)ntprinter->info_2->setuptime;
3933 t=gmtime(&setuptime);
3935 printer->year = t->tm_year+1900;
3936 printer->month = t->tm_mon+1;
3937 printer->dayofweek = t->tm_wday;
3938 printer->day = t->tm_mday;
3939 printer->hour = t->tm_hour;
3940 printer->minute = t->tm_min;
3941 printer->second = t->tm_sec;
3942 printer->milliseconds = 0;
3944 printer->global_counter = global_counter;
3945 printer->total_pages = 0;
3947 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3948 printer->major_version = 0x0005; /* NT 5 */
3949 printer->build_version = 0x0893; /* build 2195 */
3951 printer->unknown7 = 0x1;
3952 printer->unknown8 = 0x0;
3953 printer->unknown9 = 0x0;
3954 printer->session_counter = session_counter->counter;
3955 printer->unknown11 = 0x0;
3956 printer->printer_errors = 0x0; /* number of print failure */
3957 printer->unknown13 = 0x0;
3958 printer->unknown14 = 0x1;
3959 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3960 printer->unknown16 = 0x0;
3961 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3962 printer->unknown18 = 0x0;
3963 printer->status = nt_printq_status(status.status);
3964 printer->unknown20 = 0x0;
3965 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3966 printer->unknown22 = 0x0;
3967 printer->unknown23 = 0x6; /* 6 ???*/
3968 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3969 printer->unknown25 = 0;
3970 printer->unknown26 = 0;
3971 printer->unknown27 = 0;
3972 printer->unknown28 = 0;
3973 printer->unknown29 = 0;
3975 free_a_printer(&ntprinter,2);
3979 /********************************************************************
3980 * construct_printer_info_1
3981 * fill a printer_info_1 struct
3982 ********************************************************************/
3983 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3987 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3989 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3992 printer->flags=flags;
3994 if (*ntprinter->info_2->comment == '\0') {
3995 init_unistr(&printer->comment, lp_comment(snum));
3996 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3997 ntprinter->info_2->drivername, lp_comment(snum));
4000 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4001 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4002 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4005 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4007 init_unistr(&printer->description, chaine);
4008 init_unistr(&printer->name, chaine2);
4010 free_a_printer(&ntprinter,2);
4015 /****************************************************************************
4016 Free a DEVMODE struct.
4017 ****************************************************************************/
4019 static void free_dev_mode(DEVICEMODE *dev)
4024 SAFE_FREE(dev->dev_private);
4029 /****************************************************************************
4030 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4031 should be valid upon entry
4032 ****************************************************************************/
4034 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4036 if ( !devmode || !ntdevmode )
4039 init_unistr(&devmode->devicename, ntdevmode->devicename);
4041 init_unistr(&devmode->formname, ntdevmode->formname);
4043 devmode->specversion = ntdevmode->specversion;
4044 devmode->driverversion = ntdevmode->driverversion;
4045 devmode->size = ntdevmode->size;
4046 devmode->driverextra = ntdevmode->driverextra;
4047 devmode->fields = ntdevmode->fields;
4049 devmode->orientation = ntdevmode->orientation;
4050 devmode->papersize = ntdevmode->papersize;
4051 devmode->paperlength = ntdevmode->paperlength;
4052 devmode->paperwidth = ntdevmode->paperwidth;
4053 devmode->scale = ntdevmode->scale;
4054 devmode->copies = ntdevmode->copies;
4055 devmode->defaultsource = ntdevmode->defaultsource;
4056 devmode->printquality = ntdevmode->printquality;
4057 devmode->color = ntdevmode->color;
4058 devmode->duplex = ntdevmode->duplex;
4059 devmode->yresolution = ntdevmode->yresolution;
4060 devmode->ttoption = ntdevmode->ttoption;
4061 devmode->collate = ntdevmode->collate;
4062 devmode->icmmethod = ntdevmode->icmmethod;
4063 devmode->icmintent = ntdevmode->icmintent;
4064 devmode->mediatype = ntdevmode->mediatype;
4065 devmode->dithertype = ntdevmode->dithertype;
4067 if (ntdevmode->nt_dev_private != NULL) {
4068 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4075 /****************************************************************************
4076 Create a DEVMODE struct. Returns malloced memory.
4077 ****************************************************************************/
4079 DEVICEMODE *construct_dev_mode(int snum)
4081 NT_PRINTER_INFO_LEVEL *printer = NULL;
4082 DEVICEMODE *devmode = NULL;
4084 DEBUG(7,("construct_dev_mode\n"));
4086 DEBUGADD(8,("getting printer characteristics\n"));
4088 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4091 if ( !printer->info_2->devmode ) {
4092 DEBUG(5, ("BONG! There was no device mode!\n"));
4096 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4097 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4101 ZERO_STRUCTP(devmode);
4103 DEBUGADD(8,("loading DEVICEMODE\n"));
4105 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4106 free_dev_mode( devmode );
4111 free_a_printer(&printer,2);
4116 /********************************************************************
4117 * construct_printer_info_2
4118 * fill a printer_info_2 struct
4119 ********************************************************************/
4121 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4124 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4126 print_status_struct status;
4128 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4131 count = print_queue_length(snum, &status);
4133 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4134 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4135 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4136 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4137 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4139 if (*ntprinter->info_2->comment == '\0')
4140 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4142 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4144 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4145 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4146 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4147 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4148 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4150 printer->attributes = ntprinter->info_2->attributes;
4152 printer->priority = ntprinter->info_2->priority; /* priority */
4153 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4154 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4155 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4156 printer->status = nt_printq_status(status.status); /* status */
4157 printer->cjobs = count; /* jobs */
4158 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4160 if ( !(printer->devmode = construct_dev_mode(snum)) )
4161 DEBUG(8, ("Returning NULL Devicemode!\n"));
4163 printer->secdesc = NULL;
4165 if ( ntprinter->info_2->secdesc_buf
4166 && ntprinter->info_2->secdesc_buf->len != 0 )
4168 /* don't use talloc_steal() here unless you do a deep steal of all
4169 the SEC_DESC members */
4171 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4172 ntprinter->info_2->secdesc_buf->sec );
4175 free_a_printer(&ntprinter, 2);
4180 /********************************************************************
4181 * construct_printer_info_3
4182 * fill a printer_info_3 struct
4183 ********************************************************************/
4185 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4187 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4188 PRINTER_INFO_3 *printer = NULL;
4190 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4194 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4195 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4199 ZERO_STRUCTP(printer);
4201 /* These are the components of the SD we are returning. */
4203 printer->flags = 0x4;
4205 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4206 /* don't use talloc_steal() here unless you do a deep steal of all
4207 the SEC_DESC members */
4209 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4210 ntprinter->info_2->secdesc_buf->sec );
4213 free_a_printer(&ntprinter, 2);
4215 *pp_printer = printer;
4219 /********************************************************************
4220 * construct_printer_info_4
4221 * fill a printer_info_4 struct
4222 ********************************************************************/
4224 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4226 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4228 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4231 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4232 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4233 printer->attributes = ntprinter->info_2->attributes;
4235 free_a_printer(&ntprinter, 2);
4239 /********************************************************************
4240 * construct_printer_info_5
4241 * fill a printer_info_5 struct
4242 ********************************************************************/
4244 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4246 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4248 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4251 init_unistr(&printer->printername, ntprinter->info_2->printername);
4252 init_unistr(&printer->portname, ntprinter->info_2->portname);
4253 printer->attributes = ntprinter->info_2->attributes;
4255 /* these two are not used by NT+ according to MSDN */
4257 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4258 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4260 free_a_printer(&ntprinter, 2);
4265 /********************************************************************
4266 * construct_printer_info_7
4267 * fill a printer_info_7 struct
4268 ********************************************************************/
4270 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4272 char *guid_str = NULL;
4275 if (is_printer_published(print_hnd, snum, &guid)) {
4276 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4277 strupper_m(guid_str);
4278 init_unistr(&printer->guid, guid_str);
4279 printer->action = SPOOL_DS_PUBLISH;
4281 init_unistr(&printer->guid, "");
4282 printer->action = SPOOL_DS_UNPUBLISH;
4288 /********************************************************************
4289 Spoolss_enumprinters.
4290 ********************************************************************/
4292 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4296 int n_services=lp_numservices();
4297 PRINTER_INFO_1 *printers=NULL;
4298 PRINTER_INFO_1 current_prt;
4299 WERROR result = WERR_OK;
4301 DEBUG(4,("enum_all_printers_info_1\n"));
4303 for (snum=0; snum<n_services; snum++) {
4304 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4305 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4307 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4308 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4309 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4313 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4315 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4321 /* check the required size. */
4322 for (i=0; i<*returned; i++)
4323 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4325 if (*needed > offered) {
4326 result = WERR_INSUFFICIENT_BUFFER;
4330 if (!rpcbuf_alloc_size(buffer, *needed)) {
4331 result = WERR_NOMEM;
4335 /* fill the buffer with the structures */
4336 for (i=0; i<*returned; i++)
4337 smb_io_printer_info_1("", buffer, &printers[i], 0);
4342 SAFE_FREE(printers);
4344 if ( !W_ERROR_IS_OK(result) )
4350 /********************************************************************
4351 enum_all_printers_info_1_local.
4352 *********************************************************************/
4354 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4356 DEBUG(4,("enum_all_printers_info_1_local\n"));
4358 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4361 /********************************************************************
4362 enum_all_printers_info_1_name.
4363 *********************************************************************/
4365 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4369 DEBUG(4,("enum_all_printers_info_1_name\n"));
4371 if ((name[0] == '\\') && (name[1] == '\\'))
4374 if (is_myname_or_ipaddr(s)) {
4375 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4378 return WERR_INVALID_NAME;
4381 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4382 /********************************************************************
4383 enum_all_printers_info_1_remote.
4384 *********************************************************************/
4386 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4388 PRINTER_INFO_1 *printer;
4389 fstring printername;
4392 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4393 WERROR result = WERR_OK;
4395 /* JFM: currently it's more a place holder than anything else.
4396 * In the spooler world there is a notion of server registration.
4397 * the print servers are registered on the PDC (in the same domain)
4399 * We should have a TDB here. The registration is done thru an
4400 * undocumented RPC call.
4403 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4408 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4409 slprintf(desc, sizeof(desc)-1,"%s", name);
4410 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4412 init_unistr(&printer->description, desc);
4413 init_unistr(&printer->name, printername);
4414 init_unistr(&printer->comment, comment);
4415 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4417 /* check the required size. */
4418 *needed += spoolss_size_printer_info_1(printer);
4420 if (*needed > offered) {
4421 result = WERR_INSUFFICIENT_BUFFER;
4425 if (!rpcbuf_alloc_size(buffer, *needed)) {
4426 result = WERR_NOMEM;
4430 /* fill the buffer with the structures */
4431 smb_io_printer_info_1("", buffer, printer, 0);
4437 if ( !W_ERROR_IS_OK(result) )
4445 /********************************************************************
4446 enum_all_printers_info_1_network.
4447 *********************************************************************/
4449 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4453 DEBUG(4,("enum_all_printers_info_1_network\n"));
4455 /* If we respond to a enum_printers level 1 on our name with flags
4456 set to PRINTER_ENUM_REMOTE with a list of printers then these
4457 printers incorrectly appear in the APW browse list.
4458 Specifically the printers for the server appear at the workgroup
4459 level where all the other servers in the domain are
4460 listed. Windows responds to this call with a
4461 WERR_CAN_NOT_COMPLETE so we should do the same. */
4463 if (name[0] == '\\' && name[1] == '\\')
4466 if (is_myname_or_ipaddr(s))
4467 return WERR_CAN_NOT_COMPLETE;
4469 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4472 /********************************************************************
4473 * api_spoolss_enumprinters
4475 * called from api_spoolss_enumprinters (see this to understand)
4476 ********************************************************************/
4478 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4482 int n_services=lp_numservices();
4483 PRINTER_INFO_2 *printers=NULL;
4484 PRINTER_INFO_2 current_prt;
4485 WERROR result = WERR_OK;
4489 for (snum=0; snum<n_services; snum++) {
4490 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4491 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4493 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4494 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4495 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4500 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4502 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4509 /* check the required size. */
4510 for (i=0; i<*returned; i++)
4511 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4513 if (*needed > offered) {
4514 result = WERR_INSUFFICIENT_BUFFER;
4518 if (!rpcbuf_alloc_size(buffer, *needed)) {
4519 result = WERR_NOMEM;
4523 /* fill the buffer with the structures */
4524 for (i=0; i<*returned; i++)
4525 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4530 for (i=0; i<*returned; i++)
4531 free_devmode(printers[i].devmode);
4533 SAFE_FREE(printers);
4535 if ( !W_ERROR_IS_OK(result) )
4541 /********************************************************************
4542 * handle enumeration of printers at level 1
4543 ********************************************************************/
4545 static WERROR enumprinters_level1( uint32 flags, fstring name,
4546 RPC_BUFFER *buffer, uint32 offered,
4547 uint32 *needed, uint32 *returned)
4549 /* Not all the flags are equals */
4551 if (flags & PRINTER_ENUM_LOCAL)
4552 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4554 if (flags & PRINTER_ENUM_NAME)
4555 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4557 #if 0 /* JERRY - disabled for now */
4558 if (flags & PRINTER_ENUM_REMOTE)
4559 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4562 if (flags & PRINTER_ENUM_NETWORK)
4563 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4565 return WERR_OK; /* NT4sp5 does that */
4568 /********************************************************************
4569 * handle enumeration of printers at level 2
4570 ********************************************************************/
4572 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4573 RPC_BUFFER *buffer, uint32 offered,
4574 uint32 *needed, uint32 *returned)
4576 char *s = servername;
4578 if (flags & PRINTER_ENUM_LOCAL) {
4579 return enum_all_printers_info_2(buffer, offered, needed, returned);
4582 if (flags & PRINTER_ENUM_NAME) {
4583 if ((servername[0] == '\\') && (servername[1] == '\\'))
4585 if (is_myname_or_ipaddr(s))
4586 return enum_all_printers_info_2(buffer, offered, needed, returned);
4588 return WERR_INVALID_NAME;
4591 if (flags & PRINTER_ENUM_REMOTE)
4592 return WERR_UNKNOWN_LEVEL;
4597 /********************************************************************
4598 * handle enumeration of printers at level 5
4599 ********************************************************************/
4601 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4602 RPC_BUFFER *buffer, uint32 offered,
4603 uint32 *needed, uint32 *returned)
4605 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4609 /********************************************************************
4610 * api_spoolss_enumprinters
4612 * called from api_spoolss_enumprinters (see this to understand)
4613 ********************************************************************/
4615 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4617 uint32 flags = q_u->flags;
4618 UNISTR2 *servername = &q_u->servername;
4619 uint32 level = q_u->level;
4620 RPC_BUFFER *buffer = NULL;
4621 uint32 offered = q_u->offered;
4622 uint32 *needed = &r_u->needed;
4623 uint32 *returned = &r_u->returned;
4627 /* that's an [in out] buffer */
4630 return WERR_INVALID_PARAM;
4633 rpcbuf_move(q_u->buffer, &r_u->buffer);
4634 buffer = r_u->buffer;
4636 DEBUG(4,("_spoolss_enumprinters\n"));
4643 * flags==PRINTER_ENUM_NAME
4644 * if name=="" then enumerates all printers
4645 * if name!="" then enumerate the printer
4646 * flags==PRINTER_ENUM_REMOTE
4647 * name is NULL, enumerate printers
4648 * Level 2: name!="" enumerates printers, name can't be NULL
4649 * Level 3: doesn't exist
4650 * Level 4: does a local registry lookup
4651 * Level 5: same as Level 2
4654 unistr2_to_ascii(name, servername, sizeof(name)-1);
4659 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4661 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4663 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4668 return WERR_UNKNOWN_LEVEL;
4671 /****************************************************************************
4672 ****************************************************************************/
4674 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4676 PRINTER_INFO_0 *printer=NULL;
4677 WERROR result = WERR_OK;
4679 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4682 construct_printer_info_0(print_hnd, printer, snum);
4684 /* check the required size. */
4685 *needed += spoolss_size_printer_info_0(printer);
4687 if (*needed > offered) {
4688 result = WERR_INSUFFICIENT_BUFFER;
4692 if (!rpcbuf_alloc_size(buffer, *needed)) {
4693 result = WERR_NOMEM;
4697 /* fill the buffer with the structures */
4698 smb_io_printer_info_0("", buffer, printer, 0);
4708 /****************************************************************************
4709 ****************************************************************************/
4711 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4713 PRINTER_INFO_1 *printer=NULL;
4714 WERROR result = WERR_OK;
4716 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4719 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4721 /* check the required size. */
4722 *needed += spoolss_size_printer_info_1(printer);
4724 if (*needed > offered) {
4725 result = WERR_INSUFFICIENT_BUFFER;
4729 if (!rpcbuf_alloc_size(buffer, *needed)) {
4730 result = WERR_NOMEM;
4734 /* fill the buffer with the structures */
4735 smb_io_printer_info_1("", buffer, printer, 0);
4744 /****************************************************************************
4745 ****************************************************************************/
4747 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4749 PRINTER_INFO_2 *printer=NULL;
4750 WERROR result = WERR_OK;
4752 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4755 construct_printer_info_2(print_hnd, printer, snum);
4757 /* check the required size. */
4758 *needed += spoolss_size_printer_info_2(printer);
4760 if (*needed > offered) {
4761 result = WERR_INSUFFICIENT_BUFFER;
4765 if (!rpcbuf_alloc_size(buffer, *needed)) {
4766 result = WERR_NOMEM;
4770 /* fill the buffer with the structures */
4771 if (!smb_io_printer_info_2("", buffer, printer, 0))
4772 result = WERR_NOMEM;
4776 free_printer_info_2(printer);
4781 /****************************************************************************
4782 ****************************************************************************/
4784 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4786 PRINTER_INFO_3 *printer=NULL;
4787 WERROR result = WERR_OK;
4789 if (!construct_printer_info_3(print_hnd, &printer, snum))
4792 /* check the required size. */
4793 *needed += spoolss_size_printer_info_3(printer);
4795 if (*needed > offered) {
4796 result = WERR_INSUFFICIENT_BUFFER;
4800 if (!rpcbuf_alloc_size(buffer, *needed)) {
4801 result = WERR_NOMEM;
4805 /* fill the buffer with the structures */
4806 smb_io_printer_info_3("", buffer, printer, 0);
4810 free_printer_info_3(printer);
4815 /****************************************************************************
4816 ****************************************************************************/
4818 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4820 PRINTER_INFO_4 *printer=NULL;
4821 WERROR result = WERR_OK;
4823 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4826 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4831 /* check the required size. */
4832 *needed += spoolss_size_printer_info_4(printer);
4834 if (*needed > offered) {
4835 result = WERR_INSUFFICIENT_BUFFER;
4839 if (!rpcbuf_alloc_size(buffer, *needed)) {
4840 result = WERR_NOMEM;
4844 /* fill the buffer with the structures */
4845 smb_io_printer_info_4("", buffer, printer, 0);
4849 free_printer_info_4(printer);
4854 /****************************************************************************
4855 ****************************************************************************/
4857 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4859 PRINTER_INFO_5 *printer=NULL;
4860 WERROR result = WERR_OK;
4862 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4865 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4866 free_printer_info_5(printer);
4870 /* check the required size. */
4871 *needed += spoolss_size_printer_info_5(printer);
4873 if (*needed > offered) {
4874 result = WERR_INSUFFICIENT_BUFFER;
4878 if (!rpcbuf_alloc_size(buffer, *needed)) {
4879 result = WERR_NOMEM;
4883 /* fill the buffer with the structures */
4884 smb_io_printer_info_5("", buffer, printer, 0);
4888 free_printer_info_5(printer);
4893 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4895 PRINTER_INFO_7 *printer=NULL;
4896 WERROR result = WERR_OK;
4898 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4901 if (!construct_printer_info_7(print_hnd, printer, snum))
4904 /* check the required size. */
4905 *needed += spoolss_size_printer_info_7(printer);
4907 if (*needed > offered) {
4908 result = WERR_INSUFFICIENT_BUFFER;
4912 if (!rpcbuf_alloc_size(buffer, *needed)) {
4913 result = WERR_NOMEM;
4918 /* fill the buffer with the structures */
4919 smb_io_printer_info_7("", buffer, printer, 0);
4923 free_printer_info_7(printer);
4928 /****************************************************************************
4929 ****************************************************************************/
4931 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4933 POLICY_HND *handle = &q_u->handle;
4934 uint32 level = q_u->level;
4935 RPC_BUFFER *buffer = NULL;
4936 uint32 offered = q_u->offered;
4937 uint32 *needed = &r_u->needed;
4938 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4942 /* that's an [in out] buffer */
4945 return WERR_INVALID_PARAM;
4948 rpcbuf_move(q_u->buffer, &r_u->buffer);
4949 buffer = r_u->buffer;
4953 if (!get_printer_snum(p, handle, &snum))
4958 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4960 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4962 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4964 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4966 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4968 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4970 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4972 return WERR_UNKNOWN_LEVEL;
4975 /********************************************************************
4976 * fill a DRIVER_INFO_1 struct
4977 ********************************************************************/
4979 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4981 init_unistr( &info->name, driver.info_3->name);
4984 /********************************************************************
4985 * construct_printer_driver_info_1
4986 ********************************************************************/
4988 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4990 NT_PRINTER_INFO_LEVEL *printer = NULL;
4991 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4993 ZERO_STRUCT(driver);
4995 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4996 return WERR_INVALID_PRINTER_NAME;
4998 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4999 return WERR_UNKNOWN_PRINTER_DRIVER;
5001 fill_printer_driver_info_1(info, driver, servername, architecture);
5003 free_a_printer(&printer,2);
5008 /********************************************************************
5009 * construct_printer_driver_info_2
5010 * fill a printer_info_2 struct
5011 ********************************************************************/
5013 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5017 info->version=driver.info_3->cversion;
5019 init_unistr( &info->name, driver.info_3->name );
5020 init_unistr( &info->architecture, driver.info_3->environment );
5023 if (strlen(driver.info_3->driverpath)) {
5024 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5025 init_unistr( &info->driverpath, temp );
5027 init_unistr( &info->driverpath, "" );
5029 if (strlen(driver.info_3->datafile)) {
5030 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5031 init_unistr( &info->datafile, temp );
5033 init_unistr( &info->datafile, "" );
5035 if (strlen(driver.info_3->configfile)) {
5036 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5037 init_unistr( &info->configfile, temp );
5039 init_unistr( &info->configfile, "" );
5042 /********************************************************************
5043 * construct_printer_driver_info_2
5044 * fill a printer_info_2 struct
5045 ********************************************************************/
5047 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5049 NT_PRINTER_INFO_LEVEL *printer = NULL;
5050 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5052 ZERO_STRUCT(printer);
5053 ZERO_STRUCT(driver);
5055 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5056 return WERR_INVALID_PRINTER_NAME;
5058 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5059 return WERR_UNKNOWN_PRINTER_DRIVER;
5061 fill_printer_driver_info_2(info, driver, servername);
5063 free_a_printer(&printer,2);
5068 /********************************************************************
5069 * copy a strings array and convert to UNICODE
5071 * convert an array of ascii string to a UNICODE string
5072 ********************************************************************/
5074 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5081 DEBUG(6,("init_unistr_array\n"));
5092 v = ""; /* hack to handle null lists */
5095 /* hack to allow this to be used in places other than when generating
5096 the list of dependent files */
5099 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5103 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5105 /* add one extra unit16 for the second terminating NULL */
5107 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5108 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5115 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5120 /* special case for ""; we need to add both NULL's here */
5122 (*uni_array)[j++]=0x0000;
5123 (*uni_array)[j]=0x0000;
5126 DEBUGADD(6,("last one:done\n"));
5128 /* return size of array in uint16's */
5133 /********************************************************************
5134 * construct_printer_info_3
5135 * fill a printer_info_3 struct
5136 ********************************************************************/
5138 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5144 info->version=driver.info_3->cversion;
5146 init_unistr( &info->name, driver.info_3->name );
5147 init_unistr( &info->architecture, driver.info_3->environment );
5149 if (strlen(driver.info_3->driverpath)) {
5150 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5151 init_unistr( &info->driverpath, temp );
5153 init_unistr( &info->driverpath, "" );
5155 if (strlen(driver.info_3->datafile)) {
5156 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5157 init_unistr( &info->datafile, temp );
5159 init_unistr( &info->datafile, "" );
5161 if (strlen(driver.info_3->configfile)) {
5162 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5163 init_unistr( &info->configfile, temp );
5165 init_unistr( &info->configfile, "" );
5167 if (strlen(driver.info_3->helpfile)) {
5168 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5169 init_unistr( &info->helpfile, temp );
5171 init_unistr( &info->helpfile, "" );
5173 init_unistr( &info->monitorname, driver.info_3->monitorname );
5174 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5176 info->dependentfiles=NULL;
5177 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5180 /********************************************************************
5181 * construct_printer_info_3
5182 * fill a printer_info_3 struct
5183 ********************************************************************/
5185 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5187 NT_PRINTER_INFO_LEVEL *printer = NULL;
5188 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5190 ZERO_STRUCT(driver);
5192 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5193 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5194 if (!W_ERROR_IS_OK(status))
5195 return WERR_INVALID_PRINTER_NAME;
5197 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5198 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5203 * I put this code in during testing. Helpful when commenting out the
5204 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5205 * as win2k always queries the driver using an infor level of 6.
5206 * I've left it in (but ifdef'd out) because I'll probably
5207 * use it in experimentation again in the future. --jerry 22/01/2002
5210 if (!W_ERROR_IS_OK(status)) {
5212 * Is this a W2k client ?
5215 /* Yes - try again with a WinNT driver. */
5217 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5218 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5222 if (!W_ERROR_IS_OK(status)) {
5223 free_a_printer(&printer,2);
5224 return WERR_UNKNOWN_PRINTER_DRIVER;
5232 fill_printer_driver_info_3(info, driver, servername);
5234 free_a_printer(&printer,2);
5239 /********************************************************************
5240 * construct_printer_info_6
5241 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5242 ********************************************************************/
5244 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5250 memset(&nullstr, '\0', sizeof(fstring));
5252 info->version=driver.info_3->cversion;
5254 init_unistr( &info->name, driver.info_3->name );
5255 init_unistr( &info->architecture, driver.info_3->environment );
5257 if (strlen(driver.info_3->driverpath)) {
5258 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5259 init_unistr( &info->driverpath, temp );
5261 init_unistr( &info->driverpath, "" );
5263 if (strlen(driver.info_3->datafile)) {
5264 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5265 init_unistr( &info->datafile, temp );
5267 init_unistr( &info->datafile, "" );
5269 if (strlen(driver.info_3->configfile)) {
5270 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5271 init_unistr( &info->configfile, temp );
5273 init_unistr( &info->configfile, "" );
5275 if (strlen(driver.info_3->helpfile)) {
5276 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5277 init_unistr( &info->helpfile, temp );
5279 init_unistr( &info->helpfile, "" );
5281 init_unistr( &info->monitorname, driver.info_3->monitorname );
5282 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5284 info->dependentfiles = NULL;
5285 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5287 info->previousdrivernames=NULL;
5288 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5290 info->driver_date.low=0;
5291 info->driver_date.high=0;
5294 info->driver_version_low=0;
5295 info->driver_version_high=0;
5297 init_unistr( &info->mfgname, "");
5298 init_unistr( &info->oem_url, "");
5299 init_unistr( &info->hardware_id, "");
5300 init_unistr( &info->provider, "");
5303 /********************************************************************
5304 * construct_printer_info_6
5305 * fill a printer_info_6 struct
5306 ********************************************************************/
5308 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5309 fstring servername, fstring architecture, uint32 version)
5311 NT_PRINTER_INFO_LEVEL *printer = NULL;
5312 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5315 ZERO_STRUCT(driver);
5317 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5319 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5321 if (!W_ERROR_IS_OK(status))
5322 return WERR_INVALID_PRINTER_NAME;
5324 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5326 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5328 if (!W_ERROR_IS_OK(status))
5331 * Is this a W2k client ?
5335 free_a_printer(&printer,2);
5336 return WERR_UNKNOWN_PRINTER_DRIVER;
5339 /* Yes - try again with a WinNT driver. */
5341 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5342 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5343 if (!W_ERROR_IS_OK(status)) {
5344 free_a_printer(&printer,2);
5345 return WERR_UNKNOWN_PRINTER_DRIVER;
5349 fill_printer_driver_info_6(info, driver, servername);
5351 free_a_printer(&printer,2);
5352 free_a_printer_driver(driver, 3);
5357 /****************************************************************************
5358 ****************************************************************************/
5360 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5362 SAFE_FREE(info->dependentfiles);
5365 /****************************************************************************
5366 ****************************************************************************/
5368 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5370 SAFE_FREE(info->dependentfiles);
5373 /****************************************************************************
5374 ****************************************************************************/
5376 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5378 DRIVER_INFO_1 *info=NULL;
5381 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5384 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5385 if (!W_ERROR_IS_OK(result))
5388 /* check the required size. */
5389 *needed += spoolss_size_printer_driver_info_1(info);
5391 if (*needed > offered) {
5392 result = WERR_INSUFFICIENT_BUFFER;
5396 if (!rpcbuf_alloc_size(buffer, *needed)) {
5397 result = WERR_NOMEM;
5401 /* fill the buffer with the structures */
5402 smb_io_printer_driver_info_1("", buffer, info, 0);
5411 /****************************************************************************
5412 ****************************************************************************/
5414 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5416 DRIVER_INFO_2 *info=NULL;
5419 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5422 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5423 if (!W_ERROR_IS_OK(result))
5426 /* check the required size. */
5427 *needed += spoolss_size_printer_driver_info_2(info);
5429 if (*needed > offered) {
5430 result = WERR_INSUFFICIENT_BUFFER;
5434 if (!rpcbuf_alloc_size(buffer, *needed)) {
5435 result = WERR_NOMEM;
5439 /* fill the buffer with the structures */
5440 smb_io_printer_driver_info_2("", buffer, info, 0);
5449 /****************************************************************************
5450 ****************************************************************************/
5452 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5459 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5460 if (!W_ERROR_IS_OK(result))
5463 /* check the required size. */
5464 *needed += spoolss_size_printer_driver_info_3(&info);
5466 if (*needed > offered) {
5467 result = WERR_INSUFFICIENT_BUFFER;
5471 if (!rpcbuf_alloc_size(buffer, *needed)) {
5472 result = WERR_NOMEM;
5476 /* fill the buffer with the structures */
5477 smb_io_printer_driver_info_3("", buffer, &info, 0);
5480 free_printer_driver_info_3(&info);
5485 /****************************************************************************
5486 ****************************************************************************/
5488 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5495 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5496 if (!W_ERROR_IS_OK(result))
5499 /* check the required size. */
5500 *needed += spoolss_size_printer_driver_info_6(&info);
5502 if (*needed > offered) {
5503 result = WERR_INSUFFICIENT_BUFFER;
5507 if (!rpcbuf_alloc_size(buffer, *needed)) {
5508 result = WERR_NOMEM;
5512 /* fill the buffer with the structures */
5513 smb_io_printer_driver_info_6("", buffer, &info, 0);
5516 free_printer_driver_info_6(&info);
5521 /****************************************************************************
5522 ****************************************************************************/
5524 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5526 POLICY_HND *handle = &q_u->handle;
5527 UNISTR2 *uni_arch = &q_u->architecture;
5528 uint32 level = q_u->level;
5529 uint32 clientmajorversion = q_u->clientmajorversion;
5530 RPC_BUFFER *buffer = NULL;
5531 uint32 offered = q_u->offered;
5532 uint32 *needed = &r_u->needed;
5533 uint32 *servermajorversion = &r_u->servermajorversion;
5534 uint32 *serverminorversion = &r_u->serverminorversion;
5535 Printer_entry *printer;
5538 fstring architecture;
5541 /* that's an [in out] buffer */
5544 return WERR_INVALID_PARAM;
5547 rpcbuf_move(q_u->buffer, &r_u->buffer);
5548 buffer = r_u->buffer;
5550 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5552 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5553 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5554 return WERR_INVALID_PRINTER_NAME;
5558 *servermajorversion = 0;
5559 *serverminorversion = 0;
5561 fstrcpy(servername, get_server_name( printer ));
5562 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5564 if (!get_printer_snum(p, handle, &snum))
5569 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5571 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5573 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5575 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5578 /* apparently this call is the equivalent of
5579 EnumPrinterDataEx() for the DsDriver key */
5584 return WERR_UNKNOWN_LEVEL;
5587 /****************************************************************************
5588 ****************************************************************************/
5590 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5592 POLICY_HND *handle = &q_u->handle;
5594 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5597 DEBUG(3,("Error in startpageprinter printer handle\n"));
5601 Printer->page_started=True;
5605 /****************************************************************************
5606 ****************************************************************************/
5608 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5610 POLICY_HND *handle = &q_u->handle;
5613 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5616 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5620 if (!get_printer_snum(p, handle, &snum))
5623 Printer->page_started=False;
5624 print_job_endpage(snum, Printer->jobid);
5629 /********************************************************************
5630 * api_spoolss_getprinter
5631 * called from the spoolss dispatcher
5633 ********************************************************************/
5635 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5637 POLICY_HND *handle = &q_u->handle;
5638 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5639 uint32 *jobid = &r_u->jobid;
5641 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5645 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5646 struct current_user user;
5649 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5653 get_current_user(&user, p);
5656 * a nice thing with NT is it doesn't listen to what you tell it.
5657 * when asked to send _only_ RAW datas, it tries to send datas
5660 * So I add checks like in NT Server ...
5663 if (info_1->p_datatype != 0) {
5664 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5665 if (strcmp(datatype, "RAW") != 0) {
5667 return WERR_INVALID_DATATYPE;
5671 /* get the share number of the printer */
5672 if (!get_printer_snum(p, handle, &snum)) {
5676 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5678 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5680 /* An error occured in print_job_start() so return an appropriate
5683 if (Printer->jobid == -1) {
5684 return map_werror_from_unix(errno);
5687 Printer->document_started=True;
5688 (*jobid) = Printer->jobid;
5693 /********************************************************************
5694 * api_spoolss_getprinter
5695 * called from the spoolss dispatcher
5697 ********************************************************************/
5699 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5701 POLICY_HND *handle = &q_u->handle;
5703 return _spoolss_enddocprinter_internal(p, handle);
5706 /****************************************************************************
5707 ****************************************************************************/
5709 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5711 POLICY_HND *handle = &q_u->handle;
5712 uint32 buffer_size = q_u->buffer_size;
5713 uint8 *buffer = q_u->buffer;
5714 uint32 *buffer_written = &q_u->buffer_size2;
5716 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5719 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5720 r_u->buffer_written = q_u->buffer_size2;
5724 if (!get_printer_snum(p, handle, &snum))
5727 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5728 (SMB_OFF_T)-1, (size_t)buffer_size);
5729 if (*buffer_written == (uint32)-1) {
5730 r_u->buffer_written = 0;
5731 if (errno == ENOSPC)
5732 return WERR_NO_SPOOL_SPACE;
5734 return WERR_ACCESS_DENIED;
5737 r_u->buffer_written = q_u->buffer_size2;
5742 /********************************************************************
5743 * api_spoolss_getprinter
5744 * called from the spoolss dispatcher
5746 ********************************************************************/
5748 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5751 struct current_user user;
5753 WERROR errcode = WERR_BADFUNC;
5754 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5756 get_current_user(&user, p);
5759 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5763 if (!get_printer_snum(p, handle, &snum))
5767 case PRINTER_CONTROL_PAUSE:
5768 if (print_queue_pause(&user, snum, &errcode)) {
5772 case PRINTER_CONTROL_RESUME:
5773 case PRINTER_CONTROL_UNPAUSE:
5774 if (print_queue_resume(&user, snum, &errcode)) {
5778 case PRINTER_CONTROL_PURGE:
5779 if (print_queue_purge(&user, snum, &errcode)) {
5784 return WERR_UNKNOWN_LEVEL;
5790 /********************************************************************
5791 * api_spoolss_abortprinter
5792 * From MSDN: "Deletes printer's spool file if printer is configured
5794 ********************************************************************/
5796 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5798 POLICY_HND *handle = &q_u->handle;
5799 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5801 struct current_user user;
5802 WERROR errcode = WERR_OK;
5805 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5809 if (!get_printer_snum(p, handle, &snum))
5812 get_current_user( &user, p );
5814 print_job_delete( &user, snum, Printer->jobid, &errcode );
5819 /********************************************************************
5820 * called by spoolss_api_setprinter
5821 * when updating a printer description
5822 ********************************************************************/
5824 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5825 const SPOOL_PRINTER_INFO_LEVEL *info,
5826 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5828 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5832 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5834 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5835 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5836 OUR_HANDLE(handle)));
5838 result = WERR_BADFID;
5842 /* Check the user has permissions to change the security
5843 descriptor. By experimentation with two NT machines, the user
5844 requires Full Access to the printer to change security
5847 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5848 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5849 result = WERR_ACCESS_DENIED;
5853 /* NT seems to like setting the security descriptor even though
5854 nothing may have actually changed. */
5856 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5858 if (DEBUGLEVEL >= 10) {
5862 the_acl = old_secdesc_ctr->sec->dacl;
5863 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5864 PRINTERNAME(snum), the_acl->num_aces));
5866 for (i = 0; i < the_acl->num_aces; i++) {
5869 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5871 DEBUG(10, ("%s 0x%08x\n", sid_str,
5872 the_acl->ace[i].info.mask));
5875 the_acl = secdesc_ctr->sec->dacl;
5878 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5879 PRINTERNAME(snum), the_acl->num_aces));
5881 for (i = 0; i < the_acl->num_aces; i++) {
5884 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5886 DEBUG(10, ("%s 0x%08x\n", sid_str,
5887 the_acl->ace[i].info.mask));
5890 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5894 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5896 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5901 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5908 /********************************************************************
5909 Canonicalize printer info from a client
5911 ATTN: It does not matter what we set the servername to hear
5912 since we do the necessary work in get_a_printer() to set it to
5913 the correct value based on what the client sent in the
5914 _spoolss_open_printer_ex().
5915 ********************************************************************/
5917 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5919 fstring printername;
5922 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5923 "portname=%s drivername=%s comment=%s location=%s\n",
5924 info->servername, info->printername, info->sharename,
5925 info->portname, info->drivername, info->comment, info->location));
5927 /* we force some elements to "correct" values */
5928 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5929 fstrcpy(info->sharename, lp_servicename(snum));
5931 /* check to see if we allow printername != sharename */
5933 if ( lp_force_printername(snum) ) {
5934 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5935 global_myname(), info->sharename );
5938 /* make sure printername is in \\server\printername format */
5940 fstrcpy( printername, info->printername );
5942 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5943 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5947 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5948 global_myname(), p );
5951 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5952 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5959 /****************************************************************************
5960 ****************************************************************************/
5962 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
5964 char *cmd = lp_addport_cmd();
5968 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5969 BOOL is_print_op = False;
5972 return WERR_ACCESS_DENIED;
5975 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
5978 is_print_op = user_has_privileges( token, &se_printop );
5980 DEBUG(10,("Running [%s]\n", command));
5982 /********* BEGIN SePrintOperatorPrivilege **********/
5987 ret = smbrun(command, &fd);
5992 /********* END SePrintOperatorPrivilege **********/
5994 DEBUGADD(10,("returned [%d]\n", ret));
5999 return WERR_ACCESS_DENIED;
6005 /****************************************************************************
6006 ****************************************************************************/
6008 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6010 char *cmd = lp_addprinter_cmd();
6016 fstring remote_machine = "%m";
6017 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6018 BOOL is_print_op = False;
6020 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6022 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6023 cmd, printer->info_2->printername, printer->info_2->sharename,
6024 printer->info_2->portname, printer->info_2->drivername,
6025 printer->info_2->location, printer->info_2->comment, remote_machine);
6028 is_print_op = user_has_privileges( token, &se_printop );
6030 DEBUG(10,("Running [%s]\n", command));
6032 /********* BEGIN SePrintOperatorPrivilege **********/
6037 if ( (ret = smbrun(command, &fd)) == 0 ) {
6038 /* Tell everyone we updated smb.conf. */
6039 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6045 /********* END SePrintOperatorPrivilege **********/
6047 DEBUGADD(10,("returned [%d]\n", ret));
6055 /* reload our services immediately */
6056 reload_services( False );
6059 /* Get lines and convert them back to dos-codepage */
6060 qlines = fd_lines_load(fd, &numlines, 0);
6061 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6064 /* Set the portname to what the script says the portname should be. */
6065 /* but don't require anything to be return from the script exit a good error code */
6068 /* Set the portname to what the script says the portname should be. */
6069 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6070 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6073 file_lines_free(qlines);
6078 /********************************************************************
6079 * Called by spoolss_api_setprinter
6080 * when updating a printer description.
6081 ********************************************************************/
6083 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6084 const SPOOL_PRINTER_INFO_LEVEL *info,
6085 DEVICEMODE *devmode)
6088 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6089 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6094 DEBUG(8,("update_printer\n"));
6099 result = WERR_BADFID;
6103 if (!get_printer_snum(p, handle, &snum)) {
6104 result = WERR_BADFID;
6108 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6109 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6110 result = WERR_BADFID;
6114 DEBUGADD(8,("Converting info_2 struct\n"));
6117 * convert_printer_info converts the incoming
6118 * info from the client and overwrites the info
6119 * just read from the tdb in the pointer 'printer'.
6122 if (!convert_printer_info(info, printer, level)) {
6123 result = WERR_NOMEM;
6128 /* we have a valid devmode
6129 convert it and link it*/
6131 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6132 if (!convert_devicemode(printer->info_2->printername, devmode,
6133 &printer->info_2->devmode)) {
6134 result = WERR_NOMEM;
6139 /* Do sanity check on the requested changes for Samba */
6141 if (!check_printer_ok(printer->info_2, snum)) {
6142 result = WERR_INVALID_PARAM;
6146 /* FIXME!!! If the driver has changed we really should verify that
6147 it is installed before doing much else --jerry */
6149 /* Check calling user has permission to update printer description */
6151 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6152 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6153 result = WERR_ACCESS_DENIED;
6157 /* Call addprinter hook */
6158 /* Check changes to see if this is really needed */
6160 if ( *lp_addprinter_cmd()
6161 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6162 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6163 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6164 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6166 /* add_printer_hook() will call reload_services() */
6168 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6169 result = WERR_ACCESS_DENIED;
6175 * When a *new* driver is bound to a printer, the drivername is used to
6176 * lookup previously saved driver initialization info, which is then
6177 * bound to the printer, simulating what happens in the Windows arch.
6179 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6181 if (!set_driver_init(printer, 2))
6183 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6184 printer->info_2->drivername));
6187 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6188 printer->info_2->drivername));
6190 notify_printer_driver(snum, printer->info_2->drivername);
6194 * flag which changes actually occured. This is a small subset of
6195 * all the possible changes. We also have to update things in the
6199 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6200 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6201 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6202 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6204 notify_printer_comment(snum, printer->info_2->comment);
6207 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6208 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6209 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6210 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6212 notify_printer_sharename(snum, printer->info_2->sharename);
6215 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6218 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6221 pname = printer->info_2->printername;
6224 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6225 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6226 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6228 notify_printer_printername( snum, pname );
6231 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6232 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6233 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6234 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6236 notify_printer_port(snum, printer->info_2->portname);
6239 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6240 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6241 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6242 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6244 notify_printer_location(snum, printer->info_2->location);
6247 /* here we need to update some more DsSpooler keys */
6248 /* uNCName, serverName, shortServerName */
6250 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6251 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6252 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6253 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6254 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6256 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6257 global_myname(), printer->info_2->sharename );
6258 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6259 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6260 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6262 /* Update printer info */
6263 result = mod_a_printer(printer, 2);
6266 free_a_printer(&printer, 2);
6267 free_a_printer(&old_printer, 2);
6273 /****************************************************************************
6274 ****************************************************************************/
6275 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6276 const SPOOL_PRINTER_INFO_LEVEL *info)
6279 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6281 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6283 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6288 if (!get_printer_snum(p, handle, &snum))
6291 nt_printer_publish(Printer, snum, info7->action);
6295 return WERR_UNKNOWN_LEVEL;
6298 /****************************************************************************
6299 ****************************************************************************/
6301 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6303 POLICY_HND *handle = &q_u->handle;
6304 uint32 level = q_u->level;
6305 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6306 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6307 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6308 uint32 command = q_u->command;
6311 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6314 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6318 /* check the level */
6321 return control_printer(handle, command, p);
6323 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6324 if (!W_ERROR_IS_OK(result))
6327 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6330 return update_printer_sec(handle, level, info, p,
6333 return publish_or_unpublish_printer(p, handle, info);
6335 return WERR_UNKNOWN_LEVEL;
6339 /****************************************************************************
6340 ****************************************************************************/
6342 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6344 POLICY_HND *handle = &q_u->handle;
6345 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6348 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6352 if (Printer->notify.client_connected==True) {
6355 if ( Printer->printer_type == SPLHND_SERVER)
6357 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6358 !get_printer_snum(p, handle, &snum) )
6361 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6364 Printer->notify.flags=0;
6365 Printer->notify.options=0;
6366 Printer->notify.localmachine[0]='\0';
6367 Printer->notify.printerlocal=0;
6368 if (Printer->notify.option)
6369 free_spool_notify_option(&Printer->notify.option);
6370 Printer->notify.client_connected=False;
6375 /****************************************************************************
6376 ****************************************************************************/
6378 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6380 /* that's an [in out] buffer */
6383 return WERR_INVALID_PARAM;
6386 rpcbuf_move(q_u->buffer, &r_u->buffer);
6389 return WERR_INVALID_PARAM; /* this is what a NT server
6390 returns for AddJob. AddJob
6391 must fail on non-local
6395 /****************************************************************************
6396 ****************************************************************************/
6398 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6399 int position, int snum,
6400 NT_PRINTER_INFO_LEVEL *ntprinter)
6404 t=gmtime(&queue->time);
6406 job_info->jobid=queue->job;
6407 init_unistr(&job_info->printername, lp_servicename(snum));
6408 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6409 init_unistr(&job_info->username, queue->fs_user);
6410 init_unistr(&job_info->document, queue->fs_file);
6411 init_unistr(&job_info->datatype, "RAW");
6412 init_unistr(&job_info->text_status, "");
6413 job_info->status=nt_printj_status(queue->status);
6414 job_info->priority=queue->priority;
6415 job_info->position=position;
6416 job_info->totalpages=queue->page_count;
6417 job_info->pagesprinted=0;
6419 make_systemtime(&job_info->submitted, t);
6422 /****************************************************************************
6423 ****************************************************************************/
6425 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6426 int position, int snum,
6427 NT_PRINTER_INFO_LEVEL *ntprinter,
6428 DEVICEMODE *devmode)
6432 t=gmtime(&queue->time);
6434 job_info->jobid=queue->job;
6436 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6438 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6439 init_unistr(&job_info->username, queue->fs_user);
6440 init_unistr(&job_info->document, queue->fs_file);
6441 init_unistr(&job_info->notifyname, queue->fs_user);
6442 init_unistr(&job_info->datatype, "RAW");
6443 init_unistr(&job_info->printprocessor, "winprint");
6444 init_unistr(&job_info->parameters, "");
6445 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6446 init_unistr(&job_info->text_status, "");
6448 /* and here the security descriptor */
6450 job_info->status=nt_printj_status(queue->status);
6451 job_info->priority=queue->priority;
6452 job_info->position=position;
6453 job_info->starttime=0;
6454 job_info->untiltime=0;
6455 job_info->totalpages=queue->page_count;
6456 job_info->size=queue->size;
6457 make_systemtime(&(job_info->submitted), t);
6458 job_info->timeelapsed=0;
6459 job_info->pagesprinted=0;
6461 job_info->devmode = devmode;
6466 /****************************************************************************
6467 Enumjobs at level 1.
6468 ****************************************************************************/
6470 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6471 NT_PRINTER_INFO_LEVEL *ntprinter,
6472 RPC_BUFFER *buffer, uint32 offered,
6473 uint32 *needed, uint32 *returned)
6477 WERROR result = WERR_OK;
6479 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6486 for (i=0; i<*returned; i++)
6487 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6491 /* check the required size. */
6492 for (i=0; i<*returned; i++)
6493 (*needed) += spoolss_size_job_info_1(&info[i]);
6495 if (*needed > offered) {
6496 result = WERR_INSUFFICIENT_BUFFER;
6500 if (!rpcbuf_alloc_size(buffer, *needed)) {
6501 result = WERR_NOMEM;
6505 /* fill the buffer with the structures */
6506 for (i=0; i<*returned; i++)
6507 smb_io_job_info_1("", buffer, &info[i], 0);
6513 if ( !W_ERROR_IS_OK(result) )
6519 /****************************************************************************
6520 Enumjobs at level 2.
6521 ****************************************************************************/
6523 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6524 NT_PRINTER_INFO_LEVEL *ntprinter,
6525 RPC_BUFFER *buffer, uint32 offered,
6526 uint32 *needed, uint32 *returned)
6528 JOB_INFO_2 *info = NULL;
6530 WERROR result = WERR_OK;
6531 DEVICEMODE *devmode = NULL;
6533 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6538 /* this should not be a failure condition if the devmode is NULL */
6540 devmode = construct_dev_mode(snum);
6542 for (i=0; i<*returned; i++)
6543 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6545 free_a_printer(&ntprinter, 2);
6548 /* check the required size. */
6549 for (i=0; i<*returned; i++)
6550 (*needed) += spoolss_size_job_info_2(&info[i]);
6552 if (*needed > offered) {
6553 result = WERR_INSUFFICIENT_BUFFER;
6557 if (!rpcbuf_alloc_size(buffer, *needed)) {
6558 result = WERR_NOMEM;
6562 /* fill the buffer with the structures */
6563 for (i=0; i<*returned; i++)
6564 smb_io_job_info_2("", buffer, &info[i], 0);
6567 free_devmode(devmode);
6570 if ( !W_ERROR_IS_OK(result) )
6577 /****************************************************************************
6579 ****************************************************************************/
6581 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6583 POLICY_HND *handle = &q_u->handle;
6584 uint32 level = q_u->level;
6585 RPC_BUFFER *buffer = NULL;
6586 uint32 offered = q_u->offered;
6587 uint32 *needed = &r_u->needed;
6588 uint32 *returned = &r_u->returned;
6590 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6592 print_status_struct prt_status;
6593 print_queue_struct *queue=NULL;
6595 /* that's an [in out] buffer */
6598 return WERR_INVALID_PARAM;
6601 rpcbuf_move(q_u->buffer, &r_u->buffer);
6602 buffer = r_u->buffer;
6604 DEBUG(4,("_spoolss_enumjobs\n"));
6609 /* lookup the printer snum and tdb entry */
6611 if (!get_printer_snum(p, handle, &snum))
6614 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6615 if ( !W_ERROR_IS_OK(wret) )
6618 *returned = print_queue_status(snum, &queue, &prt_status);
6619 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6621 if (*returned == 0) {
6628 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6631 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6636 wret = WERR_UNKNOWN_LEVEL;
6639 free_a_printer( &ntprinter, 2 );
6643 /****************************************************************************
6644 ****************************************************************************/
6646 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6651 /****************************************************************************
6652 ****************************************************************************/
6654 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6656 POLICY_HND *handle = &q_u->handle;
6657 uint32 jobid = q_u->jobid;
6658 uint32 command = q_u->command;
6660 struct current_user user;
6662 WERROR errcode = WERR_BADFUNC;
6664 if (!get_printer_snum(p, handle, &snum)) {
6668 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6669 return WERR_INVALID_PRINTER_NAME;
6672 get_current_user(&user, p);
6675 case JOB_CONTROL_CANCEL:
6676 case JOB_CONTROL_DELETE:
6677 if (print_job_delete(&user, snum, jobid, &errcode)) {
6681 case JOB_CONTROL_PAUSE:
6682 if (print_job_pause(&user, snum, jobid, &errcode)) {
6686 case JOB_CONTROL_RESTART:
6687 case JOB_CONTROL_RESUME:
6688 if (print_job_resume(&user, snum, jobid, &errcode)) {
6693 return WERR_UNKNOWN_LEVEL;
6699 /****************************************************************************
6700 Enumerates all printer drivers at level 1.
6701 ****************************************************************************/
6703 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6708 fstring *list = NULL;
6709 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6710 DRIVER_INFO_1 *driver_info_1=NULL;
6711 WERROR result = WERR_OK;
6715 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6717 ndrivers=get_ntdrivers(&list, architecture, version);
6718 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6724 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6725 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6731 for (i=0; i<ndrivers; i++) {
6733 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6734 ZERO_STRUCT(driver);
6735 status = get_a_printer_driver(&driver, 3, list[i],
6736 architecture, version);
6737 if (!W_ERROR_IS_OK(status)) {
6739 SAFE_FREE(driver_info_1);
6742 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6743 free_a_printer_driver(driver, 3);
6746 *returned+=ndrivers;
6750 /* check the required size. */
6751 for (i=0; i<*returned; i++) {
6752 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6753 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6756 if (*needed > offered) {
6757 result = WERR_INSUFFICIENT_BUFFER;
6761 if (!rpcbuf_alloc_size(buffer, *needed)) {
6762 result = WERR_NOMEM;
6766 /* fill the buffer with the driver structures */
6767 for (i=0; i<*returned; i++) {
6768 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6769 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6773 SAFE_FREE(driver_info_1);
6775 if ( !W_ERROR_IS_OK(result) )
6781 /****************************************************************************
6782 Enumerates all printer drivers at level 2.
6783 ****************************************************************************/
6785 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6790 fstring *list = NULL;
6791 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6792 DRIVER_INFO_2 *driver_info_2=NULL;
6793 WERROR result = WERR_OK;
6797 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6799 ndrivers=get_ntdrivers(&list, architecture, version);
6800 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6806 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6807 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6813 for (i=0; i<ndrivers; i++) {
6816 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6817 ZERO_STRUCT(driver);
6818 status = get_a_printer_driver(&driver, 3, list[i],
6819 architecture, version);
6820 if (!W_ERROR_IS_OK(status)) {
6822 SAFE_FREE(driver_info_2);
6825 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6826 free_a_printer_driver(driver, 3);
6829 *returned+=ndrivers;
6833 /* check the required size. */
6834 for (i=0; i<*returned; i++) {
6835 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6836 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6839 if (*needed > offered) {
6840 result = WERR_INSUFFICIENT_BUFFER;
6844 if (!rpcbuf_alloc_size(buffer, *needed)) {
6845 result = WERR_NOMEM;
6849 /* fill the buffer with the form structures */
6850 for (i=0; i<*returned; i++) {
6851 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6852 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6856 SAFE_FREE(driver_info_2);
6858 if ( !W_ERROR_IS_OK(result) )
6864 /****************************************************************************
6865 Enumerates all printer drivers at level 3.
6866 ****************************************************************************/
6868 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6873 fstring *list = NULL;
6874 DRIVER_INFO_3 *driver_info_3=NULL;
6875 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6876 WERROR result = WERR_OK;
6880 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6882 ndrivers=get_ntdrivers(&list, architecture, version);
6883 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6885 if(ndrivers == -1) {
6886 SAFE_FREE(driver_info_3);
6891 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6892 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6898 for (i=0; i<ndrivers; i++) {
6901 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6902 ZERO_STRUCT(driver);
6903 status = get_a_printer_driver(&driver, 3, list[i],
6904 architecture, version);
6905 if (!W_ERROR_IS_OK(status)) {
6907 SAFE_FREE(driver_info_3);
6910 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6911 free_a_printer_driver(driver, 3);
6914 *returned+=ndrivers;
6918 /* check the required size. */
6919 for (i=0; i<*returned; i++) {
6920 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6921 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6924 if (*needed > offered) {
6925 result = WERR_INSUFFICIENT_BUFFER;
6929 if (!rpcbuf_alloc_size(buffer, *needed)) {
6930 result = WERR_NOMEM;
6934 /* fill the buffer with the driver structures */
6935 for (i=0; i<*returned; i++) {
6936 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6937 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6941 for (i=0; i<*returned; i++) {
6942 SAFE_FREE(driver_info_3[i].dependentfiles);
6945 SAFE_FREE(driver_info_3);
6947 if ( !W_ERROR_IS_OK(result) )
6953 /****************************************************************************
6954 Enumerates all printer drivers.
6955 ****************************************************************************/
6957 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6959 uint32 level = q_u->level;
6960 RPC_BUFFER *buffer = NULL;
6961 uint32 offered = q_u->offered;
6962 uint32 *needed = &r_u->needed;
6963 uint32 *returned = &r_u->returned;
6966 fstring architecture;
6968 /* that's an [in out] buffer */
6971 return WERR_INVALID_PARAM;
6974 rpcbuf_move(q_u->buffer, &r_u->buffer);
6975 buffer = r_u->buffer;
6977 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6982 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6983 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6985 if ( !is_myname_or_ipaddr( servername ) )
6986 return WERR_UNKNOWN_PRINTER_DRIVER;
6990 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6992 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6994 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6996 return WERR_UNKNOWN_LEVEL;
7000 /****************************************************************************
7001 ****************************************************************************/
7003 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7005 form->flag=list->flag;
7006 init_unistr(&form->name, list->name);
7007 form->width=list->width;
7008 form->length=list->length;
7009 form->left=list->left;
7010 form->top=list->top;
7011 form->right=list->right;
7012 form->bottom=list->bottom;
7015 /****************************************************************************
7016 ****************************************************************************/
7018 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7020 uint32 level = q_u->level;
7021 RPC_BUFFER *buffer = NULL;
7022 uint32 offered = q_u->offered;
7023 uint32 *needed = &r_u->needed;
7024 uint32 *numofforms = &r_u->numofforms;
7025 uint32 numbuiltinforms;
7027 nt_forms_struct *list=NULL;
7028 nt_forms_struct *builtinlist=NULL;
7033 /* that's an [in out] buffer */
7036 return WERR_INVALID_PARAM;
7039 rpcbuf_move(q_u->buffer, &r_u->buffer);
7040 buffer = r_u->buffer;
7042 DEBUG(4,("_spoolss_enumforms\n"));
7043 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7044 DEBUGADD(5,("Info level [%d]\n", level));
7046 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7047 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7048 *numofforms = get_ntforms(&list);
7049 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7050 *numofforms += numbuiltinforms;
7052 if (*numofforms == 0) {
7053 SAFE_FREE(builtinlist);
7055 return WERR_NO_MORE_ITEMS;
7060 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7061 SAFE_FREE(builtinlist);
7067 /* construct the list of form structures */
7068 for (i=0; i<numbuiltinforms; i++) {
7069 DEBUGADD(6,("Filling form number [%d]\n",i));
7070 fill_form_1(&forms_1[i], &builtinlist[i]);
7073 SAFE_FREE(builtinlist);
7075 for (; i<*numofforms; i++) {
7076 DEBUGADD(6,("Filling form number [%d]\n",i));
7077 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7082 /* check the required size. */
7083 for (i=0; i<numbuiltinforms; i++) {
7084 DEBUGADD(6,("adding form [%d]'s size\n",i));
7085 buffer_size += spoolss_size_form_1(&forms_1[i]);
7087 for (; i<*numofforms; i++) {
7088 DEBUGADD(6,("adding form [%d]'s size\n",i));
7089 buffer_size += spoolss_size_form_1(&forms_1[i]);
7092 *needed=buffer_size;
7094 if (*needed > offered) {
7097 return WERR_INSUFFICIENT_BUFFER;
7100 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7106 /* fill the buffer with the form structures */
7107 for (i=0; i<numbuiltinforms; i++) {
7108 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7109 smb_io_form_1("", buffer, &forms_1[i], 0);
7111 for (; i<*numofforms; i++) {
7112 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7113 smb_io_form_1("", buffer, &forms_1[i], 0);
7122 SAFE_FREE(builtinlist);
7123 return WERR_UNKNOWN_LEVEL;
7127 /****************************************************************************
7128 ****************************************************************************/
7130 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7132 uint32 level = q_u->level;
7133 UNISTR2 *uni_formname = &q_u->formname;
7134 RPC_BUFFER *buffer = NULL;
7135 uint32 offered = q_u->offered;
7136 uint32 *needed = &r_u->needed;
7138 nt_forms_struct *list=NULL;
7139 nt_forms_struct builtin_form;
7144 int numofforms=0, i=0;
7146 /* that's an [in out] buffer */
7149 return WERR_INVALID_PARAM;
7152 rpcbuf_move(q_u->buffer, &r_u->buffer);
7153 buffer = r_u->buffer;
7155 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7157 DEBUG(4,("_spoolss_getform\n"));
7158 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7159 DEBUGADD(5,("Info level [%d]\n", level));
7161 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7162 if (!foundBuiltin) {
7163 numofforms = get_ntforms(&list);
7164 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7166 if (numofforms == 0)
7173 fill_form_1(&form_1, &builtin_form);
7176 /* Check if the requested name is in the list of form structures */
7177 for (i=0; i<numofforms; i++) {
7179 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7181 if (strequal(form_name, list[i].name)) {
7182 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7183 fill_form_1(&form_1, &list[i]);
7189 if (i == numofforms) {
7193 /* check the required size. */
7195 *needed=spoolss_size_form_1(&form_1);
7197 if (*needed > offered)
7198 return WERR_INSUFFICIENT_BUFFER;
7200 if (!rpcbuf_alloc_size(buffer, buffer_size))
7203 /* fill the buffer with the form structures */
7204 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7205 smb_io_form_1("", buffer, &form_1, 0);
7211 return WERR_UNKNOWN_LEVEL;
7215 /****************************************************************************
7216 ****************************************************************************/
7218 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7220 init_unistr(&port->port_name, name);
7223 /****************************************************************************
7224 TODO: This probably needs distinguish between TCP/IP and Local ports
7226 ****************************************************************************/
7228 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7230 init_unistr(&port->port_name, name);
7231 init_unistr(&port->monitor_name, "Local Monitor");
7232 init_unistr(&port->description, SPL_LOCAL_PORT );
7233 port->port_type=PORT_TYPE_WRITE;
7238 /****************************************************************************
7239 wrapper around the enumer ports command
7240 ****************************************************************************/
7242 WERROR enumports_hook( int *count, char ***lines )
7244 char *cmd = lp_enumports_cmd();
7254 /* if no hook then just fill in the default port */
7257 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7258 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7263 /* we have a valid enumport command */
7265 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7267 DEBUG(10,("Running [%s]\n", command));
7268 ret = smbrun(command, &fd);
7269 DEBUG(10,("Returned [%d]\n", ret));
7274 return WERR_ACCESS_DENIED;
7278 qlines = fd_lines_load(fd, &numlines, 0);
7279 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7289 /****************************************************************************
7291 ****************************************************************************/
7293 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7295 PORT_INFO_1 *ports=NULL;
7297 WERROR result = WERR_OK;
7298 char **qlines = NULL;
7301 result = enumports_hook( &numlines, &qlines );
7302 if (!W_ERROR_IS_OK(result)) {
7303 file_lines_free(qlines);
7308 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7309 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7310 dos_errstr(WERR_NOMEM)));
7311 file_lines_free(qlines);
7315 for (i=0; i<numlines; i++) {
7316 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7317 fill_port_1(&ports[i], qlines[i]);
7320 file_lines_free(qlines);
7322 *returned = numlines;
7324 /* check the required size. */
7325 for (i=0; i<*returned; i++) {
7326 DEBUGADD(6,("adding port [%d]'s size\n", i));
7327 *needed += spoolss_size_port_info_1(&ports[i]);
7330 if (*needed > offered) {
7331 result = WERR_INSUFFICIENT_BUFFER;
7335 if (!rpcbuf_alloc_size(buffer, *needed)) {
7336 result = WERR_NOMEM;
7340 /* fill the buffer with the ports structures */
7341 for (i=0; i<*returned; i++) {
7342 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7343 smb_io_port_1("", buffer, &ports[i], 0);
7349 if ( !W_ERROR_IS_OK(result) )
7355 /****************************************************************************
7357 ****************************************************************************/
7359 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7361 PORT_INFO_2 *ports=NULL;
7363 WERROR result = WERR_OK;
7364 char **qlines = NULL;
7367 result = enumports_hook( &numlines, &qlines );
7368 if ( !W_ERROR_IS_OK(result)) {
7369 file_lines_free(qlines);
7374 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7375 file_lines_free(qlines);
7379 for (i=0; i<numlines; i++) {
7380 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7381 fill_port_2(&(ports[i]), qlines[i]);
7385 file_lines_free(qlines);
7387 *returned = numlines;
7389 /* check the required size. */
7390 for (i=0; i<*returned; i++) {
7391 DEBUGADD(6,("adding port [%d]'s size\n", i));
7392 *needed += spoolss_size_port_info_2(&ports[i]);
7395 if (*needed > offered) {
7396 result = WERR_INSUFFICIENT_BUFFER;
7400 if (!rpcbuf_alloc_size(buffer, *needed)) {
7401 result = WERR_NOMEM;
7405 /* fill the buffer with the ports structures */
7406 for (i=0; i<*returned; i++) {
7407 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7408 smb_io_port_2("", buffer, &ports[i], 0);
7414 if ( !W_ERROR_IS_OK(result) )
7420 /****************************************************************************
7422 ****************************************************************************/
7424 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7426 uint32 level = q_u->level;
7427 RPC_BUFFER *buffer = NULL;
7428 uint32 offered = q_u->offered;
7429 uint32 *needed = &r_u->needed;
7430 uint32 *returned = &r_u->returned;
7432 /* that's an [in out] buffer */
7435 return WERR_INVALID_PARAM;
7438 rpcbuf_move(q_u->buffer, &r_u->buffer);
7439 buffer = r_u->buffer;
7441 DEBUG(4,("_spoolss_enumports\n"));
7448 return enumports_level_1(buffer, offered, needed, returned);
7450 return enumports_level_2(buffer, offered, needed, returned);
7452 return WERR_UNKNOWN_LEVEL;
7456 /****************************************************************************
7457 ****************************************************************************/
7459 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7460 const SPOOL_PRINTER_INFO_LEVEL *info,
7461 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7462 uint32 user_switch, const SPOOL_USER_CTR *user,
7465 NT_PRINTER_INFO_LEVEL *printer = NULL;
7468 WERROR err = WERR_OK;
7470 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7471 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7475 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7476 if (!convert_printer_info(info, printer, 2)) {
7477 free_a_printer(&printer, 2);
7481 /* check to see if the printer already exists */
7483 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7484 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7485 printer->info_2->sharename));
7486 free_a_printer(&printer, 2);
7487 return WERR_PRINTER_ALREADY_EXISTS;
7490 /* FIXME!!! smbd should check to see if the driver is installed before
7491 trying to add a printer like this --jerry */
7493 if (*lp_addprinter_cmd() ) {
7494 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7495 free_a_printer(&printer,2);
7496 return WERR_ACCESS_DENIED;
7499 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7500 "smb.conf parameter \"addprinter command\" is defined. This"
7501 "parameter must exist for this call to succeed\n",
7502 printer->info_2->sharename ));
7505 /* use our primary netbios name since get_a_printer() will convert
7506 it to what the client expects on a case by case basis */
7508 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7509 printer->info_2->sharename);
7512 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7513 free_a_printer(&printer,2);
7514 return WERR_ACCESS_DENIED;
7517 /* you must be a printer admin to add a new printer */
7518 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7519 free_a_printer(&printer,2);
7520 return WERR_ACCESS_DENIED;
7524 * Do sanity check on the requested changes for Samba.
7527 if (!check_printer_ok(printer->info_2, snum)) {
7528 free_a_printer(&printer,2);
7529 return WERR_INVALID_PARAM;
7533 * When a printer is created, the drivername bound to the printer is used
7534 * to lookup previously saved driver initialization info, which is then
7535 * bound to the new printer, simulating what happens in the Windows arch.
7540 set_driver_init(printer, 2);
7544 /* A valid devmode was included, convert and link it
7546 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7548 if (!convert_devicemode(printer->info_2->printername, devmode,
7549 &printer->info_2->devmode))
7553 /* write the ASCII on disk */
7554 err = mod_a_printer(printer, 2);
7555 if (!W_ERROR_IS_OK(err)) {
7556 free_a_printer(&printer,2);
7560 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7561 /* Handle open failed - remove addition. */
7562 del_a_printer(printer->info_2->sharename);
7563 free_a_printer(&printer,2);
7564 return WERR_ACCESS_DENIED;
7567 update_c_setprinter(False);
7568 free_a_printer(&printer,2);
7573 /****************************************************************************
7574 ****************************************************************************/
7576 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7578 UNISTR2 *uni_srv_name = q_u->server_name;
7579 uint32 level = q_u->level;
7580 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7581 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7582 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7583 uint32 user_switch = q_u->user_switch;
7584 SPOOL_USER_CTR *user = &q_u->user_ctr;
7585 POLICY_HND *handle = &r_u->handle;
7589 /* we don't handle yet */
7590 /* but I know what to do ... */
7591 return WERR_UNKNOWN_LEVEL;
7593 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7595 user_switch, user, handle);
7597 return WERR_UNKNOWN_LEVEL;
7601 /****************************************************************************
7602 ****************************************************************************/
7604 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7606 uint32 level = q_u->level;
7607 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7608 WERROR err = WERR_OK;
7609 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7610 struct current_user user;
7611 fstring driver_name;
7614 ZERO_STRUCT(driver);
7616 get_current_user(&user, p);
7618 if (!convert_printer_driver_info(info, &driver, level)) {
7623 DEBUG(5,("Cleaning driver's information\n"));
7624 err = clean_up_driver_struct(driver, level, &user);
7625 if (!W_ERROR_IS_OK(err))
7628 DEBUG(5,("Moving driver to final destination\n"));
7629 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7633 if (add_a_printer_driver(driver, level)!=0) {
7634 err = WERR_ACCESS_DENIED;
7638 /* BEGIN_ADMIN_LOG */
7641 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7642 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7643 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.ut.uid));
7646 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7647 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7648 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.ut.uid));
7654 * I think this is where he DrvUpgradePrinter() hook would be
7655 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7656 * server. Right now, we just need to send ourselves a message
7657 * to update each printer bound to this driver. --jerry
7660 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7661 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7666 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7667 * decide if the driver init data should be deleted. The rules are:
7668 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7669 * 2) delete init data only if there is no 2k/Xp driver
7670 * 3) always delete init data
7671 * The generalized rule is always use init data from the highest order driver.
7672 * It is necessary to follow the driver install by an initialization step to
7673 * finish off this process.
7676 version = driver.info_3->cversion;
7677 else if (level == 6)
7678 version = driver.info_6->version;
7683 * 9x printer driver - never delete init data
7686 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7691 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7692 * there is no 2k/Xp driver init data for this driver name.
7696 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7698 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7700 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7702 if (!del_driver_init(driver_name))
7703 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7706 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7708 free_a_printer_driver(driver1,3);
7709 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7716 * 2k or Xp printer driver - always delete init data
7719 if (!del_driver_init(driver_name))
7720 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7724 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7730 free_a_printer_driver(driver, level);
7734 /********************************************************************
7735 * spoolss_addprinterdriverex
7736 ********************************************************************/
7738 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7740 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7741 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7744 * we only support the semantics of AddPrinterDriver()
7745 * i.e. only copy files that are newer than existing ones
7748 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7749 return WERR_ACCESS_DENIED;
7751 ZERO_STRUCT(q_u_local);
7752 ZERO_STRUCT(r_u_local);
7754 /* just pass the information off to _spoolss_addprinterdriver() */
7755 q_u_local.server_name_ptr = q_u->server_name_ptr;
7756 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7757 q_u_local.level = q_u->level;
7758 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7760 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7763 /****************************************************************************
7764 ****************************************************************************/
7766 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7768 init_unistr(&info->name, name);
7771 /****************************************************************************
7772 ****************************************************************************/
7774 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7780 const char *short_archi;
7781 DRIVER_DIRECTORY_1 *info=NULL;
7782 WERROR result = WERR_OK;
7784 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7785 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7787 /* check for beginning double '\'s and that the server
7790 pservername = servername;
7791 if ( *pservername == '\\' && strlen(servername)>2 ) {
7795 if ( !is_myname_or_ipaddr( pservername ) )
7796 return WERR_INVALID_PARAM;
7798 if (!(short_archi = get_short_archi(long_archi)))
7799 return WERR_INVALID_ENVIRONMENT;
7801 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7804 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7806 DEBUG(4,("printer driver directory: [%s]\n", path));
7808 fill_driverdir_1(info, path);
7810 *needed += spoolss_size_driverdir_info_1(info);
7812 if (*needed > offered) {
7813 result = WERR_INSUFFICIENT_BUFFER;
7817 if (!rpcbuf_alloc_size(buffer, *needed)) {
7818 result = WERR_NOMEM;
7822 smb_io_driverdir_1("", buffer, info, 0);
7830 /****************************************************************************
7831 ****************************************************************************/
7833 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7835 UNISTR2 *name = &q_u->name;
7836 UNISTR2 *uni_environment = &q_u->environment;
7837 uint32 level = q_u->level;
7838 RPC_BUFFER *buffer = NULL;
7839 uint32 offered = q_u->offered;
7840 uint32 *needed = &r_u->needed;
7842 /* that's an [in out] buffer */
7844 if (!q_u->buffer ) {
7845 return WERR_INVALID_PARAM;
7848 rpcbuf_move(q_u->buffer, &r_u->buffer);
7849 buffer = r_u->buffer;
7851 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7857 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7859 return WERR_UNKNOWN_LEVEL;
7863 /****************************************************************************
7864 ****************************************************************************/
7866 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7868 POLICY_HND *handle = &q_u->handle;
7869 uint32 idx = q_u->index;
7870 uint32 in_value_len = q_u->valuesize;
7871 uint32 in_data_len = q_u->datasize;
7872 uint32 *out_max_value_len = &r_u->valuesize;
7873 uint16 **out_value = &r_u->value;
7874 uint32 *out_value_len = &r_u->realvaluesize;
7875 uint32 *out_type = &r_u->type;
7876 uint32 *out_max_data_len = &r_u->datasize;
7877 uint8 **data_out = &r_u->data;
7878 uint32 *out_data_len = &r_u->realdatasize;
7880 NT_PRINTER_INFO_LEVEL *printer = NULL;
7882 uint32 biggest_valuesize;
7883 uint32 biggest_datasize;
7885 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7888 REGISTRY_VALUE *val = NULL;
7889 NT_PRINTER_DATA *p_data;
7890 int i, key_index, num_values;
7895 *out_max_data_len = 0;
7899 DEBUG(5,("spoolss_enumprinterdata\n"));
7902 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7906 if (!get_printer_snum(p,handle, &snum))
7909 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7910 if (!W_ERROR_IS_OK(result))
7913 p_data = printer->info_2->data;
7914 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7919 * The NT machine wants to know the biggest size of value and data
7921 * cf: MSDN EnumPrinterData remark section
7924 if ( !in_value_len && !in_data_len && (key_index != -1) )
7926 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7928 biggest_valuesize = 0;
7929 biggest_datasize = 0;
7931 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7933 for ( i=0; i<num_values; i++ )
7935 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7937 name_length = strlen(val->valuename);
7938 if ( strlen(val->valuename) > biggest_valuesize )
7939 biggest_valuesize = name_length;
7941 if ( val->size > biggest_datasize )
7942 biggest_datasize = val->size;
7944 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7948 /* the value is an UNICODE string but real_value_size is the length
7949 in bytes including the trailing 0 */
7951 *out_value_len = 2 * (1+biggest_valuesize);
7952 *out_data_len = biggest_datasize;
7954 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7960 * the value len is wrong in NT sp3
7961 * that's the number of bytes not the number of unicode chars
7964 if ( key_index != -1 )
7965 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7970 /* out_value should default to "" or else NT4 has
7971 problems unmarshalling the response */
7973 *out_max_value_len=(in_value_len/sizeof(uint16));
7975 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7977 result = WERR_NOMEM;
7981 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7983 /* the data is counted in bytes */
7985 *out_max_data_len = in_data_len;
7986 *out_data_len = in_data_len;
7988 /* only allocate when given a non-zero data_len */
7990 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7992 result = WERR_NOMEM;
7996 result = WERR_NO_MORE_ITEMS;
8002 * - counted in bytes in the request
8003 * - counted in UNICODE chars in the max reply
8004 * - counted in bytes in the real size
8006 * take a pause *before* coding not *during* coding
8010 *out_max_value_len=(in_value_len/sizeof(uint16));
8011 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8013 result = WERR_NOMEM;
8017 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
8021 *out_type = regval_type( val );
8023 /* data - counted in bytes */
8025 *out_max_data_len = in_data_len;
8026 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8028 result = WERR_NOMEM;
8031 data_len = regval_size(val);
8033 memcpy( *data_out, regval_data_p(val), data_len );
8034 *out_data_len = data_len;
8038 free_a_printer(&printer, 2);
8042 /****************************************************************************
8043 ****************************************************************************/
8045 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8047 POLICY_HND *handle = &q_u->handle;
8048 UNISTR2 *value = &q_u->value;
8049 uint32 type = q_u->type;
8050 uint8 *data = q_u->data;
8051 uint32 real_len = q_u->real_len;
8053 NT_PRINTER_INFO_LEVEL *printer = NULL;
8055 WERROR status = WERR_OK;
8056 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8059 DEBUG(5,("spoolss_setprinterdata\n"));
8062 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8066 if ( Printer->printer_type == SPLHND_SERVER ) {
8067 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8068 return WERR_INVALID_PARAM;
8071 if (!get_printer_snum(p,handle, &snum))
8075 * Access check : NT returns "access denied" if you make a
8076 * SetPrinterData call without the necessary privildge.
8077 * we were originally returning OK if nothing changed
8078 * which made Win2k issue **a lot** of SetPrinterData
8079 * when connecting to a printer --jerry
8082 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8084 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8085 status = WERR_ACCESS_DENIED;
8089 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8090 if (!W_ERROR_IS_OK(status))
8093 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8096 * When client side code sets a magic printer data key, detect it and save
8097 * the current printer data and the magic key's data (its the DEVMODE) for
8098 * future printer/driver initializations.
8100 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8102 /* Set devmode and printer initialization info */
8103 status = save_driver_init( printer, 2, data, real_len );
8105 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8109 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8110 type, data, real_len );
8111 if ( W_ERROR_IS_OK(status) )
8112 status = mod_a_printer(printer, 2);
8116 free_a_printer(&printer, 2);
8121 /****************************************************************************
8122 ****************************************************************************/
8124 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8126 POLICY_HND *handle = &q_u->handle;
8127 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8130 DEBUG(5,("_spoolss_resetprinter\n"));
8133 * All we do is to check to see if the handle and queue is valid.
8134 * This call really doesn't mean anything to us because we only
8135 * support RAW printing. --jerry
8139 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8143 if (!get_printer_snum(p,handle, &snum))
8147 /* blindly return success */
8152 /****************************************************************************
8153 ****************************************************************************/
8155 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8157 POLICY_HND *handle = &q_u->handle;
8158 UNISTR2 *value = &q_u->valuename;
8160 NT_PRINTER_INFO_LEVEL *printer = NULL;
8162 WERROR status = WERR_OK;
8163 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8166 DEBUG(5,("spoolss_deleteprinterdata\n"));
8169 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8173 if (!get_printer_snum(p, handle, &snum))
8176 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8177 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8178 return WERR_ACCESS_DENIED;
8181 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8182 if (!W_ERROR_IS_OK(status))
8185 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8187 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8189 if ( W_ERROR_IS_OK(status) )
8190 mod_a_printer( printer, 2 );
8192 free_a_printer(&printer, 2);
8197 /****************************************************************************
8198 ****************************************************************************/
8200 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8202 POLICY_HND *handle = &q_u->handle;
8203 FORM *form = &q_u->form;
8204 nt_forms_struct tmpForm;
8206 WERROR status = WERR_OK;
8207 NT_PRINTER_INFO_LEVEL *printer = NULL;
8210 nt_forms_struct *list=NULL;
8211 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8213 DEBUG(5,("spoolss_addform\n"));
8216 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8221 /* forms can be added on printer of on the print server handle */
8223 if ( Printer->printer_type == SPLHND_PRINTER )
8225 if (!get_printer_snum(p,handle, &snum))
8228 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8229 if (!W_ERROR_IS_OK(status))
8233 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8234 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8235 status = WERR_ACCESS_DENIED;
8239 /* can't add if builtin */
8241 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8242 status = WERR_ALREADY_EXISTS;
8246 count = get_ntforms(&list);
8248 if(!add_a_form(&list, form, &count)) {
8249 status = WERR_NOMEM;
8253 write_ntforms(&list, count);
8256 * ChangeID must always be set if this is a printer
8259 if ( Printer->printer_type == SPLHND_PRINTER )
8260 status = mod_a_printer(printer, 2);
8264 free_a_printer(&printer, 2);
8270 /****************************************************************************
8271 ****************************************************************************/
8273 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8275 POLICY_HND *handle = &q_u->handle;
8276 UNISTR2 *form_name = &q_u->name;
8277 nt_forms_struct tmpForm;
8279 nt_forms_struct *list=NULL;
8280 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8282 WERROR status = WERR_OK;
8283 NT_PRINTER_INFO_LEVEL *printer = NULL;
8285 DEBUG(5,("spoolss_deleteform\n"));
8288 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8292 /* forms can be deleted on printer of on the print server handle */
8294 if ( Printer->printer_type == SPLHND_PRINTER )
8296 if (!get_printer_snum(p,handle, &snum))
8299 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8300 if (!W_ERROR_IS_OK(status))
8304 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8305 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8306 status = WERR_ACCESS_DENIED;
8310 /* can't delete if builtin */
8312 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8313 status = WERR_INVALID_PARAM;
8317 count = get_ntforms(&list);
8319 if ( !delete_a_form(&list, form_name, &count, &status ))
8323 * ChangeID must always be set if this is a printer
8326 if ( Printer->printer_type == SPLHND_PRINTER )
8327 status = mod_a_printer(printer, 2);
8331 free_a_printer(&printer, 2);
8337 /****************************************************************************
8338 ****************************************************************************/
8340 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8342 POLICY_HND *handle = &q_u->handle;
8343 FORM *form = &q_u->form;
8344 nt_forms_struct tmpForm;
8346 WERROR status = WERR_OK;
8347 NT_PRINTER_INFO_LEVEL *printer = NULL;
8350 nt_forms_struct *list=NULL;
8351 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8353 DEBUG(5,("spoolss_setform\n"));
8356 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8360 /* forms can be modified on printer of on the print server handle */
8362 if ( Printer->printer_type == SPLHND_PRINTER )
8364 if (!get_printer_snum(p,handle, &snum))
8367 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8368 if (!W_ERROR_IS_OK(status))
8372 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8373 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8374 status = WERR_ACCESS_DENIED;
8378 /* can't set if builtin */
8379 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8380 status = WERR_INVALID_PARAM;
8384 count = get_ntforms(&list);
8385 update_a_form(&list, form, count);
8386 write_ntforms(&list, count);
8389 * ChangeID must always be set if this is a printer
8392 if ( Printer->printer_type == SPLHND_PRINTER )
8393 status = mod_a_printer(printer, 2);
8398 free_a_printer(&printer, 2);
8404 /****************************************************************************
8405 enumprintprocessors level 1.
8406 ****************************************************************************/
8408 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8410 PRINTPROCESSOR_1 *info_1=NULL;
8411 WERROR result = WERR_OK;
8413 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8418 init_unistr(&info_1->name, "winprint");
8420 *needed += spoolss_size_printprocessor_info_1(info_1);
8422 if (*needed > offered) {
8423 result = WERR_INSUFFICIENT_BUFFER;
8427 if (!rpcbuf_alloc_size(buffer, *needed)) {
8428 result = WERR_NOMEM;
8432 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8437 if ( !W_ERROR_IS_OK(result) )
8443 /****************************************************************************
8444 ****************************************************************************/
8446 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8448 uint32 level = q_u->level;
8449 RPC_BUFFER *buffer = NULL;
8450 uint32 offered = q_u->offered;
8451 uint32 *needed = &r_u->needed;
8452 uint32 *returned = &r_u->returned;
8454 /* that's an [in out] buffer */
8457 return WERR_INVALID_PARAM;
8460 rpcbuf_move(q_u->buffer, &r_u->buffer);
8461 buffer = r_u->buffer;
8463 DEBUG(5,("spoolss_enumprintprocessors\n"));
8466 * Enumerate the print processors ...
8468 * Just reply with "winprint", to keep NT happy
8469 * and I can use my nice printer checker.
8477 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8479 return WERR_UNKNOWN_LEVEL;
8483 /****************************************************************************
8484 enumprintprocdatatypes level 1.
8485 ****************************************************************************/
8487 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8489 PRINTPROCDATATYPE_1 *info_1=NULL;
8490 WERROR result = WERR_NOMEM;
8492 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8497 init_unistr(&info_1->name, "RAW");
8499 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8501 if (*needed > offered) {
8502 result = WERR_INSUFFICIENT_BUFFER;
8506 if (!rpcbuf_alloc_size(buffer, *needed)) {
8507 result = WERR_NOMEM;
8511 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8516 if ( !W_ERROR_IS_OK(result) )
8522 /****************************************************************************
8523 ****************************************************************************/
8525 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8527 uint32 level = q_u->level;
8528 RPC_BUFFER *buffer = NULL;
8529 uint32 offered = q_u->offered;
8530 uint32 *needed = &r_u->needed;
8531 uint32 *returned = &r_u->returned;
8533 /* that's an [in out] buffer */
8536 return WERR_INVALID_PARAM;
8539 rpcbuf_move(q_u->buffer, &r_u->buffer);
8540 buffer = r_u->buffer;
8542 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8549 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8551 return WERR_UNKNOWN_LEVEL;
8555 /****************************************************************************
8556 enumprintmonitors level 1.
8557 ****************************************************************************/
8559 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8561 PRINTMONITOR_1 *info_1;
8562 WERROR result = WERR_OK;
8565 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8570 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8571 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8573 for ( i=0; i<*returned; i++ ) {
8574 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8577 if (*needed > offered) {
8578 result = WERR_INSUFFICIENT_BUFFER;
8582 if (!rpcbuf_alloc_size(buffer, *needed)) {
8583 result = WERR_NOMEM;
8587 for ( i=0; i<*returned; i++ ) {
8588 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8594 if ( !W_ERROR_IS_OK(result) )
8600 /****************************************************************************
8601 enumprintmonitors level 2.
8602 ****************************************************************************/
8604 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8606 PRINTMONITOR_2 *info_2;
8607 WERROR result = WERR_OK;
8610 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8615 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8616 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8617 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8619 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8620 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8621 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8623 for ( i=0; i<*returned; i++ ) {
8624 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8627 if (*needed > offered) {
8628 result = WERR_INSUFFICIENT_BUFFER;
8632 if (!rpcbuf_alloc_size(buffer, *needed)) {
8633 result = WERR_NOMEM;
8637 for ( i=0; i<*returned; i++ ) {
8638 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8644 if ( !W_ERROR_IS_OK(result) )
8650 /****************************************************************************
8651 ****************************************************************************/
8653 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8655 uint32 level = q_u->level;
8656 RPC_BUFFER *buffer = NULL;
8657 uint32 offered = q_u->offered;
8658 uint32 *needed = &r_u->needed;
8659 uint32 *returned = &r_u->returned;
8661 /* that's an [in out] buffer */
8664 return WERR_INVALID_PARAM;
8667 rpcbuf_move(q_u->buffer, &r_u->buffer);
8668 buffer = r_u->buffer;
8670 DEBUG(5,("spoolss_enumprintmonitors\n"));
8673 * Enumerate the print monitors ...
8675 * Just reply with "Local Port", to keep NT happy
8676 * and I can use my nice printer checker.
8684 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8686 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8688 return WERR_UNKNOWN_LEVEL;
8692 /****************************************************************************
8693 ****************************************************************************/
8695 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8696 NT_PRINTER_INFO_LEVEL *ntprinter,
8697 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8702 JOB_INFO_1 *info_1=NULL;
8703 WERROR result = WERR_OK;
8705 info_1=SMB_MALLOC_P(JOB_INFO_1);
8707 if (info_1 == NULL) {
8711 for (i=0; i<count && found==False; i++) {
8712 if ((*queue)[i].job==(int)jobid)
8718 /* NT treats not found as bad param... yet another bad choice */
8719 return WERR_INVALID_PARAM;
8722 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8724 *needed += spoolss_size_job_info_1(info_1);
8726 if (*needed > offered) {
8727 result = WERR_INSUFFICIENT_BUFFER;
8731 if (!rpcbuf_alloc_size(buffer, *needed)) {
8732 result = WERR_NOMEM;
8736 smb_io_job_info_1("", buffer, info_1, 0);
8744 /****************************************************************************
8745 ****************************************************************************/
8747 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8748 NT_PRINTER_INFO_LEVEL *ntprinter,
8749 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8756 DEVICEMODE *devmode = NULL;
8757 NT_DEVICEMODE *nt_devmode = NULL;
8759 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8762 ZERO_STRUCTP(info_2);
8764 for ( i=0; i<count && found==False; i++ )
8766 if ((*queue)[i].job == (int)jobid)
8771 /* NT treats not found as bad param... yet another bad
8773 result = WERR_INVALID_PARAM;
8778 * if the print job does not have a DEVMODE associated with it,
8779 * just use the one for the printer. A NULL devicemode is not
8780 * a failure condition
8783 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8784 devmode = construct_dev_mode(snum);
8786 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8787 ZERO_STRUCTP( devmode );
8788 convert_nt_devicemode( devmode, nt_devmode );
8792 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8794 *needed += spoolss_size_job_info_2(info_2);
8796 if (*needed > offered) {
8797 result = WERR_INSUFFICIENT_BUFFER;
8801 if (!rpcbuf_alloc_size(buffer, *needed)) {
8802 result = WERR_NOMEM;
8806 smb_io_job_info_2("", buffer, info_2, 0);
8811 /* Cleanup allocated memory */
8813 free_job_info_2(info_2); /* Also frees devmode */
8819 /****************************************************************************
8820 ****************************************************************************/
8822 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8824 POLICY_HND *handle = &q_u->handle;
8825 uint32 jobid = q_u->jobid;
8826 uint32 level = q_u->level;
8827 RPC_BUFFER *buffer = NULL;
8828 uint32 offered = q_u->offered;
8829 uint32 *needed = &r_u->needed;
8830 WERROR wstatus = WERR_OK;
8831 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8834 print_queue_struct *queue = NULL;
8835 print_status_struct prt_status;
8837 /* that's an [in out] buffer */
8840 return WERR_INVALID_PARAM;
8843 rpcbuf_move(q_u->buffer, &r_u->buffer);
8844 buffer = r_u->buffer;
8846 DEBUG(5,("spoolss_getjob\n"));
8850 if (!get_printer_snum(p, handle, &snum))
8853 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8854 if ( !W_ERROR_IS_OK(wstatus) )
8857 count = print_queue_status(snum, &queue, &prt_status);
8859 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8860 count, prt_status.status, prt_status.message));
8864 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8865 buffer, offered, needed);
8868 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8869 buffer, offered, needed);
8872 wstatus = WERR_UNKNOWN_LEVEL;
8877 free_a_printer( &ntprinter, 2 );
8882 /********************************************************************
8883 spoolss_getprinterdataex
8885 From MSDN documentation of GetPrinterDataEx: pass request
8886 to GetPrinterData if key is "PrinterDriverData".
8887 ********************************************************************/
8889 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8891 POLICY_HND *handle = &q_u->handle;
8892 uint32 in_size = q_u->size;
8893 uint32 *type = &r_u->type;
8894 uint32 *out_size = &r_u->size;
8895 uint8 **data = &r_u->data;
8896 uint32 *needed = &r_u->needed;
8897 fstring keyname, valuename;
8899 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8901 NT_PRINTER_INFO_LEVEL *printer = NULL;
8903 WERROR status = WERR_OK;
8905 DEBUG(4,("_spoolss_getprinterdataex\n"));
8907 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8908 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8910 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8911 keyname, valuename));
8913 /* in case of problem, return some default values */
8917 *out_size = in_size;
8920 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8921 status = WERR_BADFID;
8925 /* Is the handle to a printer or to the server? */
8927 if (Printer->printer_type == SPLHND_SERVER) {
8928 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8929 status = WERR_INVALID_PARAM;
8933 if ( !get_printer_snum(p,handle, &snum) )
8936 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8937 if ( !W_ERROR_IS_OK(status) )
8940 /* check to see if the keyname is valid */
8941 if ( !strlen(keyname) ) {
8942 status = WERR_INVALID_PARAM;
8946 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8947 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8948 free_a_printer( &printer, 2 );
8949 status = WERR_BADFILE;
8953 /* When given a new keyname, we should just create it */
8955 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8957 if (*needed > *out_size)
8958 status = WERR_MORE_DATA;
8961 if ( !W_ERROR_IS_OK(status) )
8963 DEBUG(5, ("error: allocating %d\n", *out_size));
8965 /* reply this param doesn't exist */
8969 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8970 status = WERR_NOMEM;
8980 free_a_printer( &printer, 2 );
8985 /********************************************************************
8986 * spoolss_setprinterdataex
8987 ********************************************************************/
8989 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8991 POLICY_HND *handle = &q_u->handle;
8992 uint32 type = q_u->type;
8993 uint8 *data = q_u->data;
8994 uint32 real_len = q_u->real_len;
8996 NT_PRINTER_INFO_LEVEL *printer = NULL;
8998 WERROR status = WERR_OK;
8999 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9004 DEBUG(4,("_spoolss_setprinterdataex\n"));
9006 /* From MSDN documentation of SetPrinterDataEx: pass request to
9007 SetPrinterData if key is "PrinterDriverData" */
9010 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9014 if ( Printer->printer_type == SPLHND_SERVER ) {
9015 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9016 return WERR_INVALID_PARAM;
9019 if ( !get_printer_snum(p,handle, &snum) )
9023 * Access check : NT returns "access denied" if you make a
9024 * SetPrinterData call without the necessary privildge.
9025 * we were originally returning OK if nothing changed
9026 * which made Win2k issue **a lot** of SetPrinterData
9027 * when connecting to a printer --jerry
9030 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9032 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9033 return WERR_ACCESS_DENIED;
9036 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9037 if (!W_ERROR_IS_OK(status))
9040 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9041 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9043 /* check for OID in valuename */
9045 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9051 /* save the registry data */
9053 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9055 if ( W_ERROR_IS_OK(status) )
9057 /* save the OID if one was specified */
9059 fstrcat( keyname, "\\" );
9060 fstrcat( keyname, SPOOL_OID_KEY );
9063 * I'm not checking the status here on purpose. Don't know
9064 * if this is right, but I'm returning the status from the
9065 * previous set_printer_dataex() call. I have no idea if
9066 * this is right. --jerry
9069 set_printer_dataex( printer, keyname, valuename,
9070 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9073 status = mod_a_printer(printer, 2);
9076 free_a_printer(&printer, 2);
9082 /********************************************************************
9083 * spoolss_deleteprinterdataex
9084 ********************************************************************/
9086 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9088 POLICY_HND *handle = &q_u->handle;
9089 UNISTR2 *value = &q_u->valuename;
9090 UNISTR2 *key = &q_u->keyname;
9092 NT_PRINTER_INFO_LEVEL *printer = NULL;
9094 WERROR status = WERR_OK;
9095 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9096 pstring valuename, keyname;
9098 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9101 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9105 if (!get_printer_snum(p, handle, &snum))
9108 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9109 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9110 return WERR_ACCESS_DENIED;
9113 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9114 if (!W_ERROR_IS_OK(status))
9117 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9118 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9120 status = delete_printer_dataex( printer, keyname, valuename );
9122 if ( W_ERROR_IS_OK(status) )
9123 mod_a_printer( printer, 2 );
9125 free_a_printer(&printer, 2);
9130 /********************************************************************
9131 * spoolss_enumprinterkey
9132 ********************************************************************/
9135 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9138 fstring *keynames = NULL;
9139 uint16 *enumkeys = NULL;
9142 POLICY_HND *handle = &q_u->handle;
9143 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9144 NT_PRINTER_DATA *data;
9145 NT_PRINTER_INFO_LEVEL *printer = NULL;
9147 WERROR status = WERR_BADFILE;
9150 DEBUG(4,("_spoolss_enumprinterkey\n"));
9153 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9157 if ( !get_printer_snum(p,handle, &snum) )
9160 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9161 if (!W_ERROR_IS_OK(status))
9164 /* get the list of subkey names */
9166 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9167 data = printer->info_2->data;
9169 num_keys = get_printer_subkeys( data, key, &keynames );
9171 if ( num_keys == -1 ) {
9172 status = WERR_BADFILE;
9176 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9178 r_u->needed = printerkey_len*2;
9180 if ( q_u->size < r_u->needed ) {
9181 status = WERR_MORE_DATA;
9185 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9186 status = WERR_NOMEM;
9192 if ( q_u->size < r_u->needed )
9193 status = WERR_MORE_DATA;
9196 free_a_printer( &printer, 2 );
9197 SAFE_FREE( keynames );
9202 /********************************************************************
9203 * spoolss_deleteprinterkey
9204 ********************************************************************/
9206 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9208 POLICY_HND *handle = &q_u->handle;
9209 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9211 NT_PRINTER_INFO_LEVEL *printer = NULL;
9215 DEBUG(5,("spoolss_deleteprinterkey\n"));
9218 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9222 /* if keyname == NULL, return error */
9224 if ( !q_u->keyname.buffer )
9225 return WERR_INVALID_PARAM;
9227 if (!get_printer_snum(p, handle, &snum))
9230 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9231 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9232 return WERR_ACCESS_DENIED;
9235 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9236 if (!W_ERROR_IS_OK(status))
9239 /* delete the key and all subneys */
9241 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9243 status = delete_all_printer_data( printer->info_2, key );
9245 if ( W_ERROR_IS_OK(status) )
9246 status = mod_a_printer(printer, 2);
9248 free_a_printer( &printer, 2 );
9254 /********************************************************************
9255 * spoolss_enumprinterdataex
9256 ********************************************************************/
9258 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9260 POLICY_HND *handle = &q_u->handle;
9261 uint32 in_size = q_u->size;
9264 NT_PRINTER_INFO_LEVEL *printer = NULL;
9265 PRINTER_ENUM_VALUES *enum_values = NULL;
9266 NT_PRINTER_DATA *p_data;
9268 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9273 REGISTRY_VALUE *val;
9278 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9281 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9286 * first check for a keyname of NULL or "". Win2k seems to send
9287 * this a lot and we should send back WERR_INVALID_PARAM
9288 * no need to spend time looking up the printer in this case.
9292 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9293 if ( !strlen(key) ) {
9294 result = WERR_INVALID_PARAM;
9298 /* get the printer off of disk */
9300 if (!get_printer_snum(p,handle, &snum))
9303 ZERO_STRUCT(printer);
9304 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9305 if (!W_ERROR_IS_OK(result))
9308 /* now look for a match on the key name */
9310 p_data = printer->info_2->data;
9312 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9313 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9315 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9316 result = WERR_INVALID_PARAM;
9323 /* allocate the memory for the array of pointers -- if necessary */
9325 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9328 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9330 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9331 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9332 result = WERR_NOMEM;
9336 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9340 * loop through all params and build the array to pass
9341 * back to the client
9344 for ( i=0; i<num_entries; i++ )
9346 /* lookup the registry value */
9348 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9349 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9353 value_name = regval_name( val );
9354 init_unistr( &enum_values[i].valuename, value_name );
9355 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9356 enum_values[i].type = regval_type( val );
9358 data_len = regval_size( val );
9360 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9362 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9364 result = WERR_NOMEM;
9368 enum_values[i].data_len = data_len;
9370 /* keep track of the size of the array in bytes */
9372 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9375 /* housekeeping information in the reply */
9377 r_u->needed = needed;
9378 r_u->returned = num_entries;
9380 if (needed > in_size) {
9381 result = WERR_MORE_DATA;
9385 /* copy data into the reply */
9387 r_u->ctr.size = r_u->needed;
9388 r_u->ctr.size_of_array = r_u->returned;
9389 r_u->ctr.values = enum_values;
9395 free_a_printer(&printer, 2);
9400 /****************************************************************************
9401 ****************************************************************************/
9403 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9405 init_unistr(&info->name, name);
9408 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9409 UNISTR2 *environment,
9416 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9417 WERROR result = WERR_OK;
9419 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9421 if (!get_short_archi(long_archi))
9422 return WERR_INVALID_ENVIRONMENT;
9424 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9427 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9429 fill_printprocessordirectory_1(info, path);
9431 *needed += spoolss_size_printprocessordirectory_info_1(info);
9433 if (*needed > offered) {
9434 result = WERR_INSUFFICIENT_BUFFER;
9438 if (!rpcbuf_alloc_size(buffer, *needed)) {
9439 result = WERR_INSUFFICIENT_BUFFER;
9443 smb_io_printprocessordirectory_1("", buffer, info, 0);
9451 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9453 uint32 level = q_u->level;
9454 RPC_BUFFER *buffer = NULL;
9455 uint32 offered = q_u->offered;
9456 uint32 *needed = &r_u->needed;
9459 /* that's an [in out] buffer */
9462 return WERR_INVALID_PARAM;
9465 rpcbuf_move(q_u->buffer, &r_u->buffer);
9466 buffer = r_u->buffer;
9468 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9474 result = getprintprocessordirectory_level_1
9475 (&q_u->name, &q_u->environment, buffer, offered, needed);
9478 result = WERR_UNKNOWN_LEVEL;
9484 /*******************************************************************
9485 Streams the monitor UI DLL name in UNICODE
9486 *******************************************************************/
9488 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9489 RPC_BUFFER *out, uint32 *needed )
9491 const char *dllname = "tcpmonui.dll";
9493 *needed = (strlen(dllname)+1) * 2;
9495 if ( rpcbuf_get_size(out) < *needed ) {
9496 return WERR_INSUFFICIENT_BUFFER;
9499 if ( !make_monitorui_buf( out, dllname ) ) {
9506 /*******************************************************************
9507 Create a new TCP/IP port
9508 *******************************************************************/
9510 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9511 RPC_BUFFER *out, uint32 *needed )
9513 NT_PORT_DATA_1 port1;
9516 ZERO_STRUCT( port1 );
9518 /* convert to our internal port data structure */
9520 if ( !convert_port_data_1( &port1, in ) ) {
9524 /* create the device URI and call the add_port_hook() */
9526 switch ( port1.protocol ) {
9527 case PORT_PROTOCOL_DIRECT:
9528 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9531 case PORT_PROTOCOL_LPR:
9532 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9536 return WERR_UNKNOWN_PORT;
9539 return add_port_hook( token, port1.name, device_uri );
9542 /*******************************************************************
9543 *******************************************************************/
9545 struct xcv_api_table xcvtcp_cmds[] = {
9546 { "MonitorUI", xcvtcp_monitorui },
9547 { "AddPort", xcvtcp_addport},
9551 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9552 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9557 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9559 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9560 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9561 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9564 return WERR_BADFUNC;
9567 /*******************************************************************
9568 *******************************************************************/
9569 #if 0 /* don't support management using the "Local Port" monitor */
9571 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9572 RPC_BUFFER *out, uint32 *needed )
9574 const char *dllname = "localui.dll";
9576 *needed = (strlen(dllname)+1) * 2;
9578 if ( rpcbuf_get_size(out) < *needed ) {
9579 return WERR_INSUFFICIENT_BUFFER;
9582 if ( !make_monitorui_buf( out, dllname )) {
9589 /*******************************************************************
9590 *******************************************************************/
9592 struct xcv_api_table xcvlocal_cmds[] = {
9593 { "MonitorUI", xcvlocal_monitorui },
9597 struct xcv_api_table xcvlocal_cmds[] = {
9604 /*******************************************************************
9605 *******************************************************************/
9607 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9608 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9613 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9615 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9616 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9617 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9619 return WERR_BADFUNC;
9622 /*******************************************************************
9623 *******************************************************************/
9625 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9627 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9631 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9635 /* Has to be a handle to the TCP/IP port monitor */
9637 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9638 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9642 /* requires administrative access to the server */
9644 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9645 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9646 return WERR_ACCESS_DENIED;
9649 /* Get the command name. There's numerous commands supported by the
9650 TCPMON interface. */
9652 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9653 q_u->dataname.uni_str_len*2, 0);
9655 /* Allocate the outgoing buffer */
9657 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9659 switch ( Printer->printer_type ) {
9660 case SPLHND_PORTMON_TCP:
9661 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9662 &q_u->indata, &r_u->outdata, &r_u->needed );
9663 case SPLHND_PORTMON_LOCAL:
9664 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9665 &q_u->indata, &r_u->outdata, &r_u->needed );
9668 return WERR_INVALID_PRINT_MONITOR;