2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 extern userdom_struct current_user_info;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 const char *long_archi;
45 const char *short_archi;
49 static Printer_entry *printers_list;
51 typedef struct _counter_printer_0 {
52 struct _counter_printer_0 *next;
53 struct _counter_printer_0 *prev;
59 static counter_printer_0 *counter_list;
61 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
62 static uint32 smb_connections=0;
65 /* in printing/nt_printing.c */
67 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
69 /* API table for Xcv Monitor functions */
71 struct xcv_api_table {
73 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
77 /* translate between internal status numbers and NT status numbers */
78 static int nt_printj_status(int v)
84 return JOB_STATUS_PAUSED;
86 return JOB_STATUS_SPOOLING;
88 return JOB_STATUS_PRINTING;
90 return JOB_STATUS_ERROR;
92 return JOB_STATUS_DELETING;
94 return JOB_STATUS_OFFLINE;
96 return JOB_STATUS_PAPEROUT;
98 return JOB_STATUS_PRINTED;
100 return JOB_STATUS_DELETED;
102 return JOB_STATUS_BLOCKED;
103 case LPQ_USER_INTERVENTION:
104 return JOB_STATUS_USER_INTERVENTION;
109 static int nt_printq_status(int v)
113 return PRINTER_STATUS_PAUSED;
122 /****************************************************************************
123 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
124 ****************************************************************************/
126 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
131 SAFE_FREE((*pp)->ctr.type);
135 /***************************************************************************
136 Disconnect from the client
137 ****************************************************************************/
139 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
144 * Tell the specific printing tdb we no longer want messages for this printer
145 * by deregistering our PID.
148 if (!print_notify_deregister_pid(snum))
149 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
151 /* weird if the test succeds !!! */
152 if (smb_connections==0) {
153 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
157 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
159 if (!W_ERROR_IS_OK(result))
160 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
161 dos_errstr(result)));
163 /* if it's the last connection, deconnect the IPC$ share */
164 if (smb_connections==1) {
166 cli_shutdown( notify_cli_pipe->cli );
167 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
169 message_deregister(MSG_PRINTER_NOTIFY2);
171 /* Tell the connections db we're no longer interested in
172 * printer notify messages. */
174 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
180 /****************************************************************************
181 Functions to free a printer entry datastruct.
182 ****************************************************************************/
184 static void free_printer_entry(void *ptr)
186 Printer_entry *Printer = (Printer_entry *)ptr;
188 if (Printer->notify.client_connected==True) {
191 if ( Printer->printer_type == SPLHND_SERVER) {
193 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
194 } else if (Printer->printer_type == SPLHND_PRINTER) {
195 snum = print_queue_snum(Printer->sharename);
197 srv_spoolss_replycloseprinter(snum,
198 &Printer->notify.client_hnd);
202 Printer->notify.flags=0;
203 Printer->notify.options=0;
204 Printer->notify.localmachine[0]='\0';
205 Printer->notify.printerlocal=0;
206 free_spool_notify_option(&Printer->notify.option);
207 Printer->notify.option=NULL;
208 Printer->notify.client_connected=False;
210 free_nt_devicemode( &Printer->nt_devmode );
211 free_a_printer( &Printer->printer_info, 2 );
213 talloc_destroy( Printer->ctx );
215 /* Remove from the internal list. */
216 DLIST_REMOVE(printers_list, Printer);
221 /****************************************************************************
222 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
223 ****************************************************************************/
225 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
227 SPOOL_NOTIFY_OPTION *new_sp = NULL;
232 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
239 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
241 if (!new_sp->ctr.type) {
250 /****************************************************************************
251 find printer index by handle
252 ****************************************************************************/
254 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
256 Printer_entry *find_printer = NULL;
258 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
259 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
266 /****************************************************************************
267 Close printer index by handle.
268 ****************************************************************************/
270 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
272 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
275 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
279 close_policy_hnd(p, hnd);
284 /****************************************************************************
285 Delete a printer given a handle.
286 ****************************************************************************/
287 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
289 char *cmd = lp_deleteprinter_cmd();
292 SE_PRIV se_printop = SE_PRINT_OPERATOR;
293 BOOL is_print_op = False;
295 /* can't fail if we don't try */
300 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
303 is_print_op = user_has_privileges( token, &se_printop );
305 DEBUG(10,("Running [%s]\n", command));
307 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
312 if ( (ret = smbrun(command, NULL)) == 0 ) {
313 /* Tell everyone we updated smb.conf. */
314 message_send_all(smbd_messaging_context(),
315 MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
321 /********** END SePrintOperatorPrivlege BLOCK **********/
323 DEBUGADD(10,("returned [%d]\n", ret));
326 return WERR_BADFID; /* What to return here? */
328 /* go ahead and re-read the services immediately */
329 reload_services( False );
331 if ( share_defined( sharename ) )
332 return WERR_ACCESS_DENIED;
337 /****************************************************************************
338 Delete a printer given a handle.
339 ****************************************************************************/
341 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
343 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
346 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
351 * It turns out that Windows allows delete printer on a handle
352 * opened by an admin user, then used on a pipe handle created
353 * by an anonymous user..... but they're working on security.... riiight !
357 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
358 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
359 return WERR_ACCESS_DENIED;
362 /* this does not need a become root since the access check has been
363 done on the handle already */
365 if (del_a_printer( Printer->sharename ) != 0) {
366 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
370 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
373 /****************************************************************************
374 Return the snum of a printer corresponding to an handle.
375 ****************************************************************************/
377 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
378 struct share_params **params)
380 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
383 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
387 switch (Printer->printer_type) {
389 DEBUG(4,("short name:%s\n", Printer->sharename));
390 *number = print_queue_snum(Printer->sharename);
391 if ((*number != -1) && (params != NULL)) {
392 *params = get_share_params(tmp_talloc_ctx(),
394 if (*params == NULL) {
398 return (*number != -1);
406 /****************************************************************************
407 Set printer handle type.
408 Check if it's \\server or \\server\printer
409 ****************************************************************************/
411 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
413 DEBUG(3,("Setting printer type=%s\n", handlename));
415 if ( strlen(handlename) < 3 ) {
416 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
420 /* it's a print server */
421 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
422 DEBUGADD(4,("Printer is a print server\n"));
423 Printer->printer_type = SPLHND_SERVER;
425 /* it's a printer (set_printer_hnd_name() will handle port monitors */
427 DEBUGADD(4,("Printer is a printer\n"));
428 Printer->printer_type = SPLHND_PRINTER;
434 /****************************************************************************
435 Set printer handle name.. Accept names like \\server, \\server\printer,
436 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
437 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
438 XcvDataPort() interface.
439 ****************************************************************************/
441 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
444 int n_services=lp_numservices();
445 char *aprinter, *printername;
446 const char *servername;
449 NT_PRINTER_INFO_LEVEL *printer = NULL;
452 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
454 aprinter = handlename;
455 if ( *handlename == '\\' ) {
456 servername = handlename + 2;
457 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
466 /* save the servername to fill in replies on this handle */
468 if ( !is_myname_or_ipaddr( servername ) )
471 fstrcpy( Printer->servername, servername );
473 if ( Printer->printer_type == SPLHND_SERVER )
476 if ( Printer->printer_type != SPLHND_PRINTER )
479 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
481 /* check for the Port Monitor Interface */
483 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
484 Printer->printer_type = SPLHND_PORTMON_TCP;
485 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
488 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
489 Printer->printer_type = SPLHND_PORTMON_LOCAL;
490 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
494 /* Search all sharenames first as this is easier than pulling
495 the printer_info_2 off of disk. Don't use find_service() since
496 that calls out to map_username() */
498 /* do another loop to look for printernames */
500 for (snum=0; !found && snum<n_services; snum++) {
502 /* no point going on if this is not a printer */
504 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
507 fstrcpy(sname, lp_servicename(snum));
508 if ( strequal( aprinter, sname ) ) {
513 /* no point looking up the printer object if
514 we aren't allowing printername != sharename */
516 if ( lp_force_printername(snum) )
519 fstrcpy(sname, lp_servicename(snum));
522 result = get_a_printer( NULL, &printer, 2, sname );
523 if ( !W_ERROR_IS_OK(result) ) {
524 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
525 sname, dos_errstr(result)));
529 /* printername is always returned as \\server\printername */
530 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
531 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
532 printer->info_2->printername));
533 free_a_printer( &printer, 2);
539 if ( strequal(printername, aprinter) ) {
540 free_a_printer( &printer, 2);
545 DEBUGADD(10, ("printername: %s\n", printername));
547 free_a_printer( &printer, 2);
550 free_a_printer( &printer, 2);
553 DEBUGADD(4,("Printer not found\n"));
557 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
559 fstrcpy(Printer->sharename, sname);
564 /****************************************************************************
565 Find first available printer slot. creates a printer handle for you.
566 ****************************************************************************/
568 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
570 Printer_entry *new_printer;
572 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
574 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
577 ZERO_STRUCTP(new_printer);
579 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
580 SAFE_FREE(new_printer);
584 /* Add to the internal list. */
585 DLIST_ADD(printers_list, new_printer);
587 new_printer->notify.option=NULL;
589 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
590 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
591 close_printer_handle(p, hnd);
595 if (!set_printer_hnd_printertype(new_printer, name)) {
596 close_printer_handle(p, hnd);
600 if (!set_printer_hnd_name(new_printer, name)) {
601 close_printer_handle(p, hnd);
605 new_printer->access_granted = access_granted;
607 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
612 /***************************************************************************
613 check to see if the client motify handle is monitoring the notification
614 given by (notify_type, notify_field).
615 **************************************************************************/
617 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
623 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
626 SPOOL_NOTIFY_OPTION *option = p->notify.option;
630 * Flags should always be zero when the change notify
631 * is registered by the client's spooler. A user Win32 app
632 * might use the flags though instead of the NOTIFY_OPTION_INFO
641 return is_monitoring_event_flags(
642 p->notify.flags, notify_type, notify_field);
644 for (i = 0; i < option->count; i++) {
646 /* Check match for notify_type */
648 if (option->ctr.type[i].type != notify_type)
651 /* Check match for field */
653 for (j = 0; j < option->ctr.type[i].count; j++) {
654 if (option->ctr.type[i].fields[j] == notify_field) {
660 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
661 p->servername, p->sharename, notify_type, notify_field));
666 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
668 static void notify_one_value(struct spoolss_notify_msg *msg,
669 SPOOL_NOTIFY_INFO_DATA *data,
672 data->notify_data.value[0] = msg->notify.value[0];
673 data->notify_data.value[1] = 0;
676 static void notify_string(struct spoolss_notify_msg *msg,
677 SPOOL_NOTIFY_INFO_DATA *data,
682 /* The length of the message includes the trailing \0 */
684 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
686 data->notify_data.data.length = msg->len * 2;
687 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
689 if (!data->notify_data.data.string) {
690 data->notify_data.data.length = 0;
694 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
697 static void notify_system_time(struct spoolss_notify_msg *msg,
698 SPOOL_NOTIFY_INFO_DATA *data,
704 if (msg->len != sizeof(time_t)) {
705 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
710 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
711 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
715 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
716 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
721 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
726 data->notify_data.data.length = prs_offset(&ps);
727 if (prs_offset(&ps)) {
728 data->notify_data.data.string = (uint16 *)
729 TALLOC(mem_ctx, prs_offset(&ps));
730 if (!data->notify_data.data.string) {
734 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
736 data->notify_data.data.string = NULL;
742 struct notify2_message_table {
744 void (*fn)(struct spoolss_notify_msg *msg,
745 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
748 static struct notify2_message_table printer_notify_table[] = {
749 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
750 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
751 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
752 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
753 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
754 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
755 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
756 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
757 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
758 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
759 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
760 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
761 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
762 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
763 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
764 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
765 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
766 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
767 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
770 static struct notify2_message_table job_notify_table[] = {
771 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
772 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
773 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
774 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
775 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
776 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
777 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
778 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
779 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
780 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
781 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
782 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
783 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
784 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
785 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
786 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
787 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
788 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
789 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
790 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
791 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
792 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
793 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
794 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
798 /***********************************************************************
799 Allocate talloc context for container object
800 **********************************************************************/
802 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
807 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
812 /***********************************************************************
813 release all allocated memory and zero out structure
814 **********************************************************************/
816 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
822 talloc_destroy(ctr->ctx);
829 /***********************************************************************
830 **********************************************************************/
832 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
840 /***********************************************************************
841 **********************************************************************/
843 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
845 if ( !ctr || !ctr->msg_groups )
848 if ( idx >= ctr->num_groups )
851 return &ctr->msg_groups[idx];
855 /***********************************************************************
856 How many groups of change messages do we have ?
857 **********************************************************************/
859 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
864 return ctr->num_groups;
867 /***********************************************************************
868 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
869 **********************************************************************/
871 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
873 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
874 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
875 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
881 /* loop over all groups looking for a matching printer name */
883 for ( i=0; i<ctr->num_groups; i++ ) {
884 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
888 /* add a new group? */
890 if ( i == ctr->num_groups ) {
893 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
894 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
897 ctr->msg_groups = groups;
899 /* clear the new entry and set the printer name */
901 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
902 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
905 /* add the change messages; 'i' is the correct index now regardless */
907 msg_grp = &ctr->msg_groups[i];
911 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
912 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
915 msg_grp->msgs = msg_list;
917 new_slot = msg_grp->num_msgs-1;
918 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
920 /* need to allocate own copy of data */
923 msg_grp->msgs[new_slot].notify.data = (char *)
924 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
926 return ctr->num_groups;
929 /***********************************************************************
930 Send a change notication message on all handles which have a call
932 **********************************************************************/
934 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
937 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
938 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
939 SPOOLSS_NOTIFY_MSG *messages;
940 int sending_msg_count;
943 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
947 messages = msg_group->msgs;
950 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
954 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
956 /* loop over all printers */
958 for (p = printers_list; p; p = p->next) {
959 SPOOL_NOTIFY_INFO_DATA *data;
964 /* Is there notification on this handle? */
966 if ( !p->notify.client_connected )
969 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
971 /* For this printer? Print servers always receive
974 if ( ( p->printer_type == SPLHND_PRINTER ) &&
975 ( !strequal(msg_group->printername, p->sharename) ) )
978 DEBUG(10,("Our printer\n"));
980 /* allocate the max entries possible */
982 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
989 /* build the array of change notifications */
991 sending_msg_count = 0;
993 for ( i=0; i<msg_group->num_msgs; i++ ) {
994 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
996 /* Are we monitoring this event? */
998 if (!is_monitoring_event(p, msg->type, msg->field))
1001 sending_msg_count++;
1004 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1005 msg->type, msg->field, p->sharename));
1008 * if the is a printer notification handle and not a job notification
1009 * type, then set the id to 0. Other wise just use what was specified
1012 * When registering change notification on a print server handle
1013 * we always need to send back the id (snum) matching the printer
1014 * for which the change took place. For change notify registered
1015 * on a printer handle, this does not matter and the id should be 0.
1020 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1026 /* Convert unix jobid to smb jobid */
1028 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1029 id = sysjob_to_jobid(msg->id);
1032 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1037 construct_info_data( &data[data_len], msg->type, msg->field, id );
1040 case PRINTER_NOTIFY_TYPE:
1041 if ( printer_notify_table[msg->field].fn )
1042 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1045 case JOB_NOTIFY_TYPE:
1046 if ( job_notify_table[msg->field].fn )
1047 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1051 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1058 if ( sending_msg_count ) {
1059 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1060 data_len, data, p->notify.change, 0 );
1065 DEBUG(8,("send_notify2_changes: Exit...\n"));
1069 /***********************************************************************
1070 **********************************************************************/
1072 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1075 uint32 tv_sec, tv_usec;
1078 /* Unpack message */
1080 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1083 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1085 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1088 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1089 &msg->notify.value[0], &msg->notify.value[1]);
1091 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1092 &msg->len, &msg->notify.data);
1094 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1095 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1097 tv->tv_sec = tv_sec;
1098 tv->tv_usec = tv_usec;
1101 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1102 msg->notify.value[1]));
1104 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1109 /********************************************************************
1110 Receive a notify2 message list
1111 ********************************************************************/
1113 static void receive_notify2_message_list(int msg_type, struct server_id src,
1114 void *msg, size_t len,
1117 size_t msg_count, i;
1118 char *buf = (char *)msg;
1121 SPOOLSS_NOTIFY_MSG notify;
1122 SPOOLSS_NOTIFY_MSG_CTR messages;
1126 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1130 msg_count = IVAL(buf, 0);
1133 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1135 if (msg_count == 0) {
1136 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1140 /* initialize the container */
1142 ZERO_STRUCT( messages );
1143 notify_msg_ctr_init( &messages );
1146 * build message groups for each printer identified
1147 * in a change_notify msg. Remember that a PCN message
1148 * includes the handle returned for the srv_spoolss_replyopenprinter()
1149 * call. Therefore messages are grouped according to printer handle.
1152 for ( i=0; i<msg_count; i++ ) {
1153 struct timeval msg_tv;
1155 if (msg_ptr + 4 - buf > len) {
1156 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1160 msg_len = IVAL(msg_ptr,0);
1163 if (msg_ptr + msg_len - buf > len) {
1164 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1168 /* unpack messages */
1170 ZERO_STRUCT( notify );
1171 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1174 /* add to correct list in container */
1176 notify_msg_ctr_addmsg( &messages, ¬ify );
1178 /* free memory that might have been allocated by notify2_unpack_msg() */
1180 if ( notify.len != 0 )
1181 SAFE_FREE( notify.notify.data );
1184 /* process each group of messages */
1186 num_groups = notify_msg_ctr_numgroups( &messages );
1187 for ( i=0; i<num_groups; i++ )
1188 send_notify2_changes( &messages, i );
1193 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1195 notify_msg_ctr_destroy( &messages );
1200 /********************************************************************
1201 Send a message to ourself about new driver being installed
1202 so we can upgrade the information for each printer bound to this
1204 ********************************************************************/
1206 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1208 int len = strlen(drivername);
1213 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1216 messaging_send_buf(smbd_messaging_context(), procid_self(),
1217 MSG_PRINTER_DRVUPGRADE,
1218 (uint8 *)drivername, len+1);
1223 /**********************************************************************
1224 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1225 over all printers, upgrading ones as necessary
1226 **********************************************************************/
1228 void do_drv_upgrade_printer(struct messaging_context *msg,
1231 struct server_id server_id,
1236 int n_services = lp_numservices();
1239 len = MIN(data->length,sizeof(drivername)-1);
1240 strncpy(drivername, (const char *)data->data, len);
1242 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1244 /* Iterate the printer list */
1246 for (snum=0; snum<n_services; snum++)
1248 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1251 NT_PRINTER_INFO_LEVEL *printer = NULL;
1253 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1254 if (!W_ERROR_IS_OK(result))
1257 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1259 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1261 /* all we care about currently is the change_id */
1263 result = mod_a_printer(printer, 2);
1264 if (!W_ERROR_IS_OK(result)) {
1265 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1266 dos_errstr(result)));
1270 free_a_printer(&printer, 2);
1277 /********************************************************************
1278 Update the cache for all printq's with a registered client
1280 ********************************************************************/
1282 void update_monitored_printq_cache( void )
1284 Printer_entry *printer = printers_list;
1287 /* loop through all printers and update the cache where
1288 client_connected == True */
1291 if ( (printer->printer_type == SPLHND_PRINTER)
1292 && printer->notify.client_connected )
1294 snum = print_queue_snum(printer->sharename);
1295 print_queue_status( snum, NULL, NULL );
1298 printer = printer->next;
1303 /********************************************************************
1304 Send a message to ourself about new driver being installed
1305 so we can upgrade the information for each printer bound to this
1307 ********************************************************************/
1309 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1311 int len = strlen(drivername);
1316 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1319 messaging_send_buf(smbd_messaging_context(), procid_self(),
1320 MSG_PRINTERDATA_INIT_RESET,
1321 (uint8 *)drivername, len+1);
1326 /**********************************************************************
1327 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1328 over all printers, resetting printer data as neessary
1329 **********************************************************************/
1331 void reset_all_printerdata(struct messaging_context *msg,
1334 struct server_id server_id,
1339 int n_services = lp_numservices();
1342 len = MIN( data->length, sizeof(drivername)-1 );
1343 strncpy( drivername, (const char *)data->data, len );
1345 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1347 /* Iterate the printer list */
1349 for ( snum=0; snum<n_services; snum++ )
1351 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1354 NT_PRINTER_INFO_LEVEL *printer = NULL;
1356 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1357 if ( !W_ERROR_IS_OK(result) )
1361 * if the printer is bound to the driver,
1362 * then reset to the new driver initdata
1365 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1367 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1369 if ( !set_driver_init(printer, 2) ) {
1370 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1371 printer->info_2->printername, printer->info_2->drivername));
1374 result = mod_a_printer( printer, 2 );
1375 if ( !W_ERROR_IS_OK(result) ) {
1376 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1377 get_dos_error_msg(result)));
1381 free_a_printer( &printer, 2 );
1390 /********************************************************************
1391 Copy routines used by convert_to_openprinterex()
1392 *******************************************************************/
1394 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1402 DEBUG (8,("dup_devmode\n"));
1404 /* bulk copy first */
1406 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1410 /* dup the pointer members separately */
1412 len = unistrlen(devmode->devicename.buffer);
1414 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1415 if (!d->devicename.buffer) {
1418 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1423 len = unistrlen(devmode->formname.buffer);
1425 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1426 if (!d->devicename.buffer) {
1429 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1433 if (devmode->driverextra) {
1434 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1435 devmode->driverextra);
1436 if (!d->dev_private) {
1440 d->dev_private = NULL;
1445 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1447 if (!new_ctr || !ctr)
1450 DEBUG(8,("copy_devmode_ctr\n"));
1452 new_ctr->size = ctr->size;
1453 new_ctr->devmode_ptr = ctr->devmode_ptr;
1455 if(ctr->devmode_ptr)
1456 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1459 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1461 if (!new_def || !def)
1464 DEBUG(8,("copy_printer_defaults\n"));
1466 new_def->datatype_ptr = def->datatype_ptr;
1468 if (def->datatype_ptr)
1469 copy_unistr2(&new_def->datatype, &def->datatype);
1471 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1473 new_def->access_required = def->access_required;
1476 /********************************************************************
1477 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1478 * SPOOL_Q_OPEN_PRINTER_EX structure
1479 ********************************************************************/
1481 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1483 if (!q_u_ex || !q_u)
1486 DEBUG(8,("convert_to_openprinterex\n"));
1488 if ( q_u->printername ) {
1489 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1490 if (q_u_ex->printername == NULL)
1492 copy_unistr2(q_u_ex->printername, q_u->printername);
1495 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1500 /********************************************************************
1501 * spoolss_open_printer
1503 * called from the spoolss dispatcher
1504 ********************************************************************/
1506 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1508 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1509 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1514 ZERO_STRUCT(q_u_ex);
1515 ZERO_STRUCT(r_u_ex);
1517 /* convert the OpenPrinter() call to OpenPrinterEx() */
1519 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1520 if (!W_ERROR_IS_OK(r_u_ex.status))
1521 return r_u_ex.status;
1523 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1525 /* convert back to OpenPrinter() */
1527 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1532 /********************************************************************
1533 ********************************************************************/
1535 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1537 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1538 POLICY_HND *handle = &r_u->handle;
1542 Printer_entry *Printer=NULL;
1544 if ( !q_u->printername )
1545 return WERR_INVALID_PRINTER_NAME;
1547 /* some sanity check because you can open a printer or a print server */
1548 /* aka: \\server\printer or \\server */
1550 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1552 DEBUGADD(3,("checking name: %s\n",name));
1554 if (!open_printer_hnd(p, handle, name, 0))
1555 return WERR_INVALID_PRINTER_NAME;
1557 Printer=find_printer_index_by_hnd(p, handle);
1559 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1560 "handle we created for printer %s\n", name ));
1561 close_printer_handle(p,handle);
1562 return WERR_INVALID_PRINTER_NAME;
1566 * First case: the user is opening the print server:
1568 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1569 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1571 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1572 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1573 * or if the user is listed in the smb.conf printer admin parameter.
1575 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1576 * client view printer folder, but does not show the MSAPW.
1578 * Note: this test needs code to check access rights here too. Jeremy
1579 * could you look at this?
1581 * Second case: the user is opening a printer:
1582 * NT doesn't let us connect to a printer if the connecting user
1583 * doesn't have print permission.
1585 * Third case: user is opening a Port Monitor
1586 * access checks same as opening a handle to the print server.
1589 switch (Printer->printer_type )
1592 case SPLHND_PORTMON_TCP:
1593 case SPLHND_PORTMON_LOCAL:
1594 /* Printserver handles use global struct... */
1598 /* Map standard access rights to object specific access rights */
1600 se_map_standard(&printer_default->access_required,
1601 &printserver_std_mapping);
1603 /* Deny any object specific bits that don't apply to print
1604 servers (i.e printer and job specific bits) */
1606 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1608 if (printer_default->access_required &
1609 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1610 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1611 close_printer_handle(p, handle);
1612 return WERR_ACCESS_DENIED;
1615 /* Allow admin access */
1617 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1619 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1621 if (!lp_ms_add_printer_wizard()) {
1622 close_printer_handle(p, handle);
1623 return WERR_ACCESS_DENIED;
1626 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1627 and not a printer admin, then fail */
1629 if ((p->pipe_user.ut.uid != 0) &&
1630 !user_has_privileges(p->pipe_user.nt_user_token,
1632 !token_contains_name_in_list(
1633 uidtoname(p->pipe_user.ut.uid), NULL,
1634 p->pipe_user.nt_user_token,
1635 lp_printer_admin(snum))) {
1636 close_printer_handle(p, handle);
1637 return WERR_ACCESS_DENIED;
1640 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1644 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1647 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1648 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1650 /* We fall through to return WERR_OK */
1653 case SPLHND_PRINTER:
1654 /* NT doesn't let us connect to a printer if the connecting user
1655 doesn't have print permission. */
1657 if (!get_printer_snum(p, handle, &snum, NULL)) {
1658 close_printer_handle(p, handle);
1662 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1664 /* map an empty access mask to the minimum access mask */
1665 if (printer_default->access_required == 0x0)
1666 printer_default->access_required = PRINTER_ACCESS_USE;
1669 * If we are not serving the printer driver for this printer,
1670 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1671 * will keep NT clients happy --jerry
1674 if (lp_use_client_driver(snum)
1675 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1677 printer_default->access_required = PRINTER_ACCESS_USE;
1680 /* check smb.conf parameters and the the sec_desc */
1682 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1683 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1684 return WERR_ACCESS_DENIED;
1687 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1688 p->pipe_user.nt_user_token, snum) ||
1689 !print_access_check(&p->pipe_user, snum,
1690 printer_default->access_required)) {
1691 DEBUG(3, ("access DENIED for printer open\n"));
1692 close_printer_handle(p, handle);
1693 return WERR_ACCESS_DENIED;
1696 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1697 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1698 close_printer_handle(p, handle);
1699 return WERR_ACCESS_DENIED;
1702 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1703 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1705 printer_default->access_required = PRINTER_ACCESS_USE;
1707 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1708 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1713 /* sanity check to prevent programmer error */
1717 Printer->access_granted = printer_default->access_required;
1720 * If the client sent a devmode in the OpenPrinter() call, then
1721 * save it here in case we get a job submission on this handle
1724 if ( (Printer->printer_type != SPLHND_SERVER)
1725 && q_u->printer_default.devmode_cont.devmode_ptr )
1727 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1728 &Printer->nt_devmode );
1731 #if 0 /* JERRY -- I'm doubtful this is really effective */
1732 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1733 optimization in Windows 2000 clients --jerry */
1735 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1736 && (RA_WIN2K == get_remote_arch()) )
1738 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1739 sys_usleep( 500000 );
1746 /****************************************************************************
1747 ****************************************************************************/
1749 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1750 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1756 /* allocate memory if needed. Messy because
1757 convert_printer_info is used to update an existing
1758 printer or build a new one */
1760 if ( !printer->info_2 ) {
1761 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1762 if ( !printer->info_2 ) {
1763 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1768 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1769 printer->info_2->setuptime = time(NULL);
1777 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1778 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1784 printer->info_3=NULL;
1785 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1789 printer->info_6=NULL;
1790 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1800 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1801 NT_DEVICEMODE **pp_nt_devmode)
1803 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1806 * Ensure nt_devmode is a valid pointer
1807 * as we will be overwriting it.
1810 if (nt_devmode == NULL) {
1811 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1812 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1816 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1817 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1819 nt_devmode->specversion=devmode->specversion;
1820 nt_devmode->driverversion=devmode->driverversion;
1821 nt_devmode->size=devmode->size;
1822 nt_devmode->fields=devmode->fields;
1823 nt_devmode->orientation=devmode->orientation;
1824 nt_devmode->papersize=devmode->papersize;
1825 nt_devmode->paperlength=devmode->paperlength;
1826 nt_devmode->paperwidth=devmode->paperwidth;
1827 nt_devmode->scale=devmode->scale;
1828 nt_devmode->copies=devmode->copies;
1829 nt_devmode->defaultsource=devmode->defaultsource;
1830 nt_devmode->printquality=devmode->printquality;
1831 nt_devmode->color=devmode->color;
1832 nt_devmode->duplex=devmode->duplex;
1833 nt_devmode->yresolution=devmode->yresolution;
1834 nt_devmode->ttoption=devmode->ttoption;
1835 nt_devmode->collate=devmode->collate;
1837 nt_devmode->logpixels=devmode->logpixels;
1838 nt_devmode->bitsperpel=devmode->bitsperpel;
1839 nt_devmode->pelswidth=devmode->pelswidth;
1840 nt_devmode->pelsheight=devmode->pelsheight;
1841 nt_devmode->displayflags=devmode->displayflags;
1842 nt_devmode->displayfrequency=devmode->displayfrequency;
1843 nt_devmode->icmmethod=devmode->icmmethod;
1844 nt_devmode->icmintent=devmode->icmintent;
1845 nt_devmode->mediatype=devmode->mediatype;
1846 nt_devmode->dithertype=devmode->dithertype;
1847 nt_devmode->reserved1=devmode->reserved1;
1848 nt_devmode->reserved2=devmode->reserved2;
1849 nt_devmode->panningwidth=devmode->panningwidth;
1850 nt_devmode->panningheight=devmode->panningheight;
1853 * Only change private and driverextra if the incoming devmode
1854 * has a new one. JRA.
1857 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1858 SAFE_FREE(nt_devmode->nt_dev_private);
1859 nt_devmode->driverextra=devmode->driverextra;
1860 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1862 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1865 *pp_nt_devmode = nt_devmode;
1870 /********************************************************************
1871 * _spoolss_enddocprinter_internal.
1872 ********************************************************************/
1874 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1876 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1880 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1884 if (!get_printer_snum(p, handle, &snum, NULL))
1887 Printer->document_started=False;
1888 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1889 /* error codes unhandled so far ... */
1894 /********************************************************************
1895 * api_spoolss_closeprinter
1896 ********************************************************************/
1898 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1900 POLICY_HND *handle = &q_u->handle;
1902 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1904 if (Printer && Printer->document_started)
1905 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1907 if (!close_printer_handle(p, handle))
1910 /* clear the returned printer handle. Observed behavior
1911 from Win2k server. Don't think this really matters.
1912 Previous code just copied the value of the closed
1915 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1920 /********************************************************************
1921 * api_spoolss_deleteprinter
1923 ********************************************************************/
1925 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1927 POLICY_HND *handle = &q_u->handle;
1928 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1931 if (Printer && Printer->document_started)
1932 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1934 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1936 result = delete_printer_handle(p, handle);
1938 update_c_setprinter(False);
1943 /*******************************************************************
1944 * static function to lookup the version id corresponding to an
1945 * long architecture string
1946 ******************************************************************/
1948 static int get_version_id (char * arch)
1951 struct table_node archi_table[]= {
1953 {"Windows 4.0", "WIN40", 0 },
1954 {"Windows NT x86", "W32X86", 2 },
1955 {"Windows NT R4000", "W32MIPS", 2 },
1956 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1957 {"Windows NT PowerPC", "W32PPC", 2 },
1958 {"Windows IA64", "IA64", 3 },
1959 {"Windows x64", "x64", 3 },
1963 for (i=0; archi_table[i].long_archi != NULL; i++)
1965 if (strcmp(arch, archi_table[i].long_archi) == 0)
1966 return (archi_table[i].version);
1972 /********************************************************************
1973 * _spoolss_deleteprinterdriver
1974 ********************************************************************/
1976 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1980 NT_PRINTER_DRIVER_INFO_LEVEL info;
1981 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1984 WERROR status_win2k = WERR_ACCESS_DENIED;
1985 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1987 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1988 and not a printer admin, then fail */
1990 if ( (p->pipe_user.ut.uid != 0)
1991 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
1992 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
1993 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
1995 return WERR_ACCESS_DENIED;
1998 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1999 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2001 /* check that we have a valid driver name first */
2003 if ((version=get_version_id(arch)) == -1)
2004 return WERR_INVALID_ENVIRONMENT;
2007 ZERO_STRUCT(info_win2k);
2009 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2011 /* try for Win2k driver if "Windows NT x86" */
2013 if ( version == 2 ) {
2015 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2016 status = WERR_UNKNOWN_PRINTER_DRIVER;
2020 /* otherwise it was a failure */
2022 status = WERR_UNKNOWN_PRINTER_DRIVER;
2028 if (printer_driver_in_use(info.info_3)) {
2029 status = WERR_PRINTER_DRIVER_IN_USE;
2035 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2037 /* if we get to here, we now have 2 driver info structures to remove */
2038 /* remove the Win2k driver first*/
2040 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2041 free_a_printer_driver( info_win2k, 3 );
2043 /* this should not have failed---if it did, report to client */
2044 if ( !W_ERROR_IS_OK(status_win2k) )
2046 status = status_win2k;
2052 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2054 /* if at least one of the deletes succeeded return OK */
2056 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2060 free_a_printer_driver( info, 3 );
2065 /********************************************************************
2066 * spoolss_deleteprinterdriverex
2067 ********************************************************************/
2069 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2073 NT_PRINTER_DRIVER_INFO_LEVEL info;
2074 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2076 uint32 flags = q_u->delete_flags;
2079 WERROR status_win2k = WERR_ACCESS_DENIED;
2080 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2082 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2083 and not a printer admin, then fail */
2085 if ( (p->pipe_user.ut.uid != 0)
2086 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2087 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2088 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2090 return WERR_ACCESS_DENIED;
2093 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2094 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2096 /* check that we have a valid driver name first */
2097 if ((version=get_version_id(arch)) == -1) {
2098 /* this is what NT returns */
2099 return WERR_INVALID_ENVIRONMENT;
2102 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2103 version = q_u->version;
2106 ZERO_STRUCT(info_win2k);
2108 status = get_a_printer_driver(&info, 3, driver, arch, version);
2110 if ( !W_ERROR_IS_OK(status) )
2113 * if the client asked for a specific version,
2114 * or this is something other than Windows NT x86,
2118 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2121 /* try for Win2k driver if "Windows NT x86" */
2124 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2125 status = WERR_UNKNOWN_PRINTER_DRIVER;
2130 if ( printer_driver_in_use(info.info_3) ) {
2131 status = WERR_PRINTER_DRIVER_IN_USE;
2136 * we have a couple of cases to consider.
2137 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2138 * then the delete should fail if **any** files overlap with
2140 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2141 * non-overlapping files
2142 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2143 * is set, the do not delete any files
2144 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2147 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2149 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2151 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2152 /* no idea of the correct error here */
2153 status = WERR_ACCESS_DENIED;
2158 /* also check for W32X86/3 if necessary; maybe we already have? */
2160 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2161 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2164 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2165 /* no idea of the correct error here */
2166 free_a_printer_driver( info_win2k, 3 );
2167 status = WERR_ACCESS_DENIED;
2171 /* if we get to here, we now have 2 driver info structures to remove */
2172 /* remove the Win2k driver first*/
2174 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2175 free_a_printer_driver( info_win2k, 3 );
2177 /* this should not have failed---if it did, report to client */
2179 if ( !W_ERROR_IS_OK(status_win2k) )
2184 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2186 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2189 free_a_printer_driver( info, 3 );
2195 /****************************************************************************
2196 Internal routine for retreiving printerdata
2197 ***************************************************************************/
2199 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2200 const char *key, const char *value, uint32 *type, uint8 **data,
2201 uint32 *needed, uint32 in_size )
2203 REGISTRY_VALUE *val;
2207 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2208 return WERR_BADFILE;
2210 *type = regval_type( val );
2212 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2214 size = regval_size( val );
2216 /* copy the min(in_size, len) */
2219 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2221 /* special case for 0 length values */
2223 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2227 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2236 DEBUG(5,("get_printer_dataex: copy done\n"));
2241 /****************************************************************************
2242 Internal routine for removing printerdata
2243 ***************************************************************************/
2245 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2247 return delete_printer_data( printer->info_2, key, value );
2250 /****************************************************************************
2251 Internal routine for storing printerdata
2252 ***************************************************************************/
2254 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2255 uint32 type, uint8 *data, int real_len )
2257 /* the registry objects enforce uniqueness based on value name */
2259 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2262 /********************************************************************
2263 GetPrinterData on a printer server Handle.
2264 ********************************************************************/
2266 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2270 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2272 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2274 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2280 if (!StrCaseCmp(value, "BeepEnabled")) {
2282 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2284 SIVAL(*data, 0, 0x00);
2289 if (!StrCaseCmp(value, "EventLog")) {
2291 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2293 /* formally was 0x1b */
2294 SIVAL(*data, 0, 0x0);
2299 if (!StrCaseCmp(value, "NetPopup")) {
2301 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2303 SIVAL(*data, 0, 0x00);
2308 if (!StrCaseCmp(value, "MajorVersion")) {
2310 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2313 /* Windows NT 4.0 seems to not allow uploading of drivers
2314 to a server that reports 0x3 as the MajorVersion.
2315 need to investigate more how Win2k gets around this .
2318 if ( RA_WINNT == get_remote_arch() )
2327 if (!StrCaseCmp(value, "MinorVersion")) {
2329 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2337 * uint32 size = 0x114
2339 * uint32 minor = [0|1]
2340 * uint32 build = [2195|2600]
2341 * extra unicode string = e.g. "Service Pack 3"
2343 if (!StrCaseCmp(value, "OSVersion")) {
2347 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2350 SIVAL(*data, 0, *needed); /* size */
2351 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2353 SIVAL(*data, 12, 2195); /* build */
2355 /* leave extra string empty */
2361 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2362 const char *string="C:\\PRINTERS";
2364 *needed = 2*(strlen(string)+1);
2365 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2367 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2369 /* it's done by hand ready to go on the wire */
2370 for (i=0; i<strlen(string); i++) {
2371 (*data)[2*i]=string[i];
2372 (*data)[2*i+1]='\0';
2377 if (!StrCaseCmp(value, "Architecture")) {
2378 const char *string="Windows NT x86";
2380 *needed = 2*(strlen(string)+1);
2381 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2383 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2384 for (i=0; i<strlen(string); i++) {
2385 (*data)[2*i]=string[i];
2386 (*data)[2*i+1]='\0';
2391 if (!StrCaseCmp(value, "DsPresent")) {
2393 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2396 /* only show the publish check box if we are a
2397 memeber of a AD domain */
2399 if ( lp_security() == SEC_ADS )
2400 SIVAL(*data, 0, 0x01);
2402 SIVAL(*data, 0, 0x00);
2408 if (!StrCaseCmp(value, "DNSMachineName")) {
2411 if (!get_mydnsfullname(hostname))
2412 return WERR_BADFILE;
2414 *needed = 2*(strlen(hostname)+1);
2415 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2417 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2418 for (i=0; i<strlen(hostname); i++) {
2419 (*data)[2*i]=hostname[i];
2420 (*data)[2*i+1]='\0';
2426 return WERR_BADFILE;
2429 /********************************************************************
2430 * spoolss_getprinterdata
2431 ********************************************************************/
2433 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2435 POLICY_HND *handle = &q_u->handle;
2436 UNISTR2 *valuename = &q_u->valuename;
2437 uint32 in_size = q_u->size;
2438 uint32 *type = &r_u->type;
2439 uint32 *out_size = &r_u->size;
2440 uint8 **data = &r_u->data;
2441 uint32 *needed = &r_u->needed;
2444 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2445 NT_PRINTER_INFO_LEVEL *printer = NULL;
2449 * Reminder: when it's a string, the length is in BYTES
2450 * even if UNICODE is negociated.
2455 *out_size = in_size;
2457 /* in case of problem, return some default values */
2462 DEBUG(4,("_spoolss_getprinterdata\n"));
2465 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2466 status = WERR_BADFID;
2470 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2472 if ( Printer->printer_type == SPLHND_SERVER )
2473 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2476 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2477 status = WERR_BADFID;
2481 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2482 if ( !W_ERROR_IS_OK(status) )
2485 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2487 if ( strequal(value, "ChangeId") ) {
2489 *needed = sizeof(uint32);
2490 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2491 status = WERR_NOMEM;
2494 SIVAL( *data, 0, printer->info_2->changeid );
2498 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2501 if (*needed > *out_size)
2502 status = WERR_MORE_DATA;
2505 if ( !W_ERROR_IS_OK(status) )
2507 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2509 /* reply this param doesn't exist */
2512 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2514 free_a_printer( &printer, 2 );
2522 /* cleanup & exit */
2525 free_a_printer( &printer, 2 );
2530 /*********************************************************
2531 Connect to the client machine.
2532 **********************************************************/
2534 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2535 struct in_addr *client_ip, const char *remote_machine)
2538 struct cli_state *the_cli;
2539 struct in_addr rm_addr;
2541 if ( is_zero_ip(*client_ip) ) {
2542 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2543 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2547 if ( ismyip( rm_addr )) {
2548 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2552 rm_addr.s_addr = client_ip->s_addr;
2553 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2554 inet_ntoa(*client_ip) ));
2557 /* setup the connection */
2559 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2560 &rm_addr, 0, "IPC$", "IPC",
2564 0, lp_client_signing(), NULL );
2566 if ( !NT_STATUS_IS_OK( ret ) ) {
2567 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2572 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2573 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2574 cli_shutdown(the_cli);
2579 * Ok - we have an anonymous connection to the IPC$ share.
2580 * Now start the NT Domain stuff :-).
2583 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2584 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2585 remote_machine, nt_errstr(ret)));
2586 cli_shutdown(the_cli);
2590 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2592 (*pp_pipe)->cli = the_cli;
2597 /***************************************************************************
2598 Connect to the client.
2599 ****************************************************************************/
2601 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2602 uint32 localprinter, uint32 type,
2603 POLICY_HND *handle, struct in_addr *client_ip)
2608 * If it's the first connection, contact the client
2609 * and connect to the IPC$ share anonymously
2611 if (smb_connections==0) {
2612 fstring unix_printer;
2614 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2616 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2619 message_register(MSG_PRINTER_NOTIFY2,
2620 receive_notify2_message_list, NULL);
2621 /* Tell the connections db we're now interested in printer
2622 * notify messages. */
2623 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2627 * Tell the specific printing tdb we want messages for this printer
2628 * by registering our PID.
2631 if (!print_notify_register_pid(snum))
2632 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2636 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2639 if (!W_ERROR_IS_OK(result))
2640 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2641 dos_errstr(result)));
2643 return (W_ERROR_IS_OK(result));
2646 /********************************************************************
2648 * ReplyFindFirstPrinterChangeNotifyEx
2650 * before replying OK: status=0 a rpc call is made to the workstation
2651 * asking ReplyOpenPrinter
2653 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2654 * called from api_spoolss_rffpcnex
2655 ********************************************************************/
2657 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2659 POLICY_HND *handle = &q_u->handle;
2660 uint32 flags = q_u->flags;
2661 uint32 options = q_u->options;
2662 UNISTR2 *localmachine = &q_u->localmachine;
2663 uint32 printerlocal = q_u->printerlocal;
2665 SPOOL_NOTIFY_OPTION *option = q_u->option;
2666 struct in_addr client_ip;
2668 /* store the notify value in the printer struct */
2670 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2673 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2677 Printer->notify.flags=flags;
2678 Printer->notify.options=options;
2679 Printer->notify.printerlocal=printerlocal;
2681 if (Printer->notify.option)
2682 free_spool_notify_option(&Printer->notify.option);
2684 Printer->notify.option=dup_spool_notify_option(option);
2686 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2687 sizeof(Printer->notify.localmachine)-1);
2689 /* Connect to the client machine and send a ReplyOpenPrinter */
2691 if ( Printer->printer_type == SPLHND_SERVER)
2693 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2694 !get_printer_snum(p, handle, &snum, NULL) )
2697 client_ip.s_addr = inet_addr(p->conn->client_address);
2699 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2700 Printer->notify.printerlocal, 1,
2701 &Printer->notify.client_hnd, &client_ip))
2702 return WERR_SERVER_UNAVAILABLE;
2704 Printer->notify.client_connected=True;
2709 /*******************************************************************
2710 * fill a notify_info_data with the servername
2711 ********************************************************************/
2713 void spoolss_notify_server_name(int snum,
2714 SPOOL_NOTIFY_INFO_DATA *data,
2715 print_queue_struct *queue,
2716 NT_PRINTER_INFO_LEVEL *printer,
2717 TALLOC_CTX *mem_ctx)
2722 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2724 data->notify_data.data.length = len;
2726 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2727 if (!data->notify_data.data.string) {
2728 data->notify_data.data.length = 0;
2732 memcpy(data->notify_data.data.string, temp, len);
2734 data->notify_data.data.string = NULL;
2738 /*******************************************************************
2739 * fill a notify_info_data with the printername (not including the servername).
2740 ********************************************************************/
2742 void spoolss_notify_printer_name(int snum,
2743 SPOOL_NOTIFY_INFO_DATA *data,
2744 print_queue_struct *queue,
2745 NT_PRINTER_INFO_LEVEL *printer,
2746 TALLOC_CTX *mem_ctx)
2751 /* the notify name should not contain the \\server\ part */
2752 char *p = strrchr(printer->info_2->printername, '\\');
2755 p = printer->info_2->printername;
2760 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2762 data->notify_data.data.length = len;
2764 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2765 if (!data->notify_data.data.string) {
2766 data->notify_data.data.length = 0;
2769 memcpy(data->notify_data.data.string, temp, len);
2771 data->notify_data.data.string = NULL;
2775 /*******************************************************************
2776 * fill a notify_info_data with the servicename
2777 ********************************************************************/
2779 void spoolss_notify_share_name(int snum,
2780 SPOOL_NOTIFY_INFO_DATA *data,
2781 print_queue_struct *queue,
2782 NT_PRINTER_INFO_LEVEL *printer,
2783 TALLOC_CTX *mem_ctx)
2788 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2790 data->notify_data.data.length = len;
2792 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2793 if (!data->notify_data.data.string) {
2794 data->notify_data.data.length = 0;
2797 memcpy(data->notify_data.data.string, temp, len);
2799 data->notify_data.data.string = NULL;
2804 /*******************************************************************
2805 * fill a notify_info_data with the port name
2806 ********************************************************************/
2808 void spoolss_notify_port_name(int snum,
2809 SPOOL_NOTIFY_INFO_DATA *data,
2810 print_queue_struct *queue,
2811 NT_PRINTER_INFO_LEVEL *printer,
2812 TALLOC_CTX *mem_ctx)
2817 /* even if it's strange, that's consistant in all the code */
2819 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2821 data->notify_data.data.length = len;
2823 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2825 if (!data->notify_data.data.string) {
2826 data->notify_data.data.length = 0;
2830 memcpy(data->notify_data.data.string, temp, len);
2832 data->notify_data.data.string = NULL;
2836 /*******************************************************************
2837 * fill a notify_info_data with the printername
2838 * but it doesn't exist, have to see what to do
2839 ********************************************************************/
2841 void spoolss_notify_driver_name(int snum,
2842 SPOOL_NOTIFY_INFO_DATA *data,
2843 print_queue_struct *queue,
2844 NT_PRINTER_INFO_LEVEL *printer,
2845 TALLOC_CTX *mem_ctx)
2850 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2852 data->notify_data.data.length = len;
2854 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2856 if (!data->notify_data.data.string) {
2857 data->notify_data.data.length = 0;
2861 memcpy(data->notify_data.data.string, temp, len);
2863 data->notify_data.data.string = NULL;
2867 /*******************************************************************
2868 * fill a notify_info_data with the comment
2869 ********************************************************************/
2871 void spoolss_notify_comment(int snum,
2872 SPOOL_NOTIFY_INFO_DATA *data,
2873 print_queue_struct *queue,
2874 NT_PRINTER_INFO_LEVEL *printer,
2875 TALLOC_CTX *mem_ctx)
2880 if (*printer->info_2->comment == '\0')
2881 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2883 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2885 data->notify_data.data.length = len;
2887 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2889 if (!data->notify_data.data.string) {
2890 data->notify_data.data.length = 0;
2894 memcpy(data->notify_data.data.string, temp, len);
2896 data->notify_data.data.string = NULL;
2900 /*******************************************************************
2901 * fill a notify_info_data with the comment
2902 * location = "Room 1, floor 2, building 3"
2903 ********************************************************************/
2905 void spoolss_notify_location(int snum,
2906 SPOOL_NOTIFY_INFO_DATA *data,
2907 print_queue_struct *queue,
2908 NT_PRINTER_INFO_LEVEL *printer,
2909 TALLOC_CTX *mem_ctx)
2914 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2916 data->notify_data.data.length = len;
2918 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2920 if (!data->notify_data.data.string) {
2921 data->notify_data.data.length = 0;
2925 memcpy(data->notify_data.data.string, temp, len);
2927 data->notify_data.data.string = NULL;
2931 /*******************************************************************
2932 * fill a notify_info_data with the device mode
2933 * jfm:xxxx don't to it for know but that's a real problem !!!
2934 ********************************************************************/
2936 static void spoolss_notify_devmode(int snum,
2937 SPOOL_NOTIFY_INFO_DATA *data,
2938 print_queue_struct *queue,
2939 NT_PRINTER_INFO_LEVEL *printer,
2940 TALLOC_CTX *mem_ctx)
2942 /* for a dummy implementation we have to zero the fields */
2943 data->notify_data.data.length = 0;
2944 data->notify_data.data.string = NULL;
2947 /*******************************************************************
2948 * fill a notify_info_data with the separator file name
2949 ********************************************************************/
2951 void spoolss_notify_sepfile(int snum,
2952 SPOOL_NOTIFY_INFO_DATA *data,
2953 print_queue_struct *queue,
2954 NT_PRINTER_INFO_LEVEL *printer,
2955 TALLOC_CTX *mem_ctx)
2960 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2962 data->notify_data.data.length = len;
2964 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2966 if (!data->notify_data.data.string) {
2967 data->notify_data.data.length = 0;
2971 memcpy(data->notify_data.data.string, temp, len);
2973 data->notify_data.data.string = NULL;
2977 /*******************************************************************
2978 * fill a notify_info_data with the print processor
2979 * jfm:xxxx return always winprint to indicate we don't do anything to it
2980 ********************************************************************/
2982 void spoolss_notify_print_processor(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->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2993 data->notify_data.data.length = len;
2995 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2997 if (!data->notify_data.data.string) {
2998 data->notify_data.data.length = 0;
3002 memcpy(data->notify_data.data.string, temp, len);
3004 data->notify_data.data.string = NULL;
3008 /*******************************************************************
3009 * fill a notify_info_data with the print processor options
3010 * jfm:xxxx send an empty string
3011 ********************************************************************/
3013 void spoolss_notify_parameters(int snum,
3014 SPOOL_NOTIFY_INFO_DATA *data,
3015 print_queue_struct *queue,
3016 NT_PRINTER_INFO_LEVEL *printer,
3017 TALLOC_CTX *mem_ctx)
3022 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3024 data->notify_data.data.length = len;
3026 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3028 if (!data->notify_data.data.string) {
3029 data->notify_data.data.length = 0;
3033 memcpy(data->notify_data.data.string, temp, len);
3035 data->notify_data.data.string = NULL;
3039 /*******************************************************************
3040 * fill a notify_info_data with the data type
3041 * jfm:xxxx always send RAW as data type
3042 ********************************************************************/
3044 void spoolss_notify_datatype(int snum,
3045 SPOOL_NOTIFY_INFO_DATA *data,
3046 print_queue_struct *queue,
3047 NT_PRINTER_INFO_LEVEL *printer,
3048 TALLOC_CTX *mem_ctx)
3053 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3055 data->notify_data.data.length = len;
3057 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3059 if (!data->notify_data.data.string) {
3060 data->notify_data.data.length = 0;
3064 memcpy(data->notify_data.data.string, temp, len);
3066 data->notify_data.data.string = NULL;
3070 /*******************************************************************
3071 * fill a notify_info_data with the security descriptor
3072 * jfm:xxxx send an null pointer to say no security desc
3073 * have to implement security before !
3074 ********************************************************************/
3076 static void spoolss_notify_security_desc(int snum,
3077 SPOOL_NOTIFY_INFO_DATA *data,
3078 print_queue_struct *queue,
3079 NT_PRINTER_INFO_LEVEL *printer,
3080 TALLOC_CTX *mem_ctx)
3082 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3083 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3086 /*******************************************************************
3087 * fill a notify_info_data with the attributes
3088 * jfm:xxxx a samba printer is always shared
3089 ********************************************************************/
3091 void spoolss_notify_attributes(int snum,
3092 SPOOL_NOTIFY_INFO_DATA *data,
3093 print_queue_struct *queue,
3094 NT_PRINTER_INFO_LEVEL *printer,
3095 TALLOC_CTX *mem_ctx)
3097 data->notify_data.value[0] = printer->info_2->attributes;
3098 data->notify_data.value[1] = 0;
3101 /*******************************************************************
3102 * fill a notify_info_data with the priority
3103 ********************************************************************/
3105 static void spoolss_notify_priority(int snum,
3106 SPOOL_NOTIFY_INFO_DATA *data,
3107 print_queue_struct *queue,
3108 NT_PRINTER_INFO_LEVEL *printer,
3109 TALLOC_CTX *mem_ctx)
3111 data->notify_data.value[0] = printer->info_2->priority;
3112 data->notify_data.value[1] = 0;
3115 /*******************************************************************
3116 * fill a notify_info_data with the default priority
3117 ********************************************************************/
3119 static void spoolss_notify_default_priority(int snum,
3120 SPOOL_NOTIFY_INFO_DATA *data,
3121 print_queue_struct *queue,
3122 NT_PRINTER_INFO_LEVEL *printer,
3123 TALLOC_CTX *mem_ctx)
3125 data->notify_data.value[0] = printer->info_2->default_priority;
3126 data->notify_data.value[1] = 0;
3129 /*******************************************************************
3130 * fill a notify_info_data with the start time
3131 ********************************************************************/
3133 static void spoolss_notify_start_time(int snum,
3134 SPOOL_NOTIFY_INFO_DATA *data,
3135 print_queue_struct *queue,
3136 NT_PRINTER_INFO_LEVEL *printer,
3137 TALLOC_CTX *mem_ctx)
3139 data->notify_data.value[0] = printer->info_2->starttime;
3140 data->notify_data.value[1] = 0;
3143 /*******************************************************************
3144 * fill a notify_info_data with the until time
3145 ********************************************************************/
3147 static void spoolss_notify_until_time(int snum,
3148 SPOOL_NOTIFY_INFO_DATA *data,
3149 print_queue_struct *queue,
3150 NT_PRINTER_INFO_LEVEL *printer,
3151 TALLOC_CTX *mem_ctx)
3153 data->notify_data.value[0] = printer->info_2->untiltime;
3154 data->notify_data.value[1] = 0;
3157 /*******************************************************************
3158 * fill a notify_info_data with the status
3159 ********************************************************************/
3161 static void spoolss_notify_status(int snum,
3162 SPOOL_NOTIFY_INFO_DATA *data,
3163 print_queue_struct *queue,
3164 NT_PRINTER_INFO_LEVEL *printer,
3165 TALLOC_CTX *mem_ctx)
3167 print_status_struct status;
3169 print_queue_length(snum, &status);
3170 data->notify_data.value[0]=(uint32) status.status;
3171 data->notify_data.value[1] = 0;
3174 /*******************************************************************
3175 * fill a notify_info_data with the number of jobs queued
3176 ********************************************************************/
3178 void spoolss_notify_cjobs(int snum,
3179 SPOOL_NOTIFY_INFO_DATA *data,
3180 print_queue_struct *queue,
3181 NT_PRINTER_INFO_LEVEL *printer,
3182 TALLOC_CTX *mem_ctx)
3184 data->notify_data.value[0] = print_queue_length(snum, NULL);
3185 data->notify_data.value[1] = 0;
3188 /*******************************************************************
3189 * fill a notify_info_data with the average ppm
3190 ********************************************************************/
3192 static void spoolss_notify_average_ppm(int snum,
3193 SPOOL_NOTIFY_INFO_DATA *data,
3194 print_queue_struct *queue,
3195 NT_PRINTER_INFO_LEVEL *printer,
3196 TALLOC_CTX *mem_ctx)
3198 /* always respond 8 pages per minutes */
3199 /* a little hard ! */
3200 data->notify_data.value[0] = printer->info_2->averageppm;
3201 data->notify_data.value[1] = 0;
3204 /*******************************************************************
3205 * fill a notify_info_data with username
3206 ********************************************************************/
3208 static void spoolss_notify_username(int snum,
3209 SPOOL_NOTIFY_INFO_DATA *data,
3210 print_queue_struct *queue,
3211 NT_PRINTER_INFO_LEVEL *printer,
3212 TALLOC_CTX *mem_ctx)
3217 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3219 data->notify_data.data.length = len;
3221 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3223 if (!data->notify_data.data.string) {
3224 data->notify_data.data.length = 0;
3228 memcpy(data->notify_data.data.string, temp, len);
3230 data->notify_data.data.string = NULL;
3234 /*******************************************************************
3235 * fill a notify_info_data with job status
3236 ********************************************************************/
3238 static void spoolss_notify_job_status(int snum,
3239 SPOOL_NOTIFY_INFO_DATA *data,
3240 print_queue_struct *queue,
3241 NT_PRINTER_INFO_LEVEL *printer,
3242 TALLOC_CTX *mem_ctx)
3244 data->notify_data.value[0]=nt_printj_status(queue->status);
3245 data->notify_data.value[1] = 0;
3248 /*******************************************************************
3249 * fill a notify_info_data with job name
3250 ********************************************************************/
3252 static void spoolss_notify_job_name(int snum,
3253 SPOOL_NOTIFY_INFO_DATA *data,
3254 print_queue_struct *queue,
3255 NT_PRINTER_INFO_LEVEL *printer,
3256 TALLOC_CTX *mem_ctx)
3261 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3263 data->notify_data.data.length = len;
3265 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3267 if (!data->notify_data.data.string) {
3268 data->notify_data.data.length = 0;
3272 memcpy(data->notify_data.data.string, temp, len);
3274 data->notify_data.data.string = NULL;
3278 /*******************************************************************
3279 * fill a notify_info_data with job status
3280 ********************************************************************/
3282 static void spoolss_notify_job_status_string(int snum,
3283 SPOOL_NOTIFY_INFO_DATA *data,
3284 print_queue_struct *queue,
3285 NT_PRINTER_INFO_LEVEL *printer,
3286 TALLOC_CTX *mem_ctx)
3289 * Now we're returning job status codes we just return a "" here. JRA.
3296 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3299 switch (queue->status) {
3304 p = ""; /* NT provides the paused string */
3313 #endif /* NO LONGER NEEDED. */
3315 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3317 data->notify_data.data.length = len;
3319 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3321 if (!data->notify_data.data.string) {
3322 data->notify_data.data.length = 0;
3326 memcpy(data->notify_data.data.string, temp, len);
3328 data->notify_data.data.string = NULL;
3332 /*******************************************************************
3333 * fill a notify_info_data with job time
3334 ********************************************************************/
3336 static void spoolss_notify_job_time(int snum,
3337 SPOOL_NOTIFY_INFO_DATA *data,
3338 print_queue_struct *queue,
3339 NT_PRINTER_INFO_LEVEL *printer,
3340 TALLOC_CTX *mem_ctx)
3342 data->notify_data.value[0]=0x0;
3343 data->notify_data.value[1]=0;
3346 /*******************************************************************
3347 * fill a notify_info_data with job size
3348 ********************************************************************/
3350 static void spoolss_notify_job_size(int snum,
3351 SPOOL_NOTIFY_INFO_DATA *data,
3352 print_queue_struct *queue,
3353 NT_PRINTER_INFO_LEVEL *printer,
3354 TALLOC_CTX *mem_ctx)
3356 data->notify_data.value[0]=queue->size;
3357 data->notify_data.value[1]=0;
3360 /*******************************************************************
3361 * fill a notify_info_data with page info
3362 ********************************************************************/
3363 static void spoolss_notify_total_pages(int snum,
3364 SPOOL_NOTIFY_INFO_DATA *data,
3365 print_queue_struct *queue,
3366 NT_PRINTER_INFO_LEVEL *printer,
3367 TALLOC_CTX *mem_ctx)
3369 data->notify_data.value[0]=queue->page_count;
3370 data->notify_data.value[1]=0;
3373 /*******************************************************************
3374 * fill a notify_info_data with pages printed info.
3375 ********************************************************************/
3376 static void spoolss_notify_pages_printed(int snum,
3377 SPOOL_NOTIFY_INFO_DATA *data,
3378 print_queue_struct *queue,
3379 NT_PRINTER_INFO_LEVEL *printer,
3380 TALLOC_CTX *mem_ctx)
3382 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3383 data->notify_data.value[1]=0;
3386 /*******************************************************************
3387 Fill a notify_info_data with job position.
3388 ********************************************************************/
3390 static void spoolss_notify_job_position(int snum,
3391 SPOOL_NOTIFY_INFO_DATA *data,
3392 print_queue_struct *queue,
3393 NT_PRINTER_INFO_LEVEL *printer,
3394 TALLOC_CTX *mem_ctx)
3396 data->notify_data.value[0]=queue->job;
3397 data->notify_data.value[1]=0;
3400 /*******************************************************************
3401 Fill a notify_info_data with submitted time.
3402 ********************************************************************/
3404 static void spoolss_notify_submitted_time(int snum,
3405 SPOOL_NOTIFY_INFO_DATA *data,
3406 print_queue_struct *queue,
3407 NT_PRINTER_INFO_LEVEL *printer,
3408 TALLOC_CTX *mem_ctx)
3415 t=gmtime(&queue->time);
3417 len = sizeof(SYSTEMTIME);
3419 data->notify_data.data.length = len;
3420 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3422 if (!data->notify_data.data.string) {
3423 data->notify_data.data.length = 0;
3427 make_systemtime(&st, t);
3430 * Systemtime must be linearized as a set of UINT16's.
3431 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3434 p = (char *)data->notify_data.data.string;
3435 SSVAL(p, 0, st.year);
3436 SSVAL(p, 2, st.month);
3437 SSVAL(p, 4, st.dayofweek);
3438 SSVAL(p, 6, st.day);
3439 SSVAL(p, 8, st.hour);
3440 SSVAL(p, 10, st.minute);
3441 SSVAL(p, 12, st.second);
3442 SSVAL(p, 14, st.milliseconds);
3445 struct s_notify_info_data_table
3451 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3452 print_queue_struct *queue,
3453 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3456 /* A table describing the various print notification constants and
3457 whether the notification data is a pointer to a variable sized
3458 buffer, a one value uint32 or a two value uint32. */
3460 static const struct s_notify_info_data_table notify_info_data_table[] =
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3485 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3486 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3487 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3508 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3509 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3510 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3511 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3514 /*******************************************************************
3515 Return the size of info_data structure.
3516 ********************************************************************/
3518 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3522 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3523 if ( (notify_info_data_table[i].type == type)
3524 && (notify_info_data_table[i].field == field) ) {
3525 switch(notify_info_data_table[i].size) {
3526 case NOTIFY_ONE_VALUE:
3527 case NOTIFY_TWO_VALUE:
3532 /* The only pointer notify data I have seen on
3533 the wire is the submitted time and this has
3534 the notify size set to 4. -tpot */
3536 case NOTIFY_POINTER:
3539 case NOTIFY_SECDESC:
3545 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3550 /*******************************************************************
3551 Return the type of notify_info_data.
3552 ********************************************************************/
3554 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3558 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3559 if (notify_info_data_table[i].type == type &&
3560 notify_info_data_table[i].field == field)
3561 return notify_info_data_table[i].size;
3567 /****************************************************************************
3568 ****************************************************************************/
3570 static BOOL search_notify(uint16 type, uint16 field, int *value)
3574 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3575 if (notify_info_data_table[i].type == type &&
3576 notify_info_data_table[i].field == field &&
3577 notify_info_data_table[i].fn != NULL) {
3586 /****************************************************************************
3587 ****************************************************************************/
3589 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3591 info_data->type = type;
3592 info_data->field = field;
3593 info_data->reserved = 0;
3595 info_data->size = size_of_notify_info_data(type, field);
3596 info_data->enc_type = type_of_notify_info_data(type, field);
3601 /*******************************************************************
3603 * fill a notify_info struct with info asked
3605 ********************************************************************/
3607 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3608 snum, SPOOL_NOTIFY_OPTION_TYPE
3609 *option_type, uint32 id,
3610 TALLOC_CTX *mem_ctx)
3616 SPOOL_NOTIFY_INFO_DATA *current_data;
3617 NT_PRINTER_INFO_LEVEL *printer = NULL;
3618 print_queue_struct *queue=NULL;
3620 type=option_type->type;
3622 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3623 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3624 option_type->count, lp_servicename(snum)));
3626 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3629 for(field_num=0; field_num<option_type->count; field_num++) {
3630 field = option_type->fields[field_num];
3632 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3634 if (!search_notify(type, field, &j) )
3637 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3638 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3639 free_a_printer(&printer, 2);
3643 current_data = &info->data[info->count];
3645 construct_info_data(current_data, type, field, id);
3647 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3648 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3650 notify_info_data_table[j].fn(snum, current_data, queue,
3656 free_a_printer(&printer, 2);
3660 /*******************************************************************
3662 * fill a notify_info struct with info asked
3664 ********************************************************************/
3666 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3667 SPOOL_NOTIFY_INFO *info,
3668 NT_PRINTER_INFO_LEVEL *printer,
3669 int snum, SPOOL_NOTIFY_OPTION_TYPE
3670 *option_type, uint32 id,
3671 TALLOC_CTX *mem_ctx)
3677 SPOOL_NOTIFY_INFO_DATA *current_data;
3679 DEBUG(4,("construct_notify_jobs_info\n"));
3681 type = option_type->type;
3683 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3684 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3685 option_type->count));
3687 for(field_num=0; field_num<option_type->count; field_num++) {
3688 field = option_type->fields[field_num];
3690 if (!search_notify(type, field, &j) )
3693 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3694 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3698 current_data=&(info->data[info->count]);
3700 construct_info_data(current_data, type, field, id);
3701 notify_info_data_table[j].fn(snum, current_data, queue,
3710 * JFM: The enumeration is not that simple, it's even non obvious.
3712 * let's take an example: I want to monitor the PRINTER SERVER for
3713 * the printer's name and the number of jobs currently queued.
3714 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3715 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3717 * I have 3 printers on the back of my server.
3719 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3722 * 1 printer 1 name 1
3723 * 2 printer 1 cjob 1
3724 * 3 printer 2 name 2
3725 * 4 printer 2 cjob 2
3726 * 5 printer 3 name 3
3727 * 6 printer 3 name 3
3729 * that's the print server case, the printer case is even worse.
3732 /*******************************************************************
3734 * enumerate all printers on the printserver
3735 * fill a notify_info struct with info asked
3737 ********************************************************************/
3739 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3740 SPOOL_NOTIFY_INFO *info,
3741 TALLOC_CTX *mem_ctx)
3744 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3745 int n_services=lp_numservices();
3747 SPOOL_NOTIFY_OPTION *option;
3748 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3750 DEBUG(4,("printserver_notify_info\n"));
3755 option=Printer->notify.option;
3760 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3761 sending a ffpcn() request first */
3766 for (i=0; i<option->count; i++) {
3767 option_type=&(option->ctr.type[i]);
3769 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3772 for (snum=0; snum<n_services; snum++)
3774 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3775 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3781 * Debugging information, don't delete.
3784 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3785 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3786 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3788 for (i=0; i<info->count; i++) {
3789 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3790 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3791 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3798 /*******************************************************************
3800 * fill a notify_info struct with info asked
3802 ********************************************************************/
3804 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3805 TALLOC_CTX *mem_ctx)
3808 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3811 SPOOL_NOTIFY_OPTION *option;
3812 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3814 print_queue_struct *queue=NULL;
3815 print_status_struct status;
3817 DEBUG(4,("printer_notify_info\n"));
3822 option=Printer->notify.option;
3828 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3829 sending a ffpcn() request first */
3834 get_printer_snum(p, hnd, &snum, NULL);
3836 for (i=0; i<option->count; i++) {
3837 option_type=&option->ctr.type[i];
3839 switch ( option_type->type ) {
3840 case PRINTER_NOTIFY_TYPE:
3841 if(construct_notify_printer_info(Printer, info, snum,
3847 case JOB_NOTIFY_TYPE: {
3848 NT_PRINTER_INFO_LEVEL *printer = NULL;
3850 count = print_queue_status(snum, &queue, &status);
3852 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3855 for (j=0; j<count; j++) {
3856 construct_notify_jobs_info(&queue[j], info,
3863 free_a_printer(&printer, 2);
3873 * Debugging information, don't delete.
3876 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3877 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3878 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3880 for (i=0; i<info->count; i++) {
3881 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3882 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3883 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3889 /********************************************************************
3891 ********************************************************************/
3893 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3895 POLICY_HND *handle = &q_u->handle;
3896 SPOOL_NOTIFY_INFO *info = &r_u->info;
3898 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3899 WERROR result = WERR_BADFID;
3901 /* we always have a NOTIFY_INFO struct */
3905 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3906 OUR_HANDLE(handle)));
3910 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3913 * We are now using the change value, and
3914 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3915 * I don't have a global notification system, I'm sending back all the
3916 * informations even when _NOTHING_ has changed.
3919 /* We need to keep track of the change value to send back in
3920 RRPCN replies otherwise our updates are ignored. */
3922 Printer->notify.fnpcn = True;
3924 if (Printer->notify.client_connected) {
3925 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3926 Printer->notify.change = q_u->change;
3929 /* just ignore the SPOOL_NOTIFY_OPTION */
3931 switch (Printer->printer_type) {
3933 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3936 case SPLHND_PRINTER:
3937 result = printer_notify_info(p, handle, info, p->mem_ctx);
3941 Printer->notify.fnpcn = False;
3947 /********************************************************************
3948 * construct_printer_info_0
3949 * fill a printer_info_0 struct
3950 ********************************************************************/
3952 static BOOL construct_printer_info_0(Printer_entry *print_hnd,
3953 PRINTER_INFO_0 *printer,
3954 const struct share_params *params)
3958 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3959 counter_printer_0 *session_counter;
3960 uint32 global_counter;
3963 print_status_struct status;
3965 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
3966 lp_const_servicename(params->service))))
3969 count = print_queue_length(params->service, &status);
3971 /* check if we already have a counter for this printer */
3972 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3973 if (session_counter->snum == params->service)
3977 /* it's the first time, add it to the list */
3978 if (session_counter==NULL) {
3979 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3980 free_a_printer(&ntprinter, 2);
3983 ZERO_STRUCTP(session_counter);
3984 session_counter->snum=params->service;
3985 session_counter->counter=0;
3986 DLIST_ADD(counter_list, session_counter);
3990 session_counter->counter++;
3993 * the global_counter should be stored in a TDB as it's common to all the clients
3994 * and should be zeroed on samba startup
3996 global_counter=session_counter->counter;
3998 pstrcpy(chaine,ntprinter->info_2->printername);
4000 init_unistr(&printer->printername, chaine);
4002 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
4003 init_unistr(&printer->servername, chaine);
4005 printer->cjobs = count;
4006 printer->total_jobs = 0;
4007 printer->total_bytes = 0;
4009 setuptime = (time_t)ntprinter->info_2->setuptime;
4010 t=gmtime(&setuptime);
4012 printer->year = t->tm_year+1900;
4013 printer->month = t->tm_mon+1;
4014 printer->dayofweek = t->tm_wday;
4015 printer->day = t->tm_mday;
4016 printer->hour = t->tm_hour;
4017 printer->minute = t->tm_min;
4018 printer->second = t->tm_sec;
4019 printer->milliseconds = 0;
4021 printer->global_counter = global_counter;
4022 printer->total_pages = 0;
4024 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4025 printer->major_version = 0x0005; /* NT 5 */
4026 printer->build_version = 0x0893; /* build 2195 */
4028 printer->unknown7 = 0x1;
4029 printer->unknown8 = 0x0;
4030 printer->unknown9 = 0x0;
4031 printer->session_counter = session_counter->counter;
4032 printer->unknown11 = 0x0;
4033 printer->printer_errors = 0x0; /* number of print failure */
4034 printer->unknown13 = 0x0;
4035 printer->unknown14 = 0x1;
4036 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4037 printer->unknown16 = 0x0;
4038 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4039 printer->unknown18 = 0x0;
4040 printer->status = nt_printq_status(status.status);
4041 printer->unknown20 = 0x0;
4042 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4043 printer->unknown22 = 0x0;
4044 printer->unknown23 = 0x6; /* 6 ???*/
4045 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4046 printer->unknown25 = 0;
4047 printer->unknown26 = 0;
4048 printer->unknown27 = 0;
4049 printer->unknown28 = 0;
4050 printer->unknown29 = 0;
4052 free_a_printer(&ntprinter,2);
4056 /********************************************************************
4057 * construct_printer_info_1
4058 * fill a printer_info_1 struct
4059 ********************************************************************/
4060 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags,
4061 PRINTER_INFO_1 *printer,
4062 const struct share_params *params)
4066 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4068 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4069 lp_const_servicename(params->service))))
4072 printer->flags=flags;
4074 if (*ntprinter->info_2->comment == '\0') {
4075 init_unistr(&printer->comment, lp_comment(params->service));
4076 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4077 ntprinter->info_2->drivername,
4078 lp_comment(params->service));
4081 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4082 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4083 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4086 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4088 init_unistr(&printer->description, chaine);
4089 init_unistr(&printer->name, chaine2);
4091 free_a_printer(&ntprinter,2);
4096 /****************************************************************************
4097 Free a DEVMODE struct.
4098 ****************************************************************************/
4100 static void free_dev_mode(DEVICEMODE *dev)
4105 SAFE_FREE(dev->dev_private);
4110 /****************************************************************************
4111 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4112 should be valid upon entry
4113 ****************************************************************************/
4115 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4117 if ( !devmode || !ntdevmode )
4120 init_unistr(&devmode->devicename, ntdevmode->devicename);
4122 init_unistr(&devmode->formname, ntdevmode->formname);
4124 devmode->specversion = ntdevmode->specversion;
4125 devmode->driverversion = ntdevmode->driverversion;
4126 devmode->size = ntdevmode->size;
4127 devmode->driverextra = ntdevmode->driverextra;
4128 devmode->fields = ntdevmode->fields;
4130 devmode->orientation = ntdevmode->orientation;
4131 devmode->papersize = ntdevmode->papersize;
4132 devmode->paperlength = ntdevmode->paperlength;
4133 devmode->paperwidth = ntdevmode->paperwidth;
4134 devmode->scale = ntdevmode->scale;
4135 devmode->copies = ntdevmode->copies;
4136 devmode->defaultsource = ntdevmode->defaultsource;
4137 devmode->printquality = ntdevmode->printquality;
4138 devmode->color = ntdevmode->color;
4139 devmode->duplex = ntdevmode->duplex;
4140 devmode->yresolution = ntdevmode->yresolution;
4141 devmode->ttoption = ntdevmode->ttoption;
4142 devmode->collate = ntdevmode->collate;
4143 devmode->icmmethod = ntdevmode->icmmethod;
4144 devmode->icmintent = ntdevmode->icmintent;
4145 devmode->mediatype = ntdevmode->mediatype;
4146 devmode->dithertype = ntdevmode->dithertype;
4148 if (ntdevmode->nt_dev_private != NULL) {
4149 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4156 /****************************************************************************
4157 Create a DEVMODE struct. Returns malloced memory.
4158 ****************************************************************************/
4160 DEVICEMODE *construct_dev_mode(const char *servicename)
4162 NT_PRINTER_INFO_LEVEL *printer = NULL;
4163 DEVICEMODE *devmode = NULL;
4165 DEBUG(7,("construct_dev_mode\n"));
4167 DEBUGADD(8,("getting printer characteristics\n"));
4169 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4172 if ( !printer->info_2->devmode ) {
4173 DEBUG(5, ("BONG! There was no device mode!\n"));
4177 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4178 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4182 ZERO_STRUCTP(devmode);
4184 DEBUGADD(8,("loading DEVICEMODE\n"));
4186 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4187 free_dev_mode( devmode );
4192 free_a_printer(&printer,2);
4197 /********************************************************************
4198 * construct_printer_info_2
4199 * fill a printer_info_2 struct
4200 ********************************************************************/
4202 static BOOL construct_printer_info_2(Printer_entry *print_hnd,
4203 PRINTER_INFO_2 *printer,
4204 const struct share_params *params)
4207 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4209 print_status_struct status;
4211 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4212 lp_const_servicename(params->service))))
4215 count = print_queue_length(params->service, &status);
4217 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4218 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4219 init_unistr(&printer->sharename, lp_servicename(params->service)); /* sharename */
4220 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4221 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4223 if (*ntprinter->info_2->comment == '\0')
4224 init_unistr(&printer->comment, lp_comment(params->service)); /* comment */
4226 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4228 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4229 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4230 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4231 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4232 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4234 printer->attributes = ntprinter->info_2->attributes;
4236 printer->priority = ntprinter->info_2->priority; /* priority */
4237 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4238 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4239 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4240 printer->status = nt_printq_status(status.status); /* status */
4241 printer->cjobs = count; /* jobs */
4242 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4244 if ( !(printer->devmode = construct_dev_mode(
4245 lp_const_servicename(params->service))) )
4246 DEBUG(8, ("Returning NULL Devicemode!\n"));
4248 printer->secdesc = NULL;
4250 if ( ntprinter->info_2->secdesc_buf
4251 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4253 /* don't use talloc_steal() here unless you do a deep steal of all
4254 the SEC_DESC members */
4256 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4257 ntprinter->info_2->secdesc_buf->sd );
4260 free_a_printer(&ntprinter, 2);
4265 /********************************************************************
4266 * construct_printer_info_3
4267 * fill a printer_info_3 struct
4268 ********************************************************************/
4270 static BOOL construct_printer_info_3(Printer_entry *print_hnd,
4271 PRINTER_INFO_3 **pp_printer,
4272 const struct share_params *params)
4274 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4275 PRINTER_INFO_3 *printer = NULL;
4277 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4278 lp_const_servicename(params->service))))
4282 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4283 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4284 free_a_printer(&ntprinter, 2);
4288 ZERO_STRUCTP(printer);
4290 /* These are the components of the SD we are returning. */
4292 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4293 /* don't use talloc_steal() here unless you do a deep steal of all
4294 the SEC_DESC members */
4296 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4297 ntprinter->info_2->secdesc_buf->sd );
4300 free_a_printer(&ntprinter, 2);
4302 *pp_printer = printer;
4306 /********************************************************************
4307 * construct_printer_info_4
4308 * fill a printer_info_4 struct
4309 ********************************************************************/
4311 static BOOL construct_printer_info_4(Printer_entry *print_hnd,
4312 PRINTER_INFO_4 *printer,
4313 const struct share_params *params)
4315 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4317 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4318 lp_const_servicename(params->service))))
4321 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4322 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4323 printer->attributes = ntprinter->info_2->attributes;
4325 free_a_printer(&ntprinter, 2);
4329 /********************************************************************
4330 * construct_printer_info_5
4331 * fill a printer_info_5 struct
4332 ********************************************************************/
4334 static BOOL construct_printer_info_5(Printer_entry *print_hnd,
4335 PRINTER_INFO_5 *printer,
4336 const struct share_params *params)
4338 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4340 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4341 lp_const_servicename(params->service))))
4344 init_unistr(&printer->printername, ntprinter->info_2->printername);
4345 init_unistr(&printer->portname, ntprinter->info_2->portname);
4346 printer->attributes = ntprinter->info_2->attributes;
4348 /* these two are not used by NT+ according to MSDN */
4350 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4351 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4353 free_a_printer(&ntprinter, 2);
4358 /********************************************************************
4359 * construct_printer_info_6
4360 * fill a printer_info_6 struct
4361 ********************************************************************/
4363 static BOOL construct_printer_info_6(Printer_entry *print_hnd,
4364 PRINTER_INFO_6 *printer,
4365 const struct share_params *params)
4367 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4369 print_status_struct status;
4371 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4372 lp_const_servicename(params->service))))
4375 count = print_queue_length(params->service, &status);
4377 printer->status = nt_printq_status(status.status);
4379 free_a_printer(&ntprinter, 2);
4384 /********************************************************************
4385 * construct_printer_info_7
4386 * fill a printer_info_7 struct
4387 ********************************************************************/
4389 static BOOL construct_printer_info_7(Printer_entry *print_hnd,
4390 PRINTER_INFO_7 *printer,
4391 const struct share_params *params)
4393 char *guid_str = NULL;
4396 if (is_printer_published(print_hnd, params->service, &guid)) {
4397 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4398 strupper_m(guid_str);
4399 init_unistr(&printer->guid, guid_str);
4400 printer->action = SPOOL_DS_PUBLISH;
4402 init_unistr(&printer->guid, "");
4403 printer->action = SPOOL_DS_UNPUBLISH;
4409 /********************************************************************
4410 Spoolss_enumprinters.
4411 ********************************************************************/
4413 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4416 struct share_iterator *shares;
4417 struct share_params *printer;
4418 PRINTER_INFO_1 *printers=NULL;
4419 WERROR result = WERR_OK;
4421 DEBUG(4,("enum_all_printers_info_1\n"));
4423 if (!(shares = share_list_all(NULL))) {
4424 DEBUG(5, ("Could not list printers\n"));
4425 return WERR_ACCESS_DENIED;
4428 while ((printer = next_printer(shares)) != NULL) {
4429 PRINTER_INFO_1 current_prt;
4431 DEBUG(4,("Found a printer in smb.conf: %s\n",
4432 lp_servicename(printer->service)));
4434 if (!construct_printer_info_1(NULL, flags, ¤t_prt,
4439 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1,
4440 *returned +1)) == NULL) {
4441 DEBUG(2,("enum_all_printers_info_1: failed to enlarge "
4442 "printers buffer!\n"));
4444 TALLOC_FREE(shares);
4447 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n",
4450 memcpy(&printers[*returned], ¤t_prt,
4451 sizeof(PRINTER_INFO_1));
4453 TALLOC_FREE(printer);
4456 /* check the required size. */
4457 for (i=0; i<*returned; i++)
4458 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4460 if (*needed > offered) {
4461 result = WERR_INSUFFICIENT_BUFFER;
4465 if (!rpcbuf_alloc_size(buffer, *needed)) {
4466 result = WERR_NOMEM;
4470 /* fill the buffer with the structures */
4471 for (i=0; i<*returned; i++)
4472 smb_io_printer_info_1("", buffer, &printers[i], 0);
4477 SAFE_FREE(printers);
4478 TALLOC_FREE(shares);
4480 if ( !W_ERROR_IS_OK(result) )
4486 /********************************************************************
4487 enum_all_printers_info_1_local.
4488 *********************************************************************/
4490 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4492 DEBUG(4,("enum_all_printers_info_1_local\n"));
4494 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4497 /********************************************************************
4498 enum_all_printers_info_1_name.
4499 *********************************************************************/
4501 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4505 DEBUG(4,("enum_all_printers_info_1_name\n"));
4507 if ((name[0] == '\\') && (name[1] == '\\'))
4510 if (is_myname_or_ipaddr(s)) {
4511 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4514 return WERR_INVALID_NAME;
4517 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4518 /********************************************************************
4519 enum_all_printers_info_1_remote.
4520 *********************************************************************/
4522 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4524 PRINTER_INFO_1 *printer;
4525 fstring printername;
4528 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4529 WERROR result = WERR_OK;
4531 /* JFM: currently it's more a place holder than anything else.
4532 * In the spooler world there is a notion of server registration.
4533 * the print servers are registered on the PDC (in the same domain)
4535 * We should have a TDB here. The registration is done thru an
4536 * undocumented RPC call.
4539 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4544 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4545 slprintf(desc, sizeof(desc)-1,"%s", name);
4546 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4548 init_unistr(&printer->description, desc);
4549 init_unistr(&printer->name, printername);
4550 init_unistr(&printer->comment, comment);
4551 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4553 /* check the required size. */
4554 *needed += spoolss_size_printer_info_1(printer);
4556 if (*needed > offered) {
4557 result = WERR_INSUFFICIENT_BUFFER;
4561 if (!rpcbuf_alloc_size(buffer, *needed)) {
4562 result = WERR_NOMEM;
4566 /* fill the buffer with the structures */
4567 smb_io_printer_info_1("", buffer, printer, 0);
4573 if ( !W_ERROR_IS_OK(result) )
4581 /********************************************************************
4582 enum_all_printers_info_1_network.
4583 *********************************************************************/
4585 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4589 DEBUG(4,("enum_all_printers_info_1_network\n"));
4591 /* If we respond to a enum_printers level 1 on our name with flags
4592 set to PRINTER_ENUM_REMOTE with a list of printers then these
4593 printers incorrectly appear in the APW browse list.
4594 Specifically the printers for the server appear at the workgroup
4595 level where all the other servers in the domain are
4596 listed. Windows responds to this call with a
4597 WERR_CAN_NOT_COMPLETE so we should do the same. */
4599 if (name[0] == '\\' && name[1] == '\\')
4602 if (is_myname_or_ipaddr(s))
4603 return WERR_CAN_NOT_COMPLETE;
4605 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4608 /********************************************************************
4609 * api_spoolss_enumprinters
4611 * called from api_spoolss_enumprinters (see this to understand)
4612 ********************************************************************/
4614 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4617 struct share_iterator *shares;
4618 struct share_params *printer;
4619 PRINTER_INFO_2 *printers=NULL;
4620 WERROR result = WERR_OK;
4624 if (!(shares = share_list_all(NULL))) {
4625 DEBUG(5, ("Could not list printers\n"));
4626 return WERR_ACCESS_DENIED;
4629 while ((printer = next_printer(shares)) != NULL) {
4630 PRINTER_INFO_2 current_prt;
4632 DEBUG(4,("Found a printer in smb.conf: %s\n",
4633 lp_servicename(printer->service)));
4635 if (!construct_printer_info_2(NULL, ¤t_prt,
4639 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2,
4641 DEBUG(2,("enum_all_printers_info_2: failed to enlarge "
4642 "printers buffer!\n"));
4644 TALLOC_FREE(shares);
4648 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n",
4651 memcpy(&printers[*returned], ¤t_prt,
4652 sizeof(PRINTER_INFO_2));
4654 TALLOC_FREE(printer);
4657 /* check the required size. */
4658 for (i=0; i<*returned; i++)
4659 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4661 if (*needed > offered) {
4662 result = WERR_INSUFFICIENT_BUFFER;
4666 if (!rpcbuf_alloc_size(buffer, *needed)) {
4667 result = WERR_NOMEM;
4671 /* fill the buffer with the structures */
4672 for (i=0; i<*returned; i++)
4673 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4678 for (i=0; i<*returned; i++)
4679 free_devmode(printers[i].devmode);
4681 SAFE_FREE(printers);
4682 TALLOC_FREE(shares);
4684 if ( !W_ERROR_IS_OK(result) )
4690 /********************************************************************
4691 * handle enumeration of printers at level 1
4692 ********************************************************************/
4694 static WERROR enumprinters_level1( uint32 flags, fstring name,
4695 RPC_BUFFER *buffer, uint32 offered,
4696 uint32 *needed, uint32 *returned)
4698 /* Not all the flags are equals */
4700 if (flags & PRINTER_ENUM_LOCAL)
4701 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4703 if (flags & PRINTER_ENUM_NAME)
4704 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4706 #if 0 /* JERRY - disabled for now */
4707 if (flags & PRINTER_ENUM_REMOTE)
4708 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4711 if (flags & PRINTER_ENUM_NETWORK)
4712 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4714 return WERR_OK; /* NT4sp5 does that */
4717 /********************************************************************
4718 * handle enumeration of printers at level 2
4719 ********************************************************************/
4721 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4722 RPC_BUFFER *buffer, uint32 offered,
4723 uint32 *needed, uint32 *returned)
4725 char *s = servername;
4727 if (flags & PRINTER_ENUM_LOCAL) {
4728 return enum_all_printers_info_2(buffer, offered, needed, returned);
4731 if (flags & PRINTER_ENUM_NAME) {
4732 if ((servername[0] == '\\') && (servername[1] == '\\'))
4734 if (is_myname_or_ipaddr(s))
4735 return enum_all_printers_info_2(buffer, offered, needed, returned);
4737 return WERR_INVALID_NAME;
4740 if (flags & PRINTER_ENUM_REMOTE)
4741 return WERR_UNKNOWN_LEVEL;
4746 /********************************************************************
4747 * handle enumeration of printers at level 5
4748 ********************************************************************/
4750 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4751 RPC_BUFFER *buffer, uint32 offered,
4752 uint32 *needed, uint32 *returned)
4754 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4758 /********************************************************************
4759 * api_spoolss_enumprinters
4761 * called from api_spoolss_enumprinters (see this to understand)
4762 ********************************************************************/
4764 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4766 uint32 flags = q_u->flags;
4767 UNISTR2 *servername = &q_u->servername;
4768 uint32 level = q_u->level;
4769 RPC_BUFFER *buffer = NULL;
4770 uint32 offered = q_u->offered;
4771 uint32 *needed = &r_u->needed;
4772 uint32 *returned = &r_u->returned;
4776 /* that's an [in out] buffer */
4778 if (!q_u->buffer && (offered!=0)) {
4779 return WERR_INVALID_PARAM;
4782 rpcbuf_move(q_u->buffer, &r_u->buffer);
4783 buffer = r_u->buffer;
4785 DEBUG(4,("_spoolss_enumprinters\n"));
4792 * flags==PRINTER_ENUM_NAME
4793 * if name=="" then enumerates all printers
4794 * if name!="" then enumerate the printer
4795 * flags==PRINTER_ENUM_REMOTE
4796 * name is NULL, enumerate printers
4797 * Level 2: name!="" enumerates printers, name can't be NULL
4798 * Level 3: doesn't exist
4799 * Level 4: does a local registry lookup
4800 * Level 5: same as Level 2
4803 unistr2_to_ascii(name, servername, sizeof(name)-1);
4808 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4810 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4812 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4817 return WERR_UNKNOWN_LEVEL;
4820 /****************************************************************************
4821 ****************************************************************************/
4823 static WERROR getprinter_level_0(Printer_entry *print_hnd,
4824 const struct share_params *params,
4825 RPC_BUFFER *buffer, uint32 offered,
4828 PRINTER_INFO_0 *printer=NULL;
4829 WERROR result = WERR_OK;
4831 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4834 construct_printer_info_0(print_hnd, printer, params);
4836 /* check the required size. */
4837 *needed += spoolss_size_printer_info_0(printer);
4839 if (*needed > offered) {
4840 result = WERR_INSUFFICIENT_BUFFER;
4844 if (!rpcbuf_alloc_size(buffer, *needed)) {
4845 result = WERR_NOMEM;
4849 /* fill the buffer with the structures */
4850 smb_io_printer_info_0("", buffer, printer, 0);
4860 /****************************************************************************
4861 ****************************************************************************/
4863 static WERROR getprinter_level_1(Printer_entry *print_hnd,
4864 const struct share_params *params,
4865 RPC_BUFFER *buffer, uint32 offered,
4868 PRINTER_INFO_1 *printer=NULL;
4869 WERROR result = WERR_OK;
4871 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4874 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer,
4877 /* check the required size. */
4878 *needed += spoolss_size_printer_info_1(printer);
4880 if (*needed > offered) {
4881 result = WERR_INSUFFICIENT_BUFFER;
4885 if (!rpcbuf_alloc_size(buffer, *needed)) {
4886 result = WERR_NOMEM;
4890 /* fill the buffer with the structures */
4891 smb_io_printer_info_1("", buffer, printer, 0);
4900 /****************************************************************************
4901 ****************************************************************************/
4903 static WERROR getprinter_level_2(Printer_entry *print_hnd,
4904 const struct share_params *params,
4905 RPC_BUFFER *buffer, uint32 offered,
4908 PRINTER_INFO_2 *printer=NULL;
4909 WERROR result = WERR_OK;
4911 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4914 construct_printer_info_2(print_hnd, printer, params);
4916 /* check the required size. */
4917 *needed += spoolss_size_printer_info_2(printer);
4919 if (*needed > offered) {
4920 result = WERR_INSUFFICIENT_BUFFER;
4924 if (!rpcbuf_alloc_size(buffer, *needed)) {
4925 result = WERR_NOMEM;
4929 /* fill the buffer with the structures */
4930 if (!smb_io_printer_info_2("", buffer, printer, 0))
4931 result = WERR_NOMEM;
4935 free_printer_info_2(printer);
4940 /****************************************************************************
4941 ****************************************************************************/
4943 static WERROR getprinter_level_3(Printer_entry *print_hnd,
4944 const struct share_params *params,
4945 RPC_BUFFER *buffer, uint32 offered,
4948 PRINTER_INFO_3 *printer=NULL;
4949 WERROR result = WERR_OK;
4951 if (!construct_printer_info_3(print_hnd, &printer, params))
4954 /* check the required size. */
4955 *needed += spoolss_size_printer_info_3(printer);
4957 if (*needed > offered) {
4958 result = WERR_INSUFFICIENT_BUFFER;
4962 if (!rpcbuf_alloc_size(buffer, *needed)) {
4963 result = WERR_NOMEM;
4967 /* fill the buffer with the structures */
4968 smb_io_printer_info_3("", buffer, printer, 0);
4972 free_printer_info_3(printer);
4977 /****************************************************************************
4978 ****************************************************************************/
4980 static WERROR getprinter_level_4(Printer_entry *print_hnd,
4981 const struct share_params *params,
4982 RPC_BUFFER *buffer, uint32 offered,
4985 PRINTER_INFO_4 *printer=NULL;
4986 WERROR result = WERR_OK;
4988 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4991 if (!construct_printer_info_4(print_hnd, printer, params)) {
4996 /* check the required size. */
4997 *needed += spoolss_size_printer_info_4(printer);
4999 if (*needed > offered) {
5000 result = WERR_INSUFFICIENT_BUFFER;
5004 if (!rpcbuf_alloc_size(buffer, *needed)) {
5005 result = WERR_NOMEM;
5009 /* fill the buffer with the structures */
5010 smb_io_printer_info_4("", buffer, printer, 0);
5014 free_printer_info_4(printer);
5019 /****************************************************************************
5020 ****************************************************************************/
5022 static WERROR getprinter_level_5(Printer_entry *print_hnd,
5023 const struct share_params *params,
5024 RPC_BUFFER *buffer, uint32 offered,
5027 PRINTER_INFO_5 *printer=NULL;
5028 WERROR result = WERR_OK;
5030 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
5033 if (!construct_printer_info_5(print_hnd, printer, params)) {
5034 free_printer_info_5(printer);
5038 /* check the required size. */
5039 *needed += spoolss_size_printer_info_5(printer);
5041 if (*needed > offered) {
5042 result = WERR_INSUFFICIENT_BUFFER;
5046 if (!rpcbuf_alloc_size(buffer, *needed)) {
5047 result = WERR_NOMEM;
5051 /* fill the buffer with the structures */
5052 smb_io_printer_info_5("", buffer, printer, 0);
5056 free_printer_info_5(printer);
5061 static WERROR getprinter_level_6(Printer_entry *print_hnd,
5062 const struct share_params *params,
5063 RPC_BUFFER *buffer, uint32 offered,
5066 PRINTER_INFO_6 *printer;
5067 WERROR result = WERR_OK;
5069 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5073 if (!construct_printer_info_6(print_hnd, printer, params)) {
5074 free_printer_info_6(printer);
5078 /* check the required size. */
5079 *needed += spoolss_size_printer_info_6(printer);
5081 if (*needed > offered) {
5082 result = WERR_INSUFFICIENT_BUFFER;
5086 if (!rpcbuf_alloc_size(buffer, *needed)) {
5087 result = WERR_NOMEM;
5091 /* fill the buffer with the structures */
5092 smb_io_printer_info_6("", buffer, printer, 0);
5096 free_printer_info_6(printer);
5101 static WERROR getprinter_level_7(Printer_entry *print_hnd,
5102 const struct share_params *params,
5103 RPC_BUFFER *buffer, uint32 offered,
5106 PRINTER_INFO_7 *printer=NULL;
5107 WERROR result = WERR_OK;
5109 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5112 if (!construct_printer_info_7(print_hnd, printer, params))
5115 /* check the required size. */
5116 *needed += spoolss_size_printer_info_7(printer);
5118 if (*needed > offered) {
5119 result = WERR_INSUFFICIENT_BUFFER;
5123 if (!rpcbuf_alloc_size(buffer, *needed)) {
5124 result = WERR_NOMEM;
5129 /* fill the buffer with the structures */
5130 smb_io_printer_info_7("", buffer, printer, 0);
5134 free_printer_info_7(printer);
5139 /****************************************************************************
5140 ****************************************************************************/
5142 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5144 POLICY_HND *handle = &q_u->handle;
5145 uint32 level = q_u->level;
5146 RPC_BUFFER *buffer = NULL;
5147 uint32 offered = q_u->offered;
5148 uint32 *needed = &r_u->needed;
5149 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5150 struct share_params *params;
5154 /* that's an [in out] buffer */
5156 if (!q_u->buffer && (offered!=0)) {
5157 return WERR_INVALID_PARAM;
5160 rpcbuf_move(q_u->buffer, &r_u->buffer);
5161 buffer = r_u->buffer;
5165 if (!get_printer_snum(p, handle, &snum, ¶ms))
5170 return getprinter_level_0(Printer, params, buffer, offered,
5173 return getprinter_level_1(Printer, params, buffer, offered,
5176 return getprinter_level_2(Printer, params, buffer, offered,
5179 return getprinter_level_3(Printer, params, buffer, offered,
5182 return getprinter_level_4(Printer, params, buffer, offered,
5185 return getprinter_level_5(Printer, params, buffer, offered,
5188 return getprinter_level_6(Printer, params, buffer, offered,
5191 return getprinter_level_7(Printer, params, buffer, offered,
5194 return WERR_UNKNOWN_LEVEL;
5197 /********************************************************************
5198 * fill a DRIVER_INFO_1 struct
5199 ********************************************************************/
5201 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5203 init_unistr( &info->name, driver.info_3->name);
5206 /********************************************************************
5207 * construct_printer_driver_info_1
5208 ********************************************************************/
5210 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5212 NT_PRINTER_INFO_LEVEL *printer = NULL;
5213 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5215 ZERO_STRUCT(driver);
5217 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5218 return WERR_INVALID_PRINTER_NAME;
5220 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5221 free_a_printer(&printer, 2);
5222 return WERR_UNKNOWN_PRINTER_DRIVER;
5225 fill_printer_driver_info_1(info, driver, servername, architecture);
5227 free_a_printer(&printer,2);
5232 /********************************************************************
5233 * construct_printer_driver_info_2
5234 * fill a printer_info_2 struct
5235 ********************************************************************/
5237 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5241 info->version=driver.info_3->cversion;
5243 init_unistr( &info->name, driver.info_3->name );
5244 init_unistr( &info->architecture, driver.info_3->environment );
5247 if (strlen(driver.info_3->driverpath)) {
5248 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5249 init_unistr( &info->driverpath, temp );
5251 init_unistr( &info->driverpath, "" );
5253 if (strlen(driver.info_3->datafile)) {
5254 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5255 init_unistr( &info->datafile, temp );
5257 init_unistr( &info->datafile, "" );
5259 if (strlen(driver.info_3->configfile)) {
5260 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5261 init_unistr( &info->configfile, temp );
5263 init_unistr( &info->configfile, "" );
5266 /********************************************************************
5267 * construct_printer_driver_info_2
5268 * fill a printer_info_2 struct
5269 ********************************************************************/
5271 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5273 NT_PRINTER_INFO_LEVEL *printer = NULL;
5274 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5276 ZERO_STRUCT(printer);
5277 ZERO_STRUCT(driver);
5279 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5280 return WERR_INVALID_PRINTER_NAME;
5282 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5283 free_a_printer(&printer, 2);
5284 return WERR_UNKNOWN_PRINTER_DRIVER;
5287 fill_printer_driver_info_2(info, driver, servername);
5289 free_a_printer(&printer,2);
5294 /********************************************************************
5295 * copy a strings array and convert to UNICODE
5297 * convert an array of ascii string to a UNICODE string
5298 ********************************************************************/
5300 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5307 DEBUG(6,("init_unistr_array\n"));
5318 v = ""; /* hack to handle null lists */
5321 /* hack to allow this to be used in places other than when generating
5322 the list of dependent files */
5325 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5329 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5331 /* add one extra unit16 for the second terminating NULL */
5333 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5334 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5341 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5346 /* special case for ""; we need to add both NULL's here */
5348 (*uni_array)[j++]=0x0000;
5349 (*uni_array)[j]=0x0000;
5352 DEBUGADD(6,("last one:done\n"));
5354 /* return size of array in uint16's */
5359 /********************************************************************
5360 * construct_printer_info_3
5361 * fill a printer_info_3 struct
5362 ********************************************************************/
5364 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5370 info->version=driver.info_3->cversion;
5372 init_unistr( &info->name, driver.info_3->name );
5373 init_unistr( &info->architecture, driver.info_3->environment );
5375 if (strlen(driver.info_3->driverpath)) {
5376 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5377 init_unistr( &info->driverpath, temp );
5379 init_unistr( &info->driverpath, "" );
5381 if (strlen(driver.info_3->datafile)) {
5382 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5383 init_unistr( &info->datafile, temp );
5385 init_unistr( &info->datafile, "" );
5387 if (strlen(driver.info_3->configfile)) {
5388 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5389 init_unistr( &info->configfile, temp );
5391 init_unistr( &info->configfile, "" );
5393 if (strlen(driver.info_3->helpfile)) {
5394 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5395 init_unistr( &info->helpfile, temp );
5397 init_unistr( &info->helpfile, "" );
5399 init_unistr( &info->monitorname, driver.info_3->monitorname );
5400 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5402 info->dependentfiles=NULL;
5403 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5406 /********************************************************************
5407 * construct_printer_info_3
5408 * fill a printer_info_3 struct
5409 ********************************************************************/
5411 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5413 NT_PRINTER_INFO_LEVEL *printer = NULL;
5414 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5416 ZERO_STRUCT(driver);
5418 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5419 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5420 if (!W_ERROR_IS_OK(status))
5421 return WERR_INVALID_PRINTER_NAME;
5423 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5424 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5429 * I put this code in during testing. Helpful when commenting out the
5430 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5431 * as win2k always queries the driver using an infor level of 6.
5432 * I've left it in (but ifdef'd out) because I'll probably
5433 * use it in experimentation again in the future. --jerry 22/01/2002
5436 if (!W_ERROR_IS_OK(status)) {
5438 * Is this a W2k client ?
5441 /* Yes - try again with a WinNT driver. */
5443 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5444 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5448 if (!W_ERROR_IS_OK(status)) {
5449 free_a_printer(&printer,2);
5450 return WERR_UNKNOWN_PRINTER_DRIVER;
5458 fill_printer_driver_info_3(info, driver, servername);
5460 free_a_printer(&printer,2);
5465 /********************************************************************
5466 * construct_printer_info_6
5467 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5468 ********************************************************************/
5470 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5476 memset(&nullstr, '\0', sizeof(fstring));
5478 info->version=driver.info_3->cversion;
5480 init_unistr( &info->name, driver.info_3->name );
5481 init_unistr( &info->architecture, driver.info_3->environment );
5483 if (strlen(driver.info_3->driverpath)) {
5484 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5485 init_unistr( &info->driverpath, temp );
5487 init_unistr( &info->driverpath, "" );
5489 if (strlen(driver.info_3->datafile)) {
5490 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5491 init_unistr( &info->datafile, temp );
5493 init_unistr( &info->datafile, "" );
5495 if (strlen(driver.info_3->configfile)) {
5496 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5497 init_unistr( &info->configfile, temp );
5499 init_unistr( &info->configfile, "" );
5501 if (strlen(driver.info_3->helpfile)) {
5502 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5503 init_unistr( &info->helpfile, temp );
5505 init_unistr( &info->helpfile, "" );
5507 init_unistr( &info->monitorname, driver.info_3->monitorname );
5508 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5510 info->dependentfiles = NULL;
5511 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5513 info->previousdrivernames=NULL;
5514 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5516 info->driver_date=0;
5519 info->driver_version_low=0;
5520 info->driver_version_high=0;
5522 init_unistr( &info->mfgname, "");
5523 init_unistr( &info->oem_url, "");
5524 init_unistr( &info->hardware_id, "");
5525 init_unistr( &info->provider, "");
5528 /********************************************************************
5529 * construct_printer_info_6
5530 * fill a printer_info_6 struct
5531 ********************************************************************/
5533 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5534 fstring servername, fstring architecture, uint32 version)
5536 NT_PRINTER_INFO_LEVEL *printer = NULL;
5537 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5540 ZERO_STRUCT(driver);
5542 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5544 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5546 if (!W_ERROR_IS_OK(status))
5547 return WERR_INVALID_PRINTER_NAME;
5549 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5551 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5553 if (!W_ERROR_IS_OK(status))
5556 * Is this a W2k client ?
5560 free_a_printer(&printer,2);
5561 return WERR_UNKNOWN_PRINTER_DRIVER;
5564 /* Yes - try again with a WinNT driver. */
5566 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5567 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5568 if (!W_ERROR_IS_OK(status)) {
5569 free_a_printer(&printer,2);
5570 return WERR_UNKNOWN_PRINTER_DRIVER;
5574 fill_printer_driver_info_6(info, driver, servername);
5576 free_a_printer(&printer,2);
5577 free_a_printer_driver(driver, 3);
5582 /****************************************************************************
5583 ****************************************************************************/
5585 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5587 SAFE_FREE(info->dependentfiles);
5590 /****************************************************************************
5591 ****************************************************************************/
5593 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5595 SAFE_FREE(info->dependentfiles);
5598 /****************************************************************************
5599 ****************************************************************************/
5601 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5603 DRIVER_INFO_1 *info=NULL;
5606 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5609 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5610 if (!W_ERROR_IS_OK(result))
5613 /* check the required size. */
5614 *needed += spoolss_size_printer_driver_info_1(info);
5616 if (*needed > offered) {
5617 result = WERR_INSUFFICIENT_BUFFER;
5621 if (!rpcbuf_alloc_size(buffer, *needed)) {
5622 result = WERR_NOMEM;
5626 /* fill the buffer with the structures */
5627 smb_io_printer_driver_info_1("", buffer, info, 0);
5636 /****************************************************************************
5637 ****************************************************************************/
5639 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5641 DRIVER_INFO_2 *info=NULL;
5644 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5647 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5648 if (!W_ERROR_IS_OK(result))
5651 /* check the required size. */
5652 *needed += spoolss_size_printer_driver_info_2(info);
5654 if (*needed > offered) {
5655 result = WERR_INSUFFICIENT_BUFFER;
5659 if (!rpcbuf_alloc_size(buffer, *needed)) {
5660 result = WERR_NOMEM;
5664 /* fill the buffer with the structures */
5665 smb_io_printer_driver_info_2("", buffer, info, 0);
5674 /****************************************************************************
5675 ****************************************************************************/
5677 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5684 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5685 if (!W_ERROR_IS_OK(result))
5688 /* check the required size. */
5689 *needed += spoolss_size_printer_driver_info_3(&info);
5691 if (*needed > offered) {
5692 result = WERR_INSUFFICIENT_BUFFER;
5696 if (!rpcbuf_alloc_size(buffer, *needed)) {
5697 result = WERR_NOMEM;
5701 /* fill the buffer with the structures */
5702 smb_io_printer_driver_info_3("", buffer, &info, 0);
5705 free_printer_driver_info_3(&info);
5710 /****************************************************************************
5711 ****************************************************************************/
5713 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5720 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5721 if (!W_ERROR_IS_OK(result))
5724 /* check the required size. */
5725 *needed += spoolss_size_printer_driver_info_6(&info);
5727 if (*needed > offered) {
5728 result = WERR_INSUFFICIENT_BUFFER;
5732 if (!rpcbuf_alloc_size(buffer, *needed)) {
5733 result = WERR_NOMEM;
5737 /* fill the buffer with the structures */
5738 smb_io_printer_driver_info_6("", buffer, &info, 0);
5741 free_printer_driver_info_6(&info);
5746 /****************************************************************************
5747 ****************************************************************************/
5749 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5751 POLICY_HND *handle = &q_u->handle;
5752 UNISTR2 *uni_arch = &q_u->architecture;
5753 uint32 level = q_u->level;
5754 uint32 clientmajorversion = q_u->clientmajorversion;
5755 RPC_BUFFER *buffer = NULL;
5756 uint32 offered = q_u->offered;
5757 uint32 *needed = &r_u->needed;
5758 uint32 *servermajorversion = &r_u->servermajorversion;
5759 uint32 *serverminorversion = &r_u->serverminorversion;
5760 Printer_entry *printer;
5763 fstring architecture;
5766 /* that's an [in out] buffer */
5768 if (!q_u->buffer && (offered!=0)) {
5769 return WERR_INVALID_PARAM;
5772 rpcbuf_move(q_u->buffer, &r_u->buffer);
5773 buffer = r_u->buffer;
5775 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5777 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5778 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5779 return WERR_INVALID_PRINTER_NAME;
5783 *servermajorversion = 0;
5784 *serverminorversion = 0;
5786 fstrcpy(servername, get_server_name( printer ));
5787 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5789 if (!get_printer_snum(p, handle, &snum, NULL))
5794 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5796 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5798 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5800 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5803 /* apparently this call is the equivalent of
5804 EnumPrinterDataEx() for the DsDriver key */
5809 return WERR_UNKNOWN_LEVEL;
5812 /****************************************************************************
5813 ****************************************************************************/
5815 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5817 POLICY_HND *handle = &q_u->handle;
5819 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5822 DEBUG(3,("Error in startpageprinter printer handle\n"));
5826 Printer->page_started=True;
5830 /****************************************************************************
5831 ****************************************************************************/
5833 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5835 POLICY_HND *handle = &q_u->handle;
5838 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5841 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5845 if (!get_printer_snum(p, handle, &snum, NULL))
5848 Printer->page_started=False;
5849 print_job_endpage(snum, Printer->jobid);
5854 /********************************************************************
5855 * api_spoolss_getprinter
5856 * called from the spoolss dispatcher
5858 ********************************************************************/
5860 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5862 POLICY_HND *handle = &q_u->handle;
5863 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5864 uint32 *jobid = &r_u->jobid;
5866 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5870 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5873 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5878 * a nice thing with NT is it doesn't listen to what you tell it.
5879 * when asked to send _only_ RAW datas, it tries to send datas
5882 * So I add checks like in NT Server ...
5885 if (info_1->p_datatype != 0) {
5886 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5887 if (strcmp(datatype, "RAW") != 0) {
5889 return WERR_INVALID_DATATYPE;
5893 /* get the share number of the printer */
5894 if (!get_printer_snum(p, handle, &snum, NULL)) {
5898 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5900 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5902 /* An error occured in print_job_start() so return an appropriate
5905 if (Printer->jobid == -1) {
5906 return map_werror_from_unix(errno);
5909 Printer->document_started=True;
5910 (*jobid) = Printer->jobid;
5915 /********************************************************************
5916 * api_spoolss_getprinter
5917 * called from the spoolss dispatcher
5919 ********************************************************************/
5921 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5923 POLICY_HND *handle = &q_u->handle;
5925 return _spoolss_enddocprinter_internal(p, handle);
5928 /****************************************************************************
5929 ****************************************************************************/
5931 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5933 POLICY_HND *handle = &q_u->handle;
5934 uint32 buffer_size = q_u->buffer_size;
5935 uint8 *buffer = q_u->buffer;
5936 uint32 *buffer_written = &q_u->buffer_size2;
5938 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5941 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5942 r_u->buffer_written = q_u->buffer_size2;
5946 if (!get_printer_snum(p, handle, &snum, NULL))
5949 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5950 (SMB_OFF_T)-1, (size_t)buffer_size);
5951 if (*buffer_written == (uint32)-1) {
5952 r_u->buffer_written = 0;
5953 if (errno == ENOSPC)
5954 return WERR_NO_SPOOL_SPACE;
5956 return WERR_ACCESS_DENIED;
5959 r_u->buffer_written = q_u->buffer_size2;
5964 /********************************************************************
5965 * api_spoolss_getprinter
5966 * called from the spoolss dispatcher
5968 ********************************************************************/
5970 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5974 WERROR errcode = WERR_BADFUNC;
5975 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5978 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5982 if (!get_printer_snum(p, handle, &snum, NULL))
5986 case PRINTER_CONTROL_PAUSE:
5987 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5991 case PRINTER_CONTROL_RESUME:
5992 case PRINTER_CONTROL_UNPAUSE:
5993 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5997 case PRINTER_CONTROL_PURGE:
5998 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
6003 return WERR_UNKNOWN_LEVEL;
6009 /********************************************************************
6010 * api_spoolss_abortprinter
6011 * From MSDN: "Deletes printer's spool file if printer is configured
6013 ********************************************************************/
6015 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
6017 POLICY_HND *handle = &q_u->handle;
6018 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6020 WERROR errcode = WERR_OK;
6023 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
6027 if (!get_printer_snum(p, handle, &snum, NULL))
6030 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
6035 /********************************************************************
6036 * called by spoolss_api_setprinter
6037 * when updating a printer description
6038 ********************************************************************/
6040 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
6041 const SPOOL_PRINTER_INFO_LEVEL *info,
6042 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6044 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6048 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6050 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6051 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6052 OUR_HANDLE(handle)));
6054 result = WERR_BADFID;
6059 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6060 result = WERR_INVALID_PARAM;
6064 /* Check the user has permissions to change the security
6065 descriptor. By experimentation with two NT machines, the user
6066 requires Full Access to the printer to change security
6069 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6070 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6071 result = WERR_ACCESS_DENIED;
6075 /* NT seems to like setting the security descriptor even though
6076 nothing may have actually changed. */
6078 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
6080 if (DEBUGLEVEL >= 10) {
6084 the_acl = old_secdesc_ctr->sd->dacl;
6085 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6086 PRINTERNAME(snum), the_acl->num_aces));
6088 for (i = 0; i < the_acl->num_aces; i++) {
6091 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6093 DEBUG(10, ("%s 0x%08x\n", sid_str,
6094 the_acl->aces[i].access_mask));
6097 the_acl = secdesc_ctr->sd->dacl;
6100 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6101 PRINTERNAME(snum), the_acl->num_aces));
6103 for (i = 0; i < the_acl->num_aces; i++) {
6106 sid_to_string(sid_str, &the_acl->aces[i].trustee);
6108 DEBUG(10, ("%s 0x%08x\n", sid_str,
6109 the_acl->aces[i].access_mask));
6112 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6116 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6117 if (!new_secdesc_ctr) {
6118 result = WERR_NOMEM;
6122 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6127 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6134 /********************************************************************
6135 Canonicalize printer info from a client
6137 ATTN: It does not matter what we set the servername to hear
6138 since we do the necessary work in get_a_printer() to set it to
6139 the correct value based on what the client sent in the
6140 _spoolss_open_printer_ex().
6141 ********************************************************************/
6143 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6145 fstring printername;
6148 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6149 "portname=%s drivername=%s comment=%s location=%s\n",
6150 info->servername, info->printername, info->sharename,
6151 info->portname, info->drivername, info->comment, info->location));
6153 /* we force some elements to "correct" values */
6154 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6155 fstrcpy(info->sharename, lp_servicename(snum));
6157 /* check to see if we allow printername != sharename */
6159 if ( lp_force_printername(snum) ) {
6160 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6161 global_myname(), info->sharename );
6164 /* make sure printername is in \\server\printername format */
6166 fstrcpy( printername, info->printername );
6168 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6169 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6173 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6174 global_myname(), p );
6177 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6178 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6185 /****************************************************************************
6186 ****************************************************************************/
6188 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
6190 char *cmd = lp_addport_cmd();
6194 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6195 BOOL is_print_op = False;
6198 return WERR_ACCESS_DENIED;
6201 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
6204 is_print_op = user_has_privileges( token, &se_printop );
6206 DEBUG(10,("Running [%s]\n", command));
6208 /********* BEGIN SePrintOperatorPrivilege **********/
6213 ret = smbrun(command, &fd);
6218 /********* END SePrintOperatorPrivilege **********/
6220 DEBUGADD(10,("returned [%d]\n", ret));
6225 return WERR_ACCESS_DENIED;
6231 /****************************************************************************
6232 ****************************************************************************/
6234 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6236 char *cmd = lp_addprinter_cmd();
6242 fstring remote_machine = "%m";
6243 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6244 BOOL is_print_op = False;
6246 standard_sub_basic(current_user_info.smb_name,
6247 current_user_info.domain,
6248 remote_machine,sizeof(remote_machine));
6250 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6251 cmd, printer->info_2->printername, printer->info_2->sharename,
6252 printer->info_2->portname, printer->info_2->drivername,
6253 printer->info_2->location, printer->info_2->comment, remote_machine);
6256 is_print_op = user_has_privileges( token, &se_printop );
6258 DEBUG(10,("Running [%s]\n", command));
6260 /********* BEGIN SePrintOperatorPrivilege **********/
6265 if ( (ret = smbrun(command, &fd)) == 0 ) {
6266 /* Tell everyone we updated smb.conf. */
6267 message_send_all(smbd_messaging_context(),
6268 MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6274 /********* END SePrintOperatorPrivilege **********/
6276 DEBUGADD(10,("returned [%d]\n", ret));
6284 /* reload our services immediately */
6285 reload_services( False );
6288 /* Get lines and convert them back to dos-codepage */
6289 qlines = fd_lines_load(fd, &numlines, 0);
6290 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6293 /* Set the portname to what the script says the portname should be. */
6294 /* but don't require anything to be return from the script exit a good error code */
6297 /* Set the portname to what the script says the portname should be. */
6298 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6299 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6302 file_lines_free(qlines);
6307 /********************************************************************
6308 * Called by spoolss_api_setprinter
6309 * when updating a printer description.
6310 ********************************************************************/
6312 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6313 const SPOOL_PRINTER_INFO_LEVEL *info,
6314 DEVICEMODE *devmode)
6317 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6318 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6323 DEBUG(8,("update_printer\n"));
6328 result = WERR_BADFID;
6332 if (!get_printer_snum(p, handle, &snum, NULL)) {
6333 result = WERR_BADFID;
6337 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6338 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6339 result = WERR_BADFID;
6343 DEBUGADD(8,("Converting info_2 struct\n"));
6346 * convert_printer_info converts the incoming
6347 * info from the client and overwrites the info
6348 * just read from the tdb in the pointer 'printer'.
6351 if (!convert_printer_info(info, printer, level)) {
6352 result = WERR_NOMEM;
6357 /* we have a valid devmode
6358 convert it and link it*/
6360 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6361 if (!convert_devicemode(printer->info_2->printername, devmode,
6362 &printer->info_2->devmode)) {
6363 result = WERR_NOMEM;
6368 /* Do sanity check on the requested changes for Samba */
6370 if (!check_printer_ok(printer->info_2, snum)) {
6371 result = WERR_INVALID_PARAM;
6375 /* FIXME!!! If the driver has changed we really should verify that
6376 it is installed before doing much else --jerry */
6378 /* Check calling user has permission to update printer description */
6380 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6381 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6382 result = WERR_ACCESS_DENIED;
6386 /* Call addprinter hook */
6387 /* Check changes to see if this is really needed */
6389 if ( *lp_addprinter_cmd()
6390 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6391 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6392 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6393 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6395 /* add_printer_hook() will call reload_services() */
6397 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6398 result = WERR_ACCESS_DENIED;
6404 * When a *new* driver is bound to a printer, the drivername is used to
6405 * lookup previously saved driver initialization info, which is then
6406 * bound to the printer, simulating what happens in the Windows arch.
6408 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6410 if (!set_driver_init(printer, 2))
6412 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6413 printer->info_2->drivername));
6416 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6417 printer->info_2->drivername));
6419 notify_printer_driver(snum, printer->info_2->drivername);
6423 * flag which changes actually occured. This is a small subset of
6424 * all the possible changes. We also have to update things in the
6428 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6429 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6430 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6431 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6433 notify_printer_comment(snum, printer->info_2->comment);
6436 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6437 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6438 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6439 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6441 notify_printer_sharename(snum, printer->info_2->sharename);
6444 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6447 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6450 pname = printer->info_2->printername;
6453 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6454 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6455 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6457 notify_printer_printername( snum, pname );
6460 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6461 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6462 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6463 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6465 notify_printer_port(snum, printer->info_2->portname);
6468 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6469 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6470 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6471 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6473 notify_printer_location(snum, printer->info_2->location);
6476 /* here we need to update some more DsSpooler keys */
6477 /* uNCName, serverName, shortServerName */
6479 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6480 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6481 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6482 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6483 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6485 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6486 global_myname(), printer->info_2->sharename );
6487 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6488 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6489 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6491 /* Update printer info */
6492 result = mod_a_printer(printer, 2);
6495 free_a_printer(&printer, 2);
6496 free_a_printer(&old_printer, 2);
6502 /****************************************************************************
6503 ****************************************************************************/
6504 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6505 const SPOOL_PRINTER_INFO_LEVEL *info)
6508 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6510 Printer_entry *Printer;
6512 if ( lp_security() != SEC_ADS ) {
6513 return WERR_UNKNOWN_LEVEL;
6516 Printer = find_printer_index_by_hnd(p, handle);
6518 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6523 if (!get_printer_snum(p, handle, &snum, NULL))
6526 nt_printer_publish(Printer, snum, info7->action);
6530 return WERR_UNKNOWN_LEVEL;
6533 /****************************************************************************
6534 ****************************************************************************/
6536 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6538 POLICY_HND *handle = &q_u->handle;
6539 uint32 level = q_u->level;
6540 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6541 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6542 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6543 uint32 command = q_u->command;
6546 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6549 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6553 /* check the level */
6556 return control_printer(handle, command, p);
6558 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6559 if (!W_ERROR_IS_OK(result))
6562 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6565 return update_printer_sec(handle, level, info, p,
6568 return publish_or_unpublish_printer(p, handle, info);
6570 return WERR_UNKNOWN_LEVEL;
6574 /****************************************************************************
6575 ****************************************************************************/
6577 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6579 POLICY_HND *handle = &q_u->handle;
6580 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6583 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6587 if (Printer->notify.client_connected==True) {
6590 if ( Printer->printer_type == SPLHND_SERVER)
6592 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6593 !get_printer_snum(p, handle, &snum, NULL) )
6596 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6599 Printer->notify.flags=0;
6600 Printer->notify.options=0;
6601 Printer->notify.localmachine[0]='\0';
6602 Printer->notify.printerlocal=0;
6603 if (Printer->notify.option)
6604 free_spool_notify_option(&Printer->notify.option);
6605 Printer->notify.client_connected=False;
6610 /****************************************************************************
6611 ****************************************************************************/
6613 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6615 /* that's an [in out] buffer */
6617 if (!q_u->buffer && (q_u->offered!=0)) {
6618 return WERR_INVALID_PARAM;
6621 rpcbuf_move(q_u->buffer, &r_u->buffer);
6624 return WERR_INVALID_PARAM; /* this is what a NT server
6625 returns for AddJob. AddJob
6626 must fail on non-local
6630 /****************************************************************************
6631 ****************************************************************************/
6633 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6634 int position, int snum,
6635 const NT_PRINTER_INFO_LEVEL *ntprinter)
6639 t=gmtime(&queue->time);
6641 job_info->jobid=queue->job;
6642 init_unistr(&job_info->printername, lp_servicename(snum));
6643 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6644 init_unistr(&job_info->username, queue->fs_user);
6645 init_unistr(&job_info->document, queue->fs_file);
6646 init_unistr(&job_info->datatype, "RAW");
6647 init_unistr(&job_info->text_status, "");
6648 job_info->status=nt_printj_status(queue->status);
6649 job_info->priority=queue->priority;
6650 job_info->position=position;
6651 job_info->totalpages=queue->page_count;
6652 job_info->pagesprinted=0;
6654 make_systemtime(&job_info->submitted, t);
6657 /****************************************************************************
6658 ****************************************************************************/
6660 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6661 int position, int snum,
6662 const NT_PRINTER_INFO_LEVEL *ntprinter,
6663 DEVICEMODE *devmode)
6667 t=gmtime(&queue->time);
6669 job_info->jobid=queue->job;
6671 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6673 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6674 init_unistr(&job_info->username, queue->fs_user);
6675 init_unistr(&job_info->document, queue->fs_file);
6676 init_unistr(&job_info->notifyname, queue->fs_user);
6677 init_unistr(&job_info->datatype, "RAW");
6678 init_unistr(&job_info->printprocessor, "winprint");
6679 init_unistr(&job_info->parameters, "");
6680 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6681 init_unistr(&job_info->text_status, "");
6683 /* and here the security descriptor */
6685 job_info->status=nt_printj_status(queue->status);
6686 job_info->priority=queue->priority;
6687 job_info->position=position;
6688 job_info->starttime=0;
6689 job_info->untiltime=0;
6690 job_info->totalpages=queue->page_count;
6691 job_info->size=queue->size;
6692 make_systemtime(&(job_info->submitted), t);
6693 job_info->timeelapsed=0;
6694 job_info->pagesprinted=0;
6696 job_info->devmode = devmode;
6701 /****************************************************************************
6702 Enumjobs at level 1.
6703 ****************************************************************************/
6705 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6706 const NT_PRINTER_INFO_LEVEL *ntprinter,
6707 RPC_BUFFER *buffer, uint32 offered,
6708 uint32 *needed, uint32 *returned)
6712 WERROR result = WERR_OK;
6714 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6720 for (i=0; i<*returned; i++)
6721 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6723 /* check the required size. */
6724 for (i=0; i<*returned; i++)
6725 (*needed) += spoolss_size_job_info_1(&info[i]);
6727 if (*needed > offered) {
6728 result = WERR_INSUFFICIENT_BUFFER;
6732 if (!rpcbuf_alloc_size(buffer, *needed)) {
6733 result = WERR_NOMEM;
6737 /* fill the buffer with the structures */
6738 for (i=0; i<*returned; i++)
6739 smb_io_job_info_1("", buffer, &info[i], 0);
6745 if ( !W_ERROR_IS_OK(result) )
6751 /****************************************************************************
6752 Enumjobs at level 2.
6753 ****************************************************************************/
6755 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6756 const NT_PRINTER_INFO_LEVEL *ntprinter,
6757 RPC_BUFFER *buffer, uint32 offered,
6758 uint32 *needed, uint32 *returned)
6760 JOB_INFO_2 *info = NULL;
6762 WERROR result = WERR_OK;
6763 DEVICEMODE *devmode = NULL;
6765 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6770 /* this should not be a failure condition if the devmode is NULL */
6772 devmode = construct_dev_mode(lp_const_servicename(snum));
6774 for (i=0; i<*returned; i++)
6775 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6777 /* check the required size. */
6778 for (i=0; i<*returned; i++)
6779 (*needed) += spoolss_size_job_info_2(&info[i]);
6781 if (*needed > offered) {
6782 result = WERR_INSUFFICIENT_BUFFER;
6786 if (!rpcbuf_alloc_size(buffer, *needed)) {
6787 result = WERR_NOMEM;
6791 /* fill the buffer with the structures */
6792 for (i=0; i<*returned; i++)
6793 smb_io_job_info_2("", buffer, &info[i], 0);
6796 free_devmode(devmode);
6799 if ( !W_ERROR_IS_OK(result) )
6806 /****************************************************************************
6808 ****************************************************************************/
6810 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6812 POLICY_HND *handle = &q_u->handle;
6813 uint32 level = q_u->level;
6814 RPC_BUFFER *buffer = NULL;
6815 uint32 offered = q_u->offered;
6816 uint32 *needed = &r_u->needed;
6817 uint32 *returned = &r_u->returned;
6819 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6821 print_status_struct prt_status;
6822 print_queue_struct *queue=NULL;
6824 /* that's an [in out] buffer */
6826 if (!q_u->buffer && (offered!=0)) {
6827 return WERR_INVALID_PARAM;
6830 rpcbuf_move(q_u->buffer, &r_u->buffer);
6831 buffer = r_u->buffer;
6833 DEBUG(4,("_spoolss_enumjobs\n"));
6838 /* lookup the printer snum and tdb entry */
6840 if (!get_printer_snum(p, handle, &snum, NULL))
6843 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6844 if ( !W_ERROR_IS_OK(wret) )
6847 *returned = print_queue_status(snum, &queue, &prt_status);
6848 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6850 if (*returned == 0) {
6852 free_a_printer(&ntprinter, 2);
6858 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6861 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6865 wret = WERR_UNKNOWN_LEVEL;
6870 free_a_printer( &ntprinter, 2 );
6874 /****************************************************************************
6875 ****************************************************************************/
6877 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6882 /****************************************************************************
6883 ****************************************************************************/
6885 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6887 POLICY_HND *handle = &q_u->handle;
6888 uint32 jobid = q_u->jobid;
6889 uint32 command = q_u->command;
6892 WERROR errcode = WERR_BADFUNC;
6894 if (!get_printer_snum(p, handle, &snum, NULL)) {
6898 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6899 return WERR_INVALID_PRINTER_NAME;
6903 case JOB_CONTROL_CANCEL:
6904 case JOB_CONTROL_DELETE:
6905 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6909 case JOB_CONTROL_PAUSE:
6910 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6914 case JOB_CONTROL_RESTART:
6915 case JOB_CONTROL_RESUME:
6916 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6921 return WERR_UNKNOWN_LEVEL;
6927 /****************************************************************************
6928 Enumerates all printer drivers at level 1.
6929 ****************************************************************************/
6931 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6936 fstring *list = NULL;
6937 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6938 DRIVER_INFO_1 *driver_info_1=NULL;
6939 WERROR result = WERR_OK;
6943 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6945 ndrivers=get_ntdrivers(&list, architecture, version);
6946 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6948 if(ndrivers == -1) {
6949 SAFE_FREE(driver_info_1);
6954 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6955 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6961 for (i=0; i<ndrivers; i++) {
6963 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6964 ZERO_STRUCT(driver);
6965 status = get_a_printer_driver(&driver, 3, list[i],
6966 architecture, version);
6967 if (!W_ERROR_IS_OK(status)) {
6969 SAFE_FREE(driver_info_1);
6972 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6973 free_a_printer_driver(driver, 3);
6976 *returned+=ndrivers;
6980 /* check the required size. */
6981 for (i=0; i<*returned; i++) {
6982 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6983 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6986 if (*needed > offered) {
6987 result = WERR_INSUFFICIENT_BUFFER;
6991 if (!rpcbuf_alloc_size(buffer, *needed)) {
6992 result = WERR_NOMEM;
6996 /* fill the buffer with the driver structures */
6997 for (i=0; i<*returned; i++) {
6998 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6999 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
7003 SAFE_FREE(driver_info_1);
7005 if ( !W_ERROR_IS_OK(result) )
7011 /****************************************************************************
7012 Enumerates all printer drivers at level 2.
7013 ****************************************************************************/
7015 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7020 fstring *list = NULL;
7021 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7022 DRIVER_INFO_2 *driver_info_2=NULL;
7023 WERROR result = WERR_OK;
7027 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7029 ndrivers=get_ntdrivers(&list, architecture, version);
7030 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7032 if(ndrivers == -1) {
7033 SAFE_FREE(driver_info_2);
7038 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7039 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7045 for (i=0; i<ndrivers; i++) {
7048 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7049 ZERO_STRUCT(driver);
7050 status = get_a_printer_driver(&driver, 3, list[i],
7051 architecture, version);
7052 if (!W_ERROR_IS_OK(status)) {
7054 SAFE_FREE(driver_info_2);
7057 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7058 free_a_printer_driver(driver, 3);
7061 *returned+=ndrivers;
7065 /* check the required size. */
7066 for (i=0; i<*returned; i++) {
7067 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7068 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7071 if (*needed > offered) {
7072 result = WERR_INSUFFICIENT_BUFFER;
7076 if (!rpcbuf_alloc_size(buffer, *needed)) {
7077 result = WERR_NOMEM;
7081 /* fill the buffer with the form structures */
7082 for (i=0; i<*returned; i++) {
7083 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7084 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7088 SAFE_FREE(driver_info_2);
7090 if ( !W_ERROR_IS_OK(result) )
7096 /****************************************************************************
7097 Enumerates all printer drivers at level 3.
7098 ****************************************************************************/
7100 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7105 fstring *list = NULL;
7106 DRIVER_INFO_3 *driver_info_3=NULL;
7107 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7108 WERROR result = WERR_OK;
7112 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7114 ndrivers=get_ntdrivers(&list, architecture, version);
7115 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7117 if(ndrivers == -1) {
7118 SAFE_FREE(driver_info_3);
7123 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7124 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7130 for (i=0; i<ndrivers; i++) {
7133 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7134 ZERO_STRUCT(driver);
7135 status = get_a_printer_driver(&driver, 3, list[i],
7136 architecture, version);
7137 if (!W_ERROR_IS_OK(status)) {
7139 SAFE_FREE(driver_info_3);
7142 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7143 free_a_printer_driver(driver, 3);
7146 *returned+=ndrivers;
7150 /* check the required size. */
7151 for (i=0; i<*returned; i++) {
7152 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7153 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7156 if (*needed > offered) {
7157 result = WERR_INSUFFICIENT_BUFFER;
7161 if (!rpcbuf_alloc_size(buffer, *needed)) {
7162 result = WERR_NOMEM;
7166 /* fill the buffer with the driver structures */
7167 for (i=0; i<*returned; i++) {
7168 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7169 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7173 for (i=0; i<*returned; i++) {
7174 SAFE_FREE(driver_info_3[i].dependentfiles);
7177 SAFE_FREE(driver_info_3);
7179 if ( !W_ERROR_IS_OK(result) )
7185 /****************************************************************************
7186 Enumerates all printer drivers.
7187 ****************************************************************************/
7189 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7191 uint32 level = q_u->level;
7192 RPC_BUFFER *buffer = NULL;
7193 uint32 offered = q_u->offered;
7194 uint32 *needed = &r_u->needed;
7195 uint32 *returned = &r_u->returned;
7198 fstring architecture;
7200 /* that's an [in out] buffer */
7202 if (!q_u->buffer && (offered!=0)) {
7203 return WERR_INVALID_PARAM;
7206 rpcbuf_move(q_u->buffer, &r_u->buffer);
7207 buffer = r_u->buffer;
7209 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7214 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7215 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7217 if ( !is_myname_or_ipaddr( servername ) )
7218 return WERR_UNKNOWN_PRINTER_DRIVER;
7222 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7224 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7226 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7228 return WERR_UNKNOWN_LEVEL;
7232 /****************************************************************************
7233 ****************************************************************************/
7235 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7237 form->flag=list->flag;
7238 init_unistr(&form->name, list->name);
7239 form->width=list->width;
7240 form->length=list->length;
7241 form->left=list->left;
7242 form->top=list->top;
7243 form->right=list->right;
7244 form->bottom=list->bottom;
7247 /****************************************************************************
7248 ****************************************************************************/
7250 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7252 uint32 level = q_u->level;
7253 RPC_BUFFER *buffer = NULL;
7254 uint32 offered = q_u->offered;
7255 uint32 *needed = &r_u->needed;
7256 uint32 *numofforms = &r_u->numofforms;
7257 uint32 numbuiltinforms;
7259 nt_forms_struct *list=NULL;
7260 nt_forms_struct *builtinlist=NULL;
7265 /* that's an [in out] buffer */
7267 if (!q_u->buffer && (offered!=0) ) {
7268 return WERR_INVALID_PARAM;
7271 rpcbuf_move(q_u->buffer, &r_u->buffer);
7272 buffer = r_u->buffer;
7274 DEBUG(4,("_spoolss_enumforms\n"));
7275 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7276 DEBUGADD(5,("Info level [%d]\n", level));
7278 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7279 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7280 *numofforms = get_ntforms(&list);
7281 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7282 *numofforms += numbuiltinforms;
7284 if (*numofforms == 0) {
7285 SAFE_FREE(builtinlist);
7287 return WERR_NO_MORE_ITEMS;
7292 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7293 SAFE_FREE(builtinlist);
7299 /* construct the list of form structures */
7300 for (i=0; i<numbuiltinforms; i++) {
7301 DEBUGADD(6,("Filling form number [%d]\n",i));
7302 fill_form_1(&forms_1[i], &builtinlist[i]);
7305 SAFE_FREE(builtinlist);
7307 for (; i<*numofforms; i++) {
7308 DEBUGADD(6,("Filling form number [%d]\n",i));
7309 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7314 /* check the required size. */
7315 for (i=0; i<numbuiltinforms; i++) {
7316 DEBUGADD(6,("adding form [%d]'s size\n",i));
7317 buffer_size += spoolss_size_form_1(&forms_1[i]);
7319 for (; i<*numofforms; i++) {
7320 DEBUGADD(6,("adding form [%d]'s size\n",i));
7321 buffer_size += spoolss_size_form_1(&forms_1[i]);
7324 *needed=buffer_size;
7326 if (*needed > offered) {
7329 return WERR_INSUFFICIENT_BUFFER;
7332 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7338 /* fill the buffer with the form structures */
7339 for (i=0; i<numbuiltinforms; i++) {
7340 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7341 smb_io_form_1("", buffer, &forms_1[i], 0);
7343 for (; i<*numofforms; i++) {
7344 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7345 smb_io_form_1("", buffer, &forms_1[i], 0);
7354 SAFE_FREE(builtinlist);
7355 return WERR_UNKNOWN_LEVEL;
7359 /****************************************************************************
7360 ****************************************************************************/
7362 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7364 uint32 level = q_u->level;
7365 UNISTR2 *uni_formname = &q_u->formname;
7366 RPC_BUFFER *buffer = NULL;
7367 uint32 offered = q_u->offered;
7368 uint32 *needed = &r_u->needed;
7370 nt_forms_struct *list=NULL;
7371 nt_forms_struct builtin_form;
7376 int numofforms=0, i=0;
7378 /* that's an [in out] buffer */
7380 if (!q_u->buffer && (offered!=0)) {
7381 return WERR_INVALID_PARAM;
7384 rpcbuf_move(q_u->buffer, &r_u->buffer);
7385 buffer = r_u->buffer;
7387 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7389 DEBUG(4,("_spoolss_getform\n"));
7390 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7391 DEBUGADD(5,("Info level [%d]\n", level));
7393 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7394 if (!foundBuiltin) {
7395 numofforms = get_ntforms(&list);
7396 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7398 if (numofforms == 0)
7405 fill_form_1(&form_1, &builtin_form);
7408 /* Check if the requested name is in the list of form structures */
7409 for (i=0; i<numofforms; i++) {
7411 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7413 if (strequal(form_name, list[i].name)) {
7414 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7415 fill_form_1(&form_1, &list[i]);
7421 if (i == numofforms) {
7425 /* check the required size. */
7427 *needed=spoolss_size_form_1(&form_1);
7429 if (*needed > offered)
7430 return WERR_INSUFFICIENT_BUFFER;
7432 if (!rpcbuf_alloc_size(buffer, buffer_size))
7435 /* fill the buffer with the form structures */
7436 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7437 smb_io_form_1("", buffer, &form_1, 0);
7443 return WERR_UNKNOWN_LEVEL;
7447 /****************************************************************************
7448 ****************************************************************************/
7450 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7452 init_unistr(&port->port_name, name);
7455 /****************************************************************************
7456 TODO: This probably needs distinguish between TCP/IP and Local ports
7458 ****************************************************************************/
7460 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7462 init_unistr(&port->port_name, name);
7463 init_unistr(&port->monitor_name, "Local Monitor");
7464 init_unistr(&port->description, SPL_LOCAL_PORT );
7465 port->port_type=PORT_TYPE_WRITE;
7470 /****************************************************************************
7471 wrapper around the enumer ports command
7472 ****************************************************************************/
7474 WERROR enumports_hook( int *count, char ***lines )
7476 char *cmd = lp_enumports_cmd();
7486 /* if no hook then just fill in the default port */
7489 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7490 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7495 /* we have a valid enumport command */
7497 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7499 DEBUG(10,("Running [%s]\n", command));
7500 ret = smbrun(command, &fd);
7501 DEBUG(10,("Returned [%d]\n", ret));
7506 return WERR_ACCESS_DENIED;
7510 qlines = fd_lines_load(fd, &numlines, 0);
7511 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7521 /****************************************************************************
7523 ****************************************************************************/
7525 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7527 PORT_INFO_1 *ports=NULL;
7529 WERROR result = WERR_OK;
7530 char **qlines = NULL;
7533 result = enumports_hook( &numlines, &qlines );
7534 if (!W_ERROR_IS_OK(result)) {
7535 file_lines_free(qlines);
7540 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7541 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7542 dos_errstr(WERR_NOMEM)));
7543 file_lines_free(qlines);
7547 for (i=0; i<numlines; i++) {
7548 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7549 fill_port_1(&ports[i], qlines[i]);
7552 file_lines_free(qlines);
7554 *returned = numlines;
7556 /* check the required size. */
7557 for (i=0; i<*returned; i++) {
7558 DEBUGADD(6,("adding port [%d]'s size\n", i));
7559 *needed += spoolss_size_port_info_1(&ports[i]);
7562 if (*needed > offered) {
7563 result = WERR_INSUFFICIENT_BUFFER;
7567 if (!rpcbuf_alloc_size(buffer, *needed)) {
7568 result = WERR_NOMEM;
7572 /* fill the buffer with the ports structures */
7573 for (i=0; i<*returned; i++) {
7574 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7575 smb_io_port_1("", buffer, &ports[i], 0);
7581 if ( !W_ERROR_IS_OK(result) )
7587 /****************************************************************************
7589 ****************************************************************************/
7591 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7593 PORT_INFO_2 *ports=NULL;
7595 WERROR result = WERR_OK;
7596 char **qlines = NULL;
7599 result = enumports_hook( &numlines, &qlines );
7600 if ( !W_ERROR_IS_OK(result)) {
7601 file_lines_free(qlines);
7606 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7607 file_lines_free(qlines);
7611 for (i=0; i<numlines; i++) {
7612 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7613 fill_port_2(&(ports[i]), qlines[i]);
7617 file_lines_free(qlines);
7619 *returned = numlines;
7621 /* check the required size. */
7622 for (i=0; i<*returned; i++) {
7623 DEBUGADD(6,("adding port [%d]'s size\n", i));
7624 *needed += spoolss_size_port_info_2(&ports[i]);
7627 if (*needed > offered) {
7628 result = WERR_INSUFFICIENT_BUFFER;
7632 if (!rpcbuf_alloc_size(buffer, *needed)) {
7633 result = WERR_NOMEM;
7637 /* fill the buffer with the ports structures */
7638 for (i=0; i<*returned; i++) {
7639 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7640 smb_io_port_2("", buffer, &ports[i], 0);
7646 if ( !W_ERROR_IS_OK(result) )
7652 /****************************************************************************
7654 ****************************************************************************/
7656 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7658 uint32 level = q_u->level;
7659 RPC_BUFFER *buffer = NULL;
7660 uint32 offered = q_u->offered;
7661 uint32 *needed = &r_u->needed;
7662 uint32 *returned = &r_u->returned;
7664 /* that's an [in out] buffer */
7666 if (!q_u->buffer && (offered!=0)) {
7667 return WERR_INVALID_PARAM;
7670 rpcbuf_move(q_u->buffer, &r_u->buffer);
7671 buffer = r_u->buffer;
7673 DEBUG(4,("_spoolss_enumports\n"));
7680 return enumports_level_1(buffer, offered, needed, returned);
7682 return enumports_level_2(buffer, offered, needed, returned);
7684 return WERR_UNKNOWN_LEVEL;
7688 /****************************************************************************
7689 ****************************************************************************/
7691 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7692 const SPOOL_PRINTER_INFO_LEVEL *info,
7693 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7694 uint32 user_switch, const SPOOL_USER_CTR *user,
7697 NT_PRINTER_INFO_LEVEL *printer = NULL;
7700 WERROR err = WERR_OK;
7702 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7703 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7707 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7708 if (!convert_printer_info(info, printer, 2)) {
7709 free_a_printer(&printer, 2);
7713 /* check to see if the printer already exists */
7715 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7716 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7717 printer->info_2->sharename));
7718 free_a_printer(&printer, 2);
7719 return WERR_PRINTER_ALREADY_EXISTS;
7722 /* FIXME!!! smbd should check to see if the driver is installed before
7723 trying to add a printer like this --jerry */
7725 if (*lp_addprinter_cmd() ) {
7726 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7727 free_a_printer(&printer,2);
7728 return WERR_ACCESS_DENIED;
7731 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7732 "smb.conf parameter \"addprinter command\" is defined. This"
7733 "parameter must exist for this call to succeed\n",
7734 printer->info_2->sharename ));
7737 /* use our primary netbios name since get_a_printer() will convert
7738 it to what the client expects on a case by case basis */
7740 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7741 printer->info_2->sharename);
7744 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7745 free_a_printer(&printer,2);
7746 return WERR_ACCESS_DENIED;
7749 /* you must be a printer admin to add a new printer */
7750 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7751 free_a_printer(&printer,2);
7752 return WERR_ACCESS_DENIED;
7756 * Do sanity check on the requested changes for Samba.
7759 if (!check_printer_ok(printer->info_2, snum)) {
7760 free_a_printer(&printer,2);
7761 return WERR_INVALID_PARAM;
7765 * When a printer is created, the drivername bound to the printer is used
7766 * to lookup previously saved driver initialization info, which is then
7767 * bound to the new printer, simulating what happens in the Windows arch.
7772 set_driver_init(printer, 2);
7776 /* A valid devmode was included, convert and link it
7778 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7780 if (!convert_devicemode(printer->info_2->printername, devmode,
7781 &printer->info_2->devmode))
7785 /* write the ASCII on disk */
7786 err = mod_a_printer(printer, 2);
7787 if (!W_ERROR_IS_OK(err)) {
7788 free_a_printer(&printer,2);
7792 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7793 /* Handle open failed - remove addition. */
7794 del_a_printer(printer->info_2->sharename);
7795 free_a_printer(&printer,2);
7796 return WERR_ACCESS_DENIED;
7799 update_c_setprinter(False);
7800 free_a_printer(&printer,2);
7805 /****************************************************************************
7806 ****************************************************************************/
7808 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7810 UNISTR2 *uni_srv_name = q_u->server_name;
7811 uint32 level = q_u->level;
7812 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7813 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7814 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7815 uint32 user_switch = q_u->user_switch;
7816 SPOOL_USER_CTR *user = &q_u->user_ctr;
7817 POLICY_HND *handle = &r_u->handle;
7821 /* we don't handle yet */
7822 /* but I know what to do ... */
7823 return WERR_UNKNOWN_LEVEL;
7825 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7827 user_switch, user, handle);
7829 return WERR_UNKNOWN_LEVEL;
7833 /****************************************************************************
7834 ****************************************************************************/
7836 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7838 uint32 level = q_u->level;
7839 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7840 WERROR err = WERR_OK;
7841 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7842 fstring driver_name;
7845 ZERO_STRUCT(driver);
7847 if (!convert_printer_driver_info(info, &driver, level)) {
7852 DEBUG(5,("Cleaning driver's information\n"));
7853 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7854 if (!W_ERROR_IS_OK(err))
7857 DEBUG(5,("Moving driver to final destination\n"));
7858 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7862 if (add_a_printer_driver(driver, level)!=0) {
7863 err = WERR_ACCESS_DENIED;
7868 * I think this is where he DrvUpgradePrinter() hook would be
7869 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7870 * server. Right now, we just need to send ourselves a message
7871 * to update each printer bound to this driver. --jerry
7874 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7875 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7880 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7881 * decide if the driver init data should be deleted. The rules are:
7882 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7883 * 2) delete init data only if there is no 2k/Xp driver
7884 * 3) always delete init data
7885 * The generalized rule is always use init data from the highest order driver.
7886 * It is necessary to follow the driver install by an initialization step to
7887 * finish off this process.
7890 version = driver.info_3->cversion;
7891 else if (level == 6)
7892 version = driver.info_6->version;
7897 * 9x printer driver - never delete init data
7900 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7905 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7906 * there is no 2k/Xp driver init data for this driver name.
7910 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7912 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7914 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7916 if (!del_driver_init(driver_name))
7917 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7920 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7922 free_a_printer_driver(driver1,3);
7923 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7930 * 2k or Xp printer driver - always delete init data
7933 if (!del_driver_init(driver_name))
7934 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7938 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7944 free_a_printer_driver(driver, level);
7948 /********************************************************************
7949 * spoolss_addprinterdriverex
7950 ********************************************************************/
7952 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7954 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7955 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7958 * we only support the semantics of AddPrinterDriver()
7959 * i.e. only copy files that are newer than existing ones
7962 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7963 return WERR_ACCESS_DENIED;
7965 ZERO_STRUCT(q_u_local);
7966 ZERO_STRUCT(r_u_local);
7968 /* just pass the information off to _spoolss_addprinterdriver() */
7969 q_u_local.server_name_ptr = q_u->server_name_ptr;
7970 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7971 q_u_local.level = q_u->level;
7972 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7974 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7977 /****************************************************************************
7978 ****************************************************************************/
7980 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7982 init_unistr(&info->name, name);
7985 /****************************************************************************
7986 ****************************************************************************/
7988 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7994 const char *short_archi;
7995 DRIVER_DIRECTORY_1 *info=NULL;
7996 WERROR result = WERR_OK;
7998 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7999 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
8001 /* check for beginning double '\'s and that the server
8004 pservername = servername;
8005 if ( *pservername == '\\' && strlen(servername)>2 ) {
8009 if ( !is_myname_or_ipaddr( pservername ) )
8010 return WERR_INVALID_PARAM;
8012 if (!(short_archi = get_short_archi(long_archi)))
8013 return WERR_INVALID_ENVIRONMENT;
8015 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8018 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
8020 DEBUG(4,("printer driver directory: [%s]\n", path));
8022 fill_driverdir_1(info, path);
8024 *needed += spoolss_size_driverdir_info_1(info);
8026 if (*needed > offered) {
8027 result = WERR_INSUFFICIENT_BUFFER;
8031 if (!rpcbuf_alloc_size(buffer, *needed)) {
8032 result = WERR_NOMEM;
8036 smb_io_driverdir_1("", buffer, info, 0);
8044 /****************************************************************************
8045 ****************************************************************************/
8047 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8049 UNISTR2 *name = &q_u->name;
8050 UNISTR2 *uni_environment = &q_u->environment;
8051 uint32 level = q_u->level;
8052 RPC_BUFFER *buffer = NULL;
8053 uint32 offered = q_u->offered;
8054 uint32 *needed = &r_u->needed;
8056 /* that's an [in out] buffer */
8058 if (!q_u->buffer && (offered!=0)) {
8059 return WERR_INVALID_PARAM;
8062 rpcbuf_move(q_u->buffer, &r_u->buffer);
8063 buffer = r_u->buffer;
8065 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8071 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8073 return WERR_UNKNOWN_LEVEL;
8077 /****************************************************************************
8078 ****************************************************************************/
8080 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8082 POLICY_HND *handle = &q_u->handle;
8083 uint32 idx = q_u->index;
8084 uint32 in_value_len = q_u->valuesize;
8085 uint32 in_data_len = q_u->datasize;
8086 uint32 *out_max_value_len = &r_u->valuesize;
8087 uint16 **out_value = &r_u->value;
8088 uint32 *out_value_len = &r_u->realvaluesize;
8089 uint32 *out_type = &r_u->type;
8090 uint32 *out_max_data_len = &r_u->datasize;
8091 uint8 **data_out = &r_u->data;
8092 uint32 *out_data_len = &r_u->realdatasize;
8094 NT_PRINTER_INFO_LEVEL *printer = NULL;
8096 uint32 biggest_valuesize;
8097 uint32 biggest_datasize;
8099 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8102 REGISTRY_VALUE *val = NULL;
8103 NT_PRINTER_DATA *p_data;
8104 int i, key_index, num_values;
8109 *out_max_data_len = 0;
8113 DEBUG(5,("spoolss_enumprinterdata\n"));
8116 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8120 if (!get_printer_snum(p,handle, &snum, NULL))
8123 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8124 if (!W_ERROR_IS_OK(result))
8127 p_data = printer->info_2->data;
8128 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8133 * The NT machine wants to know the biggest size of value and data
8135 * cf: MSDN EnumPrinterData remark section
8138 if ( !in_value_len && !in_data_len && (key_index != -1) )
8140 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8142 biggest_valuesize = 0;
8143 biggest_datasize = 0;
8145 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8147 for ( i=0; i<num_values; i++ )
8149 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8151 name_length = strlen(val->valuename);
8152 if ( strlen(val->valuename) > biggest_valuesize )
8153 biggest_valuesize = name_length;
8155 if ( val->size > biggest_datasize )
8156 biggest_datasize = val->size;
8158 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8162 /* the value is an UNICODE string but real_value_size is the length
8163 in bytes including the trailing 0 */
8165 *out_value_len = 2 * (1+biggest_valuesize);
8166 *out_data_len = biggest_datasize;
8168 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8174 * the value len is wrong in NT sp3
8175 * that's the number of bytes not the number of unicode chars
8178 if ( key_index != -1 )
8179 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8184 /* out_value should default to "" or else NT4 has
8185 problems unmarshalling the response */
8187 *out_max_value_len=(in_value_len/sizeof(uint16));
8190 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8192 result = WERR_NOMEM;
8195 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8201 /* the data is counted in bytes */
8203 *out_max_data_len = in_data_len;
8204 *out_data_len = in_data_len;
8206 /* only allocate when given a non-zero data_len */
8208 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8210 result = WERR_NOMEM;
8214 result = WERR_NO_MORE_ITEMS;
8220 * - counted in bytes in the request
8221 * - counted in UNICODE chars in the max reply
8222 * - counted in bytes in the real size
8224 * take a pause *before* coding not *during* coding
8228 *out_max_value_len=(in_value_len/sizeof(uint16));
8230 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8232 result = WERR_NOMEM;
8236 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8244 *out_type = regval_type( val );
8246 /* data - counted in bytes */
8248 *out_max_data_len = in_data_len;
8249 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8251 result = WERR_NOMEM;
8254 data_len = regval_size(val);
8255 if ( *data_out && data_len )
8256 memcpy( *data_out, regval_data_p(val), data_len );
8257 *out_data_len = data_len;
8261 free_a_printer(&printer, 2);
8265 /****************************************************************************
8266 ****************************************************************************/
8268 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8270 POLICY_HND *handle = &q_u->handle;
8271 UNISTR2 *value = &q_u->value;
8272 uint32 type = q_u->type;
8273 uint8 *data = q_u->data;
8274 uint32 real_len = q_u->real_len;
8276 NT_PRINTER_INFO_LEVEL *printer = NULL;
8278 WERROR status = WERR_OK;
8279 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8282 DEBUG(5,("spoolss_setprinterdata\n"));
8285 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8289 if ( Printer->printer_type == SPLHND_SERVER ) {
8290 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8291 return WERR_INVALID_PARAM;
8294 if (!get_printer_snum(p,handle, &snum, NULL))
8298 * Access check : NT returns "access denied" if you make a
8299 * SetPrinterData call without the necessary privildge.
8300 * we were originally returning OK if nothing changed
8301 * which made Win2k issue **a lot** of SetPrinterData
8302 * when connecting to a printer --jerry
8305 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8307 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8308 status = WERR_ACCESS_DENIED;
8312 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8313 if (!W_ERROR_IS_OK(status))
8316 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8319 * When client side code sets a magic printer data key, detect it and save
8320 * the current printer data and the magic key's data (its the DEVMODE) for
8321 * future printer/driver initializations.
8323 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8325 /* Set devmode and printer initialization info */
8326 status = save_driver_init( printer, 2, data, real_len );
8328 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8332 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8333 type, data, real_len );
8334 if ( W_ERROR_IS_OK(status) )
8335 status = mod_a_printer(printer, 2);
8339 free_a_printer(&printer, 2);
8344 /****************************************************************************
8345 ****************************************************************************/
8347 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8349 POLICY_HND *handle = &q_u->handle;
8350 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8353 DEBUG(5,("_spoolss_resetprinter\n"));
8356 * All we do is to check to see if the handle and queue is valid.
8357 * This call really doesn't mean anything to us because we only
8358 * support RAW printing. --jerry
8362 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8366 if (!get_printer_snum(p,handle, &snum, NULL))
8370 /* blindly return success */
8375 /****************************************************************************
8376 ****************************************************************************/
8378 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8380 POLICY_HND *handle = &q_u->handle;
8381 UNISTR2 *value = &q_u->valuename;
8383 NT_PRINTER_INFO_LEVEL *printer = NULL;
8385 WERROR status = WERR_OK;
8386 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8389 DEBUG(5,("spoolss_deleteprinterdata\n"));
8392 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8396 if (!get_printer_snum(p, handle, &snum, NULL))
8399 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8400 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8401 return WERR_ACCESS_DENIED;
8404 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8405 if (!W_ERROR_IS_OK(status))
8408 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8410 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8412 if ( W_ERROR_IS_OK(status) )
8413 mod_a_printer( printer, 2 );
8415 free_a_printer(&printer, 2);
8420 /****************************************************************************
8421 ****************************************************************************/
8423 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8425 POLICY_HND *handle = &q_u->handle;
8426 FORM *form = &q_u->form;
8427 nt_forms_struct tmpForm;
8429 WERROR status = WERR_OK;
8430 NT_PRINTER_INFO_LEVEL *printer = NULL;
8433 nt_forms_struct *list=NULL;
8434 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8436 DEBUG(5,("spoolss_addform\n"));
8439 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8444 /* forms can be added on printer of on the print server handle */
8446 if ( Printer->printer_type == SPLHND_PRINTER )
8448 if (!get_printer_snum(p,handle, &snum, NULL))
8451 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8452 if (!W_ERROR_IS_OK(status))
8456 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8457 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8458 status = WERR_ACCESS_DENIED;
8462 /* can't add if builtin */
8464 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8465 status = WERR_ALREADY_EXISTS;
8469 count = get_ntforms(&list);
8471 if(!add_a_form(&list, form, &count)) {
8472 status = WERR_NOMEM;
8476 write_ntforms(&list, count);
8479 * ChangeID must always be set if this is a printer
8482 if ( Printer->printer_type == SPLHND_PRINTER )
8483 status = mod_a_printer(printer, 2);
8487 free_a_printer(&printer, 2);
8493 /****************************************************************************
8494 ****************************************************************************/
8496 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8498 POLICY_HND *handle = &q_u->handle;
8499 UNISTR2 *form_name = &q_u->name;
8500 nt_forms_struct tmpForm;
8502 nt_forms_struct *list=NULL;
8503 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8505 WERROR status = WERR_OK;
8506 NT_PRINTER_INFO_LEVEL *printer = NULL;
8508 DEBUG(5,("spoolss_deleteform\n"));
8511 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8515 /* forms can be deleted on printer of on the print server handle */
8517 if ( Printer->printer_type == SPLHND_PRINTER )
8519 if (!get_printer_snum(p,handle, &snum, NULL))
8522 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8523 if (!W_ERROR_IS_OK(status))
8527 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8528 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8529 status = WERR_ACCESS_DENIED;
8533 /* can't delete if builtin */
8535 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8536 status = WERR_INVALID_PARAM;
8540 count = get_ntforms(&list);
8542 if ( !delete_a_form(&list, form_name, &count, &status ))
8546 * ChangeID must always be set if this is a printer
8549 if ( Printer->printer_type == SPLHND_PRINTER )
8550 status = mod_a_printer(printer, 2);
8554 free_a_printer(&printer, 2);
8560 /****************************************************************************
8561 ****************************************************************************/
8563 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8565 POLICY_HND *handle = &q_u->handle;
8566 FORM *form = &q_u->form;
8567 nt_forms_struct tmpForm;
8569 WERROR status = WERR_OK;
8570 NT_PRINTER_INFO_LEVEL *printer = NULL;
8573 nt_forms_struct *list=NULL;
8574 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8576 DEBUG(5,("spoolss_setform\n"));
8579 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8583 /* forms can be modified on printer of on the print server handle */
8585 if ( Printer->printer_type == SPLHND_PRINTER )
8587 if (!get_printer_snum(p,handle, &snum, NULL))
8590 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8591 if (!W_ERROR_IS_OK(status))
8595 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8596 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8597 status = WERR_ACCESS_DENIED;
8601 /* can't set if builtin */
8602 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8603 status = WERR_INVALID_PARAM;
8607 count = get_ntforms(&list);
8608 update_a_form(&list, form, count);
8609 write_ntforms(&list, count);
8612 * ChangeID must always be set if this is a printer
8615 if ( Printer->printer_type == SPLHND_PRINTER )
8616 status = mod_a_printer(printer, 2);
8621 free_a_printer(&printer, 2);
8627 /****************************************************************************
8628 enumprintprocessors level 1.
8629 ****************************************************************************/
8631 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8633 PRINTPROCESSOR_1 *info_1=NULL;
8634 WERROR result = WERR_OK;
8636 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8641 init_unistr(&info_1->name, "winprint");
8643 *needed += spoolss_size_printprocessor_info_1(info_1);
8645 if (*needed > offered) {
8646 result = WERR_INSUFFICIENT_BUFFER;
8650 if (!rpcbuf_alloc_size(buffer, *needed)) {
8651 result = WERR_NOMEM;
8655 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8660 if ( !W_ERROR_IS_OK(result) )
8666 /****************************************************************************
8667 ****************************************************************************/
8669 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8671 uint32 level = q_u->level;
8672 RPC_BUFFER *buffer = NULL;
8673 uint32 offered = q_u->offered;
8674 uint32 *needed = &r_u->needed;
8675 uint32 *returned = &r_u->returned;
8677 /* that's an [in out] buffer */
8679 if (!q_u->buffer && (offered!=0)) {
8680 return WERR_INVALID_PARAM;
8683 rpcbuf_move(q_u->buffer, &r_u->buffer);
8684 buffer = r_u->buffer;
8686 DEBUG(5,("spoolss_enumprintprocessors\n"));
8689 * Enumerate the print processors ...
8691 * Just reply with "winprint", to keep NT happy
8692 * and I can use my nice printer checker.
8700 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8702 return WERR_UNKNOWN_LEVEL;
8706 /****************************************************************************
8707 enumprintprocdatatypes level 1.
8708 ****************************************************************************/
8710 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8712 PRINTPROCDATATYPE_1 *info_1=NULL;
8713 WERROR result = WERR_OK;
8715 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8720 init_unistr(&info_1->name, "RAW");
8722 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8724 if (*needed > offered) {
8725 result = WERR_INSUFFICIENT_BUFFER;
8729 if (!rpcbuf_alloc_size(buffer, *needed)) {
8730 result = WERR_NOMEM;
8734 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8739 if ( !W_ERROR_IS_OK(result) )
8745 /****************************************************************************
8746 ****************************************************************************/
8748 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8750 uint32 level = q_u->level;
8751 RPC_BUFFER *buffer = NULL;
8752 uint32 offered = q_u->offered;
8753 uint32 *needed = &r_u->needed;
8754 uint32 *returned = &r_u->returned;
8756 /* that's an [in out] buffer */
8758 if (!q_u->buffer && (offered!=0)) {
8759 return WERR_INVALID_PARAM;
8762 rpcbuf_move(q_u->buffer, &r_u->buffer);
8763 buffer = r_u->buffer;
8765 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8772 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8774 return WERR_UNKNOWN_LEVEL;
8778 /****************************************************************************
8779 enumprintmonitors level 1.
8780 ****************************************************************************/
8782 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8784 PRINTMONITOR_1 *info_1;
8785 WERROR result = WERR_OK;
8788 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8793 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8794 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8796 for ( i=0; i<*returned; i++ ) {
8797 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8800 if (*needed > offered) {
8801 result = WERR_INSUFFICIENT_BUFFER;
8805 if (!rpcbuf_alloc_size(buffer, *needed)) {
8806 result = WERR_NOMEM;
8810 for ( i=0; i<*returned; i++ ) {
8811 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8817 if ( !W_ERROR_IS_OK(result) )
8823 /****************************************************************************
8824 enumprintmonitors level 2.
8825 ****************************************************************************/
8827 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8829 PRINTMONITOR_2 *info_2;
8830 WERROR result = WERR_OK;
8833 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8838 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8839 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8840 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8842 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8843 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8844 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8846 for ( i=0; i<*returned; i++ ) {
8847 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8850 if (*needed > offered) {
8851 result = WERR_INSUFFICIENT_BUFFER;
8855 if (!rpcbuf_alloc_size(buffer, *needed)) {
8856 result = WERR_NOMEM;
8860 for ( i=0; i<*returned; i++ ) {
8861 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8867 if ( !W_ERROR_IS_OK(result) )
8873 /****************************************************************************
8874 ****************************************************************************/
8876 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8878 uint32 level = q_u->level;
8879 RPC_BUFFER *buffer = NULL;
8880 uint32 offered = q_u->offered;
8881 uint32 *needed = &r_u->needed;
8882 uint32 *returned = &r_u->returned;
8884 /* that's an [in out] buffer */
8886 if (!q_u->buffer && (offered!=0)) {
8887 return WERR_INVALID_PARAM;
8890 rpcbuf_move(q_u->buffer, &r_u->buffer);
8891 buffer = r_u->buffer;
8893 DEBUG(5,("spoolss_enumprintmonitors\n"));
8896 * Enumerate the print monitors ...
8898 * Just reply with "Local Port", to keep NT happy
8899 * and I can use my nice printer checker.
8907 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8909 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8911 return WERR_UNKNOWN_LEVEL;
8915 /****************************************************************************
8916 ****************************************************************************/
8918 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8919 NT_PRINTER_INFO_LEVEL *ntprinter,
8920 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8925 JOB_INFO_1 *info_1=NULL;
8926 WERROR result = WERR_OK;
8928 info_1=SMB_MALLOC_P(JOB_INFO_1);
8930 if (info_1 == NULL) {
8934 for (i=0; i<count && found==False; i++) {
8935 if ((*queue)[i].job==(int)jobid)
8941 /* NT treats not found as bad param... yet another bad choice */
8942 return WERR_INVALID_PARAM;
8945 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8947 *needed += spoolss_size_job_info_1(info_1);
8949 if (*needed > offered) {
8950 result = WERR_INSUFFICIENT_BUFFER;
8954 if (!rpcbuf_alloc_size(buffer, *needed)) {
8955 result = WERR_NOMEM;
8959 smb_io_job_info_1("", buffer, info_1, 0);
8967 /****************************************************************************
8968 ****************************************************************************/
8970 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8971 NT_PRINTER_INFO_LEVEL *ntprinter,
8972 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8979 DEVICEMODE *devmode = NULL;
8980 NT_DEVICEMODE *nt_devmode = NULL;
8982 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8985 ZERO_STRUCTP(info_2);
8987 for ( i=0; i<count && found==False; i++ )
8989 if ((*queue)[i].job == (int)jobid)
8994 /* NT treats not found as bad param... yet another bad
8996 result = WERR_INVALID_PARAM;
9001 * if the print job does not have a DEVMODE associated with it,
9002 * just use the one for the printer. A NULL devicemode is not
9003 * a failure condition
9006 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9007 devmode = construct_dev_mode(lp_const_servicename(snum));
9009 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9010 ZERO_STRUCTP( devmode );
9011 convert_nt_devicemode( devmode, nt_devmode );
9015 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9017 *needed += spoolss_size_job_info_2(info_2);
9019 if (*needed > offered) {
9020 result = WERR_INSUFFICIENT_BUFFER;
9024 if (!rpcbuf_alloc_size(buffer, *needed)) {
9025 result = WERR_NOMEM;
9029 smb_io_job_info_2("", buffer, info_2, 0);
9034 /* Cleanup allocated memory */
9036 free_job_info_2(info_2); /* Also frees devmode */
9042 /****************************************************************************
9043 ****************************************************************************/
9045 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9047 POLICY_HND *handle = &q_u->handle;
9048 uint32 jobid = q_u->jobid;
9049 uint32 level = q_u->level;
9050 RPC_BUFFER *buffer = NULL;
9051 uint32 offered = q_u->offered;
9052 uint32 *needed = &r_u->needed;
9053 WERROR wstatus = WERR_OK;
9054 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9057 print_queue_struct *queue = NULL;
9058 print_status_struct prt_status;
9060 /* that's an [in out] buffer */
9062 if (!q_u->buffer && (offered!=0)) {
9063 return WERR_INVALID_PARAM;
9066 rpcbuf_move(q_u->buffer, &r_u->buffer);
9067 buffer = r_u->buffer;
9069 DEBUG(5,("spoolss_getjob\n"));
9073 if (!get_printer_snum(p, handle, &snum, NULL))
9076 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9077 if ( !W_ERROR_IS_OK(wstatus) )
9080 count = print_queue_status(snum, &queue, &prt_status);
9082 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9083 count, prt_status.status, prt_status.message));
9087 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9088 buffer, offered, needed);
9091 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9092 buffer, offered, needed);
9095 wstatus = WERR_UNKNOWN_LEVEL;
9100 free_a_printer( &ntprinter, 2 );
9105 /********************************************************************
9106 spoolss_getprinterdataex
9108 From MSDN documentation of GetPrinterDataEx: pass request
9109 to GetPrinterData if key is "PrinterDriverData".
9110 ********************************************************************/
9112 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9114 POLICY_HND *handle = &q_u->handle;
9115 uint32 in_size = q_u->size;
9116 uint32 *type = &r_u->type;
9117 uint32 *out_size = &r_u->size;
9118 uint8 **data = &r_u->data;
9119 uint32 *needed = &r_u->needed;
9120 fstring keyname, valuename;
9122 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9124 NT_PRINTER_INFO_LEVEL *printer = NULL;
9126 WERROR status = WERR_OK;
9128 DEBUG(4,("_spoolss_getprinterdataex\n"));
9130 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
9131 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
9133 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9134 keyname, valuename));
9136 /* in case of problem, return some default values */
9140 *out_size = in_size;
9143 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9144 status = WERR_BADFID;
9148 /* Is the handle to a printer or to the server? */
9150 if (Printer->printer_type == SPLHND_SERVER) {
9151 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9152 status = WERR_INVALID_PARAM;
9156 if ( !get_printer_snum(p,handle, &snum, NULL) )
9159 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9160 if ( !W_ERROR_IS_OK(status) )
9163 /* check to see if the keyname is valid */
9164 if ( !strlen(keyname) ) {
9165 status = WERR_INVALID_PARAM;
9169 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9170 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9171 free_a_printer( &printer, 2 );
9172 status = WERR_BADFILE;
9176 /* When given a new keyname, we should just create it */
9178 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9180 if (*needed > *out_size)
9181 status = WERR_MORE_DATA;
9184 if ( !W_ERROR_IS_OK(status) )
9186 DEBUG(5, ("error: allocating %d\n", *out_size));
9188 /* reply this param doesn't exist */
9192 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9193 status = WERR_NOMEM;
9202 free_a_printer( &printer, 2 );
9207 /********************************************************************
9208 * spoolss_setprinterdataex
9209 ********************************************************************/
9211 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9213 POLICY_HND *handle = &q_u->handle;
9214 uint32 type = q_u->type;
9215 uint8 *data = q_u->data;
9216 uint32 real_len = q_u->real_len;
9218 NT_PRINTER_INFO_LEVEL *printer = NULL;
9220 WERROR status = WERR_OK;
9221 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9226 DEBUG(4,("_spoolss_setprinterdataex\n"));
9228 /* From MSDN documentation of SetPrinterDataEx: pass request to
9229 SetPrinterData if key is "PrinterDriverData" */
9232 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9236 if ( Printer->printer_type == SPLHND_SERVER ) {
9237 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9238 return WERR_INVALID_PARAM;
9241 if ( !get_printer_snum(p,handle, &snum, NULL) )
9245 * Access check : NT returns "access denied" if you make a
9246 * SetPrinterData call without the necessary privildge.
9247 * we were originally returning OK if nothing changed
9248 * which made Win2k issue **a lot** of SetPrinterData
9249 * when connecting to a printer --jerry
9252 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9254 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9255 return WERR_ACCESS_DENIED;
9258 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9259 if (!W_ERROR_IS_OK(status))
9262 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9263 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9265 /* check for OID in valuename */
9267 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9273 /* save the registry data */
9275 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9277 if ( W_ERROR_IS_OK(status) )
9279 /* save the OID if one was specified */
9281 fstrcat( keyname, "\\" );
9282 fstrcat( keyname, SPOOL_OID_KEY );
9285 * I'm not checking the status here on purpose. Don't know
9286 * if this is right, but I'm returning the status from the
9287 * previous set_printer_dataex() call. I have no idea if
9288 * this is right. --jerry
9291 set_printer_dataex( printer, keyname, valuename,
9292 REG_SZ, (uint8 *)oid_string,
9293 strlen(oid_string)+1 );
9296 status = mod_a_printer(printer, 2);
9299 free_a_printer(&printer, 2);
9305 /********************************************************************
9306 * spoolss_deleteprinterdataex
9307 ********************************************************************/
9309 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9311 POLICY_HND *handle = &q_u->handle;
9312 UNISTR2 *value = &q_u->valuename;
9313 UNISTR2 *key = &q_u->keyname;
9315 NT_PRINTER_INFO_LEVEL *printer = NULL;
9317 WERROR status = WERR_OK;
9318 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9319 pstring valuename, keyname;
9321 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9324 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9328 if (!get_printer_snum(p, handle, &snum, NULL))
9331 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9332 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9333 return WERR_ACCESS_DENIED;
9336 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9337 if (!W_ERROR_IS_OK(status))
9340 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9341 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9343 status = delete_printer_dataex( printer, keyname, valuename );
9345 if ( W_ERROR_IS_OK(status) )
9346 mod_a_printer( printer, 2 );
9348 free_a_printer(&printer, 2);
9353 /********************************************************************
9354 * spoolss_enumprinterkey
9355 ********************************************************************/
9358 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9361 fstring *keynames = NULL;
9362 uint16 *enumkeys = NULL;
9365 POLICY_HND *handle = &q_u->handle;
9366 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9367 NT_PRINTER_DATA *data;
9368 NT_PRINTER_INFO_LEVEL *printer = NULL;
9370 WERROR status = WERR_BADFILE;
9373 DEBUG(4,("_spoolss_enumprinterkey\n"));
9376 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9380 if ( !get_printer_snum(p,handle, &snum, NULL) )
9383 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9384 if (!W_ERROR_IS_OK(status))
9387 /* get the list of subkey names */
9389 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9390 data = printer->info_2->data;
9392 num_keys = get_printer_subkeys( data, key, &keynames );
9394 if ( num_keys == -1 ) {
9395 status = WERR_BADFILE;
9399 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9401 r_u->needed = printerkey_len*2;
9403 if ( q_u->size < r_u->needed ) {
9404 status = WERR_MORE_DATA;
9408 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9409 status = WERR_NOMEM;
9415 if ( q_u->size < r_u->needed )
9416 status = WERR_MORE_DATA;
9419 free_a_printer( &printer, 2 );
9420 SAFE_FREE( keynames );
9425 /********************************************************************
9426 * spoolss_deleteprinterkey
9427 ********************************************************************/
9429 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9431 POLICY_HND *handle = &q_u->handle;
9432 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9434 NT_PRINTER_INFO_LEVEL *printer = NULL;
9438 DEBUG(5,("spoolss_deleteprinterkey\n"));
9441 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9445 /* if keyname == NULL, return error */
9447 if ( !q_u->keyname.buffer )
9448 return WERR_INVALID_PARAM;
9450 if (!get_printer_snum(p, handle, &snum, NULL))
9453 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9454 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9455 return WERR_ACCESS_DENIED;
9458 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9459 if (!W_ERROR_IS_OK(status))
9462 /* delete the key and all subneys */
9464 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9466 status = delete_all_printer_data( printer->info_2, key );
9468 if ( W_ERROR_IS_OK(status) )
9469 status = mod_a_printer(printer, 2);
9471 free_a_printer( &printer, 2 );
9477 /********************************************************************
9478 * spoolss_enumprinterdataex
9479 ********************************************************************/
9481 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9483 POLICY_HND *handle = &q_u->handle;
9484 uint32 in_size = q_u->size;
9487 NT_PRINTER_INFO_LEVEL *printer = NULL;
9488 PRINTER_ENUM_VALUES *enum_values = NULL;
9489 NT_PRINTER_DATA *p_data;
9491 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9496 REGISTRY_VALUE *val;
9501 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9504 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9509 * first check for a keyname of NULL or "". Win2k seems to send
9510 * this a lot and we should send back WERR_INVALID_PARAM
9511 * no need to spend time looking up the printer in this case.
9515 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9516 if ( !strlen(key) ) {
9517 result = WERR_INVALID_PARAM;
9521 /* get the printer off of disk */
9523 if (!get_printer_snum(p,handle, &snum, NULL))
9526 ZERO_STRUCT(printer);
9527 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9528 if (!W_ERROR_IS_OK(result))
9531 /* now look for a match on the key name */
9533 p_data = printer->info_2->data;
9535 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9536 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9538 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9539 result = WERR_INVALID_PARAM;
9546 /* allocate the memory for the array of pointers -- if necessary */
9548 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9551 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9553 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9554 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9555 result = WERR_NOMEM;
9559 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9563 * loop through all params and build the array to pass
9564 * back to the client
9567 for ( i=0; i<num_entries; i++ )
9569 /* lookup the registry value */
9571 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9572 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9576 value_name = regval_name( val );
9577 init_unistr( &enum_values[i].valuename, value_name );
9578 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9579 enum_values[i].type = regval_type( val );
9581 data_len = regval_size( val );
9583 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9585 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9587 result = WERR_NOMEM;
9591 enum_values[i].data_len = data_len;
9593 /* keep track of the size of the array in bytes */
9595 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9598 /* housekeeping information in the reply */
9600 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9601 * the hand marshalled container size is a multiple
9602 * of 4 bytes for RPC alignment.
9606 needed += 4-(needed % 4);
9609 r_u->needed = needed;
9610 r_u->returned = num_entries;
9612 if (needed > in_size) {
9613 result = WERR_MORE_DATA;
9617 /* copy data into the reply */
9619 r_u->ctr.size = r_u->needed;
9621 r_u->ctr.size_of_array = r_u->returned;
9622 r_u->ctr.values = enum_values;
9628 free_a_printer(&printer, 2);
9633 /****************************************************************************
9634 ****************************************************************************/
9636 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9638 init_unistr(&info->name, name);
9641 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9642 UNISTR2 *environment,
9649 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9650 WERROR result = WERR_OK;
9652 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9654 if (!get_short_archi(long_archi))
9655 return WERR_INVALID_ENVIRONMENT;
9657 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9660 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9662 fill_printprocessordirectory_1(info, path);
9664 *needed += spoolss_size_printprocessordirectory_info_1(info);
9666 if (*needed > offered) {
9667 result = WERR_INSUFFICIENT_BUFFER;
9671 if (!rpcbuf_alloc_size(buffer, *needed)) {
9672 result = WERR_INSUFFICIENT_BUFFER;
9676 smb_io_printprocessordirectory_1("", buffer, info, 0);
9684 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9686 uint32 level = q_u->level;
9687 RPC_BUFFER *buffer = NULL;
9688 uint32 offered = q_u->offered;
9689 uint32 *needed = &r_u->needed;
9692 /* that's an [in out] buffer */
9694 if (!q_u->buffer && (offered!=0)) {
9695 return WERR_INVALID_PARAM;
9698 rpcbuf_move(q_u->buffer, &r_u->buffer);
9699 buffer = r_u->buffer;
9701 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9707 result = getprintprocessordirectory_level_1
9708 (&q_u->name, &q_u->environment, buffer, offered, needed);
9711 result = WERR_UNKNOWN_LEVEL;
9717 /*******************************************************************
9718 Streams the monitor UI DLL name in UNICODE
9719 *******************************************************************/
9721 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9722 RPC_BUFFER *out, uint32 *needed )
9724 const char *dllname = "tcpmonui.dll";
9726 *needed = (strlen(dllname)+1) * 2;
9728 if ( rpcbuf_get_size(out) < *needed ) {
9729 return WERR_INSUFFICIENT_BUFFER;
9732 if ( !make_monitorui_buf( out, dllname ) ) {
9739 /*******************************************************************
9740 Create a new TCP/IP port
9741 *******************************************************************/
9743 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9744 RPC_BUFFER *out, uint32 *needed )
9746 NT_PORT_DATA_1 port1;
9749 ZERO_STRUCT( port1 );
9751 /* convert to our internal port data structure */
9753 if ( !convert_port_data_1( &port1, in ) ) {
9757 /* create the device URI and call the add_port_hook() */
9759 switch ( port1.protocol ) {
9760 case PORT_PROTOCOL_DIRECT:
9761 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9764 case PORT_PROTOCOL_LPR:
9765 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9769 return WERR_UNKNOWN_PORT;
9772 return add_port_hook( token, port1.name, device_uri );
9775 /*******************************************************************
9776 *******************************************************************/
9778 struct xcv_api_table xcvtcp_cmds[] = {
9779 { "MonitorUI", xcvtcp_monitorui },
9780 { "AddPort", xcvtcp_addport},
9784 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9785 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9790 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9792 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9793 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9794 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9797 return WERR_BADFUNC;
9800 /*******************************************************************
9801 *******************************************************************/
9802 #if 0 /* don't support management using the "Local Port" monitor */
9804 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9805 RPC_BUFFER *out, uint32 *needed )
9807 const char *dllname = "localui.dll";
9809 *needed = (strlen(dllname)+1) * 2;
9811 if ( rpcbuf_get_size(out) < *needed ) {
9812 return WERR_INSUFFICIENT_BUFFER;
9815 if ( !make_monitorui_buf( out, dllname )) {
9822 /*******************************************************************
9823 *******************************************************************/
9825 struct xcv_api_table xcvlocal_cmds[] = {
9826 { "MonitorUI", xcvlocal_monitorui },
9830 struct xcv_api_table xcvlocal_cmds[] = {
9837 /*******************************************************************
9838 *******************************************************************/
9840 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9841 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9846 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9848 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9849 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9850 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9852 return WERR_BADFUNC;
9855 /*******************************************************************
9856 *******************************************************************/
9858 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9860 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9864 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9868 /* Has to be a handle to the TCP/IP port monitor */
9870 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9871 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9875 /* requires administrative access to the server */
9877 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9878 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9879 return WERR_ACCESS_DENIED;
9882 /* Get the command name. There's numerous commands supported by the
9883 TCPMON interface. */
9885 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9886 q_u->dataname.uni_str_len*2, 0);
9888 /* Allocate the outgoing buffer */
9890 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9892 switch ( Printer->printer_type ) {
9893 case SPLHND_PORTMON_TCP:
9894 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9895 &q_u->indata, &r_u->outdata, &r_u->needed );
9896 case SPLHND_PORTMON_LOCAL:
9897 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9898 &q_u->indata, &r_u->outdata, &r_u->needed );
9901 return WERR_INVALID_PRINT_MONITOR;