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, *tid;
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((tid=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"));
3570 current_data = &info->data[info->count];
3572 construct_info_data(current_data, type, field, id);
3574 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3575 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3577 notify_info_data_table[j].fn(snum, current_data, queue,
3583 free_a_printer(&printer, 2);
3587 /*******************************************************************
3589 * fill a notify_info struct with info asked
3591 ********************************************************************/
3593 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3594 SPOOL_NOTIFY_INFO *info,
3595 NT_PRINTER_INFO_LEVEL *printer,
3596 int snum, SPOOL_NOTIFY_OPTION_TYPE
3597 *option_type, uint32 id,
3598 TALLOC_CTX *mem_ctx)
3604 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3606 DEBUG(4,("construct_notify_jobs_info\n"));
3608 type = option_type->type;
3610 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3611 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3612 option_type->count));
3614 for(field_num=0; field_num<option_type->count; field_num++) {
3615 field = option_type->fields[field_num];
3617 if (!search_notify(type, field, &j) )
3620 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3621 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3624 else info->data = tid;
3626 current_data=&(info->data[info->count]);
3628 construct_info_data(current_data, type, field, id);
3629 notify_info_data_table[j].fn(snum, current_data, queue,
3638 * JFM: The enumeration is not that simple, it's even non obvious.
3640 * let's take an example: I want to monitor the PRINTER SERVER for
3641 * the printer's name and the number of jobs currently queued.
3642 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3643 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3645 * I have 3 printers on the back of my server.
3647 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3650 * 1 printer 1 name 1
3651 * 2 printer 1 cjob 1
3652 * 3 printer 2 name 2
3653 * 4 printer 2 cjob 2
3654 * 5 printer 3 name 3
3655 * 6 printer 3 name 3
3657 * that's the print server case, the printer case is even worse.
3660 /*******************************************************************
3662 * enumerate all printers on the printserver
3663 * fill a notify_info struct with info asked
3665 ********************************************************************/
3667 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3668 SPOOL_NOTIFY_INFO *info,
3669 TALLOC_CTX *mem_ctx)
3672 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3673 int n_services=lp_numservices();
3675 SPOOL_NOTIFY_OPTION *option;
3676 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3678 DEBUG(4,("printserver_notify_info\n"));
3683 option=Printer->notify.option;
3688 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3689 sending a ffpcn() request first */
3694 for (i=0; i<option->count; i++) {
3695 option_type=&(option->ctr.type[i]);
3697 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3700 for (snum=0; snum<n_services; snum++)
3702 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3703 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3709 * Debugging information, don't delete.
3712 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3713 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3714 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3716 for (i=0; i<info->count; i++) {
3717 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3718 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3719 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3726 /*******************************************************************
3728 * fill a notify_info struct with info asked
3730 ********************************************************************/
3732 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3733 TALLOC_CTX *mem_ctx)
3736 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3739 SPOOL_NOTIFY_OPTION *option;
3740 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3742 print_queue_struct *queue=NULL;
3743 print_status_struct status;
3745 DEBUG(4,("printer_notify_info\n"));
3750 option=Printer->notify.option;
3756 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3757 sending a ffpcn() request first */
3762 get_printer_snum(p, hnd, &snum);
3764 for (i=0; i<option->count; i++) {
3765 option_type=&option->ctr.type[i];
3767 switch ( option_type->type ) {
3768 case PRINTER_NOTIFY_TYPE:
3769 if(construct_notify_printer_info(Printer, info, snum,
3775 case JOB_NOTIFY_TYPE: {
3776 NT_PRINTER_INFO_LEVEL *printer = NULL;
3778 count = print_queue_status(snum, &queue, &status);
3780 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3783 for (j=0; j<count; j++) {
3784 construct_notify_jobs_info(&queue[j], info,
3791 free_a_printer(&printer, 2);
3801 * Debugging information, don't delete.
3804 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3805 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3806 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3808 for (i=0; i<info->count; i++) {
3809 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3810 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3811 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3817 /********************************************************************
3819 ********************************************************************/
3821 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3823 POLICY_HND *handle = &q_u->handle;
3824 SPOOL_NOTIFY_INFO *info = &r_u->info;
3826 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3827 WERROR result = WERR_BADFID;
3829 /* we always have a NOTIFY_INFO struct */
3833 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3834 OUR_HANDLE(handle)));
3838 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3841 * We are now using the change value, and
3842 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3843 * I don't have a global notification system, I'm sending back all the
3844 * informations even when _NOTHING_ has changed.
3847 /* We need to keep track of the change value to send back in
3848 RRPCN replies otherwise our updates are ignored. */
3850 Printer->notify.fnpcn = True;
3852 if (Printer->notify.client_connected) {
3853 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3854 Printer->notify.change = q_u->change;
3857 /* just ignore the SPOOL_NOTIFY_OPTION */
3859 switch (Printer->printer_type) {
3861 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3864 case SPLHND_PRINTER:
3865 result = printer_notify_info(p, handle, info, p->mem_ctx);
3869 Printer->notify.fnpcn = False;
3875 /********************************************************************
3876 * construct_printer_info_0
3877 * fill a printer_info_0 struct
3878 ********************************************************************/
3880 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3884 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3885 counter_printer_0 *session_counter;
3886 uint32 global_counter;
3889 print_status_struct status;
3891 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3894 count = print_queue_length(snum, &status);
3896 /* check if we already have a counter for this printer */
3897 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3898 if (session_counter->snum == snum)
3902 /* it's the first time, add it to the list */
3903 if (session_counter==NULL) {
3904 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3905 free_a_printer(&ntprinter, 2);
3908 ZERO_STRUCTP(session_counter);
3909 session_counter->snum=snum;
3910 session_counter->counter=0;
3911 DLIST_ADD(counter_list, session_counter);
3915 session_counter->counter++;
3918 * the global_counter should be stored in a TDB as it's common to all the clients
3919 * and should be zeroed on samba startup
3921 global_counter=session_counter->counter;
3923 pstrcpy(chaine,ntprinter->info_2->printername);
3925 init_unistr(&printer->printername, chaine);
3927 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3928 init_unistr(&printer->servername, chaine);
3930 printer->cjobs = count;
3931 printer->total_jobs = 0;
3932 printer->total_bytes = 0;
3934 setuptime = (time_t)ntprinter->info_2->setuptime;
3935 t=gmtime(&setuptime);
3937 printer->year = t->tm_year+1900;
3938 printer->month = t->tm_mon+1;
3939 printer->dayofweek = t->tm_wday;
3940 printer->day = t->tm_mday;
3941 printer->hour = t->tm_hour;
3942 printer->minute = t->tm_min;
3943 printer->second = t->tm_sec;
3944 printer->milliseconds = 0;
3946 printer->global_counter = global_counter;
3947 printer->total_pages = 0;
3949 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3950 printer->major_version = 0x0005; /* NT 5 */
3951 printer->build_version = 0x0893; /* build 2195 */
3953 printer->unknown7 = 0x1;
3954 printer->unknown8 = 0x0;
3955 printer->unknown9 = 0x0;
3956 printer->session_counter = session_counter->counter;
3957 printer->unknown11 = 0x0;
3958 printer->printer_errors = 0x0; /* number of print failure */
3959 printer->unknown13 = 0x0;
3960 printer->unknown14 = 0x1;
3961 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3962 printer->unknown16 = 0x0;
3963 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3964 printer->unknown18 = 0x0;
3965 printer->status = nt_printq_status(status.status);
3966 printer->unknown20 = 0x0;
3967 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3968 printer->unknown22 = 0x0;
3969 printer->unknown23 = 0x6; /* 6 ???*/
3970 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3971 printer->unknown25 = 0;
3972 printer->unknown26 = 0;
3973 printer->unknown27 = 0;
3974 printer->unknown28 = 0;
3975 printer->unknown29 = 0;
3977 free_a_printer(&ntprinter,2);
3981 /********************************************************************
3982 * construct_printer_info_1
3983 * fill a printer_info_1 struct
3984 ********************************************************************/
3985 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3989 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3991 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3994 printer->flags=flags;
3996 if (*ntprinter->info_2->comment == '\0') {
3997 init_unistr(&printer->comment, lp_comment(snum));
3998 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3999 ntprinter->info_2->drivername, lp_comment(snum));
4002 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4003 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4004 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4007 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4009 init_unistr(&printer->description, chaine);
4010 init_unistr(&printer->name, chaine2);
4012 free_a_printer(&ntprinter,2);
4017 /****************************************************************************
4018 Free a DEVMODE struct.
4019 ****************************************************************************/
4021 static void free_dev_mode(DEVICEMODE *dev)
4026 SAFE_FREE(dev->dev_private);
4031 /****************************************************************************
4032 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4033 should be valid upon entry
4034 ****************************************************************************/
4036 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4038 if ( !devmode || !ntdevmode )
4041 init_unistr(&devmode->devicename, ntdevmode->devicename);
4043 init_unistr(&devmode->formname, ntdevmode->formname);
4045 devmode->specversion = ntdevmode->specversion;
4046 devmode->driverversion = ntdevmode->driverversion;
4047 devmode->size = ntdevmode->size;
4048 devmode->driverextra = ntdevmode->driverextra;
4049 devmode->fields = ntdevmode->fields;
4051 devmode->orientation = ntdevmode->orientation;
4052 devmode->papersize = ntdevmode->papersize;
4053 devmode->paperlength = ntdevmode->paperlength;
4054 devmode->paperwidth = ntdevmode->paperwidth;
4055 devmode->scale = ntdevmode->scale;
4056 devmode->copies = ntdevmode->copies;
4057 devmode->defaultsource = ntdevmode->defaultsource;
4058 devmode->printquality = ntdevmode->printquality;
4059 devmode->color = ntdevmode->color;
4060 devmode->duplex = ntdevmode->duplex;
4061 devmode->yresolution = ntdevmode->yresolution;
4062 devmode->ttoption = ntdevmode->ttoption;
4063 devmode->collate = ntdevmode->collate;
4064 devmode->icmmethod = ntdevmode->icmmethod;
4065 devmode->icmintent = ntdevmode->icmintent;
4066 devmode->mediatype = ntdevmode->mediatype;
4067 devmode->dithertype = ntdevmode->dithertype;
4069 if (ntdevmode->nt_dev_private != NULL) {
4070 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4077 /****************************************************************************
4078 Create a DEVMODE struct. Returns malloced memory.
4079 ****************************************************************************/
4081 DEVICEMODE *construct_dev_mode(int snum)
4083 NT_PRINTER_INFO_LEVEL *printer = NULL;
4084 DEVICEMODE *devmode = NULL;
4086 DEBUG(7,("construct_dev_mode\n"));
4088 DEBUGADD(8,("getting printer characteristics\n"));
4090 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4093 if ( !printer->info_2->devmode ) {
4094 DEBUG(5, ("BONG! There was no device mode!\n"));
4098 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4099 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4103 ZERO_STRUCTP(devmode);
4105 DEBUGADD(8,("loading DEVICEMODE\n"));
4107 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4108 free_dev_mode( devmode );
4113 free_a_printer(&printer,2);
4118 /********************************************************************
4119 * construct_printer_info_2
4120 * fill a printer_info_2 struct
4121 ********************************************************************/
4123 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4126 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4128 print_status_struct status;
4130 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4133 count = print_queue_length(snum, &status);
4135 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4136 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4137 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4138 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4139 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4141 if (*ntprinter->info_2->comment == '\0')
4142 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4144 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4146 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4147 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4148 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4149 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4150 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4152 printer->attributes = ntprinter->info_2->attributes;
4154 printer->priority = ntprinter->info_2->priority; /* priority */
4155 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4156 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4157 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4158 printer->status = nt_printq_status(status.status); /* status */
4159 printer->cjobs = count; /* jobs */
4160 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4162 if ( !(printer->devmode = construct_dev_mode(snum)) )
4163 DEBUG(8, ("Returning NULL Devicemode!\n"));
4165 printer->secdesc = NULL;
4167 if ( ntprinter->info_2->secdesc_buf
4168 && ntprinter->info_2->secdesc_buf->len != 0 )
4170 /* don't use talloc_steal() here unless you do a deep steal of all
4171 the SEC_DESC members */
4173 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4174 ntprinter->info_2->secdesc_buf->sec );
4177 free_a_printer(&ntprinter, 2);
4182 /********************************************************************
4183 * construct_printer_info_3
4184 * fill a printer_info_3 struct
4185 ********************************************************************/
4187 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4189 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4190 PRINTER_INFO_3 *printer = NULL;
4192 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4196 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4197 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4201 ZERO_STRUCTP(printer);
4203 /* These are the components of the SD we are returning. */
4205 printer->flags = 0x4;
4207 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4208 /* don't use talloc_steal() here unless you do a deep steal of all
4209 the SEC_DESC members */
4211 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4212 ntprinter->info_2->secdesc_buf->sec );
4215 free_a_printer(&ntprinter, 2);
4217 *pp_printer = printer;
4221 /********************************************************************
4222 * construct_printer_info_4
4223 * fill a printer_info_4 struct
4224 ********************************************************************/
4226 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4228 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4230 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4233 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4234 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4235 printer->attributes = ntprinter->info_2->attributes;
4237 free_a_printer(&ntprinter, 2);
4241 /********************************************************************
4242 * construct_printer_info_5
4243 * fill a printer_info_5 struct
4244 ********************************************************************/
4246 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4248 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4250 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4253 init_unistr(&printer->printername, ntprinter->info_2->printername);
4254 init_unistr(&printer->portname, ntprinter->info_2->portname);
4255 printer->attributes = ntprinter->info_2->attributes;
4257 /* these two are not used by NT+ according to MSDN */
4259 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4260 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4262 free_a_printer(&ntprinter, 2);
4267 /********************************************************************
4268 * construct_printer_info_7
4269 * fill a printer_info_7 struct
4270 ********************************************************************/
4272 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4274 char *guid_str = NULL;
4277 if (is_printer_published(print_hnd, snum, &guid)) {
4278 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4279 strupper_m(guid_str);
4280 init_unistr(&printer->guid, guid_str);
4281 printer->action = SPOOL_DS_PUBLISH;
4283 init_unistr(&printer->guid, "");
4284 printer->action = SPOOL_DS_UNPUBLISH;
4290 /********************************************************************
4291 Spoolss_enumprinters.
4292 ********************************************************************/
4294 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4298 int n_services=lp_numservices();
4299 PRINTER_INFO_1 *tp, *printers=NULL;
4300 PRINTER_INFO_1 current_prt;
4301 WERROR result = WERR_OK;
4303 DEBUG(4,("enum_all_printers_info_1\n"));
4305 for (snum=0; snum<n_services; snum++) {
4306 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4307 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4309 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4310 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4311 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4312 SAFE_FREE(printers);
4317 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4319 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4325 /* check the required size. */
4326 for (i=0; i<*returned; i++)
4327 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4329 if (*needed > offered) {
4330 result = WERR_INSUFFICIENT_BUFFER;
4334 if (!rpcbuf_alloc_size(buffer, *needed)) {
4335 result = WERR_NOMEM;
4339 /* fill the buffer with the structures */
4340 for (i=0; i<*returned; i++)
4341 smb_io_printer_info_1("", buffer, &printers[i], 0);
4346 SAFE_FREE(printers);
4348 if ( !W_ERROR_IS_OK(result) )
4354 /********************************************************************
4355 enum_all_printers_info_1_local.
4356 *********************************************************************/
4358 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4360 DEBUG(4,("enum_all_printers_info_1_local\n"));
4362 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4365 /********************************************************************
4366 enum_all_printers_info_1_name.
4367 *********************************************************************/
4369 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4373 DEBUG(4,("enum_all_printers_info_1_name\n"));
4375 if ((name[0] == '\\') && (name[1] == '\\'))
4378 if (is_myname_or_ipaddr(s)) {
4379 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4382 return WERR_INVALID_NAME;
4385 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4386 /********************************************************************
4387 enum_all_printers_info_1_remote.
4388 *********************************************************************/
4390 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4392 PRINTER_INFO_1 *printer;
4393 fstring printername;
4396 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4397 WERROR result = WERR_OK;
4399 /* JFM: currently it's more a place holder than anything else.
4400 * In the spooler world there is a notion of server registration.
4401 * the print servers are registered on the PDC (in the same domain)
4403 * We should have a TDB here. The registration is done thru an
4404 * undocumented RPC call.
4407 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4412 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4413 slprintf(desc, sizeof(desc)-1,"%s", name);
4414 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4416 init_unistr(&printer->description, desc);
4417 init_unistr(&printer->name, printername);
4418 init_unistr(&printer->comment, comment);
4419 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4421 /* check the required size. */
4422 *needed += spoolss_size_printer_info_1(printer);
4424 if (*needed > offered) {
4425 result = WERR_INSUFFICIENT_BUFFER;
4429 if (!rpcbuf_alloc_size(buffer, *needed)) {
4430 result = WERR_NOMEM;
4434 /* fill the buffer with the structures */
4435 smb_io_printer_info_1("", buffer, printer, 0);
4441 if ( !W_ERROR_IS_OK(result) )
4449 /********************************************************************
4450 enum_all_printers_info_1_network.
4451 *********************************************************************/
4453 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4457 DEBUG(4,("enum_all_printers_info_1_network\n"));
4459 /* If we respond to a enum_printers level 1 on our name with flags
4460 set to PRINTER_ENUM_REMOTE with a list of printers then these
4461 printers incorrectly appear in the APW browse list.
4462 Specifically the printers for the server appear at the workgroup
4463 level where all the other servers in the domain are
4464 listed. Windows responds to this call with a
4465 WERR_CAN_NOT_COMPLETE so we should do the same. */
4467 if (name[0] == '\\' && name[1] == '\\')
4470 if (is_myname_or_ipaddr(s))
4471 return WERR_CAN_NOT_COMPLETE;
4473 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4476 /********************************************************************
4477 * api_spoolss_enumprinters
4479 * called from api_spoolss_enumprinters (see this to understand)
4480 ********************************************************************/
4482 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4486 int n_services=lp_numservices();
4487 PRINTER_INFO_2 *tp, *printers=NULL;
4488 PRINTER_INFO_2 current_prt;
4489 WERROR result = WERR_OK;
4491 for (snum=0; snum<n_services; snum++) {
4492 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4493 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4495 if (construct_printer_info_2(NULL, ¤t_prt, snum))
4497 if ( !(tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4498 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4499 SAFE_FREE(printers);
4504 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4507 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4514 /* check the required size. */
4515 for (i=0; i<*returned; i++)
4516 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4518 if (*needed > offered) {
4519 result = WERR_INSUFFICIENT_BUFFER;
4523 if (!rpcbuf_alloc_size(buffer, *needed)) {
4524 result = WERR_NOMEM;
4528 /* fill the buffer with the structures */
4529 for (i=0; i<*returned; i++)
4530 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4535 for (i=0; i<*returned; i++)
4536 free_devmode(printers[i].devmode);
4538 SAFE_FREE(printers);
4540 if ( !W_ERROR_IS_OK(result) )
4546 /********************************************************************
4547 * handle enumeration of printers at level 1
4548 ********************************************************************/
4550 static WERROR enumprinters_level1( uint32 flags, fstring name,
4551 RPC_BUFFER *buffer, uint32 offered,
4552 uint32 *needed, uint32 *returned)
4554 /* Not all the flags are equals */
4556 if (flags & PRINTER_ENUM_LOCAL)
4557 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4559 if (flags & PRINTER_ENUM_NAME)
4560 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4562 #if 0 /* JERRY - disabled for now */
4563 if (flags & PRINTER_ENUM_REMOTE)
4564 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4567 if (flags & PRINTER_ENUM_NETWORK)
4568 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4570 return WERR_OK; /* NT4sp5 does that */
4573 /********************************************************************
4574 * handle enumeration of printers at level 2
4575 ********************************************************************/
4577 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4578 RPC_BUFFER *buffer, uint32 offered,
4579 uint32 *needed, uint32 *returned)
4581 char *s = servername;
4583 if (flags & PRINTER_ENUM_LOCAL) {
4584 return enum_all_printers_info_2(buffer, offered, needed, returned);
4587 if (flags & PRINTER_ENUM_NAME) {
4588 if ((servername[0] == '\\') && (servername[1] == '\\'))
4590 if (is_myname_or_ipaddr(s))
4591 return enum_all_printers_info_2(buffer, offered, needed, returned);
4593 return WERR_INVALID_NAME;
4596 if (flags & PRINTER_ENUM_REMOTE)
4597 return WERR_UNKNOWN_LEVEL;
4602 /********************************************************************
4603 * handle enumeration of printers at level 5
4604 ********************************************************************/
4606 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4607 RPC_BUFFER *buffer, uint32 offered,
4608 uint32 *needed, uint32 *returned)
4610 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4614 /********************************************************************
4615 * api_spoolss_enumprinters
4617 * called from api_spoolss_enumprinters (see this to understand)
4618 ********************************************************************/
4620 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4622 uint32 flags = q_u->flags;
4623 UNISTR2 *servername = &q_u->servername;
4624 uint32 level = q_u->level;
4625 RPC_BUFFER *buffer = NULL;
4626 uint32 offered = q_u->offered;
4627 uint32 *needed = &r_u->needed;
4628 uint32 *returned = &r_u->returned;
4632 /* that's an [in out] buffer */
4634 if ( q_u->buffer ) {
4635 rpcbuf_move(q_u->buffer, &r_u->buffer);
4636 buffer = r_u->buffer;
4639 DEBUG(4,("_spoolss_enumprinters\n"));
4646 * flags==PRINTER_ENUM_NAME
4647 * if name=="" then enumerates all printers
4648 * if name!="" then enumerate the printer
4649 * flags==PRINTER_ENUM_REMOTE
4650 * name is NULL, enumerate printers
4651 * Level 2: name!="" enumerates printers, name can't be NULL
4652 * Level 3: doesn't exist
4653 * Level 4: does a local registry lookup
4654 * Level 5: same as Level 2
4657 unistr2_to_ascii(name, servername, sizeof(name)-1);
4662 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4664 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4666 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4671 return WERR_UNKNOWN_LEVEL;
4674 /****************************************************************************
4675 ****************************************************************************/
4677 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4679 PRINTER_INFO_0 *printer=NULL;
4680 WERROR result = WERR_OK;
4682 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4685 construct_printer_info_0(print_hnd, printer, snum);
4687 /* check the required size. */
4688 *needed += spoolss_size_printer_info_0(printer);
4690 if (*needed > offered) {
4691 result = WERR_INSUFFICIENT_BUFFER;
4695 if (!rpcbuf_alloc_size(buffer, *needed)) {
4696 result = WERR_NOMEM;
4700 /* fill the buffer with the structures */
4701 smb_io_printer_info_0("", buffer, printer, 0);
4711 /****************************************************************************
4712 ****************************************************************************/
4714 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4716 PRINTER_INFO_1 *printer=NULL;
4717 WERROR result = WERR_OK;
4719 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4722 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4724 /* check the required size. */
4725 *needed += spoolss_size_printer_info_1(printer);
4727 if (*needed > offered) {
4728 result = WERR_INSUFFICIENT_BUFFER;
4732 if (!rpcbuf_alloc_size(buffer, *needed)) {
4733 result = WERR_NOMEM;
4737 /* fill the buffer with the structures */
4738 smb_io_printer_info_1("", buffer, printer, 0);
4747 /****************************************************************************
4748 ****************************************************************************/
4750 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4752 PRINTER_INFO_2 *printer=NULL;
4753 WERROR result = WERR_OK;
4755 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4758 construct_printer_info_2(print_hnd, printer, snum);
4760 /* check the required size. */
4761 *needed += spoolss_size_printer_info_2(printer);
4763 if (*needed > offered) {
4764 result = WERR_INSUFFICIENT_BUFFER;
4768 if (!rpcbuf_alloc_size(buffer, *needed)) {
4769 result = WERR_NOMEM;
4773 /* fill the buffer with the structures */
4774 if (!smb_io_printer_info_2("", buffer, printer, 0))
4775 result = WERR_NOMEM;
4779 free_printer_info_2(printer);
4784 /****************************************************************************
4785 ****************************************************************************/
4787 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4789 PRINTER_INFO_3 *printer=NULL;
4790 WERROR result = WERR_OK;
4792 if (!construct_printer_info_3(print_hnd, &printer, snum))
4795 /* check the required size. */
4796 *needed += spoolss_size_printer_info_3(printer);
4798 if (*needed > offered) {
4799 result = WERR_INSUFFICIENT_BUFFER;
4803 if (!rpcbuf_alloc_size(buffer, *needed)) {
4804 result = WERR_NOMEM;
4808 /* fill the buffer with the structures */
4809 smb_io_printer_info_3("", buffer, printer, 0);
4813 free_printer_info_3(printer);
4818 /****************************************************************************
4819 ****************************************************************************/
4821 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4823 PRINTER_INFO_4 *printer=NULL;
4824 WERROR result = WERR_OK;
4826 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4829 if (!construct_printer_info_4(print_hnd, printer, snum))
4832 /* check the required size. */
4833 *needed += spoolss_size_printer_info_4(printer);
4835 if (*needed > offered) {
4836 result = WERR_INSUFFICIENT_BUFFER;
4840 if (!rpcbuf_alloc_size(buffer, *needed)) {
4841 result = WERR_NOMEM;
4845 /* fill the buffer with the structures */
4846 smb_io_printer_info_4("", buffer, printer, 0);
4850 free_printer_info_4(printer);
4855 /****************************************************************************
4856 ****************************************************************************/
4858 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4860 PRINTER_INFO_5 *printer=NULL;
4861 WERROR result = WERR_OK;
4863 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4866 if (!construct_printer_info_5(print_hnd, printer, snum))
4869 /* check the required size. */
4870 *needed += spoolss_size_printer_info_5(printer);
4872 if (*needed > offered) {
4873 result = WERR_INSUFFICIENT_BUFFER;
4877 if (!rpcbuf_alloc_size(buffer, *needed)) {
4878 result = WERR_NOMEM;
4882 /* fill the buffer with the structures */
4883 smb_io_printer_info_5("", buffer, printer, 0);
4887 free_printer_info_5(printer);
4892 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4894 PRINTER_INFO_7 *printer=NULL;
4895 WERROR result = WERR_OK;
4897 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4900 if (!construct_printer_info_7(print_hnd, printer, snum))
4903 /* check the required size. */
4904 *needed += spoolss_size_printer_info_7(printer);
4906 if (*needed > offered) {
4907 result = WERR_INSUFFICIENT_BUFFER;
4911 if (!rpcbuf_alloc_size(buffer, *needed)) {
4912 result = WERR_NOMEM;
4917 /* fill the buffer with the structures */
4918 smb_io_printer_info_7("", buffer, printer, 0);
4922 free_printer_info_7(printer);
4927 /****************************************************************************
4928 ****************************************************************************/
4930 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4932 POLICY_HND *handle = &q_u->handle;
4933 uint32 level = q_u->level;
4934 RPC_BUFFER *buffer = NULL;
4935 uint32 offered = q_u->offered;
4936 uint32 *needed = &r_u->needed;
4937 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4941 /* that's an [in out] buffer */
4943 if ( q_u->buffer ) {
4944 rpcbuf_move(q_u->buffer, &r_u->buffer);
4945 buffer = r_u->buffer;
4950 if (!get_printer_snum(p, handle, &snum))
4955 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4957 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4959 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4961 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4963 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4965 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4967 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4969 return WERR_UNKNOWN_LEVEL;
4972 /********************************************************************
4973 * fill a DRIVER_INFO_1 struct
4974 ********************************************************************/
4976 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4978 init_unistr( &info->name, driver.info_3->name);
4981 /********************************************************************
4982 * construct_printer_driver_info_1
4983 ********************************************************************/
4985 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4987 NT_PRINTER_INFO_LEVEL *printer = NULL;
4988 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4990 ZERO_STRUCT(driver);
4992 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4993 return WERR_INVALID_PRINTER_NAME;
4995 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4996 return WERR_UNKNOWN_PRINTER_DRIVER;
4998 fill_printer_driver_info_1(info, driver, servername, architecture);
5000 free_a_printer(&printer,2);
5005 /********************************************************************
5006 * construct_printer_driver_info_2
5007 * fill a printer_info_2 struct
5008 ********************************************************************/
5010 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5014 info->version=driver.info_3->cversion;
5016 init_unistr( &info->name, driver.info_3->name );
5017 init_unistr( &info->architecture, driver.info_3->environment );
5020 if (strlen(driver.info_3->driverpath)) {
5021 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5022 init_unistr( &info->driverpath, temp );
5024 init_unistr( &info->driverpath, "" );
5026 if (strlen(driver.info_3->datafile)) {
5027 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5028 init_unistr( &info->datafile, temp );
5030 init_unistr( &info->datafile, "" );
5032 if (strlen(driver.info_3->configfile)) {
5033 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5034 init_unistr( &info->configfile, temp );
5036 init_unistr( &info->configfile, "" );
5039 /********************************************************************
5040 * construct_printer_driver_info_2
5041 * fill a printer_info_2 struct
5042 ********************************************************************/
5044 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5046 NT_PRINTER_INFO_LEVEL *printer = NULL;
5047 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5049 ZERO_STRUCT(printer);
5050 ZERO_STRUCT(driver);
5052 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5053 return WERR_INVALID_PRINTER_NAME;
5055 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5056 return WERR_UNKNOWN_PRINTER_DRIVER;
5058 fill_printer_driver_info_2(info, driver, servername);
5060 free_a_printer(&printer,2);
5065 /********************************************************************
5066 * copy a strings array and convert to UNICODE
5068 * convert an array of ascii string to a UNICODE string
5069 ********************************************************************/
5071 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5079 DEBUG(6,("init_unistr_array\n"));
5090 v = ""; /* hack to handle null lists */
5093 /* hack to allow this to be used in places other than when generating
5094 the list of dependent files */
5097 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5101 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5103 /* add one extra unit16 for the second terminating NULL */
5105 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5106 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5114 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5119 /* special case for ""; we need to add both NULL's here */
5121 (*uni_array)[j++]=0x0000;
5122 (*uni_array)[j]=0x0000;
5125 DEBUGADD(6,("last one:done\n"));
5127 /* return size of array in uint16's */
5132 /********************************************************************
5133 * construct_printer_info_3
5134 * fill a printer_info_3 struct
5135 ********************************************************************/
5137 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5143 info->version=driver.info_3->cversion;
5145 init_unistr( &info->name, driver.info_3->name );
5146 init_unistr( &info->architecture, driver.info_3->environment );
5148 if (strlen(driver.info_3->driverpath)) {
5149 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5150 init_unistr( &info->driverpath, temp );
5152 init_unistr( &info->driverpath, "" );
5154 if (strlen(driver.info_3->datafile)) {
5155 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5156 init_unistr( &info->datafile, temp );
5158 init_unistr( &info->datafile, "" );
5160 if (strlen(driver.info_3->configfile)) {
5161 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5162 init_unistr( &info->configfile, temp );
5164 init_unistr( &info->configfile, "" );
5166 if (strlen(driver.info_3->helpfile)) {
5167 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5168 init_unistr( &info->helpfile, temp );
5170 init_unistr( &info->helpfile, "" );
5172 init_unistr( &info->monitorname, driver.info_3->monitorname );
5173 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5175 info->dependentfiles=NULL;
5176 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5179 /********************************************************************
5180 * construct_printer_info_3
5181 * fill a printer_info_3 struct
5182 ********************************************************************/
5184 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5186 NT_PRINTER_INFO_LEVEL *printer = NULL;
5187 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5189 ZERO_STRUCT(driver);
5191 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5192 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5193 if (!W_ERROR_IS_OK(status))
5194 return WERR_INVALID_PRINTER_NAME;
5196 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5197 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5202 * I put this code in during testing. Helpful when commenting out the
5203 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5204 * as win2k always queries the driver using an infor level of 6.
5205 * I've left it in (but ifdef'd out) because I'll probably
5206 * use it in experimentation again in the future. --jerry 22/01/2002
5209 if (!W_ERROR_IS_OK(status)) {
5211 * Is this a W2k client ?
5214 /* Yes - try again with a WinNT driver. */
5216 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5217 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5221 if (!W_ERROR_IS_OK(status)) {
5222 free_a_printer(&printer,2);
5223 return WERR_UNKNOWN_PRINTER_DRIVER;
5231 fill_printer_driver_info_3(info, driver, servername);
5233 free_a_printer(&printer,2);
5238 /********************************************************************
5239 * construct_printer_info_6
5240 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5241 ********************************************************************/
5243 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5249 memset(&nullstr, '\0', sizeof(fstring));
5251 info->version=driver.info_3->cversion;
5253 init_unistr( &info->name, driver.info_3->name );
5254 init_unistr( &info->architecture, driver.info_3->environment );
5256 if (strlen(driver.info_3->driverpath)) {
5257 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5258 init_unistr( &info->driverpath, temp );
5260 init_unistr( &info->driverpath, "" );
5262 if (strlen(driver.info_3->datafile)) {
5263 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5264 init_unistr( &info->datafile, temp );
5266 init_unistr( &info->datafile, "" );
5268 if (strlen(driver.info_3->configfile)) {
5269 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5270 init_unistr( &info->configfile, temp );
5272 init_unistr( &info->configfile, "" );
5274 if (strlen(driver.info_3->helpfile)) {
5275 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5276 init_unistr( &info->helpfile, temp );
5278 init_unistr( &info->helpfile, "" );
5280 init_unistr( &info->monitorname, driver.info_3->monitorname );
5281 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5283 info->dependentfiles = NULL;
5284 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5286 info->previousdrivernames=NULL;
5287 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5289 info->driver_date.low=0;
5290 info->driver_date.high=0;
5293 info->driver_version_low=0;
5294 info->driver_version_high=0;
5296 init_unistr( &info->mfgname, "");
5297 init_unistr( &info->oem_url, "");
5298 init_unistr( &info->hardware_id, "");
5299 init_unistr( &info->provider, "");
5302 /********************************************************************
5303 * construct_printer_info_6
5304 * fill a printer_info_6 struct
5305 ********************************************************************/
5307 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5308 fstring servername, fstring architecture, uint32 version)
5310 NT_PRINTER_INFO_LEVEL *printer = NULL;
5311 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5314 ZERO_STRUCT(driver);
5316 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5318 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5320 if (!W_ERROR_IS_OK(status))
5321 return WERR_INVALID_PRINTER_NAME;
5323 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5325 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5327 if (!W_ERROR_IS_OK(status))
5330 * Is this a W2k client ?
5334 free_a_printer(&printer,2);
5335 return WERR_UNKNOWN_PRINTER_DRIVER;
5338 /* Yes - try again with a WinNT driver. */
5340 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5341 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5342 if (!W_ERROR_IS_OK(status)) {
5343 free_a_printer(&printer,2);
5344 return WERR_UNKNOWN_PRINTER_DRIVER;
5348 fill_printer_driver_info_6(info, driver, servername);
5350 free_a_printer(&printer,2);
5351 free_a_printer_driver(driver, 3);
5356 /****************************************************************************
5357 ****************************************************************************/
5359 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5361 SAFE_FREE(info->dependentfiles);
5364 /****************************************************************************
5365 ****************************************************************************/
5367 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5369 SAFE_FREE(info->dependentfiles);
5372 /****************************************************************************
5373 ****************************************************************************/
5375 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5377 DRIVER_INFO_1 *info=NULL;
5380 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5383 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5384 if (!W_ERROR_IS_OK(result))
5387 /* check the required size. */
5388 *needed += spoolss_size_printer_driver_info_1(info);
5390 if (*needed > offered) {
5391 result = WERR_INSUFFICIENT_BUFFER;
5395 if (!rpcbuf_alloc_size(buffer, *needed)) {
5396 result = WERR_NOMEM;
5400 /* fill the buffer with the structures */
5401 smb_io_printer_driver_info_1("", buffer, info, 0);
5410 /****************************************************************************
5411 ****************************************************************************/
5413 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5415 DRIVER_INFO_2 *info=NULL;
5418 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5421 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5422 if (!W_ERROR_IS_OK(result))
5425 /* check the required size. */
5426 *needed += spoolss_size_printer_driver_info_2(info);
5428 if (*needed > offered) {
5429 result = WERR_INSUFFICIENT_BUFFER;
5433 if (!rpcbuf_alloc_size(buffer, *needed)) {
5434 result = WERR_NOMEM;
5438 /* fill the buffer with the structures */
5439 smb_io_printer_driver_info_2("", buffer, info, 0);
5448 /****************************************************************************
5449 ****************************************************************************/
5451 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5458 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5459 if (!W_ERROR_IS_OK(result))
5462 /* check the required size. */
5463 *needed += spoolss_size_printer_driver_info_3(&info);
5465 if (*needed > offered) {
5466 result = WERR_INSUFFICIENT_BUFFER;
5470 if (!rpcbuf_alloc_size(buffer, *needed)) {
5471 result = WERR_NOMEM;
5475 /* fill the buffer with the structures */
5476 smb_io_printer_driver_info_3("", buffer, &info, 0);
5479 free_printer_driver_info_3(&info);
5484 /****************************************************************************
5485 ****************************************************************************/
5487 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5494 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5495 if (!W_ERROR_IS_OK(result))
5498 /* check the required size. */
5499 *needed += spoolss_size_printer_driver_info_6(&info);
5501 if (*needed > offered) {
5502 result = WERR_INSUFFICIENT_BUFFER;
5506 if (!rpcbuf_alloc_size(buffer, *needed)) {
5507 result = WERR_NOMEM;
5511 /* fill the buffer with the structures */
5512 smb_io_printer_driver_info_6("", buffer, &info, 0);
5515 free_printer_driver_info_6(&info);
5520 /****************************************************************************
5521 ****************************************************************************/
5523 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5525 POLICY_HND *handle = &q_u->handle;
5526 UNISTR2 *uni_arch = &q_u->architecture;
5527 uint32 level = q_u->level;
5528 uint32 clientmajorversion = q_u->clientmajorversion;
5529 RPC_BUFFER *buffer = NULL;
5530 uint32 offered = q_u->offered;
5531 uint32 *needed = &r_u->needed;
5532 uint32 *servermajorversion = &r_u->servermajorversion;
5533 uint32 *serverminorversion = &r_u->serverminorversion;
5534 Printer_entry *printer;
5537 fstring architecture;
5540 /* that's an [in out] buffer */
5542 if ( q_u->buffer ) {
5543 rpcbuf_move(q_u->buffer, &r_u->buffer);
5544 buffer = r_u->buffer;
5547 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5549 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5550 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5551 return WERR_INVALID_PRINTER_NAME;
5555 *servermajorversion = 0;
5556 *serverminorversion = 0;
5558 fstrcpy(servername, get_server_name( printer ));
5559 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5561 if (!get_printer_snum(p, handle, &snum))
5566 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5568 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5570 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5572 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5575 /* apparently this call is the equivalent of
5576 EnumPrinterDataEx() for the DsDriver key */
5581 return WERR_UNKNOWN_LEVEL;
5584 /****************************************************************************
5585 ****************************************************************************/
5587 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5589 POLICY_HND *handle = &q_u->handle;
5591 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5594 DEBUG(3,("Error in startpageprinter printer handle\n"));
5598 Printer->page_started=True;
5602 /****************************************************************************
5603 ****************************************************************************/
5605 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5607 POLICY_HND *handle = &q_u->handle;
5610 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5613 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5617 if (!get_printer_snum(p, handle, &snum))
5620 Printer->page_started=False;
5621 print_job_endpage(snum, Printer->jobid);
5626 /********************************************************************
5627 * api_spoolss_getprinter
5628 * called from the spoolss dispatcher
5630 ********************************************************************/
5632 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5634 POLICY_HND *handle = &q_u->handle;
5635 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5636 uint32 *jobid = &r_u->jobid;
5638 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5642 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5643 struct current_user user;
5646 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5650 get_current_user(&user, p);
5653 * a nice thing with NT is it doesn't listen to what you tell it.
5654 * when asked to send _only_ RAW datas, it tries to send datas
5657 * So I add checks like in NT Server ...
5660 if (info_1->p_datatype != 0) {
5661 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5662 if (strcmp(datatype, "RAW") != 0) {
5664 return WERR_INVALID_DATATYPE;
5668 /* get the share number of the printer */
5669 if (!get_printer_snum(p, handle, &snum)) {
5673 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5675 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5677 /* An error occured in print_job_start() so return an appropriate
5680 if (Printer->jobid == -1) {
5681 return map_werror_from_unix(errno);
5684 Printer->document_started=True;
5685 (*jobid) = Printer->jobid;
5690 /********************************************************************
5691 * api_spoolss_getprinter
5692 * called from the spoolss dispatcher
5694 ********************************************************************/
5696 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5698 POLICY_HND *handle = &q_u->handle;
5700 return _spoolss_enddocprinter_internal(p, handle);
5703 /****************************************************************************
5704 ****************************************************************************/
5706 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5708 POLICY_HND *handle = &q_u->handle;
5709 uint32 buffer_size = q_u->buffer_size;
5710 uint8 *buffer = q_u->buffer;
5711 uint32 *buffer_written = &q_u->buffer_size2;
5713 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5716 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5717 r_u->buffer_written = q_u->buffer_size2;
5721 if (!get_printer_snum(p, handle, &snum))
5724 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5725 (SMB_OFF_T)-1, (size_t)buffer_size);
5726 if (*buffer_written == (uint32)-1) {
5727 r_u->buffer_written = 0;
5728 if (errno == ENOSPC)
5729 return WERR_NO_SPOOL_SPACE;
5731 return WERR_ACCESS_DENIED;
5734 r_u->buffer_written = q_u->buffer_size2;
5739 /********************************************************************
5740 * api_spoolss_getprinter
5741 * called from the spoolss dispatcher
5743 ********************************************************************/
5745 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5748 struct current_user user;
5750 WERROR errcode = WERR_BADFUNC;
5751 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5753 get_current_user(&user, p);
5756 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5760 if (!get_printer_snum(p, handle, &snum))
5764 case PRINTER_CONTROL_PAUSE:
5765 if (print_queue_pause(&user, snum, &errcode)) {
5769 case PRINTER_CONTROL_RESUME:
5770 case PRINTER_CONTROL_UNPAUSE:
5771 if (print_queue_resume(&user, snum, &errcode)) {
5775 case PRINTER_CONTROL_PURGE:
5776 if (print_queue_purge(&user, snum, &errcode)) {
5781 return WERR_UNKNOWN_LEVEL;
5787 /********************************************************************
5788 * api_spoolss_abortprinter
5789 * From MSDN: "Deletes printer's spool file if printer is configured
5791 ********************************************************************/
5793 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5795 POLICY_HND *handle = &q_u->handle;
5796 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5798 struct current_user user;
5799 WERROR errcode = WERR_OK;
5802 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5806 if (!get_printer_snum(p, handle, &snum))
5809 get_current_user( &user, p );
5811 print_job_delete( &user, snum, Printer->jobid, &errcode );
5816 /********************************************************************
5817 * called by spoolss_api_setprinter
5818 * when updating a printer description
5819 ********************************************************************/
5821 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5822 const SPOOL_PRINTER_INFO_LEVEL *info,
5823 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5825 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5829 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5831 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5832 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5833 OUR_HANDLE(handle)));
5835 result = WERR_BADFID;
5839 /* Check the user has permissions to change the security
5840 descriptor. By experimentation with two NT machines, the user
5841 requires Full Access to the printer to change security
5844 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5845 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5846 result = WERR_ACCESS_DENIED;
5850 /* NT seems to like setting the security descriptor even though
5851 nothing may have actually changed. */
5853 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5855 if (DEBUGLEVEL >= 10) {
5859 the_acl = old_secdesc_ctr->sec->dacl;
5860 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5861 PRINTERNAME(snum), the_acl->num_aces));
5863 for (i = 0; i < the_acl->num_aces; i++) {
5866 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5868 DEBUG(10, ("%s 0x%08x\n", sid_str,
5869 the_acl->ace[i].info.mask));
5872 the_acl = secdesc_ctr->sec->dacl;
5875 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5876 PRINTERNAME(snum), the_acl->num_aces));
5878 for (i = 0; i < the_acl->num_aces; i++) {
5881 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5883 DEBUG(10, ("%s 0x%08x\n", sid_str,
5884 the_acl->ace[i].info.mask));
5887 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5891 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5893 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5898 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5905 /********************************************************************
5906 Canonicalize printer info from a client
5908 ATTN: It does not matter what we set the servername to hear
5909 since we do the necessary work in get_a_printer() to set it to
5910 the correct value based on what the client sent in the
5911 _spoolss_open_printer_ex().
5912 ********************************************************************/
5914 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5916 fstring printername;
5919 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5920 "portname=%s drivername=%s comment=%s location=%s\n",
5921 info->servername, info->printername, info->sharename,
5922 info->portname, info->drivername, info->comment, info->location));
5924 /* we force some elements to "correct" values */
5925 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5926 fstrcpy(info->sharename, lp_servicename(snum));
5928 /* check to see if we allow printername != sharename */
5930 if ( lp_force_printername(snum) ) {
5931 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5932 global_myname(), info->sharename );
5935 /* make sure printername is in \\server\printername format */
5937 fstrcpy( printername, info->printername );
5939 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5940 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5944 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5945 global_myname(), p );
5948 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5949 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5956 /****************************************************************************
5957 ****************************************************************************/
5959 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
5961 char *cmd = lp_addport_cmd();
5965 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5966 BOOL is_print_op = False;
5969 return WERR_ACCESS_DENIED;
5972 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
5975 is_print_op = user_has_privileges( token, &se_printop );
5977 DEBUG(10,("Running [%s]\n", command));
5979 /********* BEGIN SePrintOperatorPrivilege **********/
5984 ret = smbrun(command, &fd);
5989 /********* END SePrintOperatorPrivilege **********/
5991 DEBUGADD(10,("returned [%d]\n", ret));
5996 return WERR_ACCESS_DENIED;
6002 /****************************************************************************
6003 ****************************************************************************/
6005 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6007 char *cmd = lp_addprinter_cmd();
6013 fstring remote_machine = "%m";
6014 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6015 BOOL is_print_op = False;
6017 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6019 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6020 cmd, printer->info_2->printername, printer->info_2->sharename,
6021 printer->info_2->portname, printer->info_2->drivername,
6022 printer->info_2->location, printer->info_2->comment, remote_machine);
6025 is_print_op = user_has_privileges( token, &se_printop );
6027 DEBUG(10,("Running [%s]\n", command));
6029 /********* BEGIN SePrintOperatorPrivilege **********/
6034 if ( (ret = smbrun(command, &fd)) == 0 ) {
6035 /* Tell everyone we updated smb.conf. */
6036 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6042 /********* END SePrintOperatorPrivilege **********/
6044 DEBUGADD(10,("returned [%d]\n", ret));
6052 /* reload our services immediately */
6053 reload_services( False );
6056 /* Get lines and convert them back to dos-codepage */
6057 qlines = fd_lines_load(fd, &numlines, 0);
6058 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6061 /* Set the portname to what the script says the portname should be. */
6062 /* but don't require anything to be return from the script exit a good error code */
6065 /* Set the portname to what the script says the portname should be. */
6066 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6067 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6070 file_lines_free(qlines);
6075 /********************************************************************
6076 * Called by spoolss_api_setprinter
6077 * when updating a printer description.
6078 ********************************************************************/
6080 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6081 const SPOOL_PRINTER_INFO_LEVEL *info,
6082 DEVICEMODE *devmode)
6085 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6086 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6091 DEBUG(8,("update_printer\n"));
6096 result = WERR_BADFID;
6100 if (!get_printer_snum(p, handle, &snum)) {
6101 result = WERR_BADFID;
6105 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6106 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6107 result = WERR_BADFID;
6111 DEBUGADD(8,("Converting info_2 struct\n"));
6114 * convert_printer_info converts the incoming
6115 * info from the client and overwrites the info
6116 * just read from the tdb in the pointer 'printer'.
6119 if (!convert_printer_info(info, printer, level)) {
6120 result = WERR_NOMEM;
6125 /* we have a valid devmode
6126 convert it and link it*/
6128 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6129 if (!convert_devicemode(printer->info_2->printername, devmode,
6130 &printer->info_2->devmode)) {
6131 result = WERR_NOMEM;
6136 /* Do sanity check on the requested changes for Samba */
6138 if (!check_printer_ok(printer->info_2, snum)) {
6139 result = WERR_INVALID_PARAM;
6143 /* FIXME!!! If the driver has changed we really should verify that
6144 it is installed before doing much else --jerry */
6146 /* Check calling user has permission to update printer description */
6148 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6149 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6150 result = WERR_ACCESS_DENIED;
6154 /* Call addprinter hook */
6155 /* Check changes to see if this is really needed */
6157 if ( *lp_addprinter_cmd()
6158 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6159 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6160 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6161 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6163 /* add_printer_hook() will call reload_services() */
6165 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6166 result = WERR_ACCESS_DENIED;
6172 * When a *new* driver is bound to a printer, the drivername is used to
6173 * lookup previously saved driver initialization info, which is then
6174 * bound to the printer, simulating what happens in the Windows arch.
6176 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6178 if (!set_driver_init(printer, 2))
6180 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6181 printer->info_2->drivername));
6184 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6185 printer->info_2->drivername));
6187 notify_printer_driver(snum, printer->info_2->drivername);
6191 * flag which changes actually occured. This is a small subset of
6192 * all the possible changes. We also have to update things in the
6196 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6197 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6198 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6199 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6201 notify_printer_comment(snum, printer->info_2->comment);
6204 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6205 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6206 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6207 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6209 notify_printer_sharename(snum, printer->info_2->sharename);
6212 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6215 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6218 pname = printer->info_2->printername;
6221 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6222 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6223 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6225 notify_printer_printername( snum, pname );
6228 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6229 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6230 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6231 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6233 notify_printer_port(snum, printer->info_2->portname);
6236 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6237 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6238 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6239 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6241 notify_printer_location(snum, printer->info_2->location);
6244 /* here we need to update some more DsSpooler keys */
6245 /* uNCName, serverName, shortServerName */
6247 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6248 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6249 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6250 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6251 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6253 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6254 global_myname(), printer->info_2->sharename );
6255 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6256 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6257 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6259 /* Update printer info */
6260 result = mod_a_printer(printer, 2);
6263 free_a_printer(&printer, 2);
6264 free_a_printer(&old_printer, 2);
6270 /****************************************************************************
6271 ****************************************************************************/
6272 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6273 const SPOOL_PRINTER_INFO_LEVEL *info)
6276 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6278 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6280 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6285 if (!get_printer_snum(p, handle, &snum))
6288 nt_printer_publish(Printer, snum, info7->action);
6292 return WERR_UNKNOWN_LEVEL;
6295 /****************************************************************************
6296 ****************************************************************************/
6298 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6300 POLICY_HND *handle = &q_u->handle;
6301 uint32 level = q_u->level;
6302 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6303 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6304 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6305 uint32 command = q_u->command;
6308 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6311 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6315 /* check the level */
6318 return control_printer(handle, command, p);
6320 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6321 if (!W_ERROR_IS_OK(result))
6324 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6327 return update_printer_sec(handle, level, info, p,
6330 return publish_or_unpublish_printer(p, handle, info);
6332 return WERR_UNKNOWN_LEVEL;
6336 /****************************************************************************
6337 ****************************************************************************/
6339 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6341 POLICY_HND *handle = &q_u->handle;
6342 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6345 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6349 if (Printer->notify.client_connected==True) {
6352 if ( Printer->printer_type == SPLHND_SERVER)
6354 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6355 !get_printer_snum(p, handle, &snum) )
6358 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6361 Printer->notify.flags=0;
6362 Printer->notify.options=0;
6363 Printer->notify.localmachine[0]='\0';
6364 Printer->notify.printerlocal=0;
6365 if (Printer->notify.option)
6366 free_spool_notify_option(&Printer->notify.option);
6367 Printer->notify.client_connected=False;
6372 /****************************************************************************
6373 ****************************************************************************/
6375 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6377 /* that's an [in out] buffer */
6380 rpcbuf_move(q_u->buffer, &r_u->buffer);
6383 return WERR_INVALID_PARAM; /* this is what a NT server
6384 returns for AddJob. AddJob
6385 must fail on non-local
6389 /****************************************************************************
6390 ****************************************************************************/
6392 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6393 int position, int snum,
6394 NT_PRINTER_INFO_LEVEL *ntprinter)
6398 t=gmtime(&queue->time);
6400 job_info->jobid=queue->job;
6401 init_unistr(&job_info->printername, lp_servicename(snum));
6402 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6403 init_unistr(&job_info->username, queue->fs_user);
6404 init_unistr(&job_info->document, queue->fs_file);
6405 init_unistr(&job_info->datatype, "RAW");
6406 init_unistr(&job_info->text_status, "");
6407 job_info->status=nt_printj_status(queue->status);
6408 job_info->priority=queue->priority;
6409 job_info->position=position;
6410 job_info->totalpages=queue->page_count;
6411 job_info->pagesprinted=0;
6413 make_systemtime(&job_info->submitted, t);
6416 /****************************************************************************
6417 ****************************************************************************/
6419 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6420 int position, int snum,
6421 NT_PRINTER_INFO_LEVEL *ntprinter,
6422 DEVICEMODE *devmode)
6426 t=gmtime(&queue->time);
6428 job_info->jobid=queue->job;
6430 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6432 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6433 init_unistr(&job_info->username, queue->fs_user);
6434 init_unistr(&job_info->document, queue->fs_file);
6435 init_unistr(&job_info->notifyname, queue->fs_user);
6436 init_unistr(&job_info->datatype, "RAW");
6437 init_unistr(&job_info->printprocessor, "winprint");
6438 init_unistr(&job_info->parameters, "");
6439 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6440 init_unistr(&job_info->text_status, "");
6442 /* and here the security descriptor */
6444 job_info->status=nt_printj_status(queue->status);
6445 job_info->priority=queue->priority;
6446 job_info->position=position;
6447 job_info->starttime=0;
6448 job_info->untiltime=0;
6449 job_info->totalpages=queue->page_count;
6450 job_info->size=queue->size;
6451 make_systemtime(&(job_info->submitted), t);
6452 job_info->timeelapsed=0;
6453 job_info->pagesprinted=0;
6455 job_info->devmode = devmode;
6460 /****************************************************************************
6461 Enumjobs at level 1.
6462 ****************************************************************************/
6464 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6465 NT_PRINTER_INFO_LEVEL *ntprinter,
6466 RPC_BUFFER *buffer, uint32 offered,
6467 uint32 *needed, uint32 *returned)
6471 WERROR result = WERR_OK;
6473 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6480 for (i=0; i<*returned; i++)
6481 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6485 /* check the required size. */
6486 for (i=0; i<*returned; i++)
6487 (*needed) += spoolss_size_job_info_1(&info[i]);
6489 if (*needed > offered) {
6490 result = WERR_INSUFFICIENT_BUFFER;
6494 if (!rpcbuf_alloc_size(buffer, *needed)) {
6495 result = WERR_NOMEM;
6499 /* fill the buffer with the structures */
6500 for (i=0; i<*returned; i++)
6501 smb_io_job_info_1("", buffer, &info[i], 0);
6507 if ( !W_ERROR_IS_OK(result) )
6513 /****************************************************************************
6514 Enumjobs at level 2.
6515 ****************************************************************************/
6517 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6518 NT_PRINTER_INFO_LEVEL *ntprinter,
6519 RPC_BUFFER *buffer, uint32 offered,
6520 uint32 *needed, uint32 *returned)
6522 JOB_INFO_2 *info = NULL;
6524 WERROR result = WERR_OK;
6525 DEVICEMODE *devmode = NULL;
6527 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6532 /* this should not be a failure condition if the devmode is NULL */
6534 devmode = construct_dev_mode(snum);
6536 for (i=0; i<*returned; i++)
6537 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6539 free_a_printer(&ntprinter, 2);
6542 /* check the required size. */
6543 for (i=0; i<*returned; i++)
6544 (*needed) += spoolss_size_job_info_2(&info[i]);
6546 if (*needed > offered) {
6547 result = WERR_INSUFFICIENT_BUFFER;
6551 if (!rpcbuf_alloc_size(buffer, *needed)) {
6552 result = WERR_NOMEM;
6556 /* fill the buffer with the structures */
6557 for (i=0; i<*returned; i++)
6558 smb_io_job_info_2("", buffer, &info[i], 0);
6561 free_devmode(devmode);
6564 if ( !W_ERROR_IS_OK(result) )
6571 /****************************************************************************
6573 ****************************************************************************/
6575 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6577 POLICY_HND *handle = &q_u->handle;
6578 uint32 level = q_u->level;
6579 RPC_BUFFER *buffer = NULL;
6580 uint32 offered = q_u->offered;
6581 uint32 *needed = &r_u->needed;
6582 uint32 *returned = &r_u->returned;
6584 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6586 print_status_struct prt_status;
6587 print_queue_struct *queue=NULL;
6589 /* that's an [in out] buffer */
6591 if ( q_u->buffer ) {
6592 rpcbuf_move(q_u->buffer, &r_u->buffer);
6593 buffer = r_u->buffer;
6596 DEBUG(4,("_spoolss_enumjobs\n"));
6601 /* lookup the printer snum and tdb entry */
6603 if (!get_printer_snum(p, handle, &snum))
6606 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6607 if ( !W_ERROR_IS_OK(wret) )
6610 *returned = print_queue_status(snum, &queue, &prt_status);
6611 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6613 if (*returned == 0) {
6620 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6623 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6628 wret = WERR_UNKNOWN_LEVEL;
6631 free_a_printer( &ntprinter, 2 );
6635 /****************************************************************************
6636 ****************************************************************************/
6638 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6643 /****************************************************************************
6644 ****************************************************************************/
6646 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6648 POLICY_HND *handle = &q_u->handle;
6649 uint32 jobid = q_u->jobid;
6650 uint32 command = q_u->command;
6652 struct current_user user;
6654 WERROR errcode = WERR_BADFUNC;
6656 if (!get_printer_snum(p, handle, &snum)) {
6660 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6661 return WERR_INVALID_PRINTER_NAME;
6664 get_current_user(&user, p);
6667 case JOB_CONTROL_CANCEL:
6668 case JOB_CONTROL_DELETE:
6669 if (print_job_delete(&user, snum, jobid, &errcode)) {
6673 case JOB_CONTROL_PAUSE:
6674 if (print_job_pause(&user, snum, jobid, &errcode)) {
6678 case JOB_CONTROL_RESTART:
6679 case JOB_CONTROL_RESUME:
6680 if (print_job_resume(&user, snum, jobid, &errcode)) {
6685 return WERR_UNKNOWN_LEVEL;
6691 /****************************************************************************
6692 Enumerates all printer drivers at level 1.
6693 ****************************************************************************/
6695 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6700 fstring *list = NULL;
6701 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6702 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6703 WERROR result = WERR_OK;
6707 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6709 ndrivers=get_ntdrivers(&list, architecture, version);
6710 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6716 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6717 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6718 SAFE_FREE(driver_info_1);
6722 else driver_info_1 = tdi1;
6725 for (i=0; i<ndrivers; i++) {
6727 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6728 ZERO_STRUCT(driver);
6729 status = get_a_printer_driver(&driver, 3, list[i],
6730 architecture, version);
6731 if (!W_ERROR_IS_OK(status)) {
6735 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6736 free_a_printer_driver(driver, 3);
6739 *returned+=ndrivers;
6743 /* check the required size. */
6744 for (i=0; i<*returned; i++) {
6745 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6746 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6749 if (*needed > offered) {
6750 result = WERR_INSUFFICIENT_BUFFER;
6754 if (!rpcbuf_alloc_size(buffer, *needed)) {
6755 result = WERR_NOMEM;
6759 /* fill the buffer with the driver structures */
6760 for (i=0; i<*returned; i++) {
6761 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6762 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6766 SAFE_FREE(driver_info_1);
6768 if ( !W_ERROR_IS_OK(result) )
6774 /****************************************************************************
6775 Enumerates all printer drivers at level 2.
6776 ****************************************************************************/
6778 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6783 fstring *list = NULL;
6784 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6785 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6786 WERROR result = WERR_OK;
6790 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6792 ndrivers=get_ntdrivers(&list, architecture, version);
6793 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6799 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6800 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6801 SAFE_FREE(driver_info_2);
6805 else driver_info_2 = tdi2;
6808 for (i=0; i<ndrivers; i++) {
6811 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6812 ZERO_STRUCT(driver);
6813 status = get_a_printer_driver(&driver, 3, list[i],
6814 architecture, version);
6815 if (!W_ERROR_IS_OK(status)) {
6819 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6820 free_a_printer_driver(driver, 3);
6823 *returned+=ndrivers;
6827 /* check the required size. */
6828 for (i=0; i<*returned; i++) {
6829 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6830 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6833 if (*needed > offered) {
6834 result = WERR_INSUFFICIENT_BUFFER;
6838 if (!rpcbuf_alloc_size(buffer, *needed)) {
6839 result = WERR_NOMEM;
6843 /* fill the buffer with the form structures */
6844 for (i=0; i<*returned; i++) {
6845 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6846 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6850 SAFE_FREE(driver_info_2);
6852 if ( !W_ERROR_IS_OK(result) )
6858 /****************************************************************************
6859 Enumerates all printer drivers at level 3.
6860 ****************************************************************************/
6862 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6867 fstring *list = NULL;
6868 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6869 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6870 WERROR result = WERR_OK;
6874 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6876 ndrivers=get_ntdrivers(&list, architecture, version);
6877 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6883 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6884 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6885 SAFE_FREE(driver_info_3);
6889 else driver_info_3 = tdi3;
6892 for (i=0; i<ndrivers; i++) {
6895 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6896 ZERO_STRUCT(driver);
6897 status = get_a_printer_driver(&driver, 3, list[i],
6898 architecture, version);
6899 if (!W_ERROR_IS_OK(status)) {
6903 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6904 free_a_printer_driver(driver, 3);
6907 *returned+=ndrivers;
6911 /* check the required size. */
6912 for (i=0; i<*returned; i++) {
6913 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6914 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6917 if (*needed > offered) {
6918 result = WERR_INSUFFICIENT_BUFFER;
6922 if (!rpcbuf_alloc_size(buffer, *needed)) {
6923 result = WERR_NOMEM;
6927 /* fill the buffer with the driver structures */
6928 for (i=0; i<*returned; i++) {
6929 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6930 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6934 for (i=0; i<*returned; i++)
6935 SAFE_FREE(driver_info_3[i].dependentfiles);
6937 SAFE_FREE(driver_info_3);
6939 if ( !W_ERROR_IS_OK(result) )
6945 /****************************************************************************
6946 Enumerates all printer drivers.
6947 ****************************************************************************/
6949 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6951 uint32 level = q_u->level;
6952 RPC_BUFFER *buffer = NULL;
6953 uint32 offered = q_u->offered;
6954 uint32 *needed = &r_u->needed;
6955 uint32 *returned = &r_u->returned;
6958 fstring architecture;
6960 /* that's an [in out] buffer */
6962 if ( q_u->buffer ) {
6963 rpcbuf_move(q_u->buffer, &r_u->buffer);
6964 buffer = r_u->buffer;
6967 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6972 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6973 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6975 if ( !is_myname_or_ipaddr( servername ) )
6976 return WERR_UNKNOWN_PRINTER_DRIVER;
6980 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6982 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6984 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6986 return WERR_UNKNOWN_LEVEL;
6990 /****************************************************************************
6991 ****************************************************************************/
6993 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6995 form->flag=list->flag;
6996 init_unistr(&form->name, list->name);
6997 form->width=list->width;
6998 form->length=list->length;
6999 form->left=list->left;
7000 form->top=list->top;
7001 form->right=list->right;
7002 form->bottom=list->bottom;
7005 /****************************************************************************
7006 ****************************************************************************/
7008 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7010 uint32 level = q_u->level;
7011 RPC_BUFFER *buffer = NULL;
7012 uint32 offered = q_u->offered;
7013 uint32 *needed = &r_u->needed;
7014 uint32 *numofforms = &r_u->numofforms;
7015 uint32 numbuiltinforms;
7017 nt_forms_struct *list=NULL;
7018 nt_forms_struct *builtinlist=NULL;
7023 /* that's an [in out] buffer */
7025 if ( q_u->buffer ) {
7026 rpcbuf_move(q_u->buffer, &r_u->buffer);
7027 buffer = r_u->buffer;
7030 DEBUG(4,("_spoolss_enumforms\n"));
7031 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7032 DEBUGADD(5,("Info level [%d]\n", level));
7034 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7035 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7036 *numofforms = get_ntforms(&list);
7037 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7038 *numofforms += numbuiltinforms;
7040 if (*numofforms == 0)
7041 return WERR_NO_MORE_ITEMS;
7045 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7050 /* construct the list of form structures */
7051 for (i=0; i<numbuiltinforms; i++) {
7052 DEBUGADD(6,("Filling form number [%d]\n",i));
7053 fill_form_1(&forms_1[i], &builtinlist[i]);
7056 SAFE_FREE(builtinlist);
7058 for (; i<*numofforms; i++) {
7059 DEBUGADD(6,("Filling form number [%d]\n",i));
7060 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7065 /* check the required size. */
7066 for (i=0; i<numbuiltinforms; i++) {
7067 DEBUGADD(6,("adding form [%d]'s size\n",i));
7068 buffer_size += spoolss_size_form_1(&forms_1[i]);
7070 for (; i<*numofforms; i++) {
7071 DEBUGADD(6,("adding form [%d]'s size\n",i));
7072 buffer_size += spoolss_size_form_1(&forms_1[i]);
7075 *needed=buffer_size;
7077 if (*needed > offered) {
7080 return WERR_INSUFFICIENT_BUFFER;
7083 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7089 /* fill the buffer with the form structures */
7090 for (i=0; i<numbuiltinforms; i++) {
7091 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7092 smb_io_form_1("", buffer, &forms_1[i], 0);
7094 for (; i<*numofforms; i++) {
7095 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7096 smb_io_form_1("", buffer, &forms_1[i], 0);
7105 SAFE_FREE(builtinlist);
7106 return WERR_UNKNOWN_LEVEL;
7111 /****************************************************************************
7112 ****************************************************************************/
7114 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7116 uint32 level = q_u->level;
7117 UNISTR2 *uni_formname = &q_u->formname;
7118 RPC_BUFFER *buffer = NULL;
7119 uint32 offered = q_u->offered;
7120 uint32 *needed = &r_u->needed;
7122 nt_forms_struct *list=NULL;
7123 nt_forms_struct builtin_form;
7128 int numofforms=0, i=0;
7130 /* that's an [in out] buffer */
7132 if ( q_u->buffer ) {
7133 rpcbuf_move(q_u->buffer, &r_u->buffer);
7134 buffer = r_u->buffer;
7137 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7139 DEBUG(4,("_spoolss_getform\n"));
7140 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7141 DEBUGADD(5,("Info level [%d]\n", level));
7143 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7144 if (!foundBuiltin) {
7145 numofforms = get_ntforms(&list);
7146 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7148 if (numofforms == 0)
7155 fill_form_1(&form_1, &builtin_form);
7158 /* Check if the requested name is in the list of form structures */
7159 for (i=0; i<numofforms; i++) {
7161 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7163 if (strequal(form_name, list[i].name)) {
7164 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7165 fill_form_1(&form_1, &list[i]);
7171 if (i == numofforms) {
7175 /* check the required size. */
7177 *needed=spoolss_size_form_1(&form_1);
7179 if (*needed > offered)
7180 return WERR_INSUFFICIENT_BUFFER;
7182 if (!rpcbuf_alloc_size(buffer, buffer_size))
7185 /* fill the buffer with the form structures */
7186 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7187 smb_io_form_1("", buffer, &form_1, 0);
7193 return WERR_UNKNOWN_LEVEL;
7197 /****************************************************************************
7198 ****************************************************************************/
7200 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7202 init_unistr(&port->port_name, name);
7205 /****************************************************************************
7206 TODO: This probably needs distinguish between TCP/IP and Local ports
7208 ****************************************************************************/
7210 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7212 init_unistr(&port->port_name, name);
7213 init_unistr(&port->monitor_name, "Local Monitor");
7214 init_unistr(&port->description, SPL_LOCAL_PORT );
7215 port->port_type=PORT_TYPE_WRITE;
7220 /****************************************************************************
7221 wrapper around the enumer ports command
7222 ****************************************************************************/
7224 WERROR enumports_hook( int *count, char ***lines )
7226 char *cmd = lp_enumports_cmd();
7234 /* if no hook then just fill in the default port */
7237 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7238 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7243 /* we have a valid enumport command */
7245 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7247 DEBUG(10,("Running [%s]\n", command));
7248 ret = smbrun(command, &fd);
7249 DEBUG(10,("Returned [%d]\n", ret));
7254 return WERR_ACCESS_DENIED;
7258 qlines = fd_lines_load(fd, &numlines, 0);
7259 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7269 /****************************************************************************
7271 ****************************************************************************/
7273 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7275 PORT_INFO_1 *ports=NULL;
7277 WERROR result = WERR_OK;
7281 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7285 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7286 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7287 dos_errstr(WERR_NOMEM)));
7288 file_lines_free(qlines);
7292 for (i=0; i<numlines; i++) {
7293 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7294 fill_port_1(&ports[i], qlines[i]);
7297 file_lines_free(qlines);
7300 *returned = numlines;
7302 /* check the required size. */
7303 for (i=0; i<*returned; i++) {
7304 DEBUGADD(6,("adding port [%d]'s size\n", i));
7305 *needed += spoolss_size_port_info_1(&ports[i]);
7308 if (*needed > offered) {
7309 result = WERR_INSUFFICIENT_BUFFER;
7313 if (!rpcbuf_alloc_size(buffer, *needed)) {
7314 result = WERR_NOMEM;
7318 /* fill the buffer with the ports structures */
7319 for (i=0; i<*returned; i++) {
7320 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7321 smb_io_port_1("", buffer, &ports[i], 0);
7327 if ( !W_ERROR_IS_OK(result) )
7333 /****************************************************************************
7335 ****************************************************************************/
7337 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7339 PORT_INFO_2 *ports=NULL;
7341 WERROR result = WERR_OK;
7345 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7350 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7351 file_lines_free(qlines);
7355 for (i=0; i<numlines; i++) {
7356 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7357 fill_port_2(&(ports[i]), qlines[i]);
7360 file_lines_free(qlines);
7363 *returned = numlines;
7365 /* check the required size. */
7366 for (i=0; i<*returned; i++) {
7367 DEBUGADD(6,("adding port [%d]'s size\n", i));
7368 *needed += spoolss_size_port_info_2(&ports[i]);
7371 if (*needed > offered) {
7372 result = WERR_INSUFFICIENT_BUFFER;
7376 if (!rpcbuf_alloc_size(buffer, *needed)) {
7377 result = WERR_NOMEM;
7381 /* fill the buffer with the ports structures */
7382 for (i=0; i<*returned; i++) {
7383 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7384 smb_io_port_2("", buffer, &ports[i], 0);
7390 if ( !W_ERROR_IS_OK(result) )
7396 /****************************************************************************
7398 ****************************************************************************/
7400 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7402 uint32 level = q_u->level;
7403 RPC_BUFFER *buffer = NULL;
7404 uint32 offered = q_u->offered;
7405 uint32 *needed = &r_u->needed;
7406 uint32 *returned = &r_u->returned;
7408 /* that's an [in out] buffer */
7410 if ( q_u->buffer ) {
7411 rpcbuf_move(q_u->buffer, &r_u->buffer);
7412 buffer = r_u->buffer;
7415 DEBUG(4,("_spoolss_enumports\n"));
7422 return enumports_level_1(buffer, offered, needed, returned);
7424 return enumports_level_2(buffer, offered, needed, returned);
7426 return WERR_UNKNOWN_LEVEL;
7430 /****************************************************************************
7431 ****************************************************************************/
7433 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7434 const SPOOL_PRINTER_INFO_LEVEL *info,
7435 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7436 uint32 user_switch, const SPOOL_USER_CTR *user,
7439 NT_PRINTER_INFO_LEVEL *printer = NULL;
7442 WERROR err = WERR_OK;
7444 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7445 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7449 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7450 if (!convert_printer_info(info, printer, 2)) {
7451 free_a_printer(&printer, 2);
7455 /* check to see if the printer already exists */
7457 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7458 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7459 printer->info_2->sharename));
7460 free_a_printer(&printer, 2);
7461 return WERR_PRINTER_ALREADY_EXISTS;
7464 /* FIXME!!! smbd should check to see if the driver is installed before
7465 trying to add a printer like this --jerry */
7467 if (*lp_addprinter_cmd() ) {
7468 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7469 free_a_printer(&printer,2);
7470 return WERR_ACCESS_DENIED;
7473 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7474 "smb.conf parameter \"addprinter command\" is defined. This"
7475 "parameter must exist for this call to succeed\n",
7476 printer->info_2->sharename ));
7479 /* use our primary netbios name since get_a_printer() will convert
7480 it to what the client expects on a case by case basis */
7482 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7483 printer->info_2->sharename);
7486 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7487 free_a_printer(&printer,2);
7488 return WERR_ACCESS_DENIED;
7491 /* you must be a printer admin to add a new printer */
7492 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7493 free_a_printer(&printer,2);
7494 return WERR_ACCESS_DENIED;
7498 * Do sanity check on the requested changes for Samba.
7501 if (!check_printer_ok(printer->info_2, snum)) {
7502 free_a_printer(&printer,2);
7503 return WERR_INVALID_PARAM;
7507 * When a printer is created, the drivername bound to the printer is used
7508 * to lookup previously saved driver initialization info, which is then
7509 * bound to the new printer, simulating what happens in the Windows arch.
7514 set_driver_init(printer, 2);
7518 /* A valid devmode was included, convert and link it
7520 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7522 if (!convert_devicemode(printer->info_2->printername, devmode,
7523 &printer->info_2->devmode))
7527 /* write the ASCII on disk */
7528 err = mod_a_printer(printer, 2);
7529 if (!W_ERROR_IS_OK(err)) {
7530 free_a_printer(&printer,2);
7534 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7535 /* Handle open failed - remove addition. */
7536 del_a_printer(printer->info_2->sharename);
7537 free_a_printer(&printer,2);
7538 return WERR_ACCESS_DENIED;
7541 update_c_setprinter(False);
7542 free_a_printer(&printer,2);
7547 /****************************************************************************
7548 ****************************************************************************/
7550 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7552 UNISTR2 *uni_srv_name = q_u->server_name;
7553 uint32 level = q_u->level;
7554 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7555 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7556 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7557 uint32 user_switch = q_u->user_switch;
7558 SPOOL_USER_CTR *user = &q_u->user_ctr;
7559 POLICY_HND *handle = &r_u->handle;
7563 /* we don't handle yet */
7564 /* but I know what to do ... */
7565 return WERR_UNKNOWN_LEVEL;
7567 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7569 user_switch, user, handle);
7571 return WERR_UNKNOWN_LEVEL;
7575 /****************************************************************************
7576 ****************************************************************************/
7578 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7580 uint32 level = q_u->level;
7581 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7582 WERROR err = WERR_OK;
7583 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7584 struct current_user user;
7585 fstring driver_name;
7588 ZERO_STRUCT(driver);
7590 get_current_user(&user, p);
7592 if (!convert_printer_driver_info(info, &driver, level)) {
7597 DEBUG(5,("Cleaning driver's information\n"));
7598 err = clean_up_driver_struct(driver, level, &user);
7599 if (!W_ERROR_IS_OK(err))
7602 DEBUG(5,("Moving driver to final destination\n"));
7603 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7607 if (add_a_printer_driver(driver, level)!=0) {
7608 err = WERR_ACCESS_DENIED;
7612 /* BEGIN_ADMIN_LOG */
7615 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7616 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7617 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.ut.uid));
7620 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7621 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7622 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.ut.uid));
7628 * I think this is where he DrvUpgradePrinter() hook would be
7629 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7630 * server. Right now, we just need to send ourselves a message
7631 * to update each printer bound to this driver. --jerry
7634 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7635 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7640 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7641 * decide if the driver init data should be deleted. The rules are:
7642 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7643 * 2) delete init data only if there is no 2k/Xp driver
7644 * 3) always delete init data
7645 * The generalized rule is always use init data from the highest order driver.
7646 * It is necessary to follow the driver install by an initialization step to
7647 * finish off this process.
7650 version = driver.info_3->cversion;
7651 else if (level == 6)
7652 version = driver.info_6->version;
7657 * 9x printer driver - never delete init data
7660 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7665 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7666 * there is no 2k/Xp driver init data for this driver name.
7670 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7672 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7674 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7676 if (!del_driver_init(driver_name))
7677 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7680 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7682 free_a_printer_driver(driver1,3);
7683 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7690 * 2k or Xp printer driver - always delete init data
7693 if (!del_driver_init(driver_name))
7694 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7698 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7704 free_a_printer_driver(driver, level);
7708 /********************************************************************
7709 * spoolss_addprinterdriverex
7710 ********************************************************************/
7712 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7714 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7715 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7718 * we only support the semantics of AddPrinterDriver()
7719 * i.e. only copy files that are newer than existing ones
7722 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7723 return WERR_ACCESS_DENIED;
7725 ZERO_STRUCT(q_u_local);
7726 ZERO_STRUCT(r_u_local);
7728 /* just pass the information off to _spoolss_addprinterdriver() */
7729 q_u_local.server_name_ptr = q_u->server_name_ptr;
7730 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7731 q_u_local.level = q_u->level;
7732 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7734 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7737 /****************************************************************************
7738 ****************************************************************************/
7740 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7742 init_unistr(&info->name, name);
7745 /****************************************************************************
7746 ****************************************************************************/
7748 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7754 const char *short_archi;
7755 DRIVER_DIRECTORY_1 *info=NULL;
7756 WERROR result = WERR_OK;
7758 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7759 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7761 /* check for beginning double '\'s and that the server
7764 pservername = servername;
7765 if ( *pservername == '\\' && strlen(servername)>2 ) {
7769 if ( !is_myname_or_ipaddr( pservername ) )
7770 return WERR_INVALID_PARAM;
7772 if (!(short_archi = get_short_archi(long_archi)))
7773 return WERR_INVALID_ENVIRONMENT;
7775 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7778 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7780 DEBUG(4,("printer driver directory: [%s]\n", path));
7782 fill_driverdir_1(info, path);
7784 *needed += spoolss_size_driverdir_info_1(info);
7786 if (*needed > offered) {
7787 result = WERR_INSUFFICIENT_BUFFER;
7791 if (!rpcbuf_alloc_size(buffer, *needed)) {
7792 result = WERR_NOMEM;
7796 smb_io_driverdir_1("", buffer, info, 0);
7804 /****************************************************************************
7805 ****************************************************************************/
7807 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7809 UNISTR2 *name = &q_u->name;
7810 UNISTR2 *uni_environment = &q_u->environment;
7811 uint32 level = q_u->level;
7812 RPC_BUFFER *buffer = NULL;
7813 uint32 offered = q_u->offered;
7814 uint32 *needed = &r_u->needed;
7816 /* that's an [in out] buffer */
7818 if ( q_u->buffer ) {
7819 rpcbuf_move(q_u->buffer, &r_u->buffer);
7820 buffer = r_u->buffer;
7823 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7829 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7831 return WERR_UNKNOWN_LEVEL;
7835 /****************************************************************************
7836 ****************************************************************************/
7838 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7840 POLICY_HND *handle = &q_u->handle;
7841 uint32 idx = q_u->index;
7842 uint32 in_value_len = q_u->valuesize;
7843 uint32 in_data_len = q_u->datasize;
7844 uint32 *out_max_value_len = &r_u->valuesize;
7845 uint16 **out_value = &r_u->value;
7846 uint32 *out_value_len = &r_u->realvaluesize;
7847 uint32 *out_type = &r_u->type;
7848 uint32 *out_max_data_len = &r_u->datasize;
7849 uint8 **data_out = &r_u->data;
7850 uint32 *out_data_len = &r_u->realdatasize;
7852 NT_PRINTER_INFO_LEVEL *printer = NULL;
7854 uint32 biggest_valuesize;
7855 uint32 biggest_datasize;
7857 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7860 REGISTRY_VALUE *val = NULL;
7861 NT_PRINTER_DATA *p_data;
7862 int i, key_index, num_values;
7867 *out_max_data_len = 0;
7871 DEBUG(5,("spoolss_enumprinterdata\n"));
7874 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7878 if (!get_printer_snum(p,handle, &snum))
7881 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7882 if (!W_ERROR_IS_OK(result))
7885 p_data = printer->info_2->data;
7886 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7891 * The NT machine wants to know the biggest size of value and data
7893 * cf: MSDN EnumPrinterData remark section
7896 if ( !in_value_len && !in_data_len && (key_index != -1) )
7898 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7900 biggest_valuesize = 0;
7901 biggest_datasize = 0;
7903 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7905 for ( i=0; i<num_values; i++ )
7907 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7909 name_length = strlen(val->valuename);
7910 if ( strlen(val->valuename) > biggest_valuesize )
7911 biggest_valuesize = name_length;
7913 if ( val->size > biggest_datasize )
7914 biggest_datasize = val->size;
7916 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7920 /* the value is an UNICODE string but real_value_size is the length
7921 in bytes including the trailing 0 */
7923 *out_value_len = 2 * (1+biggest_valuesize);
7924 *out_data_len = biggest_datasize;
7926 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7932 * the value len is wrong in NT sp3
7933 * that's the number of bytes not the number of unicode chars
7936 if ( key_index != -1 )
7937 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7942 /* out_value should default to "" or else NT4 has
7943 problems unmarshalling the response */
7945 *out_max_value_len=(in_value_len/sizeof(uint16));
7947 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7949 result = WERR_NOMEM;
7953 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7955 /* the data is counted in bytes */
7957 *out_max_data_len = in_data_len;
7958 *out_data_len = in_data_len;
7960 /* only allocate when given a non-zero data_len */
7962 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7964 result = WERR_NOMEM;
7968 result = WERR_NO_MORE_ITEMS;
7974 * - counted in bytes in the request
7975 * - counted in UNICODE chars in the max reply
7976 * - counted in bytes in the real size
7978 * take a pause *before* coding not *during* coding
7982 *out_max_value_len=(in_value_len/sizeof(uint16));
7983 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7985 result = WERR_NOMEM;
7989 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7993 *out_type = regval_type( val );
7995 /* data - counted in bytes */
7997 *out_max_data_len = in_data_len;
7998 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8000 result = WERR_NOMEM;
8003 data_len = regval_size(val);
8005 memcpy( *data_out, regval_data_p(val), data_len );
8006 *out_data_len = data_len;
8010 free_a_printer(&printer, 2);
8014 /****************************************************************************
8015 ****************************************************************************/
8017 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8019 POLICY_HND *handle = &q_u->handle;
8020 UNISTR2 *value = &q_u->value;
8021 uint32 type = q_u->type;
8022 uint8 *data = q_u->data;
8023 uint32 real_len = q_u->real_len;
8025 NT_PRINTER_INFO_LEVEL *printer = NULL;
8027 WERROR status = WERR_OK;
8028 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8031 DEBUG(5,("spoolss_setprinterdata\n"));
8034 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8038 if ( Printer->printer_type == SPLHND_SERVER ) {
8039 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8040 return WERR_INVALID_PARAM;
8043 if (!get_printer_snum(p,handle, &snum))
8047 * Access check : NT returns "access denied" if you make a
8048 * SetPrinterData call without the necessary privildge.
8049 * we were originally returning OK if nothing changed
8050 * which made Win2k issue **a lot** of SetPrinterData
8051 * when connecting to a printer --jerry
8054 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8056 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8057 status = WERR_ACCESS_DENIED;
8061 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8062 if (!W_ERROR_IS_OK(status))
8065 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8068 * When client side code sets a magic printer data key, detect it and save
8069 * the current printer data and the magic key's data (its the DEVMODE) for
8070 * future printer/driver initializations.
8072 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8074 /* Set devmode and printer initialization info */
8075 status = save_driver_init( printer, 2, data, real_len );
8077 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8081 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8082 type, data, real_len );
8083 if ( W_ERROR_IS_OK(status) )
8084 status = mod_a_printer(printer, 2);
8088 free_a_printer(&printer, 2);
8093 /****************************************************************************
8094 ****************************************************************************/
8096 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8098 POLICY_HND *handle = &q_u->handle;
8099 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8102 DEBUG(5,("_spoolss_resetprinter\n"));
8105 * All we do is to check to see if the handle and queue is valid.
8106 * This call really doesn't mean anything to us because we only
8107 * support RAW printing. --jerry
8111 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8115 if (!get_printer_snum(p,handle, &snum))
8119 /* blindly return success */
8124 /****************************************************************************
8125 ****************************************************************************/
8127 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8129 POLICY_HND *handle = &q_u->handle;
8130 UNISTR2 *value = &q_u->valuename;
8132 NT_PRINTER_INFO_LEVEL *printer = NULL;
8134 WERROR status = WERR_OK;
8135 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8138 DEBUG(5,("spoolss_deleteprinterdata\n"));
8141 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8145 if (!get_printer_snum(p, handle, &snum))
8148 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8149 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8150 return WERR_ACCESS_DENIED;
8153 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8154 if (!W_ERROR_IS_OK(status))
8157 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8159 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8161 if ( W_ERROR_IS_OK(status) )
8162 mod_a_printer( printer, 2 );
8164 free_a_printer(&printer, 2);
8169 /****************************************************************************
8170 ****************************************************************************/
8172 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8174 POLICY_HND *handle = &q_u->handle;
8175 FORM *form = &q_u->form;
8176 nt_forms_struct tmpForm;
8178 WERROR status = WERR_OK;
8179 NT_PRINTER_INFO_LEVEL *printer = NULL;
8182 nt_forms_struct *list=NULL;
8183 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8185 DEBUG(5,("spoolss_addform\n"));
8188 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8193 /* forms can be added on printer of on the print server handle */
8195 if ( Printer->printer_type == SPLHND_PRINTER )
8197 if (!get_printer_snum(p,handle, &snum))
8200 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8201 if (!W_ERROR_IS_OK(status))
8205 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8206 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8207 status = WERR_ACCESS_DENIED;
8211 /* can't add if builtin */
8213 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8214 status = WERR_ALREADY_EXISTS;
8218 count = get_ntforms(&list);
8220 if(!add_a_form(&list, form, &count)) {
8221 status = WERR_NOMEM;
8225 write_ntforms(&list, count);
8228 * ChangeID must always be set if this is a printer
8231 if ( Printer->printer_type == SPLHND_PRINTER )
8232 status = mod_a_printer(printer, 2);
8236 free_a_printer(&printer, 2);
8242 /****************************************************************************
8243 ****************************************************************************/
8245 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8247 POLICY_HND *handle = &q_u->handle;
8248 UNISTR2 *form_name = &q_u->name;
8249 nt_forms_struct tmpForm;
8251 nt_forms_struct *list=NULL;
8252 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8254 WERROR status = WERR_OK;
8255 NT_PRINTER_INFO_LEVEL *printer = NULL;
8257 DEBUG(5,("spoolss_deleteform\n"));
8260 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8264 /* forms can be deleted on printer of on the print server handle */
8266 if ( Printer->printer_type == SPLHND_PRINTER )
8268 if (!get_printer_snum(p,handle, &snum))
8271 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8272 if (!W_ERROR_IS_OK(status))
8276 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8277 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8278 status = WERR_ACCESS_DENIED;
8282 /* can't delete if builtin */
8284 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8285 status = WERR_INVALID_PARAM;
8289 count = get_ntforms(&list);
8291 if ( !delete_a_form(&list, form_name, &count, &status ))
8295 * ChangeID must always be set if this is a printer
8298 if ( Printer->printer_type == SPLHND_PRINTER )
8299 status = mod_a_printer(printer, 2);
8303 free_a_printer(&printer, 2);
8309 /****************************************************************************
8310 ****************************************************************************/
8312 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8314 POLICY_HND *handle = &q_u->handle;
8315 FORM *form = &q_u->form;
8316 nt_forms_struct tmpForm;
8318 WERROR status = WERR_OK;
8319 NT_PRINTER_INFO_LEVEL *printer = NULL;
8322 nt_forms_struct *list=NULL;
8323 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8325 DEBUG(5,("spoolss_setform\n"));
8328 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8332 /* forms can be modified on printer of on the print server handle */
8334 if ( Printer->printer_type == SPLHND_PRINTER )
8336 if (!get_printer_snum(p,handle, &snum))
8339 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8340 if (!W_ERROR_IS_OK(status))
8344 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8345 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8346 status = WERR_ACCESS_DENIED;
8350 /* can't set if builtin */
8351 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8352 status = WERR_INVALID_PARAM;
8356 count = get_ntforms(&list);
8357 update_a_form(&list, form, count);
8358 write_ntforms(&list, count);
8361 * ChangeID must always be set if this is a printer
8364 if ( Printer->printer_type == SPLHND_PRINTER )
8365 status = mod_a_printer(printer, 2);
8370 free_a_printer(&printer, 2);
8376 /****************************************************************************
8377 enumprintprocessors level 1.
8378 ****************************************************************************/
8380 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8382 PRINTPROCESSOR_1 *info_1=NULL;
8383 WERROR result = WERR_OK;
8385 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8390 init_unistr(&info_1->name, "winprint");
8392 *needed += spoolss_size_printprocessor_info_1(info_1);
8394 if (*needed > offered) {
8395 result = WERR_INSUFFICIENT_BUFFER;
8399 if (!rpcbuf_alloc_size(buffer, *needed)) {
8400 result = WERR_NOMEM;
8404 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8409 if ( !W_ERROR_IS_OK(result) )
8415 /****************************************************************************
8416 ****************************************************************************/
8418 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8420 uint32 level = q_u->level;
8421 RPC_BUFFER *buffer = NULL;
8422 uint32 offered = q_u->offered;
8423 uint32 *needed = &r_u->needed;
8424 uint32 *returned = &r_u->returned;
8426 /* that's an [in out] buffer */
8428 if ( q_u->buffer ) {
8429 rpcbuf_move(q_u->buffer, &r_u->buffer);
8430 buffer = r_u->buffer;
8433 DEBUG(5,("spoolss_enumprintprocessors\n"));
8436 * Enumerate the print processors ...
8438 * Just reply with "winprint", to keep NT happy
8439 * and I can use my nice printer checker.
8447 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8449 return WERR_UNKNOWN_LEVEL;
8453 /****************************************************************************
8454 enumprintprocdatatypes level 1.
8455 ****************************************************************************/
8457 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8459 PRINTPROCDATATYPE_1 *info_1=NULL;
8460 WERROR result = WERR_NOMEM;
8462 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8467 init_unistr(&info_1->name, "RAW");
8469 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8471 if (*needed > offered) {
8472 result = WERR_INSUFFICIENT_BUFFER;
8476 if (!rpcbuf_alloc_size(buffer, *needed)) {
8477 result = WERR_NOMEM;
8481 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8486 if ( !W_ERROR_IS_OK(result) )
8492 /****************************************************************************
8493 ****************************************************************************/
8495 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8497 uint32 level = q_u->level;
8498 RPC_BUFFER *buffer = NULL;
8499 uint32 offered = q_u->offered;
8500 uint32 *needed = &r_u->needed;
8501 uint32 *returned = &r_u->returned;
8503 /* that's an [in out] buffer */
8505 if ( q_u->buffer ) {
8506 rpcbuf_move(q_u->buffer, &r_u->buffer);
8507 buffer = r_u->buffer;
8510 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8517 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8519 return WERR_UNKNOWN_LEVEL;
8523 /****************************************************************************
8524 enumprintmonitors level 1.
8525 ****************************************************************************/
8527 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8529 PRINTMONITOR_1 *info_1;
8530 WERROR result = WERR_OK;
8533 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8538 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8539 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8541 for ( i=0; i<*returned; i++ ) {
8542 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8545 if (*needed > offered) {
8546 result = WERR_INSUFFICIENT_BUFFER;
8550 if (!rpcbuf_alloc_size(buffer, *needed)) {
8551 result = WERR_NOMEM;
8555 for ( i=0; i<*returned; i++ ) {
8556 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8562 if ( !W_ERROR_IS_OK(result) )
8568 /****************************************************************************
8569 enumprintmonitors level 2.
8570 ****************************************************************************/
8572 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8574 PRINTMONITOR_2 *info_2;
8575 WERROR result = WERR_OK;
8578 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8583 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8584 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8585 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8587 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8588 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8589 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8591 for ( i=0; i<*returned; i++ ) {
8592 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8595 if (*needed > offered) {
8596 result = WERR_INSUFFICIENT_BUFFER;
8600 if (!rpcbuf_alloc_size(buffer, *needed)) {
8601 result = WERR_NOMEM;
8605 for ( i=0; i<*returned; i++ ) {
8606 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8612 if ( !W_ERROR_IS_OK(result) )
8618 /****************************************************************************
8619 ****************************************************************************/
8621 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8623 uint32 level = q_u->level;
8624 RPC_BUFFER *buffer = NULL;
8625 uint32 offered = q_u->offered;
8626 uint32 *needed = &r_u->needed;
8627 uint32 *returned = &r_u->returned;
8629 /* that's an [in out] buffer */
8631 if ( q_u->buffer ) {
8632 rpcbuf_move(q_u->buffer, &r_u->buffer);
8633 buffer = r_u->buffer;
8636 DEBUG(5,("spoolss_enumprintmonitors\n"));
8639 * Enumerate the print monitors ...
8641 * Just reply with "Local Port", to keep NT happy
8642 * and I can use my nice printer checker.
8650 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8652 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8654 return WERR_UNKNOWN_LEVEL;
8658 /****************************************************************************
8659 ****************************************************************************/
8661 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8662 NT_PRINTER_INFO_LEVEL *ntprinter,
8663 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8668 JOB_INFO_1 *info_1=NULL;
8669 WERROR result = WERR_OK;
8671 info_1=SMB_MALLOC_P(JOB_INFO_1);
8673 if (info_1 == NULL) {
8677 for (i=0; i<count && found==False; i++) {
8678 if ((*queue)[i].job==(int)jobid)
8684 /* NT treats not found as bad param... yet another bad choice */
8685 return WERR_INVALID_PARAM;
8688 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8690 *needed += spoolss_size_job_info_1(info_1);
8692 if (*needed > offered) {
8693 result = WERR_INSUFFICIENT_BUFFER;
8697 if (!rpcbuf_alloc_size(buffer, *needed)) {
8698 result = WERR_NOMEM;
8702 smb_io_job_info_1("", buffer, info_1, 0);
8710 /****************************************************************************
8711 ****************************************************************************/
8713 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8714 NT_PRINTER_INFO_LEVEL *ntprinter,
8715 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8722 DEVICEMODE *devmode = NULL;
8723 NT_DEVICEMODE *nt_devmode = NULL;
8725 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8728 ZERO_STRUCTP(info_2);
8730 for ( i=0; i<count && found==False; i++ )
8732 if ((*queue)[i].job == (int)jobid)
8737 /* NT treats not found as bad param... yet another bad
8739 result = WERR_INVALID_PARAM;
8744 * if the print job does not have a DEVMODE associated with it,
8745 * just use the one for the printer. A NULL devicemode is not
8746 * a failure condition
8749 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8750 devmode = construct_dev_mode(snum);
8752 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8753 ZERO_STRUCTP( devmode );
8754 convert_nt_devicemode( devmode, nt_devmode );
8758 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8760 *needed += spoolss_size_job_info_2(info_2);
8762 if (*needed > offered) {
8763 result = WERR_INSUFFICIENT_BUFFER;
8767 if (!rpcbuf_alloc_size(buffer, *needed)) {
8768 result = WERR_NOMEM;
8772 smb_io_job_info_2("", buffer, info_2, 0);
8777 /* Cleanup allocated memory */
8779 free_job_info_2(info_2); /* Also frees devmode */
8785 /****************************************************************************
8786 ****************************************************************************/
8788 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8790 POLICY_HND *handle = &q_u->handle;
8791 uint32 jobid = q_u->jobid;
8792 uint32 level = q_u->level;
8793 RPC_BUFFER *buffer = NULL;
8794 uint32 offered = q_u->offered;
8795 uint32 *needed = &r_u->needed;
8796 WERROR wstatus = WERR_OK;
8797 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8800 print_queue_struct *queue = NULL;
8801 print_status_struct prt_status;
8803 /* that's an [in out] buffer */
8805 if ( q_u->buffer ) {
8806 rpcbuf_move(q_u->buffer, &r_u->buffer);
8807 buffer = r_u->buffer;
8810 DEBUG(5,("spoolss_getjob\n"));
8814 if (!get_printer_snum(p, handle, &snum))
8817 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8818 if ( !W_ERROR_IS_OK(wstatus) )
8821 count = print_queue_status(snum, &queue, &prt_status);
8823 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8824 count, prt_status.status, prt_status.message));
8828 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8829 buffer, offered, needed);
8832 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8833 buffer, offered, needed);
8836 wstatus = WERR_UNKNOWN_LEVEL;
8841 free_a_printer( &ntprinter, 2 );
8846 /********************************************************************
8847 spoolss_getprinterdataex
8849 From MSDN documentation of GetPrinterDataEx: pass request
8850 to GetPrinterData if key is "PrinterDriverData".
8851 ********************************************************************/
8853 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8855 POLICY_HND *handle = &q_u->handle;
8856 uint32 in_size = q_u->size;
8857 uint32 *type = &r_u->type;
8858 uint32 *out_size = &r_u->size;
8859 uint8 **data = &r_u->data;
8860 uint32 *needed = &r_u->needed;
8861 fstring keyname, valuename;
8863 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8865 NT_PRINTER_INFO_LEVEL *printer = NULL;
8867 WERROR status = WERR_OK;
8869 DEBUG(4,("_spoolss_getprinterdataex\n"));
8871 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8872 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8874 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8875 keyname, valuename));
8877 /* in case of problem, return some default values */
8881 *out_size = in_size;
8884 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8885 status = WERR_BADFID;
8889 /* Is the handle to a printer or to the server? */
8891 if (Printer->printer_type == SPLHND_SERVER) {
8892 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8893 status = WERR_INVALID_PARAM;
8897 if ( !get_printer_snum(p,handle, &snum) )
8900 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8901 if ( !W_ERROR_IS_OK(status) )
8904 /* check to see if the keyname is valid */
8905 if ( !strlen(keyname) ) {
8906 status = WERR_INVALID_PARAM;
8910 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8911 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8912 free_a_printer( &printer, 2 );
8913 status = WERR_BADFILE;
8917 /* When given a new keyname, we should just create it */
8919 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8921 if (*needed > *out_size)
8922 status = WERR_MORE_DATA;
8925 if ( !W_ERROR_IS_OK(status) )
8927 DEBUG(5, ("error: allocating %d\n", *out_size));
8929 /* reply this param doesn't exist */
8933 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8934 status = WERR_NOMEM;
8944 free_a_printer( &printer, 2 );
8949 /********************************************************************
8950 * spoolss_setprinterdataex
8951 ********************************************************************/
8953 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8955 POLICY_HND *handle = &q_u->handle;
8956 uint32 type = q_u->type;
8957 uint8 *data = q_u->data;
8958 uint32 real_len = q_u->real_len;
8960 NT_PRINTER_INFO_LEVEL *printer = NULL;
8962 WERROR status = WERR_OK;
8963 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8968 DEBUG(4,("_spoolss_setprinterdataex\n"));
8970 /* From MSDN documentation of SetPrinterDataEx: pass request to
8971 SetPrinterData if key is "PrinterDriverData" */
8974 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8978 if ( Printer->printer_type == SPLHND_SERVER ) {
8979 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8980 return WERR_INVALID_PARAM;
8983 if ( !get_printer_snum(p,handle, &snum) )
8987 * Access check : NT returns "access denied" if you make a
8988 * SetPrinterData call without the necessary privildge.
8989 * we were originally returning OK if nothing changed
8990 * which made Win2k issue **a lot** of SetPrinterData
8991 * when connecting to a printer --jerry
8994 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8996 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8997 return WERR_ACCESS_DENIED;
9000 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9001 if (!W_ERROR_IS_OK(status))
9004 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9005 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9007 /* check for OID in valuename */
9009 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9015 /* save the registry data */
9017 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9019 if ( W_ERROR_IS_OK(status) )
9021 /* save the OID if one was specified */
9023 fstrcat( keyname, "\\" );
9024 fstrcat( keyname, SPOOL_OID_KEY );
9027 * I'm not checking the status here on purpose. Don't know
9028 * if this is right, but I'm returning the status from the
9029 * previous set_printer_dataex() call. I have no idea if
9030 * this is right. --jerry
9033 set_printer_dataex( printer, keyname, valuename,
9034 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9037 status = mod_a_printer(printer, 2);
9040 free_a_printer(&printer, 2);
9046 /********************************************************************
9047 * spoolss_deleteprinterdataex
9048 ********************************************************************/
9050 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9052 POLICY_HND *handle = &q_u->handle;
9053 UNISTR2 *value = &q_u->valuename;
9054 UNISTR2 *key = &q_u->keyname;
9056 NT_PRINTER_INFO_LEVEL *printer = NULL;
9058 WERROR status = WERR_OK;
9059 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9060 pstring valuename, keyname;
9062 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9065 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9069 if (!get_printer_snum(p, handle, &snum))
9072 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9073 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9074 return WERR_ACCESS_DENIED;
9077 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9078 if (!W_ERROR_IS_OK(status))
9081 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9082 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9084 status = delete_printer_dataex( printer, keyname, valuename );
9086 if ( W_ERROR_IS_OK(status) )
9087 mod_a_printer( printer, 2 );
9089 free_a_printer(&printer, 2);
9094 /********************************************************************
9095 * spoolss_enumprinterkey
9096 ********************************************************************/
9099 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9102 fstring *keynames = NULL;
9103 uint16 *enumkeys = NULL;
9106 POLICY_HND *handle = &q_u->handle;
9107 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9108 NT_PRINTER_DATA *data;
9109 NT_PRINTER_INFO_LEVEL *printer = NULL;
9111 WERROR status = WERR_BADFILE;
9114 DEBUG(4,("_spoolss_enumprinterkey\n"));
9117 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9121 if ( !get_printer_snum(p,handle, &snum) )
9124 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9125 if (!W_ERROR_IS_OK(status))
9128 /* get the list of subkey names */
9130 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9131 data = printer->info_2->data;
9133 num_keys = get_printer_subkeys( data, key, &keynames );
9135 if ( num_keys == -1 ) {
9136 status = WERR_BADFILE;
9140 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9142 r_u->needed = printerkey_len*2;
9144 if ( q_u->size < r_u->needed ) {
9145 status = WERR_MORE_DATA;
9149 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9150 status = WERR_NOMEM;
9156 if ( q_u->size < r_u->needed )
9157 status = WERR_MORE_DATA;
9160 free_a_printer( &printer, 2 );
9161 SAFE_FREE( keynames );
9166 /********************************************************************
9167 * spoolss_deleteprinterkey
9168 ********************************************************************/
9170 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9172 POLICY_HND *handle = &q_u->handle;
9173 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9175 NT_PRINTER_INFO_LEVEL *printer = NULL;
9179 DEBUG(5,("spoolss_deleteprinterkey\n"));
9182 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9186 /* if keyname == NULL, return error */
9188 if ( !q_u->keyname.buffer )
9189 return WERR_INVALID_PARAM;
9191 if (!get_printer_snum(p, handle, &snum))
9194 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9195 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9196 return WERR_ACCESS_DENIED;
9199 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9200 if (!W_ERROR_IS_OK(status))
9203 /* delete the key and all subneys */
9205 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9207 status = delete_all_printer_data( printer->info_2, key );
9209 if ( W_ERROR_IS_OK(status) )
9210 status = mod_a_printer(printer, 2);
9212 free_a_printer( &printer, 2 );
9218 /********************************************************************
9219 * spoolss_enumprinterdataex
9220 ********************************************************************/
9222 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9224 POLICY_HND *handle = &q_u->handle;
9225 uint32 in_size = q_u->size;
9228 NT_PRINTER_INFO_LEVEL *printer = NULL;
9229 PRINTER_ENUM_VALUES *enum_values = NULL;
9230 NT_PRINTER_DATA *p_data;
9232 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9237 REGISTRY_VALUE *val;
9242 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9245 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9250 * first check for a keyname of NULL or "". Win2k seems to send
9251 * this a lot and we should send back WERR_INVALID_PARAM
9252 * no need to spend time looking up the printer in this case.
9256 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9257 if ( !strlen(key) ) {
9258 result = WERR_INVALID_PARAM;
9262 /* get the printer off of disk */
9264 if (!get_printer_snum(p,handle, &snum))
9267 ZERO_STRUCT(printer);
9268 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9269 if (!W_ERROR_IS_OK(result))
9272 /* now look for a match on the key name */
9274 p_data = printer->info_2->data;
9276 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9277 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9279 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9280 result = WERR_INVALID_PARAM;
9287 /* allocate the memory for the array of pointers -- if necessary */
9289 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9292 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9294 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9295 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9296 result = WERR_NOMEM;
9300 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9304 * loop through all params and build the array to pass
9305 * back to the client
9308 for ( i=0; i<num_entries; i++ )
9310 /* lookup the registry value */
9312 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9313 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9317 value_name = regval_name( val );
9318 init_unistr( &enum_values[i].valuename, value_name );
9319 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9320 enum_values[i].type = regval_type( val );
9322 data_len = regval_size( val );
9324 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9326 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9328 result = WERR_NOMEM;
9332 enum_values[i].data_len = data_len;
9334 /* keep track of the size of the array in bytes */
9336 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9339 /* housekeeping information in the reply */
9341 r_u->needed = needed;
9342 r_u->returned = num_entries;
9344 if (needed > in_size) {
9345 result = WERR_MORE_DATA;
9349 /* copy data into the reply */
9351 r_u->ctr.size = r_u->needed;
9352 r_u->ctr.size_of_array = r_u->returned;
9353 r_u->ctr.values = enum_values;
9359 free_a_printer(&printer, 2);
9364 /****************************************************************************
9365 ****************************************************************************/
9367 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9369 init_unistr(&info->name, name);
9372 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9373 UNISTR2 *environment,
9380 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9381 WERROR result = WERR_OK;
9383 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9385 if (!get_short_archi(long_archi))
9386 return WERR_INVALID_ENVIRONMENT;
9388 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9391 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9393 fill_printprocessordirectory_1(info, path);
9395 *needed += spoolss_size_printprocessordirectory_info_1(info);
9397 if (*needed > offered) {
9398 result = WERR_INSUFFICIENT_BUFFER;
9402 if (!rpcbuf_alloc_size(buffer, *needed)) {
9403 result = WERR_INSUFFICIENT_BUFFER;
9407 smb_io_printprocessordirectory_1("", buffer, info, 0);
9415 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9417 uint32 level = q_u->level;
9418 RPC_BUFFER *buffer = NULL;
9419 uint32 offered = q_u->offered;
9420 uint32 *needed = &r_u->needed;
9423 /* that's an [in out] buffer */
9425 if ( q_u->buffer ) {
9426 rpcbuf_move(q_u->buffer, &r_u->buffer);
9427 buffer = r_u->buffer;
9430 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9436 result = getprintprocessordirectory_level_1
9437 (&q_u->name, &q_u->environment, buffer, offered, needed);
9440 result = WERR_UNKNOWN_LEVEL;
9446 /*******************************************************************
9447 Streams the monitor UI DLL name in UNICODE
9448 *******************************************************************/
9450 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9451 RPC_BUFFER *out, uint32 *needed )
9453 const char *dllname = "tcpmonui.dll";
9455 *needed = (strlen(dllname)+1) * 2;
9457 if ( rpcbuf_get_size(out) < *needed ) {
9458 return WERR_INSUFFICIENT_BUFFER;
9461 if ( !make_monitorui_buf( out, dllname ) ) {
9468 /*******************************************************************
9469 Create a new TCP/IP port
9470 *******************************************************************/
9472 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9473 RPC_BUFFER *out, uint32 *needed )
9475 NT_PORT_DATA_1 port1;
9478 ZERO_STRUCT( port1 );
9480 /* convert to our internal port data structure */
9482 if ( !convert_port_data_1( &port1, in ) ) {
9486 /* create the device URI and call the add_port_hook() */
9488 switch ( port1.protocol ) {
9489 case PORT_PROTOCOL_DIRECT:
9490 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9493 case PORT_PROTOCOL_LPR:
9494 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9498 return WERR_UNKNOWN_PORT;
9501 return add_port_hook( token, port1.name, device_uri );
9504 /*******************************************************************
9505 *******************************************************************/
9507 struct xcv_api_table xcvtcp_cmds[] = {
9508 { "MonitorUI", xcvtcp_monitorui },
9509 { "AddPort", xcvtcp_addport},
9513 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9514 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9519 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9521 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9522 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9523 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9526 return WERR_BADFUNC;
9529 /*******************************************************************
9530 *******************************************************************/
9531 #if 0 /* don't support management using the "Local Port" monitor */
9533 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9534 RPC_BUFFER *out, uint32 *needed )
9536 const char *dllname = "localui.dll";
9538 *needed = (strlen(dllname)+1) * 2;
9540 if ( rpcbuf_get_size(out) < *needed ) {
9541 return WERR_INSUFFICIENT_BUFFER;
9544 if ( !make_monitorui_buf( out, dllname )) {
9551 /*******************************************************************
9552 *******************************************************************/
9554 struct xcv_api_table xcvlocal_cmds[] = {
9555 { "MonitorUI", xcvlocal_monitorui },
9559 struct xcv_api_table xcvlocal_cmds[] = {
9566 /*******************************************************************
9567 *******************************************************************/
9569 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9570 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9575 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9577 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9578 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9579 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9581 return WERR_BADFUNC;
9584 /*******************************************************************
9585 *******************************************************************/
9587 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9589 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9593 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9597 /* Has to be a handle to the TCP/IP port monitor */
9599 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9600 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9604 /* requires administrative access to the server */
9606 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9607 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9608 return WERR_ACCESS_DENIED;
9611 /* Get the command name. There's numerous commands supported by the
9612 TCPMON interface. */
9614 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9615 q_u->dataname.uni_str_len*2, 0);
9617 /* Allocate the outgoing buffer */
9619 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9621 switch ( Printer->printer_type ) {
9622 case SPLHND_PORTMON_TCP:
9623 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9624 &q_u->indata, &r_u->outdata, &r_u->needed );
9625 case SPLHND_PORTMON_LOCAL:
9626 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9627 &q_u->indata, &r_u->outdata, &r_u->needed );
9630 return WERR_INVALID_PRINT_MONITOR;