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 3 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, see <http://www.gnu.org/licenses/>.
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26 up, all the errors returned are DOS errors, not NT status codes. */
30 extern userdom_struct current_user_info;
33 #define DBGC_CLASS DBGC_RPC_SRV
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
43 const char *long_archi;
44 const char *short_archi;
48 static Printer_entry *printers_list;
50 typedef struct _counter_printer_0 {
51 struct _counter_printer_0 *next;
52 struct _counter_printer_0 *prev;
58 static counter_printer_0 *counter_list;
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
64 /* in printing/nt_printing.c */
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
68 /* API table for Xcv Monitor functions */
70 struct xcv_api_table {
72 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
75 /********************************************************************
76 * Canonicalize servername.
77 ********************************************************************/
79 static const char *canon_servername(const char *servername)
81 const char *pservername = servername;
82 while (*pservername == '\\') {
88 /* translate between internal status numbers and NT status numbers */
89 static int nt_printj_status(int v)
95 return JOB_STATUS_PAUSED;
97 return JOB_STATUS_SPOOLING;
99 return JOB_STATUS_PRINTING;
101 return JOB_STATUS_ERROR;
103 return JOB_STATUS_DELETING;
105 return JOB_STATUS_OFFLINE;
107 return JOB_STATUS_PAPEROUT;
109 return JOB_STATUS_PRINTED;
111 return JOB_STATUS_DELETED;
113 return JOB_STATUS_BLOCKED;
114 case LPQ_USER_INTERVENTION:
115 return JOB_STATUS_USER_INTERVENTION;
120 static int nt_printq_status(int v)
124 return PRINTER_STATUS_PAUSED;
133 /****************************************************************************
134 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
135 ****************************************************************************/
137 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
142 SAFE_FREE((*pp)->ctr.type);
146 /***************************************************************************
147 Disconnect from the client
148 ****************************************************************************/
150 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
155 * Tell the specific printing tdb we no longer want messages for this printer
156 * by deregistering our PID.
159 if (!print_notify_deregister_pid(snum))
160 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
162 /* weird if the test succeds !!! */
163 if (smb_connections==0) {
164 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
168 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe,
172 if (!W_ERROR_IS_OK(result))
173 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
174 dos_errstr(result)));
176 /* if it's the last connection, deconnect the IPC$ share */
177 if (smb_connections==1) {
179 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
180 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
182 messaging_deregister(smbd_messaging_context(),
183 MSG_PRINTER_NOTIFY2, NULL);
185 /* Tell the connections db we're no longer interested in
186 * printer notify messages. */
188 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
194 /****************************************************************************
195 Functions to free a printer entry datastruct.
196 ****************************************************************************/
198 static void free_printer_entry(void *ptr)
200 Printer_entry *Printer = (Printer_entry *)ptr;
202 if (Printer->notify.client_connected==True) {
205 if ( Printer->printer_type == SPLHND_SERVER) {
207 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
208 } else if (Printer->printer_type == SPLHND_PRINTER) {
209 snum = print_queue_snum(Printer->sharename);
211 srv_spoolss_replycloseprinter(snum,
212 &Printer->notify.client_hnd);
216 Printer->notify.flags=0;
217 Printer->notify.options=0;
218 Printer->notify.localmachine[0]='\0';
219 Printer->notify.printerlocal=0;
220 free_spool_notify_option(&Printer->notify.option);
221 Printer->notify.option=NULL;
222 Printer->notify.client_connected=False;
224 free_nt_devicemode( &Printer->nt_devmode );
225 free_a_printer( &Printer->printer_info, 2 );
227 talloc_destroy( Printer->ctx );
229 /* Remove from the internal list. */
230 DLIST_REMOVE(printers_list, Printer);
235 /****************************************************************************
236 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
237 ****************************************************************************/
239 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
241 SPOOL_NOTIFY_OPTION *new_sp = NULL;
246 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
253 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
255 if (!new_sp->ctr.type) {
264 /****************************************************************************
265 find printer index by handle
266 ****************************************************************************/
268 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
270 Printer_entry *find_printer = NULL;
272 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
273 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
280 /****************************************************************************
281 Close printer index by handle.
282 ****************************************************************************/
284 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
286 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
289 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
293 close_policy_hnd(p, hnd);
298 /****************************************************************************
299 Delete a printer given a handle.
300 ****************************************************************************/
302 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
304 char *cmd = lp_deleteprinter_cmd();
305 char *command = NULL;
307 SE_PRIV se_printop = SE_PRINT_OPERATOR;
308 bool is_print_op = False;
310 /* can't fail if we don't try */
315 command = talloc_asprintf(ctx,
322 is_print_op = user_has_privileges( token, &se_printop );
324 DEBUG(10,("Running [%s]\n", command));
326 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
331 if ( (ret = smbrun(command, NULL)) == 0 ) {
332 /* Tell everyone we updated smb.conf. */
333 message_send_all(smbd_messaging_context(),
334 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
340 /********** END SePrintOperatorPrivlege BLOCK **********/
342 DEBUGADD(10,("returned [%d]\n", ret));
344 TALLOC_FREE(command);
347 return WERR_BADFID; /* What to return here? */
349 /* go ahead and re-read the services immediately */
350 reload_services( False );
352 if ( lp_servicenumber( sharename ) < 0 )
353 return WERR_ACCESS_DENIED;
358 /****************************************************************************
359 Delete a printer given a handle.
360 ****************************************************************************/
362 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
364 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
367 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
372 * It turns out that Windows allows delete printer on a handle
373 * opened by an admin user, then used on a pipe handle created
374 * by an anonymous user..... but they're working on security.... riiight !
378 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
379 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
380 return WERR_ACCESS_DENIED;
383 /* this does not need a become root since the access check has been
384 done on the handle already */
386 if (del_a_printer( Printer->sharename ) != 0) {
387 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
391 return delete_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, Printer->sharename );
394 /****************************************************************************
395 Return the snum of a printer corresponding to an handle.
396 ****************************************************************************/
398 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
399 struct share_params **params)
401 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
404 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
408 switch (Printer->printer_type) {
410 DEBUG(4,("short name:%s\n", Printer->sharename));
411 *number = print_queue_snum(Printer->sharename);
412 return (*number != -1);
420 /****************************************************************************
421 Set printer handle type.
422 Check if it's \\server or \\server\printer
423 ****************************************************************************/
425 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
427 DEBUG(3,("Setting printer type=%s\n", handlename));
429 if ( strlen(handlename) < 3 ) {
430 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
434 /* it's a print server */
435 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
436 DEBUGADD(4,("Printer is a print server\n"));
437 Printer->printer_type = SPLHND_SERVER;
439 /* it's a printer (set_printer_hnd_name() will handle port monitors */
441 DEBUGADD(4,("Printer is a printer\n"));
442 Printer->printer_type = SPLHND_PRINTER;
448 /****************************************************************************
449 Set printer handle name.. Accept names like \\server, \\server\printer,
450 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
451 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
452 XcvDataPort() interface.
453 ****************************************************************************/
455 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
458 int n_services=lp_numservices();
459 char *aprinter, *printername;
460 const char *servername;
463 NT_PRINTER_INFO_LEVEL *printer = NULL;
466 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
468 aprinter = handlename;
469 if ( *handlename == '\\' ) {
470 servername = canon_servername(handlename);
471 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
479 /* save the servername to fill in replies on this handle */
481 if ( !is_myname_or_ipaddr( servername ) )
484 fstrcpy( Printer->servername, servername );
486 if ( Printer->printer_type == SPLHND_SERVER )
489 if ( Printer->printer_type != SPLHND_PRINTER )
492 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
494 /* check for the Port Monitor Interface */
496 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
497 Printer->printer_type = SPLHND_PORTMON_TCP;
498 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
501 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
502 Printer->printer_type = SPLHND_PORTMON_LOCAL;
503 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
507 /* Search all sharenames first as this is easier than pulling
508 the printer_info_2 off of disk. Don't use find_service() since
509 that calls out to map_username() */
511 /* do another loop to look for printernames */
513 for (snum=0; !found && snum<n_services; snum++) {
515 /* no point going on if this is not a printer */
517 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
520 fstrcpy(sname, lp_servicename(snum));
521 if ( strequal( aprinter, sname ) ) {
526 /* no point looking up the printer object if
527 we aren't allowing printername != sharename */
529 if ( lp_force_printername(snum) )
532 fstrcpy(sname, lp_servicename(snum));
536 /* This call doesn't fill in the location or comment from
537 * a CUPS server for efficiency with large numbers of printers.
541 result = get_a_printer_search( NULL, &printer, 2, sname );
542 if ( !W_ERROR_IS_OK(result) ) {
543 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
544 sname, dos_errstr(result)));
548 /* printername is always returned as \\server\printername */
549 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
550 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
551 printer->info_2->printername));
552 free_a_printer( &printer, 2);
558 if ( strequal(printername, aprinter) ) {
559 free_a_printer( &printer, 2);
564 DEBUGADD(10, ("printername: %s\n", printername));
566 free_a_printer( &printer, 2);
569 free_a_printer( &printer, 2);
572 DEBUGADD(4,("Printer not found\n"));
576 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
578 fstrcpy(Printer->sharename, sname);
583 /****************************************************************************
584 Find first available printer slot. creates a printer handle for you.
585 ****************************************************************************/
587 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
589 Printer_entry *new_printer;
591 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
593 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
596 ZERO_STRUCTP(new_printer);
598 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
599 SAFE_FREE(new_printer);
603 /* Add to the internal list. */
604 DLIST_ADD(printers_list, new_printer);
606 new_printer->notify.option=NULL;
608 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
609 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
610 close_printer_handle(p, hnd);
614 if (!set_printer_hnd_printertype(new_printer, name)) {
615 close_printer_handle(p, hnd);
619 if (!set_printer_hnd_name(new_printer, name)) {
620 close_printer_handle(p, hnd);
624 new_printer->access_granted = access_granted;
626 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
631 /***************************************************************************
632 check to see if the client motify handle is monitoring the notification
633 given by (notify_type, notify_field).
634 **************************************************************************/
636 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
642 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
645 SPOOL_NOTIFY_OPTION *option = p->notify.option;
649 * Flags should always be zero when the change notify
650 * is registered by the client's spooler. A user Win32 app
651 * might use the flags though instead of the NOTIFY_OPTION_INFO
660 return is_monitoring_event_flags(
661 p->notify.flags, notify_type, notify_field);
663 for (i = 0; i < option->count; i++) {
665 /* Check match for notify_type */
667 if (option->ctr.type[i].type != notify_type)
670 /* Check match for field */
672 for (j = 0; j < option->ctr.type[i].count; j++) {
673 if (option->ctr.type[i].fields[j] == notify_field) {
679 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
680 p->servername, p->sharename, notify_type, notify_field));
685 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
687 static void notify_one_value(struct spoolss_notify_msg *msg,
688 SPOOL_NOTIFY_INFO_DATA *data,
691 data->notify_data.value[0] = msg->notify.value[0];
692 data->notify_data.value[1] = 0;
695 static void notify_string(struct spoolss_notify_msg *msg,
696 SPOOL_NOTIFY_INFO_DATA *data,
701 /* The length of the message includes the trailing \0 */
703 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
705 data->notify_data.data.length = msg->len * 2;
706 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
708 if (!data->notify_data.data.string) {
709 data->notify_data.data.length = 0;
713 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
716 static void notify_system_time(struct spoolss_notify_msg *msg,
717 SPOOL_NOTIFY_INFO_DATA *data,
723 if (msg->len != sizeof(time_t)) {
724 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
729 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
730 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
734 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
735 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
740 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
745 data->notify_data.data.length = prs_offset(&ps);
746 if (prs_offset(&ps)) {
747 data->notify_data.data.string = (uint16 *)
748 TALLOC(mem_ctx, prs_offset(&ps));
749 if (!data->notify_data.data.string) {
753 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
755 data->notify_data.data.string = NULL;
761 struct notify2_message_table {
763 void (*fn)(struct spoolss_notify_msg *msg,
764 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
767 static struct notify2_message_table printer_notify_table[] = {
768 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
769 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
770 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
771 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
772 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
773 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
774 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
775 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
776 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
777 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
778 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
779 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
780 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
781 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
782 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
783 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
784 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
785 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
786 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
789 static struct notify2_message_table job_notify_table[] = {
790 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
791 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
792 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
793 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
794 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
795 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
796 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
797 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
798 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
799 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
800 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
801 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
802 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
803 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
804 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
805 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
806 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
807 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
808 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
809 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
810 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
811 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
812 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
813 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
817 /***********************************************************************
818 Allocate talloc context for container object
819 **********************************************************************/
821 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
826 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
831 /***********************************************************************
832 release all allocated memory and zero out structure
833 **********************************************************************/
835 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
841 talloc_destroy(ctr->ctx);
848 /***********************************************************************
849 **********************************************************************/
851 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
859 /***********************************************************************
860 **********************************************************************/
862 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
864 if ( !ctr || !ctr->msg_groups )
867 if ( idx >= ctr->num_groups )
870 return &ctr->msg_groups[idx];
874 /***********************************************************************
875 How many groups of change messages do we have ?
876 **********************************************************************/
878 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
883 return ctr->num_groups;
886 /***********************************************************************
887 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
888 **********************************************************************/
890 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
892 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
893 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
894 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
900 /* loop over all groups looking for a matching printer name */
902 for ( i=0; i<ctr->num_groups; i++ ) {
903 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
907 /* add a new group? */
909 if ( i == ctr->num_groups ) {
912 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
913 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
916 ctr->msg_groups = groups;
918 /* clear the new entry and set the printer name */
920 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
921 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
924 /* add the change messages; 'i' is the correct index now regardless */
926 msg_grp = &ctr->msg_groups[i];
930 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
931 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
934 msg_grp->msgs = msg_list;
936 new_slot = msg_grp->num_msgs-1;
937 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
939 /* need to allocate own copy of data */
942 msg_grp->msgs[new_slot].notify.data = (char *)
943 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
945 return ctr->num_groups;
948 /***********************************************************************
949 Send a change notication message on all handles which have a call
951 **********************************************************************/
953 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
956 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
957 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
958 SPOOLSS_NOTIFY_MSG *messages;
959 int sending_msg_count;
962 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
966 messages = msg_group->msgs;
969 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
973 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
975 /* loop over all printers */
977 for (p = printers_list; p; p = p->next) {
978 SPOOL_NOTIFY_INFO_DATA *data;
983 /* Is there notification on this handle? */
985 if ( !p->notify.client_connected )
988 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
990 /* For this printer? Print servers always receive
993 if ( ( p->printer_type == SPLHND_PRINTER ) &&
994 ( !strequal(msg_group->printername, p->sharename) ) )
997 DEBUG(10,("Our printer\n"));
999 /* allocate the max entries possible */
1001 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
1008 /* build the array of change notifications */
1010 sending_msg_count = 0;
1012 for ( i=0; i<msg_group->num_msgs; i++ ) {
1013 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1015 /* Are we monitoring this event? */
1017 if (!is_monitoring_event(p, msg->type, msg->field))
1020 sending_msg_count++;
1023 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1024 msg->type, msg->field, p->sharename));
1027 * if the is a printer notification handle and not a job notification
1028 * type, then set the id to 0. Other wise just use what was specified
1031 * When registering change notification on a print server handle
1032 * we always need to send back the id (snum) matching the printer
1033 * for which the change took place. For change notify registered
1034 * on a printer handle, this does not matter and the id should be 0.
1039 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1045 /* Convert unix jobid to smb jobid */
1047 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1048 id = sysjob_to_jobid(msg->id);
1051 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1056 construct_info_data( &data[data_len], msg->type, msg->field, id );
1059 case PRINTER_NOTIFY_TYPE:
1060 if ( printer_notify_table[msg->field].fn )
1061 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1064 case JOB_NOTIFY_TYPE:
1065 if ( job_notify_table[msg->field].fn )
1066 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1070 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1077 if ( sending_msg_count ) {
1078 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1079 data_len, data, p->notify.change, 0 );
1084 DEBUG(8,("send_notify2_changes: Exit...\n"));
1088 /***********************************************************************
1089 **********************************************************************/
1091 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1094 uint32 tv_sec, tv_usec;
1097 /* Unpack message */
1099 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1102 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1104 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1107 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1108 &msg->notify.value[0], &msg->notify.value[1]);
1110 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1111 &msg->len, &msg->notify.data);
1113 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1114 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1116 tv->tv_sec = tv_sec;
1117 tv->tv_usec = tv_usec;
1120 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1121 msg->notify.value[1]));
1123 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1128 /********************************************************************
1129 Receive a notify2 message list
1130 ********************************************************************/
1132 static void receive_notify2_message_list(struct messaging_context *msg,
1135 struct server_id server_id,
1138 size_t msg_count, i;
1139 char *buf = (char *)data->data;
1142 SPOOLSS_NOTIFY_MSG notify;
1143 SPOOLSS_NOTIFY_MSG_CTR messages;
1146 if (data->length < 4) {
1147 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1151 msg_count = IVAL(buf, 0);
1154 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1156 if (msg_count == 0) {
1157 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1161 /* initialize the container */
1163 ZERO_STRUCT( messages );
1164 notify_msg_ctr_init( &messages );
1167 * build message groups for each printer identified
1168 * in a change_notify msg. Remember that a PCN message
1169 * includes the handle returned for the srv_spoolss_replyopenprinter()
1170 * call. Therefore messages are grouped according to printer handle.
1173 for ( i=0; i<msg_count; i++ ) {
1174 struct timeval msg_tv;
1176 if (msg_ptr + 4 - buf > data->length) {
1177 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1181 msg_len = IVAL(msg_ptr,0);
1184 if (msg_ptr + msg_len - buf > data->length) {
1185 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1189 /* unpack messages */
1191 ZERO_STRUCT( notify );
1192 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1195 /* add to correct list in container */
1197 notify_msg_ctr_addmsg( &messages, ¬ify );
1199 /* free memory that might have been allocated by notify2_unpack_msg() */
1201 if ( notify.len != 0 )
1202 SAFE_FREE( notify.notify.data );
1205 /* process each group of messages */
1207 num_groups = notify_msg_ctr_numgroups( &messages );
1208 for ( i=0; i<num_groups; i++ )
1209 send_notify2_changes( &messages, i );
1214 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1216 notify_msg_ctr_destroy( &messages );
1221 /********************************************************************
1222 Send a message to ourself about new driver being installed
1223 so we can upgrade the information for each printer bound to this
1225 ********************************************************************/
1227 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1229 int len = strlen(drivername);
1234 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1237 messaging_send_buf(smbd_messaging_context(), procid_self(),
1238 MSG_PRINTER_DRVUPGRADE,
1239 (uint8 *)drivername, len+1);
1244 /**********************************************************************
1245 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1246 over all printers, upgrading ones as necessary
1247 **********************************************************************/
1249 void do_drv_upgrade_printer(struct messaging_context *msg,
1252 struct server_id server_id,
1257 int n_services = lp_numservices();
1260 len = MIN(data->length,sizeof(drivername)-1);
1261 strncpy(drivername, (const char *)data->data, len);
1263 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1265 /* Iterate the printer list */
1267 for (snum=0; snum<n_services; snum++)
1269 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1272 NT_PRINTER_INFO_LEVEL *printer = NULL;
1274 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1275 if (!W_ERROR_IS_OK(result))
1278 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1280 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1282 /* all we care about currently is the change_id */
1284 result = mod_a_printer(printer, 2);
1285 if (!W_ERROR_IS_OK(result)) {
1286 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1287 dos_errstr(result)));
1291 free_a_printer(&printer, 2);
1298 /********************************************************************
1299 Update the cache for all printq's with a registered client
1301 ********************************************************************/
1303 void update_monitored_printq_cache( void )
1305 Printer_entry *printer = printers_list;
1308 /* loop through all printers and update the cache where
1309 client_connected == True */
1312 if ( (printer->printer_type == SPLHND_PRINTER)
1313 && printer->notify.client_connected )
1315 snum = print_queue_snum(printer->sharename);
1316 print_queue_status( snum, NULL, NULL );
1319 printer = printer->next;
1324 /********************************************************************
1325 Send a message to ourself about new driver being installed
1326 so we can upgrade the information for each printer bound to this
1328 ********************************************************************/
1330 static bool srv_spoolss_reset_printerdata(char* drivername)
1332 int len = strlen(drivername);
1337 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1340 messaging_send_buf(smbd_messaging_context(), procid_self(),
1341 MSG_PRINTERDATA_INIT_RESET,
1342 (uint8 *)drivername, len+1);
1347 /**********************************************************************
1348 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1349 over all printers, resetting printer data as neessary
1350 **********************************************************************/
1352 void reset_all_printerdata(struct messaging_context *msg,
1355 struct server_id server_id,
1360 int n_services = lp_numservices();
1363 len = MIN( data->length, sizeof(drivername)-1 );
1364 strncpy( drivername, (const char *)data->data, len );
1366 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1368 /* Iterate the printer list */
1370 for ( snum=0; snum<n_services; snum++ )
1372 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1375 NT_PRINTER_INFO_LEVEL *printer = NULL;
1377 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1378 if ( !W_ERROR_IS_OK(result) )
1382 * if the printer is bound to the driver,
1383 * then reset to the new driver initdata
1386 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1388 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1390 if ( !set_driver_init(printer, 2) ) {
1391 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1392 printer->info_2->printername, printer->info_2->drivername));
1395 result = mod_a_printer( printer, 2 );
1396 if ( !W_ERROR_IS_OK(result) ) {
1397 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1398 get_dos_error_msg(result)));
1402 free_a_printer( &printer, 2 );
1411 /********************************************************************
1412 Copy routines used by convert_to_openprinterex()
1413 *******************************************************************/
1415 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1423 DEBUG (8,("dup_devmode\n"));
1425 /* bulk copy first */
1427 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1431 /* dup the pointer members separately */
1433 len = unistrlen(devmode->devicename.buffer);
1435 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1436 if (!d->devicename.buffer) {
1439 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1444 len = unistrlen(devmode->formname.buffer);
1446 d->formname.buffer = TALLOC_ARRAY(ctx, uint16, len);
1447 if (!d->formname.buffer) {
1450 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1454 if (devmode->driverextra) {
1455 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1456 devmode->driverextra);
1457 if (!d->dev_private) {
1461 d->dev_private = NULL;
1466 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1468 if (!new_ctr || !ctr)
1471 DEBUG(8,("copy_devmode_ctr\n"));
1473 new_ctr->size = ctr->size;
1474 new_ctr->devmode_ptr = ctr->devmode_ptr;
1476 if(ctr->devmode_ptr)
1477 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1480 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1482 if (!new_def || !def)
1485 DEBUG(8,("copy_printer_defaults\n"));
1487 new_def->datatype_ptr = def->datatype_ptr;
1489 if (def->datatype_ptr)
1490 copy_unistr2(&new_def->datatype, &def->datatype);
1492 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1494 new_def->access_required = def->access_required;
1497 /********************************************************************
1498 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1499 * SPOOL_Q_OPEN_PRINTER_EX structure
1500 ********************************************************************/
1502 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1504 if (!q_u_ex || !q_u)
1507 DEBUG(8,("convert_to_openprinterex\n"));
1509 if ( q_u->printername ) {
1510 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1511 if (q_u_ex->printername == NULL)
1513 copy_unistr2(q_u_ex->printername, q_u->printername);
1516 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1521 /********************************************************************
1522 * spoolss_open_printer
1524 * called from the spoolss dispatcher
1525 ********************************************************************/
1527 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1529 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1530 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1535 ZERO_STRUCT(q_u_ex);
1536 ZERO_STRUCT(r_u_ex);
1538 /* convert the OpenPrinter() call to OpenPrinterEx() */
1540 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1541 if (!W_ERROR_IS_OK(r_u_ex.status))
1542 return r_u_ex.status;
1544 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1546 /* convert back to OpenPrinter() */
1548 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1550 if (W_ERROR_EQUAL(r_u->status, WERR_INVALID_PARAM)) {
1551 /* OpenPrinterEx returns this for a bad
1552 * printer name. We must return WERR_INVALID_PRINTER_NAME
1555 r_u->status = WERR_INVALID_PRINTER_NAME;
1560 /********************************************************************
1561 ********************************************************************/
1563 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1565 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1566 POLICY_HND *handle = &r_u->handle;
1570 Printer_entry *Printer=NULL;
1572 if (!q_u->printername) {
1573 return WERR_INVALID_PARAM;
1576 /* some sanity check because you can open a printer or a print server */
1577 /* aka: \\server\printer or \\server */
1579 unistr2_to_ascii(name, q_u->printername, sizeof(name));
1581 DEBUGADD(3,("checking name: %s\n",name));
1583 if (!open_printer_hnd(p, handle, name, 0)) {
1584 return WERR_INVALID_PARAM;
1587 Printer=find_printer_index_by_hnd(p, handle);
1589 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1590 "handle we created for printer %s\n", name ));
1591 close_printer_handle(p,handle);
1592 return WERR_INVALID_PARAM;
1596 * First case: the user is opening the print server:
1598 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1599 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1601 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1602 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1603 * or if the user is listed in the smb.conf printer admin parameter.
1605 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1606 * client view printer folder, but does not show the MSAPW.
1608 * Note: this test needs code to check access rights here too. Jeremy
1609 * could you look at this?
1611 * Second case: the user is opening a printer:
1612 * NT doesn't let us connect to a printer if the connecting user
1613 * doesn't have print permission.
1615 * Third case: user is opening a Port Monitor
1616 * access checks same as opening a handle to the print server.
1619 switch (Printer->printer_type )
1622 case SPLHND_PORTMON_TCP:
1623 case SPLHND_PORTMON_LOCAL:
1624 /* Printserver handles use global struct... */
1628 /* Map standard access rights to object specific access rights */
1630 se_map_standard(&printer_default->access_required,
1631 &printserver_std_mapping);
1633 /* Deny any object specific bits that don't apply to print
1634 servers (i.e printer and job specific bits) */
1636 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1638 if (printer_default->access_required &
1639 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1640 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1641 close_printer_handle(p, handle);
1642 return WERR_ACCESS_DENIED;
1645 /* Allow admin access */
1647 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1649 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1651 if (!lp_ms_add_printer_wizard()) {
1652 close_printer_handle(p, handle);
1653 return WERR_ACCESS_DENIED;
1656 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1657 and not a printer admin, then fail */
1659 if ((p->pipe_user.ut.uid != 0) &&
1660 !user_has_privileges(p->pipe_user.nt_user_token,
1662 !token_contains_name_in_list(
1663 uidtoname(p->pipe_user.ut.uid),
1665 p->pipe_user.nt_user_token,
1666 lp_printer_admin(snum))) {
1667 close_printer_handle(p, handle);
1668 return WERR_ACCESS_DENIED;
1671 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1675 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1678 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1679 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1681 /* We fall through to return WERR_OK */
1684 case SPLHND_PRINTER:
1685 /* NT doesn't let us connect to a printer if the connecting user
1686 doesn't have print permission. */
1688 if (!get_printer_snum(p, handle, &snum, NULL)) {
1689 close_printer_handle(p, handle);
1693 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1695 /* map an empty access mask to the minimum access mask */
1696 if (printer_default->access_required == 0x0)
1697 printer_default->access_required = PRINTER_ACCESS_USE;
1700 * If we are not serving the printer driver for this printer,
1701 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1702 * will keep NT clients happy --jerry
1705 if (lp_use_client_driver(snum)
1706 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1708 printer_default->access_required = PRINTER_ACCESS_USE;
1711 /* check smb.conf parameters and the the sec_desc */
1713 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1714 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1715 return WERR_ACCESS_DENIED;
1718 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid), NULL,
1719 p->pipe_user.nt_user_token, snum) ||
1720 !print_access_check(p->server_info, snum,
1721 printer_default->access_required)) {
1722 DEBUG(3, ("access DENIED for printer open\n"));
1723 close_printer_handle(p, handle);
1724 return WERR_ACCESS_DENIED;
1727 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1728 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1729 close_printer_handle(p, handle);
1730 return WERR_ACCESS_DENIED;
1733 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1734 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1736 printer_default->access_required = PRINTER_ACCESS_USE;
1738 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1739 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1744 /* sanity check to prevent programmer error */
1748 Printer->access_granted = printer_default->access_required;
1751 * If the client sent a devmode in the OpenPrinter() call, then
1752 * save it here in case we get a job submission on this handle
1755 if ( (Printer->printer_type != SPLHND_SERVER)
1756 && q_u->printer_default.devmode_cont.devmode_ptr )
1758 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1759 &Printer->nt_devmode );
1762 #if 0 /* JERRY -- I'm doubtful this is really effective */
1763 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1764 optimization in Windows 2000 clients --jerry */
1766 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1767 && (RA_WIN2K == get_remote_arch()) )
1769 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1770 sys_usleep( 500000 );
1777 /****************************************************************************
1778 ****************************************************************************/
1780 static bool convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1781 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1787 /* allocate memory if needed. Messy because
1788 convert_printer_info is used to update an existing
1789 printer or build a new one */
1791 if ( !printer->info_2 ) {
1792 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1793 if ( !printer->info_2 ) {
1794 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1799 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1800 printer->info_2->setuptime = time(NULL);
1808 static bool convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1809 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1815 printer->info_3=NULL;
1816 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1820 printer->info_6=NULL;
1821 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1831 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1832 NT_DEVICEMODE **pp_nt_devmode)
1834 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1837 * Ensure nt_devmode is a valid pointer
1838 * as we will be overwriting it.
1841 if (nt_devmode == NULL) {
1842 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1843 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1847 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1848 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1850 nt_devmode->specversion=devmode->specversion;
1851 nt_devmode->driverversion=devmode->driverversion;
1852 nt_devmode->size=devmode->size;
1853 nt_devmode->fields=devmode->fields;
1854 nt_devmode->orientation=devmode->orientation;
1855 nt_devmode->papersize=devmode->papersize;
1856 nt_devmode->paperlength=devmode->paperlength;
1857 nt_devmode->paperwidth=devmode->paperwidth;
1858 nt_devmode->scale=devmode->scale;
1859 nt_devmode->copies=devmode->copies;
1860 nt_devmode->defaultsource=devmode->defaultsource;
1861 nt_devmode->printquality=devmode->printquality;
1862 nt_devmode->color=devmode->color;
1863 nt_devmode->duplex=devmode->duplex;
1864 nt_devmode->yresolution=devmode->yresolution;
1865 nt_devmode->ttoption=devmode->ttoption;
1866 nt_devmode->collate=devmode->collate;
1868 nt_devmode->logpixels=devmode->logpixels;
1869 nt_devmode->bitsperpel=devmode->bitsperpel;
1870 nt_devmode->pelswidth=devmode->pelswidth;
1871 nt_devmode->pelsheight=devmode->pelsheight;
1872 nt_devmode->displayflags=devmode->displayflags;
1873 nt_devmode->displayfrequency=devmode->displayfrequency;
1874 nt_devmode->icmmethod=devmode->icmmethod;
1875 nt_devmode->icmintent=devmode->icmintent;
1876 nt_devmode->mediatype=devmode->mediatype;
1877 nt_devmode->dithertype=devmode->dithertype;
1878 nt_devmode->reserved1=devmode->reserved1;
1879 nt_devmode->reserved2=devmode->reserved2;
1880 nt_devmode->panningwidth=devmode->panningwidth;
1881 nt_devmode->panningheight=devmode->panningheight;
1884 * Only change private and driverextra if the incoming devmode
1885 * has a new one. JRA.
1888 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1889 SAFE_FREE(nt_devmode->nt_dev_private);
1890 nt_devmode->driverextra=devmode->driverextra;
1891 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1893 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1896 *pp_nt_devmode = nt_devmode;
1901 /********************************************************************
1902 * _spoolss_enddocprinter_internal.
1903 ********************************************************************/
1905 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1907 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1911 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1915 if (!get_printer_snum(p, handle, &snum, NULL))
1918 Printer->document_started=False;
1919 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1920 /* error codes unhandled so far ... */
1925 /********************************************************************
1926 * api_spoolss_closeprinter
1927 ********************************************************************/
1929 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1931 POLICY_HND *handle = &q_u->handle;
1933 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1935 if (Printer && Printer->document_started)
1936 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1938 if (!close_printer_handle(p, handle))
1941 /* clear the returned printer handle. Observed behavior
1942 from Win2k server. Don't think this really matters.
1943 Previous code just copied the value of the closed
1946 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1951 /********************************************************************
1952 * api_spoolss_deleteprinter
1954 ********************************************************************/
1956 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1958 POLICY_HND *handle = &q_u->handle;
1959 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1962 if (Printer && Printer->document_started)
1963 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1965 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1967 result = delete_printer_handle(p, handle);
1969 update_c_setprinter(False);
1974 /*******************************************************************
1975 * static function to lookup the version id corresponding to an
1976 * long architecture string
1977 ******************************************************************/
1979 static int get_version_id (char * arch)
1982 struct table_node archi_table[]= {
1984 {"Windows 4.0", "WIN40", 0 },
1985 {"Windows NT x86", "W32X86", 2 },
1986 {"Windows NT R4000", "W32MIPS", 2 },
1987 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1988 {"Windows NT PowerPC", "W32PPC", 2 },
1989 {"Windows IA64", "IA64", 3 },
1990 {"Windows x64", "x64", 3 },
1994 for (i=0; archi_table[i].long_archi != NULL; i++)
1996 if (strcmp(arch, archi_table[i].long_archi) == 0)
1997 return (archi_table[i].version);
2003 /********************************************************************
2004 * _spoolss_deleteprinterdriver
2005 ********************************************************************/
2007 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2011 NT_PRINTER_DRIVER_INFO_LEVEL info;
2012 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2015 WERROR status_win2k = WERR_ACCESS_DENIED;
2016 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2018 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2019 and not a printer admin, then fail */
2021 if ( (p->pipe_user.ut.uid != 0)
2022 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2023 && !token_contains_name_in_list(
2024 uidtoname(p->pipe_user.ut.uid), NULL,
2025 NULL, p->pipe_user.nt_user_token,
2026 lp_printer_admin(-1)) )
2028 return WERR_ACCESS_DENIED;
2031 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2032 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2034 /* check that we have a valid driver name first */
2036 if ((version=get_version_id(arch)) == -1)
2037 return WERR_INVALID_ENVIRONMENT;
2040 ZERO_STRUCT(info_win2k);
2042 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2044 /* try for Win2k driver if "Windows NT x86" */
2046 if ( version == 2 ) {
2048 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2049 status = WERR_UNKNOWN_PRINTER_DRIVER;
2053 /* otherwise it was a failure */
2055 status = WERR_UNKNOWN_PRINTER_DRIVER;
2061 if (printer_driver_in_use(info.info_3)) {
2062 status = WERR_PRINTER_DRIVER_IN_USE;
2068 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2070 /* if we get to here, we now have 2 driver info structures to remove */
2071 /* remove the Win2k driver first*/
2073 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2074 free_a_printer_driver( info_win2k, 3 );
2076 /* this should not have failed---if it did, report to client */
2077 if ( !W_ERROR_IS_OK(status_win2k) )
2079 status = status_win2k;
2085 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2087 /* if at least one of the deletes succeeded return OK */
2089 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2093 free_a_printer_driver( info, 3 );
2098 /********************************************************************
2099 * spoolss_deleteprinterdriverex
2100 ********************************************************************/
2102 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2106 NT_PRINTER_DRIVER_INFO_LEVEL info;
2107 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2109 uint32 flags = q_u->delete_flags;
2112 WERROR status_win2k = WERR_ACCESS_DENIED;
2113 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2115 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2116 and not a printer admin, then fail */
2118 if ( (p->pipe_user.ut.uid != 0)
2119 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2120 && !token_contains_name_in_list(
2121 uidtoname(p->pipe_user.ut.uid), NULL, NULL,
2122 p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2124 return WERR_ACCESS_DENIED;
2127 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2128 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2130 /* check that we have a valid driver name first */
2131 if ((version=get_version_id(arch)) == -1) {
2132 /* this is what NT returns */
2133 return WERR_INVALID_ENVIRONMENT;
2136 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2137 version = q_u->version;
2140 ZERO_STRUCT(info_win2k);
2142 status = get_a_printer_driver(&info, 3, driver, arch, version);
2144 if ( !W_ERROR_IS_OK(status) )
2147 * if the client asked for a specific version,
2148 * or this is something other than Windows NT x86,
2152 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2155 /* try for Win2k driver if "Windows NT x86" */
2158 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2159 status = WERR_UNKNOWN_PRINTER_DRIVER;
2164 if ( printer_driver_in_use(info.info_3) ) {
2165 status = WERR_PRINTER_DRIVER_IN_USE;
2170 * we have a couple of cases to consider.
2171 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2172 * then the delete should fail if **any** files overlap with
2174 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2175 * non-overlapping files
2176 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2177 * is set, the do not delete any files
2178 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2181 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2183 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2185 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2186 /* no idea of the correct error here */
2187 status = WERR_ACCESS_DENIED;
2192 /* also check for W32X86/3 if necessary; maybe we already have? */
2194 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2195 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2198 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2199 /* no idea of the correct error here */
2200 free_a_printer_driver( info_win2k, 3 );
2201 status = WERR_ACCESS_DENIED;
2205 /* if we get to here, we now have 2 driver info structures to remove */
2206 /* remove the Win2k driver first*/
2208 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2209 free_a_printer_driver( info_win2k, 3 );
2211 /* this should not have failed---if it did, report to client */
2213 if ( !W_ERROR_IS_OK(status_win2k) )
2218 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2220 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2223 free_a_printer_driver( info, 3 );
2229 /****************************************************************************
2230 Internal routine for retreiving printerdata
2231 ***************************************************************************/
2233 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2234 const char *key, const char *value, uint32 *type, uint8 **data,
2235 uint32 *needed, uint32 in_size )
2237 REGISTRY_VALUE *val;
2241 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2242 return WERR_BADFILE;
2244 *type = regval_type( val );
2246 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2248 size = regval_size( val );
2250 /* copy the min(in_size, len) */
2253 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2255 /* special case for 0 length values */
2257 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2261 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2270 DEBUG(5,("get_printer_dataex: copy done\n"));
2275 /****************************************************************************
2276 Internal routine for removing printerdata
2277 ***************************************************************************/
2279 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2281 return delete_printer_data( printer->info_2, key, value );
2284 /****************************************************************************
2285 Internal routine for storing printerdata
2286 ***************************************************************************/
2288 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2289 uint32 type, uint8 *data, int real_len )
2291 /* the registry objects enforce uniqueness based on value name */
2293 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2296 /********************************************************************
2297 GetPrinterData on a printer server Handle.
2298 ********************************************************************/
2300 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2304 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2306 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2308 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2310 SIVAL(*data, 0, 0x00);
2315 if (!StrCaseCmp(value, "BeepEnabled")) {
2317 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2319 SIVAL(*data, 0, 0x00);
2324 if (!StrCaseCmp(value, "EventLog")) {
2326 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2328 /* formally was 0x1b */
2329 SIVAL(*data, 0, 0x0);
2334 if (!StrCaseCmp(value, "NetPopup")) {
2336 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2338 SIVAL(*data, 0, 0x00);
2343 if (!StrCaseCmp(value, "MajorVersion")) {
2345 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2348 /* Windows NT 4.0 seems to not allow uploading of drivers
2349 to a server that reports 0x3 as the MajorVersion.
2350 need to investigate more how Win2k gets around this .
2353 if ( RA_WINNT == get_remote_arch() )
2362 if (!StrCaseCmp(value, "MinorVersion")) {
2364 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2372 * uint32 size = 0x114
2374 * uint32 minor = [0|1]
2375 * uint32 build = [2195|2600]
2376 * extra unicode string = e.g. "Service Pack 3"
2378 if (!StrCaseCmp(value, "OSVersion")) {
2382 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2385 SIVAL(*data, 0, *needed); /* size */
2386 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2388 SIVAL(*data, 12, 2195); /* build */
2390 /* leave extra string empty */
2396 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2397 const char *string="C:\\PRINTERS";
2399 *needed = 2*(strlen(string)+1);
2400 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2402 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2404 /* it's done by hand ready to go on the wire */
2405 for (i=0; i<strlen(string); i++) {
2406 (*data)[2*i]=string[i];
2407 (*data)[2*i+1]='\0';
2412 if (!StrCaseCmp(value, "Architecture")) {
2413 const char *string="Windows NT x86";
2415 *needed = 2*(strlen(string)+1);
2416 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2418 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2419 for (i=0; i<strlen(string); i++) {
2420 (*data)[2*i]=string[i];
2421 (*data)[2*i+1]='\0';
2426 if (!StrCaseCmp(value, "DsPresent")) {
2428 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2431 /* only show the publish check box if we are a
2432 memeber of a AD domain */
2434 if ( lp_security() == SEC_ADS )
2435 SIVAL(*data, 0, 0x01);
2437 SIVAL(*data, 0, 0x00);
2443 if (!StrCaseCmp(value, "DNSMachineName")) {
2444 const char *hostname = get_mydnsfullname();
2447 return WERR_BADFILE;
2449 *needed = 2*(strlen(hostname)+1);
2450 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2452 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2453 for (i=0; i<strlen(hostname); i++) {
2454 (*data)[2*i]=hostname[i];
2455 (*data)[2*i+1]='\0';
2461 return WERR_BADFILE;
2464 /********************************************************************
2465 * spoolss_getprinterdata
2466 ********************************************************************/
2468 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2470 POLICY_HND *handle = &q_u->handle;
2471 UNISTR2 *valuename = &q_u->valuename;
2472 uint32 in_size = q_u->size;
2473 uint32 *type = &r_u->type;
2474 uint32 *out_size = &r_u->size;
2475 uint8 **data = &r_u->data;
2476 uint32 *needed = &r_u->needed;
2479 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2480 NT_PRINTER_INFO_LEVEL *printer = NULL;
2484 * Reminder: when it's a string, the length is in BYTES
2485 * even if UNICODE is negociated.
2490 *out_size = in_size;
2492 /* in case of problem, return some default values */
2497 DEBUG(4,("_spoolss_getprinterdata\n"));
2500 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2501 status = WERR_BADFID;
2505 unistr2_to_ascii(value, valuename, sizeof(value));
2507 if ( Printer->printer_type == SPLHND_SERVER )
2508 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2511 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2512 status = WERR_BADFID;
2516 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2517 if ( !W_ERROR_IS_OK(status) )
2520 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2522 if ( strequal(value, "ChangeId") ) {
2524 *needed = sizeof(uint32);
2525 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2526 status = WERR_NOMEM;
2529 SIVAL( *data, 0, printer->info_2->changeid );
2533 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2536 if (*needed > *out_size)
2537 status = WERR_MORE_DATA;
2540 if ( !W_ERROR_IS_OK(status) )
2542 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2544 /* reply this param doesn't exist */
2547 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2549 free_a_printer( &printer, 2 );
2557 /* cleanup & exit */
2560 free_a_printer( &printer, 2 );
2565 /*********************************************************
2566 Connect to the client machine.
2567 **********************************************************/
2569 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2570 struct sockaddr_storage *client_ss, const char *remote_machine)
2573 struct cli_state *the_cli;
2574 struct sockaddr_storage rm_addr;
2576 if ( is_zero_addr(client_ss) ) {
2577 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2578 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2582 if (ismyaddr(&rm_addr)) {
2583 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2587 char addr[INET6_ADDRSTRLEN];
2588 rm_addr = *client_ss;
2589 print_sockaddr(addr, sizeof(addr), &rm_addr);
2590 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2594 /* setup the connection */
2596 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2597 &rm_addr, 0, "IPC$", "IPC",
2601 0, lp_client_signing(), NULL );
2603 if ( !NT_STATUS_IS_OK( ret ) ) {
2604 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2609 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2610 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2611 cli_shutdown(the_cli);
2616 * Ok - we have an anonymous connection to the IPC$ share.
2617 * Now start the NT Domain stuff :-).
2620 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2621 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2622 remote_machine, nt_errstr(ret)));
2623 cli_shutdown(the_cli);
2630 /***************************************************************************
2631 Connect to the client.
2632 ****************************************************************************/
2634 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2635 uint32 localprinter, uint32 type,
2636 POLICY_HND *handle, struct sockaddr_storage *client_ss)
2641 * If it's the first connection, contact the client
2642 * and connect to the IPC$ share anonymously
2644 if (smb_connections==0) {
2645 fstring unix_printer;
2647 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2649 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ss, unix_printer ))
2652 messaging_register(smbd_messaging_context(), NULL,
2653 MSG_PRINTER_NOTIFY2,
2654 receive_notify2_message_list);
2655 /* Tell the connections db we're now interested in printer
2656 * notify messages. */
2657 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2661 * Tell the specific printing tdb we want messages for this printer
2662 * by registering our PID.
2665 if (!print_notify_register_pid(snum))
2666 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2670 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe,
2677 if (!W_ERROR_IS_OK(result))
2678 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2679 dos_errstr(result)));
2681 return (W_ERROR_IS_OK(result));
2684 /********************************************************************
2686 * ReplyFindFirstPrinterChangeNotifyEx
2688 * before replying OK: status=0 a rpc call is made to the workstation
2689 * asking ReplyOpenPrinter
2691 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2692 * called from api_spoolss_rffpcnex
2693 ********************************************************************/
2695 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2697 POLICY_HND *handle = &q_u->handle;
2698 uint32 flags = q_u->flags;
2699 uint32 options = q_u->options;
2700 UNISTR2 *localmachine = &q_u->localmachine;
2701 uint32 printerlocal = q_u->printerlocal;
2703 SPOOL_NOTIFY_OPTION *option = q_u->option;
2704 struct sockaddr_storage client_ss;
2706 /* store the notify value in the printer struct */
2708 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2711 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2715 Printer->notify.flags=flags;
2716 Printer->notify.options=options;
2717 Printer->notify.printerlocal=printerlocal;
2719 if (Printer->notify.option)
2720 free_spool_notify_option(&Printer->notify.option);
2722 Printer->notify.option=dup_spool_notify_option(option);
2724 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2725 sizeof(Printer->notify.localmachine));
2727 /* Connect to the client machine and send a ReplyOpenPrinter */
2729 if ( Printer->printer_type == SPLHND_SERVER)
2731 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2732 !get_printer_snum(p, handle, &snum, NULL) )
2735 if (!interpret_string_addr(&client_ss, p->client_address,
2737 return WERR_SERVER_UNAVAILABLE;
2740 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2741 Printer->notify.printerlocal, 1,
2742 &Printer->notify.client_hnd, &client_ss))
2743 return WERR_SERVER_UNAVAILABLE;
2745 Printer->notify.client_connected=True;
2750 /*******************************************************************
2751 * fill a notify_info_data with the servername
2752 ********************************************************************/
2754 void spoolss_notify_server_name(int snum,
2755 SPOOL_NOTIFY_INFO_DATA *data,
2756 print_queue_struct *queue,
2757 NT_PRINTER_INFO_LEVEL *printer,
2758 TALLOC_CTX *mem_ctx)
2760 smb_ucs2_t *temp = NULL;
2763 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
2764 if (len == (uint32)-1) {
2768 data->notify_data.data.length = len;
2770 data->notify_data.data.string = (uint16 *)temp;
2772 data->notify_data.data.string = NULL;
2776 /*******************************************************************
2777 * fill a notify_info_data with the printername (not including the servername).
2778 ********************************************************************/
2780 void spoolss_notify_printer_name(int snum,
2781 SPOOL_NOTIFY_INFO_DATA *data,
2782 print_queue_struct *queue,
2783 NT_PRINTER_INFO_LEVEL *printer,
2784 TALLOC_CTX *mem_ctx)
2786 smb_ucs2_t *temp = NULL;
2789 /* the notify name should not contain the \\server\ part */
2790 char *p = strrchr(printer->info_2->printername, '\\');
2793 p = printer->info_2->printername;
2798 len = rpcstr_push_talloc(mem_ctx, &temp, p);
2799 if (len == (uint32)-1) {
2803 data->notify_data.data.length = len;
2805 data->notify_data.data.string = (uint16 *)temp;
2807 data->notify_data.data.string = NULL;
2811 /*******************************************************************
2812 * fill a notify_info_data with the servicename
2813 ********************************************************************/
2815 void spoolss_notify_share_name(int snum,
2816 SPOOL_NOTIFY_INFO_DATA *data,
2817 print_queue_struct *queue,
2818 NT_PRINTER_INFO_LEVEL *printer,
2819 TALLOC_CTX *mem_ctx)
2821 smb_ucs2_t *temp = NULL;
2824 len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
2825 if (len == (uint32)-1) {
2829 data->notify_data.data.length = len;
2831 data->notify_data.data.string = (uint16 *)temp;
2833 data->notify_data.data.string = NULL;
2838 /*******************************************************************
2839 * fill a notify_info_data with the port name
2840 ********************************************************************/
2842 void spoolss_notify_port_name(int snum,
2843 SPOOL_NOTIFY_INFO_DATA *data,
2844 print_queue_struct *queue,
2845 NT_PRINTER_INFO_LEVEL *printer,
2846 TALLOC_CTX *mem_ctx)
2848 smb_ucs2_t *temp = NULL;
2851 /* even if it's strange, that's consistant in all the code */
2853 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
2854 if (len == (uint32)-1) {
2858 data->notify_data.data.length = len;
2860 data->notify_data.data.string = (uint16 *)temp;
2862 data->notify_data.data.string = NULL;
2866 /*******************************************************************
2867 * fill a notify_info_data with the printername
2868 * but it doesn't exist, have to see what to do
2869 ********************************************************************/
2871 void spoolss_notify_driver_name(int snum,
2872 SPOOL_NOTIFY_INFO_DATA *data,
2873 print_queue_struct *queue,
2874 NT_PRINTER_INFO_LEVEL *printer,
2875 TALLOC_CTX *mem_ctx)
2877 smb_ucs2_t *temp = NULL;
2880 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
2881 if (len == (uint32)-1) {
2885 data->notify_data.data.length = len;
2887 data->notify_data.data.string = (uint16 *)temp;
2889 data->notify_data.data.string = NULL;
2893 /*******************************************************************
2894 * fill a notify_info_data with the comment
2895 ********************************************************************/
2897 void spoolss_notify_comment(int snum,
2898 SPOOL_NOTIFY_INFO_DATA *data,
2899 print_queue_struct *queue,
2900 NT_PRINTER_INFO_LEVEL *printer,
2901 TALLOC_CTX *mem_ctx)
2903 smb_ucs2_t *temp = NULL;
2906 if (*printer->info_2->comment == '\0')
2907 len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
2909 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
2911 if (len == (uint32)-1) {
2914 data->notify_data.data.length = len;
2916 data->notify_data.data.string = (uint16 *)temp;
2918 data->notify_data.data.string = NULL;
2922 /*******************************************************************
2923 * fill a notify_info_data with the comment
2924 * location = "Room 1, floor 2, building 3"
2925 ********************************************************************/
2927 void spoolss_notify_location(int snum,
2928 SPOOL_NOTIFY_INFO_DATA *data,
2929 print_queue_struct *queue,
2930 NT_PRINTER_INFO_LEVEL *printer,
2931 TALLOC_CTX *mem_ctx)
2933 smb_ucs2_t *temp = NULL;
2936 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
2937 if (len == (uint32)-1) {
2941 data->notify_data.data.length = len;
2943 data->notify_data.data.string = (uint16 *)temp;
2945 data->notify_data.data.string = NULL;
2949 /*******************************************************************
2950 * fill a notify_info_data with the device mode
2951 * jfm:xxxx don't to it for know but that's a real problem !!!
2952 ********************************************************************/
2954 static void spoolss_notify_devmode(int snum,
2955 SPOOL_NOTIFY_INFO_DATA *data,
2956 print_queue_struct *queue,
2957 NT_PRINTER_INFO_LEVEL *printer,
2958 TALLOC_CTX *mem_ctx)
2960 /* for a dummy implementation we have to zero the fields */
2961 data->notify_data.data.length = 0;
2962 data->notify_data.data.string = NULL;
2965 /*******************************************************************
2966 * fill a notify_info_data with the separator file name
2967 ********************************************************************/
2969 void spoolss_notify_sepfile(int snum,
2970 SPOOL_NOTIFY_INFO_DATA *data,
2971 print_queue_struct *queue,
2972 NT_PRINTER_INFO_LEVEL *printer,
2973 TALLOC_CTX *mem_ctx)
2975 smb_ucs2_t *temp = NULL;
2978 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
2979 if (len == (uint32)-1) {
2983 data->notify_data.data.length = len;
2985 data->notify_data.data.string = (uint16 *)temp;
2987 data->notify_data.data.string = NULL;
2991 /*******************************************************************
2992 * fill a notify_info_data with the print processor
2993 * jfm:xxxx return always winprint to indicate we don't do anything to it
2994 ********************************************************************/
2996 void spoolss_notify_print_processor(int snum,
2997 SPOOL_NOTIFY_INFO_DATA *data,
2998 print_queue_struct *queue,
2999 NT_PRINTER_INFO_LEVEL *printer,
3000 TALLOC_CTX *mem_ctx)
3002 smb_ucs2_t *temp = NULL;
3005 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
3006 if (len == (uint32)-1) {
3010 data->notify_data.data.length = len;
3012 data->notify_data.data.string = (uint16 *)temp;
3014 data->notify_data.data.string = NULL;
3018 /*******************************************************************
3019 * fill a notify_info_data with the print processor options
3020 * jfm:xxxx send an empty string
3021 ********************************************************************/
3023 void spoolss_notify_parameters(int snum,
3024 SPOOL_NOTIFY_INFO_DATA *data,
3025 print_queue_struct *queue,
3026 NT_PRINTER_INFO_LEVEL *printer,
3027 TALLOC_CTX *mem_ctx)
3029 smb_ucs2_t *temp = NULL;
3032 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
3033 if (len == (uint32)-1) {
3037 data->notify_data.data.length = len;
3039 data->notify_data.data.string = (uint16 *)temp;
3041 data->notify_data.data.string = NULL;
3045 /*******************************************************************
3046 * fill a notify_info_data with the data type
3047 * jfm:xxxx always send RAW as data type
3048 ********************************************************************/
3050 void spoolss_notify_datatype(int snum,
3051 SPOOL_NOTIFY_INFO_DATA *data,
3052 print_queue_struct *queue,
3053 NT_PRINTER_INFO_LEVEL *printer,
3054 TALLOC_CTX *mem_ctx)
3056 smb_ucs2_t *temp = NULL;
3059 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
3060 if (len == (uint32)-1) {
3064 data->notify_data.data.length = len;
3066 data->notify_data.data.string = (uint16 *)temp;
3068 data->notify_data.data.string = NULL;
3072 /*******************************************************************
3073 * fill a notify_info_data with the security descriptor
3074 * jfm:xxxx send an null pointer to say no security desc
3075 * have to implement security before !
3076 ********************************************************************/
3078 static void spoolss_notify_security_desc(int snum,
3079 SPOOL_NOTIFY_INFO_DATA *data,
3080 print_queue_struct *queue,
3081 NT_PRINTER_INFO_LEVEL *printer,
3082 TALLOC_CTX *mem_ctx)
3084 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3085 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3088 /*******************************************************************
3089 * fill a notify_info_data with the attributes
3090 * jfm:xxxx a samba printer is always shared
3091 ********************************************************************/
3093 void spoolss_notify_attributes(int snum,
3094 SPOOL_NOTIFY_INFO_DATA *data,
3095 print_queue_struct *queue,
3096 NT_PRINTER_INFO_LEVEL *printer,
3097 TALLOC_CTX *mem_ctx)
3099 data->notify_data.value[0] = printer->info_2->attributes;
3100 data->notify_data.value[1] = 0;
3103 /*******************************************************************
3104 * fill a notify_info_data with the priority
3105 ********************************************************************/
3107 static void spoolss_notify_priority(int snum,
3108 SPOOL_NOTIFY_INFO_DATA *data,
3109 print_queue_struct *queue,
3110 NT_PRINTER_INFO_LEVEL *printer,
3111 TALLOC_CTX *mem_ctx)
3113 data->notify_data.value[0] = printer->info_2->priority;
3114 data->notify_data.value[1] = 0;
3117 /*******************************************************************
3118 * fill a notify_info_data with the default priority
3119 ********************************************************************/
3121 static void spoolss_notify_default_priority(int snum,
3122 SPOOL_NOTIFY_INFO_DATA *data,
3123 print_queue_struct *queue,
3124 NT_PRINTER_INFO_LEVEL *printer,
3125 TALLOC_CTX *mem_ctx)
3127 data->notify_data.value[0] = printer->info_2->default_priority;
3128 data->notify_data.value[1] = 0;
3131 /*******************************************************************
3132 * fill a notify_info_data with the start time
3133 ********************************************************************/
3135 static void spoolss_notify_start_time(int snum,
3136 SPOOL_NOTIFY_INFO_DATA *data,
3137 print_queue_struct *queue,
3138 NT_PRINTER_INFO_LEVEL *printer,
3139 TALLOC_CTX *mem_ctx)
3141 data->notify_data.value[0] = printer->info_2->starttime;
3142 data->notify_data.value[1] = 0;
3145 /*******************************************************************
3146 * fill a notify_info_data with the until time
3147 ********************************************************************/
3149 static void spoolss_notify_until_time(int snum,
3150 SPOOL_NOTIFY_INFO_DATA *data,
3151 print_queue_struct *queue,
3152 NT_PRINTER_INFO_LEVEL *printer,
3153 TALLOC_CTX *mem_ctx)
3155 data->notify_data.value[0] = printer->info_2->untiltime;
3156 data->notify_data.value[1] = 0;
3159 /*******************************************************************
3160 * fill a notify_info_data with the status
3161 ********************************************************************/
3163 static void spoolss_notify_status(int snum,
3164 SPOOL_NOTIFY_INFO_DATA *data,
3165 print_queue_struct *queue,
3166 NT_PRINTER_INFO_LEVEL *printer,
3167 TALLOC_CTX *mem_ctx)
3169 print_status_struct status;
3171 print_queue_length(snum, &status);
3172 data->notify_data.value[0]=(uint32) status.status;
3173 data->notify_data.value[1] = 0;
3176 /*******************************************************************
3177 * fill a notify_info_data with the number of jobs queued
3178 ********************************************************************/
3180 void spoolss_notify_cjobs(int snum,
3181 SPOOL_NOTIFY_INFO_DATA *data,
3182 print_queue_struct *queue,
3183 NT_PRINTER_INFO_LEVEL *printer,
3184 TALLOC_CTX *mem_ctx)
3186 data->notify_data.value[0] = print_queue_length(snum, NULL);
3187 data->notify_data.value[1] = 0;
3190 /*******************************************************************
3191 * fill a notify_info_data with the average ppm
3192 ********************************************************************/
3194 static void spoolss_notify_average_ppm(int snum,
3195 SPOOL_NOTIFY_INFO_DATA *data,
3196 print_queue_struct *queue,
3197 NT_PRINTER_INFO_LEVEL *printer,
3198 TALLOC_CTX *mem_ctx)
3200 /* always respond 8 pages per minutes */
3201 /* a little hard ! */
3202 data->notify_data.value[0] = printer->info_2->averageppm;
3203 data->notify_data.value[1] = 0;
3206 /*******************************************************************
3207 * fill a notify_info_data with username
3208 ********************************************************************/
3210 static void spoolss_notify_username(int snum,
3211 SPOOL_NOTIFY_INFO_DATA *data,
3212 print_queue_struct *queue,
3213 NT_PRINTER_INFO_LEVEL *printer,
3214 TALLOC_CTX *mem_ctx)
3216 smb_ucs2_t *temp = NULL;
3219 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
3220 if (len == (uint32)-1) {
3224 data->notify_data.data.length = len;
3226 data->notify_data.data.string = (uint16 *)temp;
3228 data->notify_data.data.string = NULL;
3232 /*******************************************************************
3233 * fill a notify_info_data with job status
3234 ********************************************************************/
3236 static void spoolss_notify_job_status(int snum,
3237 SPOOL_NOTIFY_INFO_DATA *data,
3238 print_queue_struct *queue,
3239 NT_PRINTER_INFO_LEVEL *printer,
3240 TALLOC_CTX *mem_ctx)
3242 data->notify_data.value[0]=nt_printj_status(queue->status);
3243 data->notify_data.value[1] = 0;
3246 /*******************************************************************
3247 * fill a notify_info_data with job name
3248 ********************************************************************/
3250 static void spoolss_notify_job_name(int snum,
3251 SPOOL_NOTIFY_INFO_DATA *data,
3252 print_queue_struct *queue,
3253 NT_PRINTER_INFO_LEVEL *printer,
3254 TALLOC_CTX *mem_ctx)
3256 smb_ucs2_t *temp = NULL;
3259 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
3260 if (len == (uint32)-1) {
3264 data->notify_data.data.length = len;
3266 data->notify_data.data.string = (uint16 *)temp;
3268 data->notify_data.data.string = NULL;
3272 /*******************************************************************
3273 * fill a notify_info_data with job status
3274 ********************************************************************/
3276 static void spoolss_notify_job_status_string(int snum,
3277 SPOOL_NOTIFY_INFO_DATA *data,
3278 print_queue_struct *queue,
3279 NT_PRINTER_INFO_LEVEL *printer,
3280 TALLOC_CTX *mem_ctx)
3283 * Now we're returning job status codes we just return a "" here. JRA.
3287 smb_ucs2_t *temp = NULL;
3290 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3293 switch (queue->status) {
3298 p = ""; /* NT provides the paused string */
3307 #endif /* NO LONGER NEEDED. */
3309 len = rpcstr_push_talloc(mem_ctx, &temp, p);
3310 if (len == (uint32)-1) {
3314 data->notify_data.data.length = len;
3316 data->notify_data.data.string = (uint16 *)temp;
3318 data->notify_data.data.string = NULL;
3322 /*******************************************************************
3323 * fill a notify_info_data with job time
3324 ********************************************************************/
3326 static void spoolss_notify_job_time(int snum,
3327 SPOOL_NOTIFY_INFO_DATA *data,
3328 print_queue_struct *queue,
3329 NT_PRINTER_INFO_LEVEL *printer,
3330 TALLOC_CTX *mem_ctx)
3332 data->notify_data.value[0]=0x0;
3333 data->notify_data.value[1]=0;
3336 /*******************************************************************
3337 * fill a notify_info_data with job size
3338 ********************************************************************/
3340 static void spoolss_notify_job_size(int snum,
3341 SPOOL_NOTIFY_INFO_DATA *data,
3342 print_queue_struct *queue,
3343 NT_PRINTER_INFO_LEVEL *printer,
3344 TALLOC_CTX *mem_ctx)
3346 data->notify_data.value[0]=queue->size;
3347 data->notify_data.value[1]=0;
3350 /*******************************************************************
3351 * fill a notify_info_data with page info
3352 ********************************************************************/
3353 static void spoolss_notify_total_pages(int snum,
3354 SPOOL_NOTIFY_INFO_DATA *data,
3355 print_queue_struct *queue,
3356 NT_PRINTER_INFO_LEVEL *printer,
3357 TALLOC_CTX *mem_ctx)
3359 data->notify_data.value[0]=queue->page_count;
3360 data->notify_data.value[1]=0;
3363 /*******************************************************************
3364 * fill a notify_info_data with pages printed info.
3365 ********************************************************************/
3366 static void spoolss_notify_pages_printed(int snum,
3367 SPOOL_NOTIFY_INFO_DATA *data,
3368 print_queue_struct *queue,
3369 NT_PRINTER_INFO_LEVEL *printer,
3370 TALLOC_CTX *mem_ctx)
3372 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3373 data->notify_data.value[1]=0;
3376 /*******************************************************************
3377 Fill a notify_info_data with job position.
3378 ********************************************************************/
3380 static void spoolss_notify_job_position(int snum,
3381 SPOOL_NOTIFY_INFO_DATA *data,
3382 print_queue_struct *queue,
3383 NT_PRINTER_INFO_LEVEL *printer,
3384 TALLOC_CTX *mem_ctx)
3386 data->notify_data.value[0]=queue->job;
3387 data->notify_data.value[1]=0;
3390 /*******************************************************************
3391 Fill a notify_info_data with submitted time.
3392 ********************************************************************/
3394 static void spoolss_notify_submitted_time(int snum,
3395 SPOOL_NOTIFY_INFO_DATA *data,
3396 print_queue_struct *queue,
3397 NT_PRINTER_INFO_LEVEL *printer,
3398 TALLOC_CTX *mem_ctx)
3405 t=gmtime(&queue->time);
3407 len = sizeof(SYSTEMTIME);
3409 data->notify_data.data.length = len;
3410 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3412 if (!data->notify_data.data.string) {
3413 data->notify_data.data.length = 0;
3417 make_systemtime(&st, t);
3420 * Systemtime must be linearized as a set of UINT16's.
3421 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3424 p = (char *)data->notify_data.data.string;
3425 SSVAL(p, 0, st.year);
3426 SSVAL(p, 2, st.month);
3427 SSVAL(p, 4, st.dayofweek);
3428 SSVAL(p, 6, st.day);
3429 SSVAL(p, 8, st.hour);
3430 SSVAL(p, 10, st.minute);
3431 SSVAL(p, 12, st.second);
3432 SSVAL(p, 14, st.milliseconds);
3435 struct s_notify_info_data_table
3441 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3442 print_queue_struct *queue,
3443 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3446 /* A table describing the various print notification constants and
3447 whether the notification data is a pointer to a variable sized
3448 buffer, a one value uint32 or a two value uint32. */
3450 static const struct s_notify_info_data_table notify_info_data_table[] =
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3501 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3504 /*******************************************************************
3505 Return the size of info_data structure.
3506 ********************************************************************/
3508 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3512 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3513 if ( (notify_info_data_table[i].type == type)
3514 && (notify_info_data_table[i].field == field) ) {
3515 switch(notify_info_data_table[i].size) {
3516 case NOTIFY_ONE_VALUE:
3517 case NOTIFY_TWO_VALUE:
3522 /* The only pointer notify data I have seen on
3523 the wire is the submitted time and this has
3524 the notify size set to 4. -tpot */
3526 case NOTIFY_POINTER:
3529 case NOTIFY_SECDESC:
3535 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3540 /*******************************************************************
3541 Return the type of notify_info_data.
3542 ********************************************************************/
3544 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3548 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3549 if (notify_info_data_table[i].type == type &&
3550 notify_info_data_table[i].field == field)
3551 return notify_info_data_table[i].size;
3557 /****************************************************************************
3558 ****************************************************************************/
3560 static bool search_notify(uint16 type, uint16 field, int *value)
3564 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3565 if (notify_info_data_table[i].type == type &&
3566 notify_info_data_table[i].field == field &&
3567 notify_info_data_table[i].fn != NULL) {
3576 /****************************************************************************
3577 ****************************************************************************/
3579 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3581 info_data->type = type;
3582 info_data->field = field;
3583 info_data->reserved = 0;
3585 info_data->size = size_of_notify_info_data(type, field);
3586 info_data->enc_type = type_of_notify_info_data(type, field);
3591 /*******************************************************************
3593 * fill a notify_info struct with info asked
3595 ********************************************************************/
3597 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3598 snum, SPOOL_NOTIFY_OPTION_TYPE
3599 *option_type, uint32 id,
3600 TALLOC_CTX *mem_ctx)
3606 SPOOL_NOTIFY_INFO_DATA *current_data;
3607 NT_PRINTER_INFO_LEVEL *printer = NULL;
3608 print_queue_struct *queue=NULL;
3610 type=option_type->type;
3612 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3613 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3614 option_type->count, lp_servicename(snum)));
3616 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3619 for(field_num=0; field_num<option_type->count; field_num++) {
3620 field = option_type->fields[field_num];
3622 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3624 if (!search_notify(type, field, &j) )
3627 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3628 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3629 free_a_printer(&printer, 2);
3633 current_data = &info->data[info->count];
3635 construct_info_data(current_data, type, field, id);
3637 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3638 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3640 notify_info_data_table[j].fn(snum, current_data, queue,
3646 free_a_printer(&printer, 2);
3650 /*******************************************************************
3652 * fill a notify_info struct with info asked
3654 ********************************************************************/
3656 static bool construct_notify_jobs_info(print_queue_struct *queue,
3657 SPOOL_NOTIFY_INFO *info,
3658 NT_PRINTER_INFO_LEVEL *printer,
3659 int snum, SPOOL_NOTIFY_OPTION_TYPE
3660 *option_type, uint32 id,
3661 TALLOC_CTX *mem_ctx)
3667 SPOOL_NOTIFY_INFO_DATA *current_data;
3669 DEBUG(4,("construct_notify_jobs_info\n"));
3671 type = option_type->type;
3673 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3674 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3675 option_type->count));
3677 for(field_num=0; field_num<option_type->count; field_num++) {
3678 field = option_type->fields[field_num];
3680 if (!search_notify(type, field, &j) )
3683 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3684 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3688 current_data=&(info->data[info->count]);
3690 construct_info_data(current_data, type, field, id);
3691 notify_info_data_table[j].fn(snum, current_data, queue,
3700 * JFM: The enumeration is not that simple, it's even non obvious.
3702 * let's take an example: I want to monitor the PRINTER SERVER for
3703 * the printer's name and the number of jobs currently queued.
3704 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3705 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3707 * I have 3 printers on the back of my server.
3709 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3712 * 1 printer 1 name 1
3713 * 2 printer 1 cjob 1
3714 * 3 printer 2 name 2
3715 * 4 printer 2 cjob 2
3716 * 5 printer 3 name 3
3717 * 6 printer 3 name 3
3719 * that's the print server case, the printer case is even worse.
3722 /*******************************************************************
3724 * enumerate all printers on the printserver
3725 * fill a notify_info struct with info asked
3727 ********************************************************************/
3729 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3730 SPOOL_NOTIFY_INFO *info,
3731 TALLOC_CTX *mem_ctx)
3734 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3735 int n_services=lp_numservices();
3737 SPOOL_NOTIFY_OPTION *option;
3738 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3740 DEBUG(4,("printserver_notify_info\n"));
3745 option=Printer->notify.option;
3750 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3751 sending a ffpcn() request first */
3756 for (i=0; i<option->count; i++) {
3757 option_type=&(option->ctr.type[i]);
3759 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3762 for (snum=0; snum<n_services; snum++)
3764 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3765 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3771 * Debugging information, don't delete.
3774 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3775 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3776 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3778 for (i=0; i<info->count; i++) {
3779 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3780 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3781 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3788 /*******************************************************************
3790 * fill a notify_info struct with info asked
3792 ********************************************************************/
3794 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3795 TALLOC_CTX *mem_ctx)
3798 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3801 SPOOL_NOTIFY_OPTION *option;
3802 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3804 print_queue_struct *queue=NULL;
3805 print_status_struct status;
3807 DEBUG(4,("printer_notify_info\n"));
3812 option=Printer->notify.option;
3818 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3819 sending a ffpcn() request first */
3824 get_printer_snum(p, hnd, &snum, NULL);
3826 for (i=0; i<option->count; i++) {
3827 option_type=&option->ctr.type[i];
3829 switch ( option_type->type ) {
3830 case PRINTER_NOTIFY_TYPE:
3831 if(construct_notify_printer_info(Printer, info, snum,
3837 case JOB_NOTIFY_TYPE: {
3838 NT_PRINTER_INFO_LEVEL *printer = NULL;
3840 count = print_queue_status(snum, &queue, &status);
3842 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3845 for (j=0; j<count; j++) {
3846 construct_notify_jobs_info(&queue[j], info,
3853 free_a_printer(&printer, 2);
3863 * Debugging information, don't delete.
3866 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3867 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3868 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3870 for (i=0; i<info->count; i++) {
3871 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3872 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3873 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3879 /********************************************************************
3881 ********************************************************************/
3883 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3885 POLICY_HND *handle = &q_u->handle;
3886 SPOOL_NOTIFY_INFO *info = &r_u->info;
3888 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3889 WERROR result = WERR_BADFID;
3891 /* we always have a NOTIFY_INFO struct */
3895 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3896 OUR_HANDLE(handle)));
3900 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3903 * We are now using the change value, and
3904 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3905 * I don't have a global notification system, I'm sending back all the
3906 * informations even when _NOTHING_ has changed.
3909 /* We need to keep track of the change value to send back in
3910 RRPCN replies otherwise our updates are ignored. */
3912 Printer->notify.fnpcn = True;
3914 if (Printer->notify.client_connected) {
3915 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3916 Printer->notify.change = q_u->change;
3919 /* just ignore the SPOOL_NOTIFY_OPTION */
3921 switch (Printer->printer_type) {
3923 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3926 case SPLHND_PRINTER:
3927 result = printer_notify_info(p, handle, info, p->mem_ctx);
3931 Printer->notify.fnpcn = False;
3937 /********************************************************************
3938 * construct_printer_info_0
3939 * fill a printer_info_0 struct
3940 ********************************************************************/
3942 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3944 char *chaine = NULL;
3946 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3947 counter_printer_0 *session_counter;
3948 uint32 global_counter;
3951 print_status_struct status;
3952 TALLOC_CTX *ctx = talloc_tos();
3954 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3957 init_unistr(&printer->printername, ntprinter->info_2->printername);
3959 chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3961 free_a_printer(&ntprinter,2);
3965 count = print_queue_length(snum, &status);
3967 /* check if we already have a counter for this printer */
3968 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3969 if (session_counter->snum == snum)
3973 init_unistr(&printer->servername, chaine);
3975 /* it's the first time, add it to the list */
3976 if (session_counter==NULL) {
3977 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3978 free_a_printer(&ntprinter, 2);
3981 ZERO_STRUCTP(session_counter);
3982 session_counter->snum=snum;
3983 session_counter->counter=0;
3984 DLIST_ADD(counter_list, session_counter);
3988 session_counter->counter++;
3991 * the global_counter should be stored in a TDB as it's common to all the clients
3992 * and should be zeroed on samba startup
3994 global_counter=session_counter->counter;
3995 printer->cjobs = count;
3996 printer->total_jobs = 0;
3997 printer->total_bytes = 0;
3999 setuptime = (time_t)ntprinter->info_2->setuptime;
4000 t=gmtime(&setuptime);
4002 printer->year = t->tm_year+1900;
4003 printer->month = t->tm_mon+1;
4004 printer->dayofweek = t->tm_wday;
4005 printer->day = t->tm_mday;
4006 printer->hour = t->tm_hour;
4007 printer->minute = t->tm_min;
4008 printer->second = t->tm_sec;
4009 printer->milliseconds = 0;
4011 printer->global_counter = global_counter;
4012 printer->total_pages = 0;
4014 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4015 printer->major_version = 0x0005; /* NT 5 */
4016 printer->build_version = 0x0893; /* build 2195 */
4018 printer->unknown7 = 0x1;
4019 printer->unknown8 = 0x0;
4020 printer->unknown9 = 0x0;
4021 printer->session_counter = session_counter->counter;
4022 printer->unknown11 = 0x0;
4023 printer->printer_errors = 0x0; /* number of print failure */
4024 printer->unknown13 = 0x0;
4025 printer->unknown14 = 0x1;
4026 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4027 printer->unknown16 = 0x0;
4028 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4029 printer->unknown18 = 0x0;
4030 printer->status = nt_printq_status(status.status);
4031 printer->unknown20 = 0x0;
4032 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4033 printer->unknown22 = 0x0;
4034 printer->unknown23 = 0x6; /* 6 ???*/
4035 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4036 printer->unknown25 = 0;
4037 printer->unknown26 = 0;
4038 printer->unknown27 = 0;
4039 printer->unknown28 = 0;
4040 printer->unknown29 = 0;
4042 free_a_printer(&ntprinter,2);
4046 /********************************************************************
4047 * construct_printer_info_1
4048 * fill a printer_info_1 struct
4049 ********************************************************************/
4050 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4052 char *chaine = NULL;
4053 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4054 TALLOC_CTX *ctx = talloc_tos();
4056 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4059 printer->flags=flags;
4061 if (*ntprinter->info_2->comment == '\0') {
4062 init_unistr(&printer->comment, lp_comment(snum));
4063 chaine = talloc_asprintf(ctx,
4064 "%s,%s,%s", ntprinter->info_2->printername,
4065 ntprinter->info_2->drivername, lp_comment(snum));
4068 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4069 chaine = talloc_asprintf(ctx,
4070 "%s,%s,%s", ntprinter->info_2->printername,
4071 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4075 free_a_printer(&ntprinter,2);
4079 init_unistr(&printer->description, chaine);
4080 init_unistr(&printer->name, ntprinter->info_2->printername);
4082 free_a_printer(&ntprinter,2);
4087 /****************************************************************************
4088 Free a DEVMODE struct.
4089 ****************************************************************************/
4091 static void free_dev_mode(DEVICEMODE *dev)
4096 SAFE_FREE(dev->dev_private);
4101 /****************************************************************************
4102 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4103 should be valid upon entry
4104 ****************************************************************************/
4106 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4108 if ( !devmode || !ntdevmode )
4111 init_unistr(&devmode->devicename, ntdevmode->devicename);
4113 init_unistr(&devmode->formname, ntdevmode->formname);
4115 devmode->specversion = ntdevmode->specversion;
4116 devmode->driverversion = ntdevmode->driverversion;
4117 devmode->size = ntdevmode->size;
4118 devmode->driverextra = ntdevmode->driverextra;
4119 devmode->fields = ntdevmode->fields;
4121 devmode->orientation = ntdevmode->orientation;
4122 devmode->papersize = ntdevmode->papersize;
4123 devmode->paperlength = ntdevmode->paperlength;
4124 devmode->paperwidth = ntdevmode->paperwidth;
4125 devmode->scale = ntdevmode->scale;
4126 devmode->copies = ntdevmode->copies;
4127 devmode->defaultsource = ntdevmode->defaultsource;
4128 devmode->printquality = ntdevmode->printquality;
4129 devmode->color = ntdevmode->color;
4130 devmode->duplex = ntdevmode->duplex;
4131 devmode->yresolution = ntdevmode->yresolution;
4132 devmode->ttoption = ntdevmode->ttoption;
4133 devmode->collate = ntdevmode->collate;
4134 devmode->icmmethod = ntdevmode->icmmethod;
4135 devmode->icmintent = ntdevmode->icmintent;
4136 devmode->mediatype = ntdevmode->mediatype;
4137 devmode->dithertype = ntdevmode->dithertype;
4139 if (ntdevmode->nt_dev_private != NULL) {
4140 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4147 /****************************************************************************
4148 Create a DEVMODE struct. Returns malloced memory.
4149 ****************************************************************************/
4151 DEVICEMODE *construct_dev_mode(const char *servicename)
4153 NT_PRINTER_INFO_LEVEL *printer = NULL;
4154 DEVICEMODE *devmode = NULL;
4156 DEBUG(7,("construct_dev_mode\n"));
4158 DEBUGADD(8,("getting printer characteristics\n"));
4160 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4163 if ( !printer->info_2->devmode ) {
4164 DEBUG(5, ("BONG! There was no device mode!\n"));
4168 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4169 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4173 ZERO_STRUCTP(devmode);
4175 DEBUGADD(8,("loading DEVICEMODE\n"));
4177 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4178 free_dev_mode( devmode );
4183 free_a_printer(&printer,2);
4188 /********************************************************************
4189 * construct_printer_info_2
4190 * fill a printer_info_2 struct
4191 ********************************************************************/
4193 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4196 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4198 print_status_struct status;
4200 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4203 count = print_queue_length(snum, &status);
4205 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4206 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4207 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4208 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4209 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4211 if (*ntprinter->info_2->comment == '\0')
4212 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4214 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4216 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4217 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4218 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4219 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4220 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4222 printer->attributes = ntprinter->info_2->attributes;
4224 printer->priority = ntprinter->info_2->priority; /* priority */
4225 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4226 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4227 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4228 printer->status = nt_printq_status(status.status); /* status */
4229 printer->cjobs = count; /* jobs */
4230 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4232 if ( !(printer->devmode = construct_dev_mode(
4233 lp_const_servicename(snum))) )
4234 DEBUG(8, ("Returning NULL Devicemode!\n"));
4236 printer->secdesc = NULL;
4238 if ( ntprinter->info_2->secdesc_buf
4239 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4241 /* don't use talloc_steal() here unless you do a deep steal of all
4242 the SEC_DESC members */
4244 printer->secdesc = dup_sec_desc( talloc_tos(),
4245 ntprinter->info_2->secdesc_buf->sd );
4248 free_a_printer(&ntprinter, 2);
4253 /********************************************************************
4254 * construct_printer_info_3
4255 * fill a printer_info_3 struct
4256 ********************************************************************/
4258 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4260 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4261 PRINTER_INFO_3 *printer = NULL;
4263 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4267 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4268 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4269 free_a_printer(&ntprinter, 2);
4273 ZERO_STRUCTP(printer);
4275 /* These are the components of the SD we are returning. */
4277 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4278 /* don't use talloc_steal() here unless you do a deep steal of all
4279 the SEC_DESC members */
4281 printer->secdesc = dup_sec_desc( talloc_tos(),
4282 ntprinter->info_2->secdesc_buf->sd );
4285 free_a_printer(&ntprinter, 2);
4287 *pp_printer = printer;
4291 /********************************************************************
4292 * construct_printer_info_4
4293 * fill a printer_info_4 struct
4294 ********************************************************************/
4296 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4298 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4300 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4303 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4304 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4305 printer->attributes = ntprinter->info_2->attributes;
4307 free_a_printer(&ntprinter, 2);
4311 /********************************************************************
4312 * construct_printer_info_5
4313 * fill a printer_info_5 struct
4314 ********************************************************************/
4316 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4318 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4320 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4323 init_unistr(&printer->printername, ntprinter->info_2->printername);
4324 init_unistr(&printer->portname, ntprinter->info_2->portname);
4325 printer->attributes = ntprinter->info_2->attributes;
4327 /* these two are not used by NT+ according to MSDN */
4329 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4330 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4332 free_a_printer(&ntprinter, 2);
4337 /********************************************************************
4338 * construct_printer_info_6
4339 * fill a printer_info_6 struct
4340 ********************************************************************/
4342 static bool construct_printer_info_6(Printer_entry *print_hnd,
4343 PRINTER_INFO_6 *printer,
4346 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4348 print_status_struct status;
4350 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4351 lp_const_servicename(snum))))
4354 count = print_queue_length(snum, &status);
4356 printer->status = nt_printq_status(status.status);
4358 free_a_printer(&ntprinter, 2);
4363 /********************************************************************
4364 * construct_printer_info_7
4365 * fill a printer_info_7 struct
4366 ********************************************************************/
4368 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4370 char *guid_str = NULL;
4373 if (is_printer_published(print_hnd, snum, &guid)) {
4374 if (asprintf(&guid_str, "{%s}",
4375 smb_uuid_string(talloc_tos(), guid)) == -1) {
4378 strupper_m(guid_str);
4379 init_unistr(&printer->guid, guid_str);
4380 SAFE_FREE(guid_str);
4381 printer->action = SPOOL_DS_PUBLISH;
4383 init_unistr(&printer->guid, "");
4384 printer->action = SPOOL_DS_UNPUBLISH;
4390 /********************************************************************
4391 Spoolss_enumprinters.
4392 ********************************************************************/
4394 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4398 int n_services=lp_numservices();
4399 PRINTER_INFO_1 *printers=NULL;
4400 PRINTER_INFO_1 current_prt;
4401 WERROR result = WERR_OK;
4403 DEBUG(4,("enum_all_printers_info_1\n"));
4405 for (snum=0; snum<n_services; snum++) {
4406 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4407 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4409 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4410 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4411 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4415 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4417 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4423 /* check the required size. */
4424 for (i=0; i<*returned; i++)
4425 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4427 if (*needed > offered) {
4428 result = WERR_INSUFFICIENT_BUFFER;
4432 if (!rpcbuf_alloc_size(buffer, *needed)) {
4433 result = WERR_NOMEM;
4437 /* fill the buffer with the structures */
4438 for (i=0; i<*returned; i++)
4439 smb_io_printer_info_1("", buffer, &printers[i], 0);
4444 SAFE_FREE(printers);
4446 if ( !W_ERROR_IS_OK(result) )
4452 /********************************************************************
4453 enum_all_printers_info_1_local.
4454 *********************************************************************/
4456 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4458 DEBUG(4,("enum_all_printers_info_1_local\n"));
4460 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4463 /********************************************************************
4464 enum_all_printers_info_1_name.
4465 *********************************************************************/
4467 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4471 DEBUG(4,("enum_all_printers_info_1_name\n"));
4473 if ((name[0] == '\\') && (name[1] == '\\'))
4476 if (is_myname_or_ipaddr(s)) {
4477 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4480 return WERR_INVALID_NAME;
4483 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4484 /********************************************************************
4485 enum_all_printers_info_1_remote.
4486 *********************************************************************/
4488 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4490 PRINTER_INFO_1 *printer;
4491 fstring printername;
4494 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4495 WERROR result = WERR_OK;
4497 /* JFM: currently it's more a place holder than anything else.
4498 * In the spooler world there is a notion of server registration.
4499 * the print servers are registered on the PDC (in the same domain)
4501 * We should have a TDB here. The registration is done thru an
4502 * undocumented RPC call.
4505 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4510 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4511 slprintf(desc, sizeof(desc)-1,"%s", name);
4512 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4514 init_unistr(&printer->description, desc);
4515 init_unistr(&printer->name, printername);
4516 init_unistr(&printer->comment, comment);
4517 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4519 /* check the required size. */
4520 *needed += spoolss_size_printer_info_1(printer);
4522 if (*needed > offered) {
4523 result = WERR_INSUFFICIENT_BUFFER;
4527 if (!rpcbuf_alloc_size(buffer, *needed)) {
4528 result = WERR_NOMEM;
4532 /* fill the buffer with the structures */
4533 smb_io_printer_info_1("", buffer, printer, 0);
4539 if ( !W_ERROR_IS_OK(result) )
4547 /********************************************************************
4548 enum_all_printers_info_1_network.
4549 *********************************************************************/
4551 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4555 DEBUG(4,("enum_all_printers_info_1_network\n"));
4557 /* If we respond to a enum_printers level 1 on our name with flags
4558 set to PRINTER_ENUM_REMOTE with a list of printers then these
4559 printers incorrectly appear in the APW browse list.
4560 Specifically the printers for the server appear at the workgroup
4561 level where all the other servers in the domain are
4562 listed. Windows responds to this call with a
4563 WERR_CAN_NOT_COMPLETE so we should do the same. */
4565 if (name[0] == '\\' && name[1] == '\\')
4568 if (is_myname_or_ipaddr(s))
4569 return WERR_CAN_NOT_COMPLETE;
4571 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4574 /********************************************************************
4575 * api_spoolss_enumprinters
4577 * called from api_spoolss_enumprinters (see this to understand)
4578 ********************************************************************/
4580 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4584 int n_services=lp_numservices();
4585 PRINTER_INFO_2 *printers=NULL;
4586 PRINTER_INFO_2 current_prt;
4587 WERROR result = WERR_OK;
4591 for (snum=0; snum<n_services; snum++) {
4592 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4593 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4595 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4596 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4597 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4602 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4604 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4611 /* check the required size. */
4612 for (i=0; i<*returned; i++)
4613 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4615 if (*needed > offered) {
4616 result = WERR_INSUFFICIENT_BUFFER;
4620 if (!rpcbuf_alloc_size(buffer, *needed)) {
4621 result = WERR_NOMEM;
4625 /* fill the buffer with the structures */
4626 for (i=0; i<*returned; i++)
4627 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4632 for (i=0; i<*returned; i++)
4633 free_devmode(printers[i].devmode);
4635 SAFE_FREE(printers);
4637 if ( !W_ERROR_IS_OK(result) )
4643 /********************************************************************
4644 * handle enumeration of printers at level 1
4645 ********************************************************************/
4647 static WERROR enumprinters_level1( uint32 flags, fstring name,
4648 RPC_BUFFER *buffer, uint32 offered,
4649 uint32 *needed, uint32 *returned)
4651 /* Not all the flags are equals */
4653 if (flags & PRINTER_ENUM_LOCAL)
4654 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4656 if (flags & PRINTER_ENUM_NAME)
4657 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4659 #if 0 /* JERRY - disabled for now */
4660 if (flags & PRINTER_ENUM_REMOTE)
4661 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4664 if (flags & PRINTER_ENUM_NETWORK)
4665 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4667 return WERR_OK; /* NT4sp5 does that */
4670 /********************************************************************
4671 * handle enumeration of printers at level 2
4672 ********************************************************************/
4674 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4675 RPC_BUFFER *buffer, uint32 offered,
4676 uint32 *needed, uint32 *returned)
4678 if (flags & PRINTER_ENUM_LOCAL) {
4679 return enum_all_printers_info_2(buffer, offered, needed, returned);
4682 if (flags & PRINTER_ENUM_NAME) {
4683 if (is_myname_or_ipaddr(canon_servername(servername)))
4684 return enum_all_printers_info_2(buffer, offered, needed, returned);
4686 return WERR_INVALID_NAME;
4689 if (flags & PRINTER_ENUM_REMOTE)
4690 return WERR_UNKNOWN_LEVEL;
4695 /********************************************************************
4696 * handle enumeration of printers at level 5
4697 ********************************************************************/
4699 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4700 RPC_BUFFER *buffer, uint32 offered,
4701 uint32 *needed, uint32 *returned)
4703 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4707 /********************************************************************
4708 * api_spoolss_enumprinters
4710 * called from api_spoolss_enumprinters (see this to understand)
4711 ********************************************************************/
4713 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4715 uint32 flags = q_u->flags;
4716 UNISTR2 *servername = &q_u->servername;
4717 uint32 level = q_u->level;
4718 RPC_BUFFER *buffer = NULL;
4719 uint32 offered = q_u->offered;
4720 uint32 *needed = &r_u->needed;
4721 uint32 *returned = &r_u->returned;
4725 /* that's an [in out] buffer */
4727 if (!q_u->buffer && (offered!=0)) {
4728 return WERR_INVALID_PARAM;
4731 rpcbuf_move(q_u->buffer, &r_u->buffer);
4732 buffer = r_u->buffer;
4734 DEBUG(4,("_spoolss_enumprinters\n"));
4741 * flags==PRINTER_ENUM_NAME
4742 * if name=="" then enumerates all printers
4743 * if name!="" then enumerate the printer
4744 * flags==PRINTER_ENUM_REMOTE
4745 * name is NULL, enumerate printers
4746 * Level 2: name!="" enumerates printers, name can't be NULL
4747 * Level 3: doesn't exist
4748 * Level 4: does a local registry lookup
4749 * Level 5: same as Level 2
4752 unistr2_to_ascii(name, servername, sizeof(name));
4757 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4759 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4761 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4766 return WERR_UNKNOWN_LEVEL;
4769 /****************************************************************************
4770 ****************************************************************************/
4772 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4774 PRINTER_INFO_0 *printer=NULL;
4775 WERROR result = WERR_OK;
4777 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4780 construct_printer_info_0(print_hnd, printer, snum);
4782 /* check the required size. */
4783 *needed += spoolss_size_printer_info_0(printer);
4785 if (*needed > offered) {
4786 result = WERR_INSUFFICIENT_BUFFER;
4790 if (!rpcbuf_alloc_size(buffer, *needed)) {
4791 result = WERR_NOMEM;
4795 /* fill the buffer with the structures */
4796 smb_io_printer_info_0("", buffer, printer, 0);
4806 /****************************************************************************
4807 ****************************************************************************/
4809 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4811 PRINTER_INFO_1 *printer=NULL;
4812 WERROR result = WERR_OK;
4814 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4817 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4819 /* check the required size. */
4820 *needed += spoolss_size_printer_info_1(printer);
4822 if (*needed > offered) {
4823 result = WERR_INSUFFICIENT_BUFFER;
4827 if (!rpcbuf_alloc_size(buffer, *needed)) {
4828 result = WERR_NOMEM;
4832 /* fill the buffer with the structures */
4833 smb_io_printer_info_1("", buffer, printer, 0);
4842 /****************************************************************************
4843 ****************************************************************************/
4845 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4847 PRINTER_INFO_2 *printer=NULL;
4848 WERROR result = WERR_OK;
4850 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4853 construct_printer_info_2(print_hnd, printer, snum);
4855 /* check the required size. */
4856 *needed += spoolss_size_printer_info_2(printer);
4858 if (*needed > offered) {
4859 result = WERR_INSUFFICIENT_BUFFER;
4863 if (!rpcbuf_alloc_size(buffer, *needed)) {
4864 result = WERR_NOMEM;
4868 /* fill the buffer with the structures */
4869 if (!smb_io_printer_info_2("", buffer, printer, 0))
4870 result = WERR_NOMEM;
4874 free_printer_info_2(printer);
4879 /****************************************************************************
4880 ****************************************************************************/
4882 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4884 PRINTER_INFO_3 *printer=NULL;
4885 WERROR result = WERR_OK;
4887 if (!construct_printer_info_3(print_hnd, &printer, snum))
4890 /* check the required size. */
4891 *needed += spoolss_size_printer_info_3(printer);
4893 if (*needed > offered) {
4894 result = WERR_INSUFFICIENT_BUFFER;
4898 if (!rpcbuf_alloc_size(buffer, *needed)) {
4899 result = WERR_NOMEM;
4903 /* fill the buffer with the structures */
4904 smb_io_printer_info_3("", buffer, printer, 0);
4908 free_printer_info_3(printer);
4913 /****************************************************************************
4914 ****************************************************************************/
4916 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4918 PRINTER_INFO_4 *printer=NULL;
4919 WERROR result = WERR_OK;
4921 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4924 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4929 /* check the required size. */
4930 *needed += spoolss_size_printer_info_4(printer);
4932 if (*needed > offered) {
4933 result = WERR_INSUFFICIENT_BUFFER;
4937 if (!rpcbuf_alloc_size(buffer, *needed)) {
4938 result = WERR_NOMEM;
4942 /* fill the buffer with the structures */
4943 smb_io_printer_info_4("", buffer, printer, 0);
4947 free_printer_info_4(printer);
4952 /****************************************************************************
4953 ****************************************************************************/
4955 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4957 PRINTER_INFO_5 *printer=NULL;
4958 WERROR result = WERR_OK;
4960 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4963 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4964 free_printer_info_5(printer);
4968 /* check the required size. */
4969 *needed += spoolss_size_printer_info_5(printer);
4971 if (*needed > offered) {
4972 result = WERR_INSUFFICIENT_BUFFER;
4976 if (!rpcbuf_alloc_size(buffer, *needed)) {
4977 result = WERR_NOMEM;
4981 /* fill the buffer with the structures */
4982 smb_io_printer_info_5("", buffer, printer, 0);
4986 free_printer_info_5(printer);
4991 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4993 RPC_BUFFER *buffer, uint32 offered,
4996 PRINTER_INFO_6 *printer;
4997 WERROR result = WERR_OK;
4999 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
5003 if (!construct_printer_info_6(print_hnd, printer, snum)) {
5004 free_printer_info_6(printer);
5008 /* check the required size. */
5009 *needed += spoolss_size_printer_info_6(printer);
5011 if (*needed > offered) {
5012 result = WERR_INSUFFICIENT_BUFFER;
5016 if (!rpcbuf_alloc_size(buffer, *needed)) {
5017 result = WERR_NOMEM;
5021 /* fill the buffer with the structures */
5022 smb_io_printer_info_6("", buffer, printer, 0);
5026 free_printer_info_6(printer);
5031 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5033 PRINTER_INFO_7 *printer=NULL;
5034 WERROR result = WERR_OK;
5036 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5039 if (!construct_printer_info_7(print_hnd, printer, snum))
5042 /* check the required size. */
5043 *needed += spoolss_size_printer_info_7(printer);
5045 if (*needed > offered) {
5046 result = WERR_INSUFFICIENT_BUFFER;
5050 if (!rpcbuf_alloc_size(buffer, *needed)) {
5051 result = WERR_NOMEM;
5056 /* fill the buffer with the structures */
5057 smb_io_printer_info_7("", buffer, printer, 0);
5061 free_printer_info_7(printer);
5066 /****************************************************************************
5067 ****************************************************************************/
5069 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5071 POLICY_HND *handle = &q_u->handle;
5072 uint32 level = q_u->level;
5073 RPC_BUFFER *buffer = NULL;
5074 uint32 offered = q_u->offered;
5075 uint32 *needed = &r_u->needed;
5076 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5080 /* that's an [in out] buffer */
5082 if (!q_u->buffer && (offered!=0)) {
5083 return WERR_INVALID_PARAM;
5086 rpcbuf_move(q_u->buffer, &r_u->buffer);
5087 buffer = r_u->buffer;
5091 if (!get_printer_snum(p, handle, &snum, NULL))
5096 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5098 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5100 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5102 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5104 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5106 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5108 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5110 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5112 return WERR_UNKNOWN_LEVEL;
5115 /********************************************************************
5116 * fill a DRIVER_INFO_1 struct
5117 ********************************************************************/
5119 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5121 init_unistr( &info->name, driver.info_3->name);
5124 /********************************************************************
5125 * construct_printer_driver_info_1
5126 ********************************************************************/
5128 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5130 NT_PRINTER_INFO_LEVEL *printer = NULL;
5131 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5133 ZERO_STRUCT(driver);
5135 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5136 return WERR_INVALID_PRINTER_NAME;
5138 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5139 free_a_printer(&printer, 2);
5140 return WERR_UNKNOWN_PRINTER_DRIVER;
5143 fill_printer_driver_info_1(info, driver, servername, architecture);
5145 free_a_printer(&printer,2);
5150 /********************************************************************
5151 * construct_printer_driver_info_2
5152 * fill a printer_info_2 struct
5153 ********************************************************************/
5155 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5157 TALLOC_CTX *ctx = talloc_tos();
5159 const char *cservername = canon_servername(servername);
5161 info->version=driver.info_3->cversion;
5163 init_unistr( &info->name, driver.info_3->name );
5164 init_unistr( &info->architecture, driver.info_3->environment );
5166 if (strlen(driver.info_3->driverpath)) {
5167 temp = talloc_asprintf(ctx,
5170 driver.info_3->driverpath);
5171 init_unistr( &info->driverpath, temp );
5173 init_unistr( &info->driverpath, "" );
5177 if (strlen(driver.info_3->datafile)) {
5178 temp = talloc_asprintf(ctx,
5181 driver.info_3->datafile);
5182 init_unistr( &info->datafile, temp );
5184 init_unistr( &info->datafile, "" );
5187 if (strlen(driver.info_3->configfile)) {
5188 temp = talloc_asprintf(ctx,
5191 driver.info_3->configfile);
5192 init_unistr( &info->configfile, temp );
5194 init_unistr( &info->configfile, "" );
5197 /********************************************************************
5198 * construct_printer_driver_info_2
5199 * fill a printer_info_2 struct
5200 ********************************************************************/
5202 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5204 NT_PRINTER_INFO_LEVEL *printer = NULL;
5205 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5207 ZERO_STRUCT(printer);
5208 ZERO_STRUCT(driver);
5210 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5211 return WERR_INVALID_PRINTER_NAME;
5213 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5214 free_a_printer(&printer, 2);
5215 return WERR_UNKNOWN_PRINTER_DRIVER;
5218 fill_printer_driver_info_2(info, driver, servername);
5220 free_a_printer(&printer,2);
5225 /********************************************************************
5226 * copy a strings array and convert to UNICODE
5228 * convert an array of ascii string to a UNICODE string
5229 ********************************************************************/
5231 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5237 TALLOC_CTX *ctx = talloc_tos();
5239 DEBUG(6,("init_unistr_array\n"));
5243 if ( !char_array ) {
5248 v = ""; /* hack to handle null lists */
5251 /* hack to allow this to be used in places other than when generating
5252 the list of dependent files */
5256 line = talloc_asprintf(ctx,
5258 canon_servername(servername),
5261 line = talloc_strdup(ctx, v);
5265 SAFE_FREE(*uni_array);
5268 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5270 /* add one extra unit16 for the second terminating NULL */
5272 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5273 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5280 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5285 /* special case for ""; we need to add both NULL's here */
5287 (*uni_array)[j++]=0x0000;
5288 (*uni_array)[j]=0x0000;
5291 DEBUGADD(6,("last one:done\n"));
5293 /* return size of array in uint16's */
5298 /********************************************************************
5299 * construct_printer_info_3
5300 * fill a printer_info_3 struct
5301 ********************************************************************/
5303 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5306 TALLOC_CTX *ctx = talloc_tos();
5307 const char *cservername = canon_servername(servername);
5311 info->version=driver.info_3->cversion;
5313 init_unistr( &info->name, driver.info_3->name );
5314 init_unistr( &info->architecture, driver.info_3->environment );
5316 if (strlen(driver.info_3->driverpath)) {
5317 temp = talloc_asprintf(ctx,
5320 driver.info_3->driverpath);
5321 init_unistr( &info->driverpath, temp );
5323 init_unistr( &info->driverpath, "" );
5326 if (strlen(driver.info_3->datafile)) {
5327 temp = talloc_asprintf(ctx,
5330 driver.info_3->datafile);
5331 init_unistr( &info->datafile, temp );
5333 init_unistr( &info->datafile, "" );
5336 if (strlen(driver.info_3->configfile)) {
5337 temp = talloc_asprintf(ctx,
5340 driver.info_3->configfile);
5341 init_unistr( &info->configfile, temp );
5343 init_unistr( &info->configfile, "" );
5346 if (strlen(driver.info_3->helpfile)) {
5347 temp = talloc_asprintf(ctx,
5350 driver.info_3->helpfile);
5351 init_unistr( &info->helpfile, temp );
5353 init_unistr( &info->helpfile, "" );
5356 init_unistr( &info->monitorname, driver.info_3->monitorname );
5357 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5359 info->dependentfiles=NULL;
5360 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5363 /********************************************************************
5364 * construct_printer_info_3
5365 * fill a printer_info_3 struct
5366 ********************************************************************/
5368 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5370 NT_PRINTER_INFO_LEVEL *printer = NULL;
5371 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5373 ZERO_STRUCT(driver);
5375 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5376 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5377 if (!W_ERROR_IS_OK(status))
5378 return WERR_INVALID_PRINTER_NAME;
5380 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5381 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5386 * I put this code in during testing. Helpful when commenting out the
5387 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5388 * as win2k always queries the driver using an infor level of 6.
5389 * I've left it in (but ifdef'd out) because I'll probably
5390 * use it in experimentation again in the future. --jerry 22/01/2002
5393 if (!W_ERROR_IS_OK(status)) {
5395 * Is this a W2k client ?
5398 /* Yes - try again with a WinNT driver. */
5400 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5401 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5405 if (!W_ERROR_IS_OK(status)) {
5406 free_a_printer(&printer,2);
5407 return WERR_UNKNOWN_PRINTER_DRIVER;
5415 fill_printer_driver_info_3(info, driver, servername);
5417 free_a_printer(&printer,2);
5422 /********************************************************************
5423 * construct_printer_info_6
5424 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5425 ********************************************************************/
5427 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5431 TALLOC_CTX *ctx = talloc_tos();
5432 const char *cservername = canon_servername(servername);
5435 memset(&nullstr, '\0', sizeof(fstring));
5437 info->version=driver.info_3->cversion;
5439 init_unistr( &info->name, driver.info_3->name );
5440 init_unistr( &info->architecture, driver.info_3->environment );
5442 if (strlen(driver.info_3->driverpath)) {
5443 temp = talloc_asprintf(ctx,
5446 driver.info_3->driverpath);
5447 init_unistr( &info->driverpath, temp );
5449 init_unistr( &info->driverpath, "" );
5452 if (strlen(driver.info_3->datafile)) {
5453 temp = talloc_asprintf(ctx,
5456 driver.info_3->datafile);
5457 init_unistr( &info->datafile, temp );
5459 init_unistr( &info->datafile, "" );
5462 if (strlen(driver.info_3->configfile)) {
5463 temp = talloc_asprintf(ctx,
5466 driver.info_3->configfile);
5467 init_unistr( &info->configfile, temp );
5469 init_unistr( &info->configfile, "" );
5472 if (strlen(driver.info_3->helpfile)) {
5473 temp = talloc_asprintf(ctx,
5476 driver.info_3->helpfile);
5477 init_unistr( &info->helpfile, temp );
5479 init_unistr( &info->helpfile, "" );
5482 init_unistr( &info->monitorname, driver.info_3->monitorname );
5483 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5485 info->dependentfiles = NULL;
5486 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5488 info->previousdrivernames=NULL;
5489 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5491 info->driver_date=0;
5494 info->driver_version_low=0;
5495 info->driver_version_high=0;
5497 init_unistr( &info->mfgname, "");
5498 init_unistr( &info->oem_url, "");
5499 init_unistr( &info->hardware_id, "");
5500 init_unistr( &info->provider, "");
5503 /********************************************************************
5504 * construct_printer_info_6
5505 * fill a printer_info_6 struct
5506 ********************************************************************/
5508 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5509 const char *servername, fstring architecture, uint32 version)
5511 NT_PRINTER_INFO_LEVEL *printer = NULL;
5512 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5515 ZERO_STRUCT(driver);
5517 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5519 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5521 if (!W_ERROR_IS_OK(status))
5522 return WERR_INVALID_PRINTER_NAME;
5524 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5526 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5528 if (!W_ERROR_IS_OK(status))
5531 * Is this a W2k client ?
5535 free_a_printer(&printer,2);
5536 return WERR_UNKNOWN_PRINTER_DRIVER;
5539 /* Yes - try again with a WinNT driver. */
5541 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5542 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5543 if (!W_ERROR_IS_OK(status)) {
5544 free_a_printer(&printer,2);
5545 return WERR_UNKNOWN_PRINTER_DRIVER;
5549 fill_printer_driver_info_6(info, driver, servername);
5551 free_a_printer(&printer,2);
5552 free_a_printer_driver(driver, 3);
5557 /****************************************************************************
5558 ****************************************************************************/
5560 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5562 SAFE_FREE(info->dependentfiles);
5565 /****************************************************************************
5566 ****************************************************************************/
5568 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5570 SAFE_FREE(info->dependentfiles);
5573 /****************************************************************************
5574 ****************************************************************************/
5576 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5578 DRIVER_INFO_1 *info=NULL;
5581 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5584 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5585 if (!W_ERROR_IS_OK(result))
5588 /* check the required size. */
5589 *needed += spoolss_size_printer_driver_info_1(info);
5591 if (*needed > offered) {
5592 result = WERR_INSUFFICIENT_BUFFER;
5596 if (!rpcbuf_alloc_size(buffer, *needed)) {
5597 result = WERR_NOMEM;
5601 /* fill the buffer with the structures */
5602 smb_io_printer_driver_info_1("", buffer, info, 0);
5611 /****************************************************************************
5612 ****************************************************************************/
5614 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5616 DRIVER_INFO_2 *info=NULL;
5619 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5622 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5623 if (!W_ERROR_IS_OK(result))
5626 /* check the required size. */
5627 *needed += spoolss_size_printer_driver_info_2(info);
5629 if (*needed > offered) {
5630 result = WERR_INSUFFICIENT_BUFFER;
5634 if (!rpcbuf_alloc_size(buffer, *needed)) {
5635 result = WERR_NOMEM;
5639 /* fill the buffer with the structures */
5640 smb_io_printer_driver_info_2("", buffer, info, 0);
5649 /****************************************************************************
5650 ****************************************************************************/
5652 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5659 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5660 if (!W_ERROR_IS_OK(result))
5663 /* check the required size. */
5664 *needed += spoolss_size_printer_driver_info_3(&info);
5666 if (*needed > offered) {
5667 result = WERR_INSUFFICIENT_BUFFER;
5671 if (!rpcbuf_alloc_size(buffer, *needed)) {
5672 result = WERR_NOMEM;
5676 /* fill the buffer with the structures */
5677 smb_io_printer_driver_info_3("", buffer, &info, 0);
5680 free_printer_driver_info_3(&info);
5685 /****************************************************************************
5686 ****************************************************************************/
5688 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5695 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5696 if (!W_ERROR_IS_OK(result))
5699 /* check the required size. */
5700 *needed += spoolss_size_printer_driver_info_6(&info);
5702 if (*needed > offered) {
5703 result = WERR_INSUFFICIENT_BUFFER;
5707 if (!rpcbuf_alloc_size(buffer, *needed)) {
5708 result = WERR_NOMEM;
5712 /* fill the buffer with the structures */
5713 smb_io_printer_driver_info_6("", buffer, &info, 0);
5716 free_printer_driver_info_6(&info);
5721 /****************************************************************************
5722 ****************************************************************************/
5724 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5726 POLICY_HND *handle = &q_u->handle;
5727 UNISTR2 *uni_arch = &q_u->architecture;
5728 uint32 level = q_u->level;
5729 uint32 clientmajorversion = q_u->clientmajorversion;
5730 RPC_BUFFER *buffer = NULL;
5731 uint32 offered = q_u->offered;
5732 uint32 *needed = &r_u->needed;
5733 uint32 *servermajorversion = &r_u->servermajorversion;
5734 uint32 *serverminorversion = &r_u->serverminorversion;
5735 Printer_entry *printer;
5738 fstring architecture;
5741 /* that's an [in out] buffer */
5743 if (!q_u->buffer && (offered!=0)) {
5744 return WERR_INVALID_PARAM;
5747 rpcbuf_move(q_u->buffer, &r_u->buffer);
5748 buffer = r_u->buffer;
5750 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5752 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5753 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5754 return WERR_INVALID_PRINTER_NAME;
5758 *servermajorversion = 0;
5759 *serverminorversion = 0;
5761 fstrcpy(servername, get_server_name( printer ));
5762 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5764 if (!get_printer_snum(p, handle, &snum, NULL))
5769 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5771 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5773 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5775 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5778 /* apparently this call is the equivalent of
5779 EnumPrinterDataEx() for the DsDriver key */
5784 return WERR_UNKNOWN_LEVEL;
5787 /****************************************************************************
5788 ****************************************************************************/
5790 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5792 POLICY_HND *handle = &q_u->handle;
5794 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5797 DEBUG(3,("Error in startpageprinter printer handle\n"));
5801 Printer->page_started=True;
5805 /****************************************************************************
5806 ****************************************************************************/
5808 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5810 POLICY_HND *handle = &q_u->handle;
5813 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5816 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5820 if (!get_printer_snum(p, handle, &snum, NULL))
5823 Printer->page_started=False;
5824 print_job_endpage(snum, Printer->jobid);
5829 /********************************************************************
5830 * api_spoolss_getprinter
5831 * called from the spoolss dispatcher
5833 ********************************************************************/
5835 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5837 POLICY_HND *handle = &q_u->handle;
5838 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5839 uint32 *jobid = &r_u->jobid;
5840 TALLOC_CTX *ctx = p->mem_ctx;
5841 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5843 char *jobname = NULL;
5845 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5848 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5853 * a nice thing with NT is it doesn't listen to what you tell it.
5854 * when asked to send _only_ RAW datas, it tries to send datas
5857 * So I add checks like in NT Server ...
5860 if (info_1->p_datatype != 0) {
5861 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5862 if (strcmp(datatype, "RAW") != 0) {
5864 return WERR_INVALID_DATATYPE;
5868 /* get the share number of the printer */
5869 if (!get_printer_snum(p, handle, &snum, NULL)) {
5873 jobname = unistr2_to_ascii_talloc(ctx, &info_1->docname);
5875 Printer->jobid = print_job_start(p->server_info, snum, jobname,
5876 Printer->nt_devmode);
5878 /* An error occured in print_job_start() so return an appropriate
5881 if (Printer->jobid == -1) {
5882 return map_werror_from_unix(errno);
5885 Printer->document_started=True;
5886 (*jobid) = Printer->jobid;
5891 /********************************************************************
5892 * api_spoolss_getprinter
5893 * called from the spoolss dispatcher
5895 ********************************************************************/
5897 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5899 POLICY_HND *handle = &q_u->handle;
5901 return _spoolss_enddocprinter_internal(p, handle);
5904 /****************************************************************************
5905 ****************************************************************************/
5907 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5909 POLICY_HND *handle = &q_u->handle;
5910 uint32 buffer_size = q_u->buffer_size;
5911 uint8 *buffer = q_u->buffer;
5912 uint32 *buffer_written = &q_u->buffer_size2;
5914 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5917 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5918 r_u->buffer_written = q_u->buffer_size2;
5922 if (!get_printer_snum(p, handle, &snum, NULL))
5925 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5926 (SMB_OFF_T)-1, (size_t)buffer_size);
5927 if (*buffer_written == (uint32)-1) {
5928 r_u->buffer_written = 0;
5929 if (errno == ENOSPC)
5930 return WERR_NO_SPOOL_SPACE;
5932 return WERR_ACCESS_DENIED;
5935 r_u->buffer_written = q_u->buffer_size2;
5940 /********************************************************************
5941 * api_spoolss_getprinter
5942 * called from the spoolss dispatcher
5944 ********************************************************************/
5946 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5950 WERROR errcode = WERR_BADFUNC;
5951 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5954 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5958 if (!get_printer_snum(p, handle, &snum, NULL))
5962 case PRINTER_CONTROL_PAUSE:
5963 if (print_queue_pause(p->server_info, snum, &errcode)) {
5967 case PRINTER_CONTROL_RESUME:
5968 case PRINTER_CONTROL_UNPAUSE:
5969 if (print_queue_resume(p->server_info, snum, &errcode)) {
5973 case PRINTER_CONTROL_PURGE:
5974 if (print_queue_purge(p->server_info, snum, &errcode)) {
5979 return WERR_UNKNOWN_LEVEL;
5985 /********************************************************************
5986 * api_spoolss_abortprinter
5987 * From MSDN: "Deletes printer's spool file if printer is configured
5989 ********************************************************************/
5991 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5993 POLICY_HND *handle = &q_u->handle;
5994 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5996 WERROR errcode = WERR_OK;
5999 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
6003 if (!get_printer_snum(p, handle, &snum, NULL))
6006 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
6011 /********************************************************************
6012 * called by spoolss_api_setprinter
6013 * when updating a printer description
6014 ********************************************************************/
6016 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
6017 const SPOOL_PRINTER_INFO_LEVEL *info,
6018 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6020 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6024 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6026 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6027 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6028 OUR_HANDLE(handle)));
6030 result = WERR_BADFID;
6035 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6036 result = WERR_INVALID_PARAM;
6040 /* Check the user has permissions to change the security
6041 descriptor. By experimentation with two NT machines, the user
6042 requires Full Access to the printer to change security
6045 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6046 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6047 result = WERR_ACCESS_DENIED;
6051 /* NT seems to like setting the security descriptor even though
6052 nothing may have actually changed. */
6054 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6055 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6056 result = WERR_BADFID;
6060 if (DEBUGLEVEL >= 10) {
6064 the_acl = old_secdesc_ctr->sd->dacl;
6065 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6066 PRINTERNAME(snum), the_acl->num_aces));
6068 for (i = 0; i < the_acl->num_aces; i++) {
6069 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6070 &the_acl->aces[i].trustee),
6071 the_acl->aces[i].access_mask));
6074 the_acl = secdesc_ctr->sd->dacl;
6077 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6078 PRINTERNAME(snum), the_acl->num_aces));
6080 for (i = 0; i < the_acl->num_aces; i++) {
6081 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6082 &the_acl->aces[i].trustee),
6083 the_acl->aces[i].access_mask));
6086 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6090 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6091 if (!new_secdesc_ctr) {
6092 result = WERR_NOMEM;
6096 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6101 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6108 /********************************************************************
6109 Canonicalize printer info from a client
6111 ATTN: It does not matter what we set the servername to hear
6112 since we do the necessary work in get_a_printer() to set it to
6113 the correct value based on what the client sent in the
6114 _spoolss_open_printer_ex().
6115 ********************************************************************/
6117 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6119 fstring printername;
6122 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6123 "portname=%s drivername=%s comment=%s location=%s\n",
6124 info->servername, info->printername, info->sharename,
6125 info->portname, info->drivername, info->comment, info->location));
6127 /* we force some elements to "correct" values */
6128 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6129 fstrcpy(info->sharename, lp_servicename(snum));
6131 /* check to see if we allow printername != sharename */
6133 if ( lp_force_printername(snum) ) {
6134 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6135 global_myname(), info->sharename );
6138 /* make sure printername is in \\server\printername format */
6140 fstrcpy( printername, info->printername );
6142 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6143 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6147 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6148 global_myname(), p );
6151 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6152 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6159 /****************************************************************************
6160 ****************************************************************************/
6162 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6164 char *cmd = lp_addport_cmd();
6165 char *command = NULL;
6167 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6168 bool is_print_op = False;
6171 return WERR_ACCESS_DENIED;
6174 command = talloc_asprintf(ctx,
6175 "%s \"%s\" \"%s\"", cmd, portname, uri );
6181 is_print_op = user_has_privileges( token, &se_printop );
6183 DEBUG(10,("Running [%s]\n", command));
6185 /********* BEGIN SePrintOperatorPrivilege **********/
6190 ret = smbrun(command, NULL);
6195 /********* END SePrintOperatorPrivilege **********/
6197 DEBUGADD(10,("returned [%d]\n", ret));
6199 TALLOC_FREE(command);
6202 return WERR_ACCESS_DENIED;
6208 /****************************************************************************
6209 ****************************************************************************/
6211 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6213 char *cmd = lp_addprinter_cmd();
6215 char *command = NULL;
6219 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6220 bool is_print_op = False;
6221 char *remote_machine = talloc_strdup(ctx, "%m");
6223 if (!remote_machine) {
6226 remote_machine = talloc_sub_basic(ctx,
6227 current_user_info.smb_name,
6228 current_user_info.domain,
6230 if (!remote_machine) {
6234 command = talloc_asprintf(ctx,
6235 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6236 cmd, printer->info_2->printername, printer->info_2->sharename,
6237 printer->info_2->portname, printer->info_2->drivername,
6238 printer->info_2->location, printer->info_2->comment, remote_machine);
6244 is_print_op = user_has_privileges( token, &se_printop );
6246 DEBUG(10,("Running [%s]\n", command));
6248 /********* BEGIN SePrintOperatorPrivilege **********/
6253 if ( (ret = smbrun(command, &fd)) == 0 ) {
6254 /* Tell everyone we updated smb.conf. */
6255 message_send_all(smbd_messaging_context(),
6256 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6262 /********* END SePrintOperatorPrivilege **********/
6264 DEBUGADD(10,("returned [%d]\n", ret));
6266 TALLOC_FREE(command);
6267 TALLOC_FREE(remote_machine);
6275 /* reload our services immediately */
6276 reload_services( False );
6279 /* Get lines and convert them back to dos-codepage */
6280 qlines = fd_lines_load(fd, &numlines, 0);
6281 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6284 /* Set the portname to what the script says the portname should be. */
6285 /* but don't require anything to be return from the script exit a good error code */
6288 /* Set the portname to what the script says the portname should be. */
6289 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6290 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6293 file_lines_free(qlines);
6298 /********************************************************************
6299 * Called by spoolss_api_setprinter
6300 * when updating a printer description.
6301 ********************************************************************/
6303 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6304 const SPOOL_PRINTER_INFO_LEVEL *info,
6305 DEVICEMODE *devmode)
6308 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6309 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6314 DEBUG(8,("update_printer\n"));
6319 result = WERR_BADFID;
6323 if (!get_printer_snum(p, handle, &snum, NULL)) {
6324 result = WERR_BADFID;
6328 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6329 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6330 result = WERR_BADFID;
6334 DEBUGADD(8,("Converting info_2 struct\n"));
6337 * convert_printer_info converts the incoming
6338 * info from the client and overwrites the info
6339 * just read from the tdb in the pointer 'printer'.
6342 if (!convert_printer_info(info, printer, level)) {
6343 result = WERR_NOMEM;
6348 /* we have a valid devmode
6349 convert it and link it*/
6351 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6352 if (!convert_devicemode(printer->info_2->printername, devmode,
6353 &printer->info_2->devmode)) {
6354 result = WERR_NOMEM;
6359 /* Do sanity check on the requested changes for Samba */
6361 if (!check_printer_ok(printer->info_2, snum)) {
6362 result = WERR_INVALID_PARAM;
6366 /* FIXME!!! If the driver has changed we really should verify that
6367 it is installed before doing much else --jerry */
6369 /* Check calling user has permission to update printer description */
6371 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6372 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6373 result = WERR_ACCESS_DENIED;
6377 /* Call addprinter hook */
6378 /* Check changes to see if this is really needed */
6380 if ( *lp_addprinter_cmd()
6381 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6382 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6383 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6384 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6386 /* add_printer_hook() will call reload_services() */
6388 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
6389 result = WERR_ACCESS_DENIED;
6395 * When a *new* driver is bound to a printer, the drivername is used to
6396 * lookup previously saved driver initialization info, which is then
6397 * bound to the printer, simulating what happens in the Windows arch.
6399 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6401 if (!set_driver_init(printer, 2))
6403 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6404 printer->info_2->drivername));
6407 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6408 printer->info_2->drivername));
6410 notify_printer_driver(snum, printer->info_2->drivername);
6414 * flag which changes actually occured. This is a small subset of
6415 * all the possible changes. We also have to update things in the
6419 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6420 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6421 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6422 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6424 notify_printer_comment(snum, printer->info_2->comment);
6427 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6428 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6429 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6430 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6432 notify_printer_sharename(snum, printer->info_2->sharename);
6435 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6438 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6441 pname = printer->info_2->printername;
6444 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6445 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6446 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6448 notify_printer_printername( snum, pname );
6451 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6452 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6453 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6454 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6456 notify_printer_port(snum, printer->info_2->portname);
6459 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6460 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6461 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6462 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6464 notify_printer_location(snum, printer->info_2->location);
6467 /* here we need to update some more DsSpooler keys */
6468 /* uNCName, serverName, shortServerName */
6470 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6471 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6472 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6473 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6474 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6476 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6477 global_myname(), printer->info_2->sharename );
6478 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6479 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6480 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6482 /* Update printer info */
6483 result = mod_a_printer(printer, 2);
6486 free_a_printer(&printer, 2);
6487 free_a_printer(&old_printer, 2);
6493 /****************************************************************************
6494 ****************************************************************************/
6495 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6496 const SPOOL_PRINTER_INFO_LEVEL *info)
6499 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6501 Printer_entry *Printer;
6503 if ( lp_security() != SEC_ADS ) {
6504 return WERR_UNKNOWN_LEVEL;
6507 Printer = find_printer_index_by_hnd(p, handle);
6509 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6514 if (!get_printer_snum(p, handle, &snum, NULL))
6517 nt_printer_publish(Printer, snum, info7->action);
6521 return WERR_UNKNOWN_LEVEL;
6524 /****************************************************************************
6525 ****************************************************************************/
6527 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6529 POLICY_HND *handle = &q_u->handle;
6530 uint32 level = q_u->level;
6531 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6532 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6533 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6534 uint32 command = q_u->command;
6537 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6540 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6544 /* check the level */
6547 return control_printer(handle, command, p);
6549 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6550 if (!W_ERROR_IS_OK(result))
6553 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6556 return update_printer_sec(handle, level, info, p,
6559 return publish_or_unpublish_printer(p, handle, info);
6561 return WERR_UNKNOWN_LEVEL;
6565 /****************************************************************************
6566 ****************************************************************************/
6568 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6570 POLICY_HND *handle = &q_u->handle;
6571 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6574 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6578 if (Printer->notify.client_connected==True) {
6581 if ( Printer->printer_type == SPLHND_SERVER)
6583 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6584 !get_printer_snum(p, handle, &snum, NULL) )
6587 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6590 Printer->notify.flags=0;
6591 Printer->notify.options=0;
6592 Printer->notify.localmachine[0]='\0';
6593 Printer->notify.printerlocal=0;
6594 if (Printer->notify.option)
6595 free_spool_notify_option(&Printer->notify.option);
6596 Printer->notify.client_connected=False;
6601 /****************************************************************************
6602 ****************************************************************************/
6604 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6606 /* that's an [in out] buffer */
6608 if (!q_u->buffer && (q_u->offered!=0)) {
6609 return WERR_INVALID_PARAM;
6612 rpcbuf_move(q_u->buffer, &r_u->buffer);
6615 return WERR_INVALID_PARAM; /* this is what a NT server
6616 returns for AddJob. AddJob
6617 must fail on non-local
6621 /****************************************************************************
6622 ****************************************************************************/
6624 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6625 int position, int snum,
6626 const NT_PRINTER_INFO_LEVEL *ntprinter)
6630 t=gmtime(&queue->time);
6632 job_info->jobid=queue->job;
6633 init_unistr(&job_info->printername, lp_servicename(snum));
6634 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6635 init_unistr(&job_info->username, queue->fs_user);
6636 init_unistr(&job_info->document, queue->fs_file);
6637 init_unistr(&job_info->datatype, "RAW");
6638 init_unistr(&job_info->text_status, "");
6639 job_info->status=nt_printj_status(queue->status);
6640 job_info->priority=queue->priority;
6641 job_info->position=position;
6642 job_info->totalpages=queue->page_count;
6643 job_info->pagesprinted=0;
6645 make_systemtime(&job_info->submitted, t);
6648 /****************************************************************************
6649 ****************************************************************************/
6651 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6652 int position, int snum,
6653 const NT_PRINTER_INFO_LEVEL *ntprinter,
6654 DEVICEMODE *devmode)
6658 t=gmtime(&queue->time);
6660 job_info->jobid=queue->job;
6662 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6664 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6665 init_unistr(&job_info->username, queue->fs_user);
6666 init_unistr(&job_info->document, queue->fs_file);
6667 init_unistr(&job_info->notifyname, queue->fs_user);
6668 init_unistr(&job_info->datatype, "RAW");
6669 init_unistr(&job_info->printprocessor, "winprint");
6670 init_unistr(&job_info->parameters, "");
6671 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6672 init_unistr(&job_info->text_status, "");
6674 /* and here the security descriptor */
6676 job_info->status=nt_printj_status(queue->status);
6677 job_info->priority=queue->priority;
6678 job_info->position=position;
6679 job_info->starttime=0;
6680 job_info->untiltime=0;
6681 job_info->totalpages=queue->page_count;
6682 job_info->size=queue->size;
6683 make_systemtime(&(job_info->submitted), t);
6684 job_info->timeelapsed=0;
6685 job_info->pagesprinted=0;
6687 job_info->devmode = devmode;
6692 /****************************************************************************
6693 Enumjobs at level 1.
6694 ****************************************************************************/
6696 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6697 const NT_PRINTER_INFO_LEVEL *ntprinter,
6698 RPC_BUFFER *buffer, uint32 offered,
6699 uint32 *needed, uint32 *returned)
6703 WERROR result = WERR_OK;
6705 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6711 for (i=0; i<*returned; i++)
6712 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6714 /* check the required size. */
6715 for (i=0; i<*returned; i++)
6716 (*needed) += spoolss_size_job_info_1(&info[i]);
6718 if (*needed > offered) {
6719 result = WERR_INSUFFICIENT_BUFFER;
6723 if (!rpcbuf_alloc_size(buffer, *needed)) {
6724 result = WERR_NOMEM;
6728 /* fill the buffer with the structures */
6729 for (i=0; i<*returned; i++)
6730 smb_io_job_info_1("", buffer, &info[i], 0);
6736 if ( !W_ERROR_IS_OK(result) )
6742 /****************************************************************************
6743 Enumjobs at level 2.
6744 ****************************************************************************/
6746 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6747 const NT_PRINTER_INFO_LEVEL *ntprinter,
6748 RPC_BUFFER *buffer, uint32 offered,
6749 uint32 *needed, uint32 *returned)
6751 JOB_INFO_2 *info = NULL;
6753 WERROR result = WERR_OK;
6754 DEVICEMODE *devmode = NULL;
6756 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6761 /* this should not be a failure condition if the devmode is NULL */
6763 devmode = construct_dev_mode(lp_const_servicename(snum));
6765 for (i=0; i<*returned; i++)
6766 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6768 /* check the required size. */
6769 for (i=0; i<*returned; i++)
6770 (*needed) += spoolss_size_job_info_2(&info[i]);
6772 if (*needed > offered) {
6773 result = WERR_INSUFFICIENT_BUFFER;
6777 if (!rpcbuf_alloc_size(buffer, *needed)) {
6778 result = WERR_NOMEM;
6782 /* fill the buffer with the structures */
6783 for (i=0; i<*returned; i++)
6784 smb_io_job_info_2("", buffer, &info[i], 0);
6787 free_devmode(devmode);
6790 if ( !W_ERROR_IS_OK(result) )
6797 /****************************************************************************
6799 ****************************************************************************/
6801 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6803 POLICY_HND *handle = &q_u->handle;
6804 uint32 level = q_u->level;
6805 RPC_BUFFER *buffer = NULL;
6806 uint32 offered = q_u->offered;
6807 uint32 *needed = &r_u->needed;
6808 uint32 *returned = &r_u->returned;
6810 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6812 print_status_struct prt_status;
6813 print_queue_struct *queue=NULL;
6815 /* that's an [in out] buffer */
6817 if (!q_u->buffer && (offered!=0)) {
6818 return WERR_INVALID_PARAM;
6821 rpcbuf_move(q_u->buffer, &r_u->buffer);
6822 buffer = r_u->buffer;
6824 DEBUG(4,("_spoolss_enumjobs\n"));
6829 /* lookup the printer snum and tdb entry */
6831 if (!get_printer_snum(p, handle, &snum, NULL))
6834 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6835 if ( !W_ERROR_IS_OK(wret) )
6838 *returned = print_queue_status(snum, &queue, &prt_status);
6839 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6841 if (*returned == 0) {
6843 free_a_printer(&ntprinter, 2);
6849 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6852 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6856 wret = WERR_UNKNOWN_LEVEL;
6861 free_a_printer( &ntprinter, 2 );
6865 /****************************************************************************
6866 ****************************************************************************/
6868 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6873 /****************************************************************************
6874 ****************************************************************************/
6876 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6878 POLICY_HND *handle = &q_u->handle;
6879 uint32 jobid = q_u->jobid;
6880 uint32 command = q_u->command;
6883 WERROR errcode = WERR_BADFUNC;
6885 if (!get_printer_snum(p, handle, &snum, NULL)) {
6889 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6890 return WERR_INVALID_PRINTER_NAME;
6894 case JOB_CONTROL_CANCEL:
6895 case JOB_CONTROL_DELETE:
6896 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6900 case JOB_CONTROL_PAUSE:
6901 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6905 case JOB_CONTROL_RESTART:
6906 case JOB_CONTROL_RESUME:
6907 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6912 return WERR_UNKNOWN_LEVEL;
6918 /****************************************************************************
6919 Enumerates all printer drivers at level 1.
6920 ****************************************************************************/
6922 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6927 fstring *list = NULL;
6928 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6929 DRIVER_INFO_1 *driver_info_1=NULL;
6930 WERROR result = WERR_OK;
6934 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6936 ndrivers=get_ntdrivers(&list, architecture, version);
6937 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6939 if(ndrivers == -1) {
6940 SAFE_FREE(driver_info_1);
6945 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6946 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6952 for (i=0; i<ndrivers; i++) {
6954 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6955 ZERO_STRUCT(driver);
6956 status = get_a_printer_driver(&driver, 3, list[i],
6957 architecture, version);
6958 if (!W_ERROR_IS_OK(status)) {
6960 SAFE_FREE(driver_info_1);
6963 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6964 free_a_printer_driver(driver, 3);
6967 *returned+=ndrivers;
6971 /* check the required size. */
6972 for (i=0; i<*returned; i++) {
6973 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6974 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6977 if (*needed > offered) {
6978 result = WERR_INSUFFICIENT_BUFFER;
6982 if (!rpcbuf_alloc_size(buffer, *needed)) {
6983 result = WERR_NOMEM;
6987 /* fill the buffer with the driver structures */
6988 for (i=0; i<*returned; i++) {
6989 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6990 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6994 SAFE_FREE(driver_info_1);
6996 if ( !W_ERROR_IS_OK(result) )
7002 /****************************************************************************
7003 Enumerates all printer drivers at level 2.
7004 ****************************************************************************/
7006 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7011 fstring *list = NULL;
7012 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7013 DRIVER_INFO_2 *driver_info_2=NULL;
7014 WERROR result = WERR_OK;
7018 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7020 ndrivers=get_ntdrivers(&list, architecture, version);
7021 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7023 if(ndrivers == -1) {
7024 SAFE_FREE(driver_info_2);
7029 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7030 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7036 for (i=0; i<ndrivers; i++) {
7039 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7040 ZERO_STRUCT(driver);
7041 status = get_a_printer_driver(&driver, 3, list[i],
7042 architecture, version);
7043 if (!W_ERROR_IS_OK(status)) {
7045 SAFE_FREE(driver_info_2);
7048 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7049 free_a_printer_driver(driver, 3);
7052 *returned+=ndrivers;
7056 /* check the required size. */
7057 for (i=0; i<*returned; i++) {
7058 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7059 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7062 if (*needed > offered) {
7063 result = WERR_INSUFFICIENT_BUFFER;
7067 if (!rpcbuf_alloc_size(buffer, *needed)) {
7068 result = WERR_NOMEM;
7072 /* fill the buffer with the form structures */
7073 for (i=0; i<*returned; i++) {
7074 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7075 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7079 SAFE_FREE(driver_info_2);
7081 if ( !W_ERROR_IS_OK(result) )
7087 /****************************************************************************
7088 Enumerates all printer drivers at level 3.
7089 ****************************************************************************/
7091 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7096 fstring *list = NULL;
7097 DRIVER_INFO_3 *driver_info_3=NULL;
7098 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7099 WERROR result = WERR_OK;
7103 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7105 ndrivers=get_ntdrivers(&list, architecture, version);
7106 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7108 if(ndrivers == -1) {
7109 SAFE_FREE(driver_info_3);
7114 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7115 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7121 for (i=0; i<ndrivers; i++) {
7124 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7125 ZERO_STRUCT(driver);
7126 status = get_a_printer_driver(&driver, 3, list[i],
7127 architecture, version);
7128 if (!W_ERROR_IS_OK(status)) {
7130 SAFE_FREE(driver_info_3);
7133 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7134 free_a_printer_driver(driver, 3);
7137 *returned+=ndrivers;
7141 /* check the required size. */
7142 for (i=0; i<*returned; i++) {
7143 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7144 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7147 if (*needed > offered) {
7148 result = WERR_INSUFFICIENT_BUFFER;
7152 if (!rpcbuf_alloc_size(buffer, *needed)) {
7153 result = WERR_NOMEM;
7157 /* fill the buffer with the driver structures */
7158 for (i=0; i<*returned; i++) {
7159 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7160 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7164 for (i=0; i<*returned; i++) {
7165 SAFE_FREE(driver_info_3[i].dependentfiles);
7168 SAFE_FREE(driver_info_3);
7170 if ( !W_ERROR_IS_OK(result) )
7176 /****************************************************************************
7177 Enumerates all printer drivers.
7178 ****************************************************************************/
7180 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7182 uint32 level = q_u->level;
7183 RPC_BUFFER *buffer = NULL;
7184 uint32 offered = q_u->offered;
7185 uint32 *needed = &r_u->needed;
7186 uint32 *returned = &r_u->returned;
7187 const char *cservername;
7189 fstring architecture;
7191 /* that's an [in out] buffer */
7193 if (!q_u->buffer && (offered!=0)) {
7194 return WERR_INVALID_PARAM;
7197 rpcbuf_move(q_u->buffer, &r_u->buffer);
7198 buffer = r_u->buffer;
7200 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7205 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7206 unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7208 cservername = canon_servername(servername);
7210 if (!is_myname_or_ipaddr(cservername))
7211 return WERR_UNKNOWN_PRINTER_DRIVER;
7215 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7217 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7219 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7221 return WERR_UNKNOWN_LEVEL;
7225 /****************************************************************************
7226 ****************************************************************************/
7228 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7230 form->flag=list->flag;
7231 init_unistr(&form->name, list->name);
7232 form->width=list->width;
7233 form->length=list->length;
7234 form->left=list->left;
7235 form->top=list->top;
7236 form->right=list->right;
7237 form->bottom=list->bottom;
7240 /****************************************************************************
7241 ****************************************************************************/
7243 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7245 uint32 level = q_u->level;
7246 RPC_BUFFER *buffer = NULL;
7247 uint32 offered = q_u->offered;
7248 uint32 *needed = &r_u->needed;
7249 uint32 *numofforms = &r_u->numofforms;
7250 uint32 numbuiltinforms;
7252 nt_forms_struct *list=NULL;
7253 nt_forms_struct *builtinlist=NULL;
7258 /* that's an [in out] buffer */
7260 if (!q_u->buffer && (offered!=0) ) {
7261 return WERR_INVALID_PARAM;
7264 rpcbuf_move(q_u->buffer, &r_u->buffer);
7265 buffer = r_u->buffer;
7267 DEBUG(4,("_spoolss_enumforms\n"));
7268 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7269 DEBUGADD(5,("Info level [%d]\n", level));
7271 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7272 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7273 *numofforms = get_ntforms(&list);
7274 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7275 *numofforms += numbuiltinforms;
7277 if (*numofforms == 0) {
7278 SAFE_FREE(builtinlist);
7280 return WERR_NO_MORE_ITEMS;
7285 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7286 SAFE_FREE(builtinlist);
7292 /* construct the list of form structures */
7293 for (i=0; i<numbuiltinforms; i++) {
7294 DEBUGADD(6,("Filling form number [%d]\n",i));
7295 fill_form_1(&forms_1[i], &builtinlist[i]);
7298 SAFE_FREE(builtinlist);
7300 for (; i<*numofforms; i++) {
7301 DEBUGADD(6,("Filling form number [%d]\n",i));
7302 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7307 /* check the required size. */
7308 for (i=0; i<numbuiltinforms; i++) {
7309 DEBUGADD(6,("adding form [%d]'s size\n",i));
7310 buffer_size += spoolss_size_form_1(&forms_1[i]);
7312 for (; i<*numofforms; i++) {
7313 DEBUGADD(6,("adding form [%d]'s size\n",i));
7314 buffer_size += spoolss_size_form_1(&forms_1[i]);
7317 *needed=buffer_size;
7319 if (*needed > offered) {
7322 return WERR_INSUFFICIENT_BUFFER;
7325 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7331 /* fill the buffer with the form structures */
7332 for (i=0; i<numbuiltinforms; i++) {
7333 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7334 smb_io_form_1("", buffer, &forms_1[i], 0);
7336 for (; i<*numofforms; i++) {
7337 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7338 smb_io_form_1("", buffer, &forms_1[i], 0);
7347 SAFE_FREE(builtinlist);
7348 return WERR_UNKNOWN_LEVEL;
7352 /****************************************************************************
7353 ****************************************************************************/
7355 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7357 uint32 level = q_u->level;
7358 UNISTR2 *uni_formname = &q_u->formname;
7359 RPC_BUFFER *buffer = NULL;
7360 uint32 offered = q_u->offered;
7361 uint32 *needed = &r_u->needed;
7363 nt_forms_struct *list=NULL;
7364 nt_forms_struct builtin_form;
7369 int numofforms=0, i=0;
7371 /* that's an [in out] buffer */
7373 if (!q_u->buffer && (offered!=0)) {
7374 return WERR_INVALID_PARAM;
7377 rpcbuf_move(q_u->buffer, &r_u->buffer);
7378 buffer = r_u->buffer;
7380 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
7382 DEBUG(4,("_spoolss_getform\n"));
7383 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7384 DEBUGADD(5,("Info level [%d]\n", level));
7386 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7387 if (!foundBuiltin) {
7388 numofforms = get_ntforms(&list);
7389 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7391 if (numofforms == 0)
7398 fill_form_1(&form_1, &builtin_form);
7401 /* Check if the requested name is in the list of form structures */
7402 for (i=0; i<numofforms; i++) {
7404 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7406 if (strequal(form_name, list[i].name)) {
7407 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7408 fill_form_1(&form_1, &list[i]);
7414 if (i == numofforms) {
7418 /* check the required size. */
7420 *needed=spoolss_size_form_1(&form_1);
7422 if (*needed > offered)
7423 return WERR_INSUFFICIENT_BUFFER;
7425 if (!rpcbuf_alloc_size(buffer, buffer_size))
7428 /* fill the buffer with the form structures */
7429 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7430 smb_io_form_1("", buffer, &form_1, 0);
7436 return WERR_UNKNOWN_LEVEL;
7440 /****************************************************************************
7441 ****************************************************************************/
7443 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7445 init_unistr(&port->port_name, name);
7448 /****************************************************************************
7449 TODO: This probably needs distinguish between TCP/IP and Local ports
7451 ****************************************************************************/
7453 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7455 init_unistr(&port->port_name, name);
7456 init_unistr(&port->monitor_name, "Local Monitor");
7457 init_unistr(&port->description, SPL_LOCAL_PORT );
7458 port->port_type=PORT_TYPE_WRITE;
7463 /****************************************************************************
7464 wrapper around the enumer ports command
7465 ****************************************************************************/
7467 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7469 char *cmd = lp_enumports_cmd();
7470 char **qlines = NULL;
7471 char *command = NULL;
7479 /* if no hook then just fill in the default port */
7482 if (!(qlines = SMB_MALLOC_ARRAY( char*, 2 ))) {
7485 if (!(qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME ))) {
7493 /* we have a valid enumport command */
7495 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7500 DEBUG(10,("Running [%s]\n", command));
7501 ret = smbrun(command, &fd);
7502 DEBUG(10,("Returned [%d]\n", ret));
7503 TALLOC_FREE(command);
7508 return WERR_ACCESS_DENIED;
7512 qlines = fd_lines_load(fd, &numlines, 0);
7513 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7523 /****************************************************************************
7525 ****************************************************************************/
7527 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7529 PORT_INFO_1 *ports=NULL;
7531 WERROR result = WERR_OK;
7532 char **qlines = NULL;
7535 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7536 if (!W_ERROR_IS_OK(result)) {
7537 file_lines_free(qlines);
7542 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7543 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7544 dos_errstr(WERR_NOMEM)));
7545 file_lines_free(qlines);
7549 for (i=0; i<numlines; i++) {
7550 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7551 fill_port_1(&ports[i], qlines[i]);
7554 file_lines_free(qlines);
7556 *returned = numlines;
7558 /* check the required size. */
7559 for (i=0; i<*returned; i++) {
7560 DEBUGADD(6,("adding port [%d]'s size\n", i));
7561 *needed += spoolss_size_port_info_1(&ports[i]);
7564 if (*needed > offered) {
7565 result = WERR_INSUFFICIENT_BUFFER;
7569 if (!rpcbuf_alloc_size(buffer, *needed)) {
7570 result = WERR_NOMEM;
7574 /* fill the buffer with the ports structures */
7575 for (i=0; i<*returned; i++) {
7576 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7577 smb_io_port_1("", buffer, &ports[i], 0);
7583 if ( !W_ERROR_IS_OK(result) )
7589 /****************************************************************************
7591 ****************************************************************************/
7593 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7595 PORT_INFO_2 *ports=NULL;
7597 WERROR result = WERR_OK;
7598 char **qlines = NULL;
7601 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7602 if ( !W_ERROR_IS_OK(result)) {
7603 file_lines_free(qlines);
7608 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7609 file_lines_free(qlines);
7613 for (i=0; i<numlines; i++) {
7614 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7615 fill_port_2(&(ports[i]), qlines[i]);
7619 file_lines_free(qlines);
7621 *returned = numlines;
7623 /* check the required size. */
7624 for (i=0; i<*returned; i++) {
7625 DEBUGADD(6,("adding port [%d]'s size\n", i));
7626 *needed += spoolss_size_port_info_2(&ports[i]);
7629 if (*needed > offered) {
7630 result = WERR_INSUFFICIENT_BUFFER;
7634 if (!rpcbuf_alloc_size(buffer, *needed)) {
7635 result = WERR_NOMEM;
7639 /* fill the buffer with the ports structures */
7640 for (i=0; i<*returned; i++) {
7641 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7642 smb_io_port_2("", buffer, &ports[i], 0);
7648 if ( !W_ERROR_IS_OK(result) )
7654 /****************************************************************************
7656 ****************************************************************************/
7658 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7660 uint32 level = q_u->level;
7661 RPC_BUFFER *buffer = NULL;
7662 uint32 offered = q_u->offered;
7663 uint32 *needed = &r_u->needed;
7664 uint32 *returned = &r_u->returned;
7666 /* that's an [in out] buffer */
7668 if (!q_u->buffer && (offered!=0)) {
7669 return WERR_INVALID_PARAM;
7672 rpcbuf_move(q_u->buffer, &r_u->buffer);
7673 buffer = r_u->buffer;
7675 DEBUG(4,("_spoolss_enumports\n"));
7682 return enumports_level_1(buffer, offered, needed, returned);
7684 return enumports_level_2(buffer, offered, needed, returned);
7686 return WERR_UNKNOWN_LEVEL;
7690 /****************************************************************************
7691 ****************************************************************************/
7693 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7694 const SPOOL_PRINTER_INFO_LEVEL *info,
7695 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7696 uint32 user_switch, const SPOOL_USER_CTR *user,
7699 NT_PRINTER_INFO_LEVEL *printer = NULL;
7702 WERROR err = WERR_OK;
7704 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7705 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7709 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7710 if (!convert_printer_info(info, printer, 2)) {
7711 free_a_printer(&printer, 2);
7715 /* check to see if the printer already exists */
7717 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7718 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7719 printer->info_2->sharename));
7720 free_a_printer(&printer, 2);
7721 return WERR_PRINTER_ALREADY_EXISTS;
7724 /* FIXME!!! smbd should check to see if the driver is installed before
7725 trying to add a printer like this --jerry */
7727 if (*lp_addprinter_cmd() ) {
7728 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
7729 free_a_printer(&printer,2);
7730 return WERR_ACCESS_DENIED;
7733 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7734 "smb.conf parameter \"addprinter command\" is defined. This"
7735 "parameter must exist for this call to succeed\n",
7736 printer->info_2->sharename ));
7739 /* use our primary netbios name since get_a_printer() will convert
7740 it to what the client expects on a case by case basis */
7742 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7743 printer->info_2->sharename);
7746 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7747 free_a_printer(&printer,2);
7748 return WERR_ACCESS_DENIED;
7751 /* you must be a printer admin to add a new printer */
7752 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7753 free_a_printer(&printer,2);
7754 return WERR_ACCESS_DENIED;
7758 * Do sanity check on the requested changes for Samba.
7761 if (!check_printer_ok(printer->info_2, snum)) {
7762 free_a_printer(&printer,2);
7763 return WERR_INVALID_PARAM;
7767 * When a printer is created, the drivername bound to the printer is used
7768 * to lookup previously saved driver initialization info, which is then
7769 * bound to the new printer, simulating what happens in the Windows arch.
7774 set_driver_init(printer, 2);
7778 /* A valid devmode was included, convert and link it
7780 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7782 if (!convert_devicemode(printer->info_2->printername, devmode,
7783 &printer->info_2->devmode))
7787 /* write the ASCII on disk */
7788 err = mod_a_printer(printer, 2);
7789 if (!W_ERROR_IS_OK(err)) {
7790 free_a_printer(&printer,2);
7794 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7795 /* Handle open failed - remove addition. */
7796 del_a_printer(printer->info_2->sharename);
7797 free_a_printer(&printer,2);
7798 return WERR_ACCESS_DENIED;
7801 update_c_setprinter(False);
7802 free_a_printer(&printer,2);
7807 /****************************************************************************
7808 ****************************************************************************/
7810 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7812 UNISTR2 *uni_srv_name = q_u->server_name;
7813 uint32 level = q_u->level;
7814 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7815 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7816 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7817 uint32 user_switch = q_u->user_switch;
7818 SPOOL_USER_CTR *user = &q_u->user_ctr;
7819 POLICY_HND *handle = &r_u->handle;
7823 /* we don't handle yet */
7824 /* but I know what to do ... */
7825 return WERR_UNKNOWN_LEVEL;
7827 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7829 user_switch, user, handle);
7831 return WERR_UNKNOWN_LEVEL;
7835 /****************************************************************************
7836 ****************************************************************************/
7838 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7840 uint32 level = q_u->level;
7841 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7842 WERROR err = WERR_OK;
7843 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7844 fstring driver_name;
7847 ZERO_STRUCT(driver);
7849 if (!convert_printer_driver_info(info, &driver, level)) {
7854 DEBUG(5,("Cleaning driver's information\n"));
7855 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7856 if (!W_ERROR_IS_OK(err))
7859 DEBUG(5,("Moving driver to final destination\n"));
7860 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7864 if (add_a_printer_driver(driver, level)!=0) {
7865 err = WERR_ACCESS_DENIED;
7871 fstrcpy(driver_name,
7872 driver.info_3->name ? driver.info_3->name : "");
7875 fstrcpy(driver_name,
7876 driver.info_6->name ? driver.info_6->name : "");
7881 * I think this is where he DrvUpgradePrinter() hook would be
7882 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7883 * server. Right now, we just need to send ourselves a message
7884 * to update each printer bound to this driver. --jerry
7887 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7888 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7893 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7894 * decide if the driver init data should be deleted. The rules are:
7895 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7896 * 2) delete init data only if there is no 2k/Xp driver
7897 * 3) always delete init data
7898 * The generalized rule is always use init data from the highest order driver.
7899 * It is necessary to follow the driver install by an initialization step to
7900 * finish off this process.
7903 version = driver.info_3->cversion;
7904 else if (level == 6)
7905 version = driver.info_6->version;
7910 * 9x printer driver - never delete init data
7913 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7918 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7919 * there is no 2k/Xp driver init data for this driver name.
7923 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7925 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7927 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7929 if (!del_driver_init(driver_name))
7930 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7933 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7935 free_a_printer_driver(driver1,3);
7936 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7943 * 2k or Xp printer driver - always delete init data
7946 if (!del_driver_init(driver_name))
7947 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7951 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7957 free_a_printer_driver(driver, level);
7961 /********************************************************************
7962 * spoolss_addprinterdriverex
7963 ********************************************************************/
7965 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7967 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7968 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7971 * we only support the semantics of AddPrinterDriver()
7972 * i.e. only copy files that are newer than existing ones
7975 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7976 return WERR_ACCESS_DENIED;
7978 ZERO_STRUCT(q_u_local);
7979 ZERO_STRUCT(r_u_local);
7981 /* just pass the information off to _spoolss_addprinterdriver() */
7982 q_u_local.server_name_ptr = q_u->server_name_ptr;
7983 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7984 q_u_local.level = q_u->level;
7985 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7987 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7990 /****************************************************************************
7991 ****************************************************************************/
7993 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7995 init_unistr(&info->name, name);
7998 /****************************************************************************
7999 ****************************************************************************/
8001 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
8004 char *long_archi = NULL;
8005 char *servername = NULL;
8006 const char *pservername = NULL;
8007 const char *short_archi;
8008 DRIVER_DIRECTORY_1 *info=NULL;
8009 WERROR result = WERR_OK;
8010 TALLOC_CTX *ctx = talloc_tos();
8012 servername = unistr2_to_ascii_talloc(ctx, name);
8016 long_archi = unistr2_to_ascii_talloc(ctx, uni_environment);
8021 pservername = canon_servername(servername);
8023 if ( !is_myname_or_ipaddr(pservername))
8024 return WERR_INVALID_PARAM;
8026 if (!(short_archi = get_short_archi(long_archi)))
8027 return WERR_INVALID_ENVIRONMENT;
8029 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8032 path = talloc_asprintf(ctx,
8033 "\\\\%s\\print$\\%s", pservername, short_archi);
8035 result = WERR_NOMEM;
8039 DEBUG(4,("printer driver directory: [%s]\n", path));
8041 fill_driverdir_1(info, path);
8043 *needed += spoolss_size_driverdir_info_1(info);
8045 if (*needed > offered) {
8046 result = WERR_INSUFFICIENT_BUFFER;
8050 if (!rpcbuf_alloc_size(buffer, *needed)) {
8051 result = WERR_NOMEM;
8055 smb_io_driverdir_1("", buffer, info, 0);
8063 /****************************************************************************
8064 ****************************************************************************/
8066 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8068 UNISTR2 *name = &q_u->name;
8069 UNISTR2 *uni_environment = &q_u->environment;
8070 uint32 level = q_u->level;
8071 RPC_BUFFER *buffer = NULL;
8072 uint32 offered = q_u->offered;
8073 uint32 *needed = &r_u->needed;
8075 /* that's an [in out] buffer */
8077 if (!q_u->buffer && (offered!=0)) {
8078 return WERR_INVALID_PARAM;
8081 rpcbuf_move(q_u->buffer, &r_u->buffer);
8082 buffer = r_u->buffer;
8084 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8090 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8092 return WERR_UNKNOWN_LEVEL;
8096 /****************************************************************************
8097 ****************************************************************************/
8099 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8101 POLICY_HND *handle = &q_u->handle;
8102 uint32 idx = q_u->index;
8103 uint32 in_value_len = q_u->valuesize;
8104 uint32 in_data_len = q_u->datasize;
8105 uint32 *out_max_value_len = &r_u->valuesize;
8106 uint16 **out_value = &r_u->value;
8107 uint32 *out_value_len = &r_u->realvaluesize;
8108 uint32 *out_type = &r_u->type;
8109 uint32 *out_max_data_len = &r_u->datasize;
8110 uint8 **data_out = &r_u->data;
8111 uint32 *out_data_len = &r_u->realdatasize;
8113 NT_PRINTER_INFO_LEVEL *printer = NULL;
8115 uint32 biggest_valuesize;
8116 uint32 biggest_datasize;
8118 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8121 REGISTRY_VALUE *val = NULL;
8122 NT_PRINTER_DATA *p_data;
8123 int i, key_index, num_values;
8128 *out_max_data_len = 0;
8132 DEBUG(5,("spoolss_enumprinterdata\n"));
8135 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8139 if (!get_printer_snum(p,handle, &snum, NULL))
8142 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8143 if (!W_ERROR_IS_OK(result))
8146 p_data = printer->info_2->data;
8147 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8152 * The NT machine wants to know the biggest size of value and data
8154 * cf: MSDN EnumPrinterData remark section
8157 if ( !in_value_len && !in_data_len && (key_index != -1) )
8159 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8161 biggest_valuesize = 0;
8162 biggest_datasize = 0;
8164 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8166 for ( i=0; i<num_values; i++ )
8168 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8170 name_length = strlen(val->valuename);
8171 if ( strlen(val->valuename) > biggest_valuesize )
8172 biggest_valuesize = name_length;
8174 if ( val->size > biggest_datasize )
8175 biggest_datasize = val->size;
8177 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8181 /* the value is an UNICODE string but real_value_size is the length
8182 in bytes including the trailing 0 */
8184 *out_value_len = 2 * (1+biggest_valuesize);
8185 *out_data_len = biggest_datasize;
8187 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8193 * the value len is wrong in NT sp3
8194 * that's the number of bytes not the number of unicode chars
8197 if ( key_index != -1 )
8198 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8203 /* out_value should default to "" or else NT4 has
8204 problems unmarshalling the response */
8206 *out_max_value_len=(in_value_len/sizeof(uint16));
8209 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8211 result = WERR_NOMEM;
8214 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8220 /* the data is counted in bytes */
8222 *out_max_data_len = in_data_len;
8223 *out_data_len = in_data_len;
8225 /* only allocate when given a non-zero data_len */
8227 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8229 result = WERR_NOMEM;
8233 result = WERR_NO_MORE_ITEMS;
8239 * - counted in bytes in the request
8240 * - counted in UNICODE chars in the max reply
8241 * - counted in bytes in the real size
8243 * take a pause *before* coding not *during* coding
8247 *out_max_value_len=(in_value_len/sizeof(uint16));
8249 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8251 result = WERR_NOMEM;
8255 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8263 *out_type = regval_type( val );
8265 /* data - counted in bytes */
8267 *out_max_data_len = in_data_len;
8268 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8270 result = WERR_NOMEM;
8273 data_len = regval_size(val);
8274 if ( *data_out && data_len )
8275 memcpy( *data_out, regval_data_p(val), data_len );
8276 *out_data_len = data_len;
8280 free_a_printer(&printer, 2);
8284 /****************************************************************************
8285 ****************************************************************************/
8287 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8289 POLICY_HND *handle = &q_u->handle;
8290 UNISTR2 *value = &q_u->value;
8291 uint32 type = q_u->type;
8292 uint8 *data = q_u->data;
8293 uint32 real_len = q_u->real_len;
8295 NT_PRINTER_INFO_LEVEL *printer = NULL;
8297 WERROR status = WERR_OK;
8298 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8301 DEBUG(5,("spoolss_setprinterdata\n"));
8304 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8308 if ( Printer->printer_type == SPLHND_SERVER ) {
8309 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8310 return WERR_INVALID_PARAM;
8313 if (!get_printer_snum(p,handle, &snum, NULL))
8317 * Access check : NT returns "access denied" if you make a
8318 * SetPrinterData call without the necessary privildge.
8319 * we were originally returning OK if nothing changed
8320 * which made Win2k issue **a lot** of SetPrinterData
8321 * when connecting to a printer --jerry
8324 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8326 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8327 status = WERR_ACCESS_DENIED;
8331 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8332 if (!W_ERROR_IS_OK(status))
8335 unistr2_to_ascii(valuename, value, sizeof(valuename));
8338 * When client side code sets a magic printer data key, detect it and save
8339 * the current printer data and the magic key's data (its the DEVMODE) for
8340 * future printer/driver initializations.
8342 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8344 /* Set devmode and printer initialization info */
8345 status = save_driver_init( printer, 2, data, real_len );
8347 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8351 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8352 type, data, real_len );
8353 if ( W_ERROR_IS_OK(status) )
8354 status = mod_a_printer(printer, 2);
8358 free_a_printer(&printer, 2);
8363 /****************************************************************************
8364 ****************************************************************************/
8366 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8368 POLICY_HND *handle = &q_u->handle;
8369 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8372 DEBUG(5,("_spoolss_resetprinter\n"));
8375 * All we do is to check to see if the handle and queue is valid.
8376 * This call really doesn't mean anything to us because we only
8377 * support RAW printing. --jerry
8381 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8385 if (!get_printer_snum(p,handle, &snum, NULL))
8389 /* blindly return success */
8394 /****************************************************************************
8395 ****************************************************************************/
8397 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8399 POLICY_HND *handle = &q_u->handle;
8400 UNISTR2 *value = &q_u->valuename;
8402 NT_PRINTER_INFO_LEVEL *printer = NULL;
8404 WERROR status = WERR_OK;
8405 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8406 char *valuename = NULL;
8407 TALLOC_CTX *ctx = p->mem_ctx;
8409 DEBUG(5,("spoolss_deleteprinterdata\n"));
8412 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8416 if (!get_printer_snum(p, handle, &snum, NULL))
8419 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8420 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8421 return WERR_ACCESS_DENIED;
8424 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8425 if (!W_ERROR_IS_OK(status))
8428 valuename = unistr2_to_ascii_talloc(ctx, value);
8430 free_a_printer(&printer, 2);
8434 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8436 if ( W_ERROR_IS_OK(status) )
8437 mod_a_printer( printer, 2 );
8439 free_a_printer(&printer, 2);
8440 TALLOC_FREE(valuename);
8445 /****************************************************************************
8446 ****************************************************************************/
8448 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8450 POLICY_HND *handle = &q_u->handle;
8451 FORM *form = &q_u->form;
8452 nt_forms_struct tmpForm;
8454 WERROR status = WERR_OK;
8455 NT_PRINTER_INFO_LEVEL *printer = NULL;
8458 nt_forms_struct *list=NULL;
8459 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8461 DEBUG(5,("spoolss_addform\n"));
8464 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8469 /* forms can be added on printer of on the print server handle */
8471 if ( Printer->printer_type == SPLHND_PRINTER )
8473 if (!get_printer_snum(p,handle, &snum, NULL))
8476 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8477 if (!W_ERROR_IS_OK(status))
8481 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8482 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8483 status = WERR_ACCESS_DENIED;
8487 /* can't add if builtin */
8489 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8490 status = WERR_ALREADY_EXISTS;
8494 count = get_ntforms(&list);
8496 if(!add_a_form(&list, form, &count)) {
8497 status = WERR_NOMEM;
8501 write_ntforms(&list, count);
8504 * ChangeID must always be set if this is a printer
8507 if ( Printer->printer_type == SPLHND_PRINTER )
8508 status = mod_a_printer(printer, 2);
8512 free_a_printer(&printer, 2);
8518 /****************************************************************************
8519 ****************************************************************************/
8521 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8523 POLICY_HND *handle = &q_u->handle;
8524 UNISTR2 *form_name = &q_u->name;
8525 nt_forms_struct tmpForm;
8527 nt_forms_struct *list=NULL;
8528 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8530 WERROR status = WERR_OK;
8531 NT_PRINTER_INFO_LEVEL *printer = NULL;
8533 DEBUG(5,("spoolss_deleteform\n"));
8536 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8540 /* forms can be deleted on printer of on the print server handle */
8542 if ( Printer->printer_type == SPLHND_PRINTER )
8544 if (!get_printer_snum(p,handle, &snum, NULL))
8547 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8548 if (!W_ERROR_IS_OK(status))
8552 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8553 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8554 status = WERR_ACCESS_DENIED;
8558 /* can't delete if builtin */
8560 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8561 status = WERR_INVALID_PARAM;
8565 count = get_ntforms(&list);
8567 if ( !delete_a_form(&list, form_name, &count, &status ))
8571 * ChangeID must always be set if this is a printer
8574 if ( Printer->printer_type == SPLHND_PRINTER )
8575 status = mod_a_printer(printer, 2);
8579 free_a_printer(&printer, 2);
8585 /****************************************************************************
8586 ****************************************************************************/
8588 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8590 POLICY_HND *handle = &q_u->handle;
8591 FORM *form = &q_u->form;
8592 nt_forms_struct tmpForm;
8594 WERROR status = WERR_OK;
8595 NT_PRINTER_INFO_LEVEL *printer = NULL;
8598 nt_forms_struct *list=NULL;
8599 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8601 DEBUG(5,("spoolss_setform\n"));
8604 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8608 /* forms can be modified on printer of on the print server handle */
8610 if ( Printer->printer_type == SPLHND_PRINTER )
8612 if (!get_printer_snum(p,handle, &snum, NULL))
8615 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8616 if (!W_ERROR_IS_OK(status))
8620 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8621 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8622 status = WERR_ACCESS_DENIED;
8626 /* can't set if builtin */
8627 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8628 status = WERR_INVALID_PARAM;
8632 count = get_ntforms(&list);
8633 update_a_form(&list, form, count);
8634 write_ntforms(&list, count);
8637 * ChangeID must always be set if this is a printer
8640 if ( Printer->printer_type == SPLHND_PRINTER )
8641 status = mod_a_printer(printer, 2);
8646 free_a_printer(&printer, 2);
8652 /****************************************************************************
8653 enumprintprocessors level 1.
8654 ****************************************************************************/
8656 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8658 PRINTPROCESSOR_1 *info_1=NULL;
8659 WERROR result = WERR_OK;
8661 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8666 init_unistr(&info_1->name, "winprint");
8668 *needed += spoolss_size_printprocessor_info_1(info_1);
8670 if (*needed > offered) {
8671 result = WERR_INSUFFICIENT_BUFFER;
8675 if (!rpcbuf_alloc_size(buffer, *needed)) {
8676 result = WERR_NOMEM;
8680 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8685 if ( !W_ERROR_IS_OK(result) )
8691 /****************************************************************************
8692 ****************************************************************************/
8694 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8696 uint32 level = q_u->level;
8697 RPC_BUFFER *buffer = NULL;
8698 uint32 offered = q_u->offered;
8699 uint32 *needed = &r_u->needed;
8700 uint32 *returned = &r_u->returned;
8702 /* that's an [in out] buffer */
8704 if (!q_u->buffer && (offered!=0)) {
8705 return WERR_INVALID_PARAM;
8708 rpcbuf_move(q_u->buffer, &r_u->buffer);
8709 buffer = r_u->buffer;
8711 DEBUG(5,("spoolss_enumprintprocessors\n"));
8714 * Enumerate the print processors ...
8716 * Just reply with "winprint", to keep NT happy
8717 * and I can use my nice printer checker.
8725 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8727 return WERR_UNKNOWN_LEVEL;
8731 /****************************************************************************
8732 enumprintprocdatatypes level 1.
8733 ****************************************************************************/
8735 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8737 PRINTPROCDATATYPE_1 *info_1=NULL;
8738 WERROR result = WERR_OK;
8740 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8745 init_unistr(&info_1->name, "RAW");
8747 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8749 if (*needed > offered) {
8750 result = WERR_INSUFFICIENT_BUFFER;
8754 if (!rpcbuf_alloc_size(buffer, *needed)) {
8755 result = WERR_NOMEM;
8759 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8764 if ( !W_ERROR_IS_OK(result) )
8770 /****************************************************************************
8771 ****************************************************************************/
8773 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8775 uint32 level = q_u->level;
8776 RPC_BUFFER *buffer = NULL;
8777 uint32 offered = q_u->offered;
8778 uint32 *needed = &r_u->needed;
8779 uint32 *returned = &r_u->returned;
8781 /* that's an [in out] buffer */
8783 if (!q_u->buffer && (offered!=0)) {
8784 return WERR_INVALID_PARAM;
8787 rpcbuf_move(q_u->buffer, &r_u->buffer);
8788 buffer = r_u->buffer;
8790 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8797 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8799 return WERR_UNKNOWN_LEVEL;
8803 /****************************************************************************
8804 enumprintmonitors level 1.
8805 ****************************************************************************/
8807 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8809 PRINTMONITOR_1 *info_1;
8810 WERROR result = WERR_OK;
8813 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8818 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8819 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8821 for ( i=0; i<*returned; i++ ) {
8822 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8825 if (*needed > offered) {
8826 result = WERR_INSUFFICIENT_BUFFER;
8830 if (!rpcbuf_alloc_size(buffer, *needed)) {
8831 result = WERR_NOMEM;
8835 for ( i=0; i<*returned; i++ ) {
8836 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8842 if ( !W_ERROR_IS_OK(result) )
8848 /****************************************************************************
8849 enumprintmonitors level 2.
8850 ****************************************************************************/
8852 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8854 PRINTMONITOR_2 *info_2;
8855 WERROR result = WERR_OK;
8858 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8863 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8864 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8865 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8867 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8868 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8869 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8871 for ( i=0; i<*returned; i++ ) {
8872 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8875 if (*needed > offered) {
8876 result = WERR_INSUFFICIENT_BUFFER;
8880 if (!rpcbuf_alloc_size(buffer, *needed)) {
8881 result = WERR_NOMEM;
8885 for ( i=0; i<*returned; i++ ) {
8886 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8892 if ( !W_ERROR_IS_OK(result) )
8898 /****************************************************************************
8899 ****************************************************************************/
8901 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8903 uint32 level = q_u->level;
8904 RPC_BUFFER *buffer = NULL;
8905 uint32 offered = q_u->offered;
8906 uint32 *needed = &r_u->needed;
8907 uint32 *returned = &r_u->returned;
8909 /* that's an [in out] buffer */
8911 if (!q_u->buffer && (offered!=0)) {
8912 return WERR_INVALID_PARAM;
8915 rpcbuf_move(q_u->buffer, &r_u->buffer);
8916 buffer = r_u->buffer;
8918 DEBUG(5,("spoolss_enumprintmonitors\n"));
8921 * Enumerate the print monitors ...
8923 * Just reply with "Local Port", to keep NT happy
8924 * and I can use my nice printer checker.
8932 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8934 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8936 return WERR_UNKNOWN_LEVEL;
8940 /****************************************************************************
8941 ****************************************************************************/
8943 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8944 NT_PRINTER_INFO_LEVEL *ntprinter,
8945 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8950 JOB_INFO_1 *info_1=NULL;
8951 WERROR result = WERR_OK;
8953 info_1=SMB_MALLOC_P(JOB_INFO_1);
8955 if (info_1 == NULL) {
8959 for (i=0; i<count && found==False; i++) {
8960 if ((*queue)[i].job==(int)jobid)
8966 /* NT treats not found as bad param... yet another bad choice */
8967 return WERR_INVALID_PARAM;
8970 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8972 *needed += spoolss_size_job_info_1(info_1);
8974 if (*needed > offered) {
8975 result = WERR_INSUFFICIENT_BUFFER;
8979 if (!rpcbuf_alloc_size(buffer, *needed)) {
8980 result = WERR_NOMEM;
8984 smb_io_job_info_1("", buffer, info_1, 0);
8992 /****************************************************************************
8993 ****************************************************************************/
8995 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8996 NT_PRINTER_INFO_LEVEL *ntprinter,
8997 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9004 DEVICEMODE *devmode = NULL;
9005 NT_DEVICEMODE *nt_devmode = NULL;
9007 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9010 ZERO_STRUCTP(info_2);
9012 for ( i=0; i<count && found==False; i++ )
9014 if ((*queue)[i].job == (int)jobid)
9019 /* NT treats not found as bad param... yet another bad
9021 result = WERR_INVALID_PARAM;
9026 * if the print job does not have a DEVMODE associated with it,
9027 * just use the one for the printer. A NULL devicemode is not
9028 * a failure condition
9031 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9032 devmode = construct_dev_mode(lp_const_servicename(snum));
9034 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9035 ZERO_STRUCTP( devmode );
9036 convert_nt_devicemode( devmode, nt_devmode );
9040 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9042 *needed += spoolss_size_job_info_2(info_2);
9044 if (*needed > offered) {
9045 result = WERR_INSUFFICIENT_BUFFER;
9049 if (!rpcbuf_alloc_size(buffer, *needed)) {
9050 result = WERR_NOMEM;
9054 smb_io_job_info_2("", buffer, info_2, 0);
9059 /* Cleanup allocated memory */
9061 free_job_info_2(info_2); /* Also frees devmode */
9067 /****************************************************************************
9068 ****************************************************************************/
9070 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9072 POLICY_HND *handle = &q_u->handle;
9073 uint32 jobid = q_u->jobid;
9074 uint32 level = q_u->level;
9075 RPC_BUFFER *buffer = NULL;
9076 uint32 offered = q_u->offered;
9077 uint32 *needed = &r_u->needed;
9078 WERROR wstatus = WERR_OK;
9079 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9082 print_queue_struct *queue = NULL;
9083 print_status_struct prt_status;
9085 /* that's an [in out] buffer */
9087 if (!q_u->buffer && (offered!=0)) {
9088 return WERR_INVALID_PARAM;
9091 rpcbuf_move(q_u->buffer, &r_u->buffer);
9092 buffer = r_u->buffer;
9094 DEBUG(5,("spoolss_getjob\n"));
9098 if (!get_printer_snum(p, handle, &snum, NULL))
9101 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9102 if ( !W_ERROR_IS_OK(wstatus) )
9105 count = print_queue_status(snum, &queue, &prt_status);
9107 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9108 count, prt_status.status, prt_status.message));
9112 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9113 buffer, offered, needed);
9116 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9117 buffer, offered, needed);
9120 wstatus = WERR_UNKNOWN_LEVEL;
9125 free_a_printer( &ntprinter, 2 );
9130 /********************************************************************
9131 spoolss_getprinterdataex
9133 From MSDN documentation of GetPrinterDataEx: pass request
9134 to GetPrinterData if key is "PrinterDriverData".
9135 ********************************************************************/
9137 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9139 POLICY_HND *handle = &q_u->handle;
9140 uint32 in_size = q_u->size;
9141 uint32 *type = &r_u->type;
9142 uint32 *out_size = &r_u->size;
9143 uint8 **data = &r_u->data;
9144 uint32 *needed = &r_u->needed;
9145 fstring keyname, valuename;
9147 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9149 NT_PRINTER_INFO_LEVEL *printer = NULL;
9151 WERROR status = WERR_OK;
9153 DEBUG(4,("_spoolss_getprinterdataex\n"));
9155 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname));
9156 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename));
9158 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9159 keyname, valuename));
9161 /* in case of problem, return some default values */
9165 *out_size = in_size;
9168 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9169 status = WERR_BADFID;
9173 /* Is the handle to a printer or to the server? */
9175 if (Printer->printer_type == SPLHND_SERVER) {
9176 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9177 status = WERR_INVALID_PARAM;
9181 if ( !get_printer_snum(p,handle, &snum, NULL) )
9184 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9185 if ( !W_ERROR_IS_OK(status) )
9188 /* check to see if the keyname is valid */
9189 if ( !strlen(keyname) ) {
9190 status = WERR_INVALID_PARAM;
9194 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9195 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9196 free_a_printer( &printer, 2 );
9197 status = WERR_BADFILE;
9201 /* When given a new keyname, we should just create it */
9203 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9205 if (*needed > *out_size)
9206 status = WERR_MORE_DATA;
9209 if ( !W_ERROR_IS_OK(status) )
9211 DEBUG(5, ("error: allocating %d\n", *out_size));
9213 /* reply this param doesn't exist */
9217 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9218 status = WERR_NOMEM;
9227 free_a_printer( &printer, 2 );
9232 /********************************************************************
9233 * spoolss_setprinterdataex
9234 ********************************************************************/
9236 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9238 POLICY_HND *handle = &q_u->handle;
9239 uint32 type = q_u->type;
9240 uint8 *data = q_u->data;
9241 uint32 real_len = q_u->real_len;
9243 NT_PRINTER_INFO_LEVEL *printer = NULL;
9245 WERROR status = WERR_OK;
9246 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9251 DEBUG(4,("_spoolss_setprinterdataex\n"));
9253 /* From MSDN documentation of SetPrinterDataEx: pass request to
9254 SetPrinterData if key is "PrinterDriverData" */
9257 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9261 if ( Printer->printer_type == SPLHND_SERVER ) {
9262 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9263 return WERR_INVALID_PARAM;
9266 if ( !get_printer_snum(p,handle, &snum, NULL) )
9270 * Access check : NT returns "access denied" if you make a
9271 * SetPrinterData call without the necessary privildge.
9272 * we were originally returning OK if nothing changed
9273 * which made Win2k issue **a lot** of SetPrinterData
9274 * when connecting to a printer --jerry
9277 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9279 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9280 return WERR_ACCESS_DENIED;
9283 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9284 if (!W_ERROR_IS_OK(status))
9287 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename));
9288 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname));
9290 /* check for OID in valuename */
9292 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9298 /* save the registry data */
9300 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9302 if ( W_ERROR_IS_OK(status) )
9304 /* save the OID if one was specified */
9306 fstrcat( keyname, "\\" );
9307 fstrcat( keyname, SPOOL_OID_KEY );
9310 * I'm not checking the status here on purpose. Don't know
9311 * if this is right, but I'm returning the status from the
9312 * previous set_printer_dataex() call. I have no idea if
9313 * this is right. --jerry
9316 set_printer_dataex( printer, keyname, valuename,
9317 REG_SZ, (uint8 *)oid_string,
9318 strlen(oid_string)+1 );
9321 status = mod_a_printer(printer, 2);
9324 free_a_printer(&printer, 2);
9330 /********************************************************************
9331 * spoolss_deleteprinterdataex
9332 ********************************************************************/
9334 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9336 POLICY_HND *handle = &q_u->handle;
9337 UNISTR2 *value = &q_u->valuename;
9338 UNISTR2 *key = &q_u->keyname;
9340 NT_PRINTER_INFO_LEVEL *printer = NULL;
9342 WERROR status = WERR_OK;
9343 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9344 char *valuename = NULL;
9345 char *keyname = NULL;
9346 TALLOC_CTX *ctx = p->mem_ctx;
9348 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9351 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9355 if (!get_printer_snum(p, handle, &snum, NULL))
9358 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9359 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9360 return WERR_ACCESS_DENIED;
9363 valuename = unistr2_to_ascii_talloc(ctx, value);
9364 keyname = unistr2_to_ascii_talloc(ctx, key);
9365 if (!valuename || !keyname) {
9369 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9370 if (!W_ERROR_IS_OK(status))
9373 status = delete_printer_dataex( printer, keyname, valuename );
9375 if ( W_ERROR_IS_OK(status) )
9376 mod_a_printer( printer, 2 );
9378 free_a_printer(&printer, 2);
9383 /********************************************************************
9384 * spoolss_enumprinterkey
9385 ********************************************************************/
9388 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9391 fstring *keynames = NULL;
9392 uint16 *enumkeys = NULL;
9395 POLICY_HND *handle = &q_u->handle;
9396 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9397 NT_PRINTER_DATA *data;
9398 NT_PRINTER_INFO_LEVEL *printer = NULL;
9400 WERROR status = WERR_BADFILE;
9403 DEBUG(4,("_spoolss_enumprinterkey\n"));
9406 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9410 if ( !get_printer_snum(p,handle, &snum, NULL) )
9413 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9414 if (!W_ERROR_IS_OK(status))
9417 /* get the list of subkey names */
9419 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9420 data = printer->info_2->data;
9422 num_keys = get_printer_subkeys( data, key, &keynames );
9424 if ( num_keys == -1 ) {
9425 status = WERR_BADFILE;
9429 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9431 r_u->needed = printerkey_len*2;
9433 if ( q_u->size < r_u->needed ) {
9434 status = WERR_MORE_DATA;
9438 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9439 status = WERR_NOMEM;
9445 if ( q_u->size < r_u->needed )
9446 status = WERR_MORE_DATA;
9449 free_a_printer( &printer, 2 );
9450 SAFE_FREE( keynames );
9455 /********************************************************************
9456 * spoolss_deleteprinterkey
9457 ********************************************************************/
9459 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9461 POLICY_HND *handle = &q_u->handle;
9462 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9464 NT_PRINTER_INFO_LEVEL *printer = NULL;
9468 DEBUG(5,("spoolss_deleteprinterkey\n"));
9471 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9475 /* if keyname == NULL, return error */
9477 if ( !q_u->keyname.buffer )
9478 return WERR_INVALID_PARAM;
9480 if (!get_printer_snum(p, handle, &snum, NULL))
9483 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9484 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9485 return WERR_ACCESS_DENIED;
9488 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9489 if (!W_ERROR_IS_OK(status))
9492 /* delete the key and all subneys */
9494 unistr2_to_ascii(key, &q_u->keyname, sizeof(key));
9496 status = delete_all_printer_data( printer->info_2, key );
9498 if ( W_ERROR_IS_OK(status) )
9499 status = mod_a_printer(printer, 2);
9501 free_a_printer( &printer, 2 );
9507 /********************************************************************
9508 * spoolss_enumprinterdataex
9509 ********************************************************************/
9511 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9513 POLICY_HND *handle = &q_u->handle;
9514 uint32 in_size = q_u->size;
9517 NT_PRINTER_INFO_LEVEL *printer = NULL;
9518 PRINTER_ENUM_VALUES *enum_values = NULL;
9519 NT_PRINTER_DATA *p_data;
9521 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9526 REGISTRY_VALUE *val;
9531 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9534 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9539 * first check for a keyname of NULL or "". Win2k seems to send
9540 * this a lot and we should send back WERR_INVALID_PARAM
9541 * no need to spend time looking up the printer in this case.
9545 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9546 if ( !strlen(key) ) {
9547 result = WERR_INVALID_PARAM;
9551 /* get the printer off of disk */
9553 if (!get_printer_snum(p,handle, &snum, NULL))
9556 ZERO_STRUCT(printer);
9557 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9558 if (!W_ERROR_IS_OK(result))
9561 /* now look for a match on the key name */
9563 p_data = printer->info_2->data;
9565 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9566 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9568 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9569 result = WERR_INVALID_PARAM;
9576 /* allocate the memory for the array of pointers -- if necessary */
9578 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9581 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9583 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9584 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9585 result = WERR_NOMEM;
9589 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9593 * loop through all params and build the array to pass
9594 * back to the client
9597 for ( i=0; i<num_entries; i++ )
9599 /* lookup the registry value */
9601 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9602 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9606 value_name = regval_name( val );
9607 init_unistr( &enum_values[i].valuename, value_name );
9608 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9609 enum_values[i].type = regval_type( val );
9611 data_len = regval_size( val );
9613 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9615 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9617 result = WERR_NOMEM;
9621 enum_values[i].data_len = data_len;
9623 /* keep track of the size of the array in bytes */
9625 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9628 /* housekeeping information in the reply */
9630 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9631 * the hand marshalled container size is a multiple
9632 * of 4 bytes for RPC alignment.
9636 needed += 4-(needed % 4);
9639 r_u->needed = needed;
9640 r_u->returned = num_entries;
9642 if (needed > in_size) {
9643 result = WERR_MORE_DATA;
9647 /* copy data into the reply */
9649 /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9650 response buffer size is != the offered buffer size
9652 r_u->ctr.size = r_u->needed;
9654 r_u->ctr.size = in_size;
9656 r_u->ctr.size_of_array = r_u->returned;
9657 r_u->ctr.values = enum_values;
9661 free_a_printer(&printer, 2);
9666 /****************************************************************************
9667 ****************************************************************************/
9669 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
9671 init_unistr(&info->name, name);
9674 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9675 UNISTR2 *environment,
9680 char *long_archi = NULL;
9681 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9682 WERROR result = WERR_OK;
9683 TALLOC_CTX *ctx = talloc_tos();
9685 long_archi = unistr2_to_ascii_talloc(ctx, environment);
9690 if (!get_short_archi(long_archi))
9691 return WERR_INVALID_ENVIRONMENT;
9693 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9696 fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9698 *needed += spoolss_size_printprocessordirectory_info_1(info);
9700 if (*needed > offered) {
9701 result = WERR_INSUFFICIENT_BUFFER;
9705 if (!rpcbuf_alloc_size(buffer, *needed)) {
9706 result = WERR_INSUFFICIENT_BUFFER;
9710 smb_io_printprocessordirectory_1("", buffer, info, 0);
9718 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9720 uint32 level = q_u->level;
9721 RPC_BUFFER *buffer = NULL;
9722 uint32 offered = q_u->offered;
9723 uint32 *needed = &r_u->needed;
9726 /* that's an [in out] buffer */
9728 if (!q_u->buffer && (offered!=0)) {
9729 return WERR_INVALID_PARAM;
9732 rpcbuf_move(q_u->buffer, &r_u->buffer);
9733 buffer = r_u->buffer;
9735 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9741 result = getprintprocessordirectory_level_1
9742 (&q_u->name, &q_u->environment, buffer, offered, needed);
9745 result = WERR_UNKNOWN_LEVEL;
9751 /*******************************************************************
9752 Streams the monitor UI DLL name in UNICODE
9753 *******************************************************************/
9755 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9756 RPC_BUFFER *out, uint32 *needed )
9758 const char *dllname = "tcpmonui.dll";
9760 *needed = (strlen(dllname)+1) * 2;
9762 if ( rpcbuf_get_size(out) < *needed ) {
9763 return WERR_INSUFFICIENT_BUFFER;
9766 if ( !make_monitorui_buf( out, dllname ) ) {
9773 /*******************************************************************
9774 Create a new TCP/IP port
9775 *******************************************************************/
9777 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9778 RPC_BUFFER *out, uint32 *needed )
9780 NT_PORT_DATA_1 port1;
9781 TALLOC_CTX *ctx = talloc_tos();
9782 char *device_uri = NULL;
9784 ZERO_STRUCT( port1 );
9786 /* convert to our internal port data structure */
9788 if ( !convert_port_data_1( &port1, in ) ) {
9792 /* create the device URI and call the add_port_hook() */
9794 switch ( port1.protocol ) {
9795 case PORT_PROTOCOL_DIRECT:
9796 device_uri = talloc_asprintf(ctx,
9797 "socket://%s:%d/", port1.hostaddr, port1.port );
9800 case PORT_PROTOCOL_LPR:
9801 device_uri = talloc_asprintf(ctx,
9802 "lpr://%s/%s", port1.hostaddr, port1.queue );
9806 return WERR_UNKNOWN_PORT;
9813 return add_port_hook(ctx, token, port1.name, device_uri );
9816 /*******************************************************************
9817 *******************************************************************/
9819 struct xcv_api_table xcvtcp_cmds[] = {
9820 { "MonitorUI", xcvtcp_monitorui },
9821 { "AddPort", xcvtcp_addport},
9825 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9826 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9831 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9833 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9834 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9835 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9838 return WERR_BADFUNC;
9841 /*******************************************************************
9842 *******************************************************************/
9843 #if 0 /* don't support management using the "Local Port" monitor */
9845 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9846 RPC_BUFFER *out, uint32 *needed )
9848 const char *dllname = "localui.dll";
9850 *needed = (strlen(dllname)+1) * 2;
9852 if ( rpcbuf_get_size(out) < *needed ) {
9853 return WERR_INSUFFICIENT_BUFFER;
9856 if ( !make_monitorui_buf( out, dllname )) {
9863 /*******************************************************************
9864 *******************************************************************/
9866 struct xcv_api_table xcvlocal_cmds[] = {
9867 { "MonitorUI", xcvlocal_monitorui },
9871 struct xcv_api_table xcvlocal_cmds[] = {
9878 /*******************************************************************
9879 *******************************************************************/
9881 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9882 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9887 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9889 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9890 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9891 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9893 return WERR_BADFUNC;
9896 /*******************************************************************
9897 *******************************************************************/
9899 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9901 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9905 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9909 /* Has to be a handle to the TCP/IP port monitor */
9911 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9912 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9916 /* requires administrative access to the server */
9918 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9919 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9920 return WERR_ACCESS_DENIED;
9923 /* Get the command name. There's numerous commands supported by the
9924 TCPMON interface. */
9926 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9927 q_u->dataname.uni_str_len*2, 0);
9929 /* Allocate the outgoing buffer */
9931 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9933 switch ( Printer->printer_type ) {
9934 case SPLHND_PORTMON_TCP:
9935 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9936 &q_u->indata, &r_u->outdata, &r_u->needed );
9937 case SPLHND_PORTMON_LOCAL:
9938 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9939 &q_u->indata, &r_u->outdata, &r_u->needed );
9942 return WERR_INVALID_PRINT_MONITOR;