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.
10 * Copyright (C) Guenther Deschner 2009.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 /* macros stolen from s4 spoolss server */
32 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
33 ((info)?ndr_size_##fn(info, level, ic, 0):0)
35 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
36 ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
38 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
39 ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
41 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
44 extern userdom_struct current_user_info;
47 #define DBGC_CLASS DBGC_RPC_SRV
49 #ifndef MAX_OPEN_PRINTER_EXS
50 #define MAX_OPEN_PRINTER_EXS 50
53 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
54 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
56 static Printer_entry *printers_list;
58 typedef struct _counter_printer_0 {
59 struct _counter_printer_0 *next;
60 struct _counter_printer_0 *prev;
66 static counter_printer_0 *counter_list;
68 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
69 static uint32_t smb_connections = 0;
72 /* in printing/nt_printing.c */
74 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
76 /* API table for Xcv Monitor functions */
78 struct xcv_api_table {
80 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
83 /********************************************************************
84 * Canonicalize servername.
85 ********************************************************************/
87 static const char *canon_servername(const char *servername)
89 const char *pservername = servername;
90 while (*pservername == '\\') {
96 /* translate between internal status numbers and NT status numbers */
97 static int nt_printj_status(int v)
103 return JOB_STATUS_PAUSED;
105 return JOB_STATUS_SPOOLING;
107 return JOB_STATUS_PRINTING;
109 return JOB_STATUS_ERROR;
111 return JOB_STATUS_DELETING;
113 return JOB_STATUS_OFFLINE;
115 return JOB_STATUS_PAPEROUT;
117 return JOB_STATUS_PRINTED;
119 return JOB_STATUS_DELETED;
121 return JOB_STATUS_BLOCKED_DEVQ;
122 case LPQ_USER_INTERVENTION:
123 return JOB_STATUS_USER_INTERVENTION;
128 static int nt_printq_status(int v)
132 return PRINTER_STATUS_PAUSED;
141 /***************************************************************************
142 Disconnect from the client
143 ****************************************************************************/
145 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
151 * Tell the specific printing tdb we no longer want messages for this printer
152 * by deregistering our PID.
155 if (!print_notify_deregister_pid(snum))
156 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
158 /* weird if the test succeds !!! */
159 if (smb_connections==0) {
160 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
164 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
167 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
168 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
169 win_errstr(result)));
171 /* if it's the last connection, deconnect the IPC$ share */
172 if (smb_connections==1) {
174 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
175 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
177 messaging_deregister(smbd_messaging_context(),
178 MSG_PRINTER_NOTIFY2, NULL);
180 /* Tell the connections db we're no longer interested in
181 * printer notify messages. */
183 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
189 /****************************************************************************
190 Functions to free a printer entry datastruct.
191 ****************************************************************************/
193 static int printer_entry_destructor(Printer_entry *Printer)
195 if (Printer->notify.client_connected == true) {
198 if ( Printer->printer_type == SPLHND_SERVER) {
200 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
201 } else if (Printer->printer_type == SPLHND_PRINTER) {
202 snum = print_queue_snum(Printer->sharename);
204 srv_spoolss_replycloseprinter(snum,
205 &Printer->notify.client_hnd);
209 Printer->notify.flags=0;
210 Printer->notify.options=0;
211 Printer->notify.localmachine[0]='\0';
212 Printer->notify.printerlocal=0;
213 TALLOC_FREE(Printer->notify.option);
214 Printer->notify.client_connected = false;
216 free_nt_devicemode( &Printer->nt_devmode );
217 free_a_printer( &Printer->printer_info, 2 );
219 /* Remove from the internal list. */
220 DLIST_REMOVE(printers_list, Printer);
224 /****************************************************************************
225 find printer index by handle
226 ****************************************************************************/
228 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
229 struct policy_handle *hnd)
231 Printer_entry *find_printer = NULL;
233 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
234 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
241 /****************************************************************************
242 Close printer index by handle.
243 ****************************************************************************/
245 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
247 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
250 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
255 close_policy_hnd(p, hnd);
260 /****************************************************************************
261 Delete a printer given a handle.
262 ****************************************************************************/
264 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
266 char *cmd = lp_deleteprinter_cmd();
267 char *command = NULL;
269 SE_PRIV se_printop = SE_PRINT_OPERATOR;
270 bool is_print_op = false;
272 /* can't fail if we don't try */
277 command = talloc_asprintf(ctx,
284 is_print_op = user_has_privileges( token, &se_printop );
286 DEBUG(10,("Running [%s]\n", command));
288 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
293 if ( (ret = smbrun(command, NULL)) == 0 ) {
294 /* Tell everyone we updated smb.conf. */
295 message_send_all(smbd_messaging_context(),
296 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
302 /********** END SePrintOperatorPrivlege BLOCK **********/
304 DEBUGADD(10,("returned [%d]\n", ret));
306 TALLOC_FREE(command);
309 return WERR_BADFID; /* What to return here? */
311 /* go ahead and re-read the services immediately */
313 reload_services(false);
316 if ( lp_servicenumber( sharename ) < 0 )
317 return WERR_ACCESS_DENIED;
322 /****************************************************************************
323 Delete a printer given a handle.
324 ****************************************************************************/
326 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
328 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
331 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
337 * It turns out that Windows allows delete printer on a handle
338 * opened by an admin user, then used on a pipe handle created
339 * by an anonymous user..... but they're working on security.... riiight !
343 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
344 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
345 return WERR_ACCESS_DENIED;
348 /* this does not need a become root since the access check has been
349 done on the handle already */
351 if (del_a_printer( Printer->sharename ) != 0) {
352 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
356 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
357 Printer->sharename );
360 /****************************************************************************
361 Return the snum of a printer corresponding to an handle.
362 ****************************************************************************/
364 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
365 int *number, struct share_params **params)
367 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
370 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
375 switch (Printer->printer_type) {
377 DEBUG(4,("short name:%s\n", Printer->sharename));
378 *number = print_queue_snum(Printer->sharename);
379 return (*number != -1);
387 /****************************************************************************
388 Set printer handle type.
389 Check if it's \\server or \\server\printer
390 ****************************************************************************/
392 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
394 DEBUG(3,("Setting printer type=%s\n", handlename));
396 if ( strlen(handlename) < 3 ) {
397 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
401 /* it's a print server */
402 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
403 DEBUGADD(4,("Printer is a print server\n"));
404 Printer->printer_type = SPLHND_SERVER;
406 /* it's a printer (set_printer_hnd_name() will handle port monitors */
408 DEBUGADD(4,("Printer is a printer\n"));
409 Printer->printer_type = SPLHND_PRINTER;
415 /****************************************************************************
416 Set printer handle name.. Accept names like \\server, \\server\printer,
417 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
418 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
419 XcvDataPort() interface.
420 ****************************************************************************/
422 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
425 int n_services=lp_numservices();
426 char *aprinter, *printername;
427 const char *servername;
430 NT_PRINTER_INFO_LEVEL *printer = NULL;
433 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
434 (unsigned long)strlen(handlename)));
436 aprinter = CONST_DISCARD(char *, handlename);
437 if ( *handlename == '\\' ) {
438 servername = canon_servername(handlename);
439 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
444 servername = global_myname();
447 /* save the servername to fill in replies on this handle */
449 if ( !is_myname_or_ipaddr( servername ) )
452 fstrcpy( Printer->servername, servername );
454 if ( Printer->printer_type == SPLHND_SERVER )
457 if ( Printer->printer_type != SPLHND_PRINTER )
460 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
462 /* check for the Port Monitor Interface */
464 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
465 Printer->printer_type = SPLHND_PORTMON_TCP;
466 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
469 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
470 Printer->printer_type = SPLHND_PORTMON_LOCAL;
471 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
475 /* Search all sharenames first as this is easier than pulling
476 the printer_info_2 off of disk. Don't use find_service() since
477 that calls out to map_username() */
479 /* do another loop to look for printernames */
481 for (snum=0; !found && snum<n_services; snum++) {
483 /* no point going on if this is not a printer */
485 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
488 fstrcpy(sname, lp_servicename(snum));
489 if ( strequal( aprinter, sname ) ) {
494 /* no point looking up the printer object if
495 we aren't allowing printername != sharename */
497 if ( lp_force_printername(snum) )
500 fstrcpy(sname, lp_servicename(snum));
504 /* This call doesn't fill in the location or comment from
505 * a CUPS server for efficiency with large numbers of printers.
509 result = get_a_printer_search( NULL, &printer, 2, sname );
510 if ( !W_ERROR_IS_OK(result) ) {
511 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
512 sname, win_errstr(result)));
516 /* printername is always returned as \\server\printername */
517 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
518 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
519 printer->info_2->printername));
520 free_a_printer( &printer, 2);
526 if ( strequal(printername, aprinter) ) {
527 free_a_printer( &printer, 2);
532 DEBUGADD(10, ("printername: %s\n", printername));
534 free_a_printer( &printer, 2);
537 free_a_printer( &printer, 2);
540 DEBUGADD(4,("Printer not found\n"));
544 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
546 fstrcpy(Printer->sharename, sname);
551 /****************************************************************************
552 Find first available printer slot. creates a printer handle for you.
553 ****************************************************************************/
555 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
556 const char *name, uint32_t access_granted)
558 Printer_entry *new_printer;
560 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
562 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
563 if (new_printer == NULL) {
566 talloc_set_destructor(new_printer, printer_entry_destructor);
568 if (!create_policy_hnd(p, hnd, new_printer)) {
569 TALLOC_FREE(new_printer);
573 /* Add to the internal list. */
574 DLIST_ADD(printers_list, new_printer);
576 new_printer->notify.option=NULL;
578 if (!set_printer_hnd_printertype(new_printer, name)) {
579 close_printer_handle(p, hnd);
583 if (!set_printer_hnd_name(new_printer, name)) {
584 close_printer_handle(p, hnd);
588 new_printer->access_granted = access_granted;
590 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
595 /***************************************************************************
596 check to see if the client motify handle is monitoring the notification
597 given by (notify_type, notify_field).
598 **************************************************************************/
600 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
601 uint16_t notify_field)
606 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
607 uint16_t notify_field)
609 struct spoolss_NotifyOption *option = p->notify.option;
613 * Flags should always be zero when the change notify
614 * is registered by the client's spooler. A user Win32 app
615 * might use the flags though instead of the NOTIFY_OPTION_INFO
624 return is_monitoring_event_flags(
625 p->notify.flags, notify_type, notify_field);
627 for (i = 0; i < option->count; i++) {
629 /* Check match for notify_type */
631 if (option->types[i].type != notify_type)
634 /* Check match for field */
636 for (j = 0; j < option->types[i].count; j++) {
637 if (option->types[i].fields[j].field == notify_field) {
643 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
644 p->servername, p->sharename, notify_type, notify_field));
649 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
650 _data->data.integer[0] = _integer; \
651 _data->data.integer[1] = 0;
654 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
655 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
656 if (!_data->data.string.string) {\
657 _data->data.string.size = 0; \
659 _data->data.string.size = strlen_m_term(_p) * 2;
661 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
662 _data->data.devmode.devmode = _devmode;
664 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
665 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
666 if (!_data->data.sd.sd) { \
667 _data->data.sd.sd_size = 0; \
669 _data->data.sd.sd_size = _size;
671 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
676 struct spoolss_Time st;
680 if (!init_systemtime(&st, t)) {
684 p = talloc_array(mem_ctx, char, len);
690 * Systemtime must be linearized as a set of UINT16's.
691 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
694 SSVAL(p, 0, st.year);
695 SSVAL(p, 2, st.month);
696 SSVAL(p, 4, st.day_of_week);
698 SSVAL(p, 8, st.hour);
699 SSVAL(p, 10, st.minute);
700 SSVAL(p, 12, st.second);
701 SSVAL(p, 14, st.millisecond);
707 /* Convert a notification message to a struct spoolss_Notify */
709 static void notify_one_value(struct spoolss_notify_msg *msg,
710 struct spoolss_Notify *data,
713 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
716 static void notify_string(struct spoolss_notify_msg *msg,
717 struct spoolss_Notify *data,
720 /* The length of the message includes the trailing \0 */
722 data->data.string.size = msg->len * 2;
723 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
724 if (!data->data.string.string) {
725 data->data.string.size = 0;
730 static void notify_system_time(struct spoolss_notify_msg *msg,
731 struct spoolss_Notify *data,
734 data->data.string.string = NULL;
735 data->data.string.size = 0;
737 if (msg->len != sizeof(time_t)) {
738 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
743 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
744 &data->data.string.string,
745 &data->data.string.size);
748 struct notify2_message_table {
750 void (*fn)(struct spoolss_notify_msg *msg,
751 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
754 static struct notify2_message_table printer_notify_table[] = {
755 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
756 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
757 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
758 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
759 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
760 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
761 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
762 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
763 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
764 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
765 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
766 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
767 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
768 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
769 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
770 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
771 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
772 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
773 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
776 static struct notify2_message_table job_notify_table[] = {
777 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
778 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
779 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
780 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
781 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
782 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
783 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
784 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
785 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
786 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
787 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
788 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
789 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
790 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
791 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
792 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
793 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
794 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
795 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
796 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
797 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
798 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
799 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
800 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
804 /***********************************************************************
805 Allocate talloc context for container object
806 **********************************************************************/
808 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
813 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
818 /***********************************************************************
819 release all allocated memory and zero out structure
820 **********************************************************************/
822 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
828 talloc_destroy(ctr->ctx);
835 /***********************************************************************
836 **********************************************************************/
838 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
846 /***********************************************************************
847 **********************************************************************/
849 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
851 if ( !ctr || !ctr->msg_groups )
854 if ( idx >= ctr->num_groups )
857 return &ctr->msg_groups[idx];
861 /***********************************************************************
862 How many groups of change messages do we have ?
863 **********************************************************************/
865 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
870 return ctr->num_groups;
873 /***********************************************************************
874 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
875 **********************************************************************/
877 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
879 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
880 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
881 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
887 /* loop over all groups looking for a matching printer name */
889 for ( i=0; i<ctr->num_groups; i++ ) {
890 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
894 /* add a new group? */
896 if ( i == ctr->num_groups ) {
899 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
900 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
903 ctr->msg_groups = groups;
905 /* clear the new entry and set the printer name */
907 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
908 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
911 /* add the change messages; 'i' is the correct index now regardless */
913 msg_grp = &ctr->msg_groups[i];
917 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
918 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
921 msg_grp->msgs = msg_list;
923 new_slot = msg_grp->num_msgs-1;
924 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
926 /* need to allocate own copy of data */
929 msg_grp->msgs[new_slot].notify.data = (char *)
930 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
932 return ctr->num_groups;
935 /***********************************************************************
936 Send a change notication message on all handles which have a call
938 **********************************************************************/
940 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
943 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
944 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
945 SPOOLSS_NOTIFY_MSG *messages;
946 int sending_msg_count;
949 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
953 messages = msg_group->msgs;
956 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
960 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
962 /* loop over all printers */
964 for (p = printers_list; p; p = p->next) {
965 struct spoolss_Notify *notifies;
970 /* Is there notification on this handle? */
972 if ( !p->notify.client_connected )
975 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
977 /* For this printer? Print servers always receive
980 if ( ( p->printer_type == SPLHND_PRINTER ) &&
981 ( !strequal(msg_group->printername, p->sharename) ) )
984 DEBUG(10,("Our printer\n"));
986 /* allocate the max entries possible */
988 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
993 /* build the array of change notifications */
995 sending_msg_count = 0;
997 for ( i=0; i<msg_group->num_msgs; i++ ) {
998 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1000 /* Are we monitoring this event? */
1002 if (!is_monitoring_event(p, msg->type, msg->field))
1005 sending_msg_count++;
1008 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1009 msg->type, msg->field, p->sharename));
1012 * if the is a printer notification handle and not a job notification
1013 * type, then set the id to 0. Other wise just use what was specified
1016 * When registering change notification on a print server handle
1017 * we always need to send back the id (snum) matching the printer
1018 * for which the change took place. For change notify registered
1019 * on a printer handle, this does not matter and the id should be 0.
1024 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1030 /* Convert unix jobid to smb jobid */
1032 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1033 id = sysjob_to_jobid(msg->id);
1036 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1041 construct_info_data( ¬ifies[count], msg->type, msg->field, id );
1044 case PRINTER_NOTIFY_TYPE:
1045 if ( printer_notify_table[msg->field].fn )
1046 printer_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1049 case JOB_NOTIFY_TYPE:
1050 if ( job_notify_table[msg->field].fn )
1051 job_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1055 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1062 if ( sending_msg_count ) {
1065 union spoolss_ReplyPrinterInfo info;
1066 struct spoolss_NotifyInfo info0;
1067 uint32_t reply_result;
1069 info0.version = 0x2;
1070 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1071 info0.count = count;
1072 info0.notifies = notifies;
1074 info.info0 = &info0;
1076 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1077 &p->notify.client_hnd,
1078 p->notify.change, /* color */
1081 0, /* reply_type, must be 0 */
1084 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1085 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1086 notify_cli_pipe->srv_name_slash,
1089 switch (reply_result) {
1092 case PRINTER_NOTIFY_INFO_DISCARDED:
1093 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1094 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1103 DEBUG(8,("send_notify2_changes: Exit...\n"));
1107 /***********************************************************************
1108 **********************************************************************/
1110 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1113 uint32_t tv_sec, tv_usec;
1116 /* Unpack message */
1118 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1121 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1123 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1126 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1127 &msg->notify.value[0], &msg->notify.value[1]);
1129 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1130 &msg->len, &msg->notify.data);
1132 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1133 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1135 tv->tv_sec = tv_sec;
1136 tv->tv_usec = tv_usec;
1139 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1140 msg->notify.value[1]));
1142 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1147 /********************************************************************
1148 Receive a notify2 message list
1149 ********************************************************************/
1151 static void receive_notify2_message_list(struct messaging_context *msg,
1154 struct server_id server_id,
1157 size_t msg_count, i;
1158 char *buf = (char *)data->data;
1161 SPOOLSS_NOTIFY_MSG notify;
1162 SPOOLSS_NOTIFY_MSG_CTR messages;
1165 if (data->length < 4) {
1166 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1170 msg_count = IVAL(buf, 0);
1173 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1175 if (msg_count == 0) {
1176 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1180 /* initialize the container */
1182 ZERO_STRUCT( messages );
1183 notify_msg_ctr_init( &messages );
1186 * build message groups for each printer identified
1187 * in a change_notify msg. Remember that a PCN message
1188 * includes the handle returned for the srv_spoolss_replyopenprinter()
1189 * call. Therefore messages are grouped according to printer handle.
1192 for ( i=0; i<msg_count; i++ ) {
1193 struct timeval msg_tv;
1195 if (msg_ptr + 4 - buf > data->length) {
1196 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1200 msg_len = IVAL(msg_ptr,0);
1203 if (msg_ptr + msg_len - buf > data->length) {
1204 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1208 /* unpack messages */
1210 ZERO_STRUCT( notify );
1211 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1214 /* add to correct list in container */
1216 notify_msg_ctr_addmsg( &messages, ¬ify );
1218 /* free memory that might have been allocated by notify2_unpack_msg() */
1220 if ( notify.len != 0 )
1221 SAFE_FREE( notify.notify.data );
1224 /* process each group of messages */
1226 num_groups = notify_msg_ctr_numgroups( &messages );
1227 for ( i=0; i<num_groups; i++ )
1228 send_notify2_changes( &messages, i );
1233 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1234 (uint32_t)msg_count ));
1236 notify_msg_ctr_destroy( &messages );
1241 /********************************************************************
1242 Send a message to ourself about new driver being installed
1243 so we can upgrade the information for each printer bound to this
1245 ********************************************************************/
1247 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1249 int len = strlen(drivername);
1254 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1257 messaging_send_buf(smbd_messaging_context(), procid_self(),
1258 MSG_PRINTER_DRVUPGRADE,
1259 (uint8_t *)drivername, len+1);
1264 /**********************************************************************
1265 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1266 over all printers, upgrading ones as necessary
1267 **********************************************************************/
1269 void do_drv_upgrade_printer(struct messaging_context *msg,
1272 struct server_id server_id,
1277 int n_services = lp_numservices();
1280 len = MIN(data->length,sizeof(drivername)-1);
1281 strncpy(drivername, (const char *)data->data, len);
1283 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1285 /* Iterate the printer list */
1287 for (snum=0; snum<n_services; snum++)
1289 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1292 NT_PRINTER_INFO_LEVEL *printer = NULL;
1294 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1295 if (!W_ERROR_IS_OK(result))
1298 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1300 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1302 /* all we care about currently is the change_id */
1304 result = mod_a_printer(printer, 2);
1305 if (!W_ERROR_IS_OK(result)) {
1306 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1307 win_errstr(result)));
1311 free_a_printer(&printer, 2);
1318 /********************************************************************
1319 Update the cache for all printq's with a registered client
1321 ********************************************************************/
1323 void update_monitored_printq_cache( void )
1325 Printer_entry *printer = printers_list;
1328 /* loop through all printers and update the cache where
1329 client_connected == true */
1332 if ( (printer->printer_type == SPLHND_PRINTER)
1333 && printer->notify.client_connected )
1335 snum = print_queue_snum(printer->sharename);
1336 print_queue_status( snum, NULL, NULL );
1339 printer = printer->next;
1344 /********************************************************************
1345 Send a message to ourself about new driver being installed
1346 so we can upgrade the information for each printer bound to this
1348 ********************************************************************/
1350 static bool srv_spoolss_reset_printerdata(char* drivername)
1352 int len = strlen(drivername);
1357 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1360 messaging_send_buf(smbd_messaging_context(), procid_self(),
1361 MSG_PRINTERDATA_INIT_RESET,
1362 (uint8_t *)drivername, len+1);
1367 /**********************************************************************
1368 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1369 over all printers, resetting printer data as neessary
1370 **********************************************************************/
1372 void reset_all_printerdata(struct messaging_context *msg,
1375 struct server_id server_id,
1380 int n_services = lp_numservices();
1383 len = MIN( data->length, sizeof(drivername)-1 );
1384 strncpy( drivername, (const char *)data->data, len );
1386 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1388 /* Iterate the printer list */
1390 for ( snum=0; snum<n_services; snum++ )
1392 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1395 NT_PRINTER_INFO_LEVEL *printer = NULL;
1397 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1398 if ( !W_ERROR_IS_OK(result) )
1402 * if the printer is bound to the driver,
1403 * then reset to the new driver initdata
1406 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1408 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1410 if ( !set_driver_init(printer, 2) ) {
1411 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1412 printer->info_2->printername, printer->info_2->drivername));
1415 result = mod_a_printer( printer, 2 );
1416 if ( !W_ERROR_IS_OK(result) ) {
1417 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1418 get_dos_error_msg(result)));
1422 free_a_printer( &printer, 2 );
1431 /****************************************************************
1432 _spoolss_OpenPrinter
1433 ****************************************************************/
1435 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1436 struct spoolss_OpenPrinter *r)
1438 struct spoolss_OpenPrinterEx e;
1441 ZERO_STRUCT(e.in.userlevel);
1443 e.in.printername = r->in.printername;
1444 e.in.datatype = r->in.datatype;
1445 e.in.devmode_ctr = r->in.devmode_ctr;
1446 e.in.access_mask = r->in.access_mask;
1449 e.out.handle = r->out.handle;
1451 werr = _spoolss_OpenPrinterEx(p, &e);
1453 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1454 /* OpenPrinterEx returns this for a bad
1455 * printer name. We must return WERR_INVALID_PRINTER_NAME
1458 werr = WERR_INVALID_PRINTER_NAME;
1464 /********************************************************************
1465 ********************************************************************/
1467 bool convert_devicemode(const char *printername,
1468 const struct spoolss_DeviceMode *devmode,
1469 NT_DEVICEMODE **pp_nt_devmode)
1471 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1474 * Ensure nt_devmode is a valid pointer
1475 * as we will be overwriting it.
1478 if (nt_devmode == NULL) {
1479 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1480 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1484 fstrcpy(nt_devmode->devicename, devmode->devicename);
1485 fstrcpy(nt_devmode->formname, devmode->formname);
1487 nt_devmode->devicename[31] = '\0';
1488 nt_devmode->formname[31] = '\0';
1490 nt_devmode->specversion = devmode->specversion;
1491 nt_devmode->driverversion = devmode->driverversion;
1492 nt_devmode->size = devmode->size;
1493 nt_devmode->fields = devmode->fields;
1494 nt_devmode->orientation = devmode->orientation;
1495 nt_devmode->papersize = devmode->papersize;
1496 nt_devmode->paperlength = devmode->paperlength;
1497 nt_devmode->paperwidth = devmode->paperwidth;
1498 nt_devmode->scale = devmode->scale;
1499 nt_devmode->copies = devmode->copies;
1500 nt_devmode->defaultsource = devmode->defaultsource;
1501 nt_devmode->printquality = devmode->printquality;
1502 nt_devmode->color = devmode->color;
1503 nt_devmode->duplex = devmode->duplex;
1504 nt_devmode->yresolution = devmode->yresolution;
1505 nt_devmode->ttoption = devmode->ttoption;
1506 nt_devmode->collate = devmode->collate;
1508 nt_devmode->logpixels = devmode->logpixels;
1509 nt_devmode->bitsperpel = devmode->bitsperpel;
1510 nt_devmode->pelswidth = devmode->pelswidth;
1511 nt_devmode->pelsheight = devmode->pelsheight;
1512 nt_devmode->displayflags = devmode->displayflags;
1513 nt_devmode->displayfrequency = devmode->displayfrequency;
1514 nt_devmode->icmmethod = devmode->icmmethod;
1515 nt_devmode->icmintent = devmode->icmintent;
1516 nt_devmode->mediatype = devmode->mediatype;
1517 nt_devmode->dithertype = devmode->dithertype;
1518 nt_devmode->reserved1 = devmode->reserved1;
1519 nt_devmode->reserved2 = devmode->reserved2;
1520 nt_devmode->panningwidth = devmode->panningwidth;
1521 nt_devmode->panningheight = devmode->panningheight;
1524 * Only change private and driverextra if the incoming devmode
1525 * has a new one. JRA.
1528 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1529 SAFE_FREE(nt_devmode->nt_dev_private);
1530 nt_devmode->driverextra = devmode->__driverextra_length;
1531 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1533 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1536 *pp_nt_devmode = nt_devmode;
1541 /****************************************************************
1542 _spoolss_OpenPrinterEx
1543 ****************************************************************/
1545 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1546 struct spoolss_OpenPrinterEx *r)
1549 Printer_entry *Printer=NULL;
1551 if (!r->in.printername) {
1552 return WERR_INVALID_PARAM;
1555 /* some sanity check because you can open a printer or a print server */
1556 /* aka: \\server\printer or \\server */
1558 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1560 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1561 ZERO_STRUCTP(r->out.handle);
1562 return WERR_INVALID_PARAM;
1565 Printer = find_printer_index_by_hnd(p, r->out.handle);
1567 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1568 "handle we created for printer %s\n", r->in.printername));
1569 close_printer_handle(p, r->out.handle);
1570 ZERO_STRUCTP(r->out.handle);
1571 return WERR_INVALID_PARAM;
1575 * First case: the user is opening the print server:
1577 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1578 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1580 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1581 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1582 * or if the user is listed in the smb.conf printer admin parameter.
1584 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1585 * client view printer folder, but does not show the MSAPW.
1587 * Note: this test needs code to check access rights here too. Jeremy
1588 * could you look at this?
1590 * Second case: the user is opening a printer:
1591 * NT doesn't let us connect to a printer if the connecting user
1592 * doesn't have print permission.
1594 * Third case: user is opening a Port Monitor
1595 * access checks same as opening a handle to the print server.
1598 switch (Printer->printer_type )
1601 case SPLHND_PORTMON_TCP:
1602 case SPLHND_PORTMON_LOCAL:
1603 /* Printserver handles use global struct... */
1607 /* Map standard access rights to object specific access rights */
1609 se_map_standard(&r->in.access_mask,
1610 &printserver_std_mapping);
1612 /* Deny any object specific bits that don't apply to print
1613 servers (i.e printer and job specific bits) */
1615 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1617 if (r->in.access_mask &
1618 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1619 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1620 close_printer_handle(p, r->out.handle);
1621 ZERO_STRUCTP(r->out.handle);
1622 return WERR_ACCESS_DENIED;
1625 /* Allow admin access */
1627 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1629 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1631 if (!lp_ms_add_printer_wizard()) {
1632 close_printer_handle(p, r->out.handle);
1633 ZERO_STRUCTP(r->out.handle);
1634 return WERR_ACCESS_DENIED;
1637 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1638 and not a printer admin, then fail */
1640 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1641 !user_has_privileges(p->server_info->ptok,
1643 !token_contains_name_in_list(
1644 uidtoname(p->server_info->utok.uid),
1646 p->server_info->ptok,
1647 lp_printer_admin(snum))) {
1648 close_printer_handle(p, r->out.handle);
1649 ZERO_STRUCTP(r->out.handle);
1650 return WERR_ACCESS_DENIED;
1653 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1657 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1660 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1661 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1663 /* We fall through to return WERR_OK */
1666 case SPLHND_PRINTER:
1667 /* NT doesn't let us connect to a printer if the connecting user
1668 doesn't have print permission. */
1670 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1671 close_printer_handle(p, r->out.handle);
1672 ZERO_STRUCTP(r->out.handle);
1676 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1677 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1680 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1682 /* map an empty access mask to the minimum access mask */
1683 if (r->in.access_mask == 0x0)
1684 r->in.access_mask = PRINTER_ACCESS_USE;
1687 * If we are not serving the printer driver for this printer,
1688 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1689 * will keep NT clients happy --jerry
1692 if (lp_use_client_driver(snum)
1693 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1695 r->in.access_mask = PRINTER_ACCESS_USE;
1698 /* check smb.conf parameters and the the sec_desc */
1700 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1701 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1702 ZERO_STRUCTP(r->out.handle);
1703 return WERR_ACCESS_DENIED;
1706 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1707 p->server_info->ptok, snum) ||
1708 !print_access_check(p->server_info, snum,
1709 r->in.access_mask)) {
1710 DEBUG(3, ("access DENIED for printer open\n"));
1711 close_printer_handle(p, r->out.handle);
1712 ZERO_STRUCTP(r->out.handle);
1713 return WERR_ACCESS_DENIED;
1716 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1717 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1718 close_printer_handle(p, r->out.handle);
1719 ZERO_STRUCTP(r->out.handle);
1720 return WERR_ACCESS_DENIED;
1723 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1724 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1726 r->in.access_mask = PRINTER_ACCESS_USE;
1728 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1729 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1734 /* sanity check to prevent programmer error */
1735 ZERO_STRUCTP(r->out.handle);
1739 Printer->access_granted = r->in.access_mask;
1742 * If the client sent a devmode in the OpenPrinter() call, then
1743 * save it here in case we get a job submission on this handle
1746 if ((Printer->printer_type != SPLHND_SERVER) &&
1747 r->in.devmode_ctr.devmode) {
1748 convert_devicemode(Printer->sharename,
1749 r->in.devmode_ctr.devmode,
1750 &Printer->nt_devmode);
1753 #if 0 /* JERRY -- I'm doubtful this is really effective */
1754 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1755 optimization in Windows 2000 clients --jerry */
1757 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1758 && (RA_WIN2K == get_remote_arch()) )
1760 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1761 sys_usleep( 500000 );
1768 /****************************************************************************
1769 ****************************************************************************/
1771 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1772 NT_PRINTER_INFO_LEVEL_2 *d)
1774 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1780 d->attributes = r->attributes;
1781 d->priority = r->priority;
1782 d->default_priority = r->defaultpriority;
1783 d->starttime = r->starttime;
1784 d->untiltime = r->untiltime;
1785 d->status = r->status;
1786 d->cjobs = r->cjobs;
1788 fstrcpy(d->servername, r->servername);
1789 fstrcpy(d->printername, r->printername);
1790 fstrcpy(d->sharename, r->sharename);
1791 fstrcpy(d->portname, r->portname);
1792 fstrcpy(d->drivername, r->drivername);
1793 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1794 fstrcpy(d->location, r->location);
1795 fstrcpy(d->sepfile, r->sepfile);
1796 fstrcpy(d->printprocessor, r->printprocessor);
1797 fstrcpy(d->datatype, r->datatype);
1798 fstrcpy(d->parameters, r->parameters);
1803 /****************************************************************************
1804 ****************************************************************************/
1806 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1807 NT_PRINTER_INFO_LEVEL *printer)
1811 switch (info_ctr->level) {
1813 /* allocate memory if needed. Messy because
1814 convert_printer_info is used to update an existing
1815 printer or build a new one */
1817 if (!printer->info_2) {
1818 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1819 if (!printer->info_2) {
1820 DEBUG(0,("convert_printer_info: "
1821 "talloc() failed!\n"));
1826 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1828 printer->info_2->setuptime = time(NULL);
1835 /*******************************************************************
1836 ********************************************************************/
1838 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1847 *farray = SMB_MALLOC_ARRAY(fstring, 1);
1852 for (i=0; sarray[i] != NULL; i++) {
1853 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1857 fstrcpy((*farray)[i], sarray[i]);
1860 fstrcpy((*farray)[i], "");
1865 /*******************************************************************
1866 ********************************************************************/
1868 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1869 NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1871 NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1873 DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1876 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1885 d->cversion = r->version;
1887 fstrcpy(d->name, r->driver_name);
1888 fstrcpy(d->environment, r->architecture);
1889 fstrcpy(d->driverpath, r->driver_path);
1890 fstrcpy(d->datafile, r->data_file);
1891 fstrcpy(d->configfile, r->config_file);
1892 fstrcpy(d->helpfile, r->help_file);
1893 fstrcpy(d->monitorname, r->monitor_name);
1894 fstrcpy(d->defaultdatatype, r->default_datatype);
1896 DEBUGADD(8,( "version: %d\n", d->cversion));
1897 DEBUGADD(8,( "name: %s\n", d->name));
1898 DEBUGADD(8,( "environment: %s\n", d->environment));
1899 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1900 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1901 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1902 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1903 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1904 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1906 if (r->dependent_files) {
1907 if (!string_array_to_fstring_array(r->dependent_files->string,
1908 &d->dependentfiles)) {
1917 /*******************************************************************
1918 ********************************************************************/
1920 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1921 NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1923 NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1925 DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1928 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1937 d->version = r->version;
1939 fstrcpy(d->name, r->driver_name);
1940 fstrcpy(d->environment, r->architecture);
1941 fstrcpy(d->driverpath, r->driver_path);
1942 fstrcpy(d->datafile, r->data_file);
1943 fstrcpy(d->configfile, r->config_file);
1944 fstrcpy(d->helpfile, r->help_file);
1945 fstrcpy(d->monitorname, r->monitor_name);
1946 fstrcpy(d->defaultdatatype, r->default_datatype);
1948 DEBUGADD(8,( "version: %d\n", d->version));
1949 DEBUGADD(8,( "name: %s\n", d->name));
1950 DEBUGADD(8,( "environment: %s\n", d->environment));
1951 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1952 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1953 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1954 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1955 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1956 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1958 if (r->dependent_files) {
1959 if (!string_array_to_fstring_array(r->dependent_files->string,
1960 &d->dependentfiles)) {
1965 if (r->previous_names) {
1966 if (!string_array_to_fstring_array(r->previous_names->string,
1967 &d->previousnames)) {
1979 /********************************************************************
1980 ********************************************************************/
1982 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1983 NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1988 printer->info_3 = NULL;
1989 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1994 printer->info_6 = NULL;
1995 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
2006 /********************************************************************
2007 * _spoolss_enddocprinter_internal.
2008 ********************************************************************/
2010 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p,
2011 struct policy_handle *handle)
2013 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2017 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2021 if (!get_printer_snum(p, handle, &snum, NULL))
2024 Printer->document_started = false;
2025 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2026 /* error codes unhandled so far ... */
2031 /****************************************************************
2032 _spoolss_ClosePrinter
2033 ****************************************************************/
2035 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2036 struct spoolss_ClosePrinter *r)
2038 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2040 if (Printer && Printer->document_started)
2041 _spoolss_enddocprinter_internal(p, r->in.handle); /* print job was not closed */
2043 if (!close_printer_handle(p, r->in.handle))
2046 /* clear the returned printer handle. Observed behavior
2047 from Win2k server. Don't think this really matters.
2048 Previous code just copied the value of the closed
2051 ZERO_STRUCTP(r->out.handle);
2056 /****************************************************************
2057 _spoolss_DeletePrinter
2058 ****************************************************************/
2060 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2061 struct spoolss_DeletePrinter *r)
2063 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2066 if (Printer && Printer->document_started)
2067 _spoolss_enddocprinter_internal(p, r->in.handle); /* print job was not closed */
2069 result = delete_printer_handle(p, r->in.handle);
2071 update_c_setprinter(false);
2076 /*******************************************************************
2077 * static function to lookup the version id corresponding to an
2078 * long architecture string
2079 ******************************************************************/
2081 static int get_version_id(const char *arch)
2084 struct print_architecture_table_node archi_table[]= {
2086 {"Windows 4.0", "WIN40", 0 },
2087 {"Windows NT x86", "W32X86", 2 },
2088 {"Windows NT R4000", "W32MIPS", 2 },
2089 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2090 {"Windows NT PowerPC", "W32PPC", 2 },
2091 {"Windows IA64", "IA64", 3 },
2092 {"Windows x64", "x64", 3 },
2096 for (i=0; archi_table[i].long_archi != NULL; i++)
2098 if (strcmp(arch, archi_table[i].long_archi) == 0)
2099 return (archi_table[i].version);
2105 /****************************************************************
2106 _spoolss_DeletePrinterDriver
2107 ****************************************************************/
2109 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2110 struct spoolss_DeletePrinterDriver *r)
2112 NT_PRINTER_DRIVER_INFO_LEVEL info;
2113 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2116 WERROR status_win2k = WERR_ACCESS_DENIED;
2117 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2119 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2120 and not a printer admin, then fail */
2122 if ( (p->server_info->utok.uid != sec_initial_uid())
2123 && !user_has_privileges(p->server_info->ptok, &se_printop )
2124 && !token_contains_name_in_list(
2125 uidtoname(p->server_info->utok.uid), NULL,
2126 NULL, p->server_info->ptok,
2127 lp_printer_admin(-1)) )
2129 return WERR_ACCESS_DENIED;
2132 /* check that we have a valid driver name first */
2134 if ((version = get_version_id(r->in.architecture)) == -1)
2135 return WERR_INVALID_ENVIRONMENT;
2138 ZERO_STRUCT(info_win2k);
2140 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2144 /* try for Win2k driver if "Windows NT x86" */
2146 if ( version == 2 ) {
2148 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3,
2152 status = WERR_UNKNOWN_PRINTER_DRIVER;
2156 /* otherwise it was a failure */
2158 status = WERR_UNKNOWN_PRINTER_DRIVER;
2164 if (printer_driver_in_use(info.info_3)) {
2165 status = WERR_PRINTER_DRIVER_IN_USE;
2171 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2173 r->in.architecture, 3)))
2175 /* if we get to here, we now have 2 driver info structures to remove */
2176 /* remove the Win2k driver first*/
2178 status_win2k = delete_printer_driver(
2179 p, info_win2k.info_3, 3, false);
2180 free_a_printer_driver( info_win2k, 3 );
2182 /* this should not have failed---if it did, report to client */
2183 if ( !W_ERROR_IS_OK(status_win2k) )
2185 status = status_win2k;
2191 status = delete_printer_driver(p, info.info_3, version, false);
2193 /* if at least one of the deletes succeeded return OK */
2195 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2199 free_a_printer_driver( info, 3 );
2204 /****************************************************************
2205 _spoolss_DeletePrinterDriverEx
2206 ****************************************************************/
2208 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2209 struct spoolss_DeletePrinterDriverEx *r)
2211 NT_PRINTER_DRIVER_INFO_LEVEL info;
2212 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2216 WERROR status_win2k = WERR_ACCESS_DENIED;
2217 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2219 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2220 and not a printer admin, then fail */
2222 if ( (p->server_info->utok.uid != sec_initial_uid())
2223 && !user_has_privileges(p->server_info->ptok, &se_printop )
2224 && !token_contains_name_in_list(
2225 uidtoname(p->server_info->utok.uid), NULL, NULL,
2226 p->server_info->ptok, lp_printer_admin(-1)) )
2228 return WERR_ACCESS_DENIED;
2231 /* check that we have a valid driver name first */
2232 if ((version = get_version_id(r->in.architecture)) == -1) {
2233 /* this is what NT returns */
2234 return WERR_INVALID_ENVIRONMENT;
2237 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2238 version = r->in.version;
2241 ZERO_STRUCT(info_win2k);
2243 status = get_a_printer_driver(&info, 3, r->in.driver,
2244 r->in.architecture, version);
2246 if ( !W_ERROR_IS_OK(status) )
2249 * if the client asked for a specific version,
2250 * or this is something other than Windows NT x86,
2254 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2257 /* try for Win2k driver if "Windows NT x86" */
2260 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2263 status = WERR_UNKNOWN_PRINTER_DRIVER;
2268 if ( printer_driver_in_use(info.info_3) ) {
2269 status = WERR_PRINTER_DRIVER_IN_USE;
2274 * we have a couple of cases to consider.
2275 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2276 * then the delete should fail if **any** files overlap with
2278 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2279 * non-overlapping files
2280 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2281 * is set, the do not delete any files
2282 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2285 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2287 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2289 if ( delete_files && printer_driver_files_in_use(info.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2290 /* no idea of the correct error here */
2291 status = WERR_ACCESS_DENIED;
2296 /* also check for W32X86/3 if necessary; maybe we already have? */
2298 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2299 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2301 r->in.architecture, 3)))
2304 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2305 /* no idea of the correct error here */
2306 free_a_printer_driver( info_win2k, 3 );
2307 status = WERR_ACCESS_DENIED;
2311 /* if we get to here, we now have 2 driver info structures to remove */
2312 /* remove the Win2k driver first*/
2314 status_win2k = delete_printer_driver(
2315 p, info_win2k.info_3, 3, delete_files);
2316 free_a_printer_driver( info_win2k, 3 );
2318 /* this should not have failed---if it did, report to client */
2320 if ( !W_ERROR_IS_OK(status_win2k) )
2325 status = delete_printer_driver(p, info.info_3, version, delete_files);
2327 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2330 free_a_printer_driver( info, 3 );
2336 /****************************************************************************
2337 Internal routine for removing printerdata
2338 ***************************************************************************/
2340 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2342 return delete_printer_data( printer->info_2, key, value );
2345 /****************************************************************************
2346 Internal routine for storing printerdata
2347 ***************************************************************************/
2349 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2350 const char *key, const char *value,
2351 uint32_t type, uint8_t *data, int real_len)
2353 /* the registry objects enforce uniqueness based on value name */
2355 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2358 /********************************************************************
2359 GetPrinterData on a printer server Handle.
2360 ********************************************************************/
2362 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2364 enum winreg_Type *type,
2365 union spoolss_PrinterData *data)
2367 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2369 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2375 if (!StrCaseCmp(value, "BeepEnabled")) {
2381 if (!StrCaseCmp(value, "EventLog")) {
2383 /* formally was 0x1b */
2388 if (!StrCaseCmp(value, "NetPopup")) {
2394 if (!StrCaseCmp(value, "MajorVersion")) {
2397 /* Windows NT 4.0 seems to not allow uploading of drivers
2398 to a server that reports 0x3 as the MajorVersion.
2399 need to investigate more how Win2k gets around this .
2402 if (RA_WINNT == get_remote_arch()) {
2411 if (!StrCaseCmp(value, "MinorVersion")) {
2418 * uint32_t size = 0x114
2419 * uint32_t major = 5
2420 * uint32_t minor = [0|1]
2421 * uint32_t build = [2195|2600]
2422 * extra unicode string = e.g. "Service Pack 3"
2424 if (!StrCaseCmp(value, "OSVersion")) {
2426 enum ndr_err_code ndr_err;
2427 struct spoolss_OSVersion os;
2429 os.major = 5; /* Windows 2000 == 5.0 */
2431 os.build = 2195; /* build */
2432 os.extra_string = ""; /* leave extra string empty */
2434 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2435 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2436 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2437 return WERR_GENERAL_FAILURE;
2441 data->binary = blob;
2447 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2450 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2451 W_ERROR_HAVE_NO_MEMORY(data->string);
2456 if (!StrCaseCmp(value, "Architecture")) {
2459 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2460 W_ERROR_HAVE_NO_MEMORY(data->string);
2465 if (!StrCaseCmp(value, "DsPresent")) {
2468 /* only show the publish check box if we are a
2469 member of a AD domain */
2471 if (lp_security() == SEC_ADS) {
2479 if (!StrCaseCmp(value, "DNSMachineName")) {
2480 const char *hostname = get_mydnsfullname();
2483 return WERR_BADFILE;
2487 data->string = talloc_strdup(mem_ctx, hostname);
2488 W_ERROR_HAVE_NO_MEMORY(data->string);
2495 return WERR_INVALID_PARAM;
2498 /****************************************************************
2499 _spoolss_GetPrinterData
2500 ****************************************************************/
2502 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2503 struct spoolss_GetPrinterData *r)
2505 struct spoolss_GetPrinterDataEx r2;
2507 r2.in.handle = r->in.handle;
2508 r2.in.key_name = "PrinterDriverData";
2509 r2.in.value_name = r->in.value_name;
2510 r2.in.offered = r->in.offered;
2511 r2.out.type = r->out.type;
2512 r2.out.data = r->out.data;
2513 r2.out.needed = r->out.needed;
2515 return _spoolss_GetPrinterDataEx(p, &r2);
2518 /*********************************************************
2519 Connect to the client machine.
2520 **********************************************************/
2522 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2523 struct sockaddr_storage *client_ss, const char *remote_machine)
2526 struct cli_state *the_cli;
2527 struct sockaddr_storage rm_addr;
2529 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2530 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2531 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2535 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2536 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2540 char addr[INET6_ADDRSTRLEN];
2541 rm_addr = *client_ss;
2542 print_sockaddr(addr, sizeof(addr), &rm_addr);
2543 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2547 /* setup the connection */
2549 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2550 &rm_addr, 0, "IPC$", "IPC",
2554 0, lp_client_signing(), NULL );
2556 if ( !NT_STATUS_IS_OK( ret ) ) {
2557 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2562 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2563 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2564 cli_shutdown(the_cli);
2569 * Ok - we have an anonymous connection to the IPC$ share.
2570 * Now start the NT Domain stuff :-).
2573 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2574 if (!NT_STATUS_IS_OK(ret)) {
2575 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2576 remote_machine, nt_errstr(ret)));
2577 cli_shutdown(the_cli);
2584 /***************************************************************************
2585 Connect to the client.
2586 ****************************************************************************/
2588 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2589 uint32_t localprinter, uint32_t type,
2590 struct policy_handle *handle,
2591 struct sockaddr_storage *client_ss)
2597 * If it's the first connection, contact the client
2598 * and connect to the IPC$ share anonymously
2600 if (smb_connections==0) {
2601 fstring unix_printer;
2603 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2605 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ss, unix_printer ))
2608 messaging_register(smbd_messaging_context(), NULL,
2609 MSG_PRINTER_NOTIFY2,
2610 receive_notify2_message_list);
2611 /* Tell the connections db we're now interested in printer
2612 * notify messages. */
2613 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2617 * Tell the specific printing tdb we want messages for this printer
2618 * by registering our PID.
2621 if (!print_notify_register_pid(snum))
2622 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2626 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2634 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2635 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2636 win_errstr(result)));
2638 return (W_ERROR_IS_OK(result));
2641 /****************************************************************
2642 ****************************************************************/
2644 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2645 const struct spoolss_NotifyOption *r)
2647 struct spoolss_NotifyOption *option;
2654 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2661 if (!option->count) {
2665 option->types = talloc_zero_array(option,
2666 struct spoolss_NotifyOptionType, option->count);
2667 if (!option->types) {
2668 talloc_free(option);
2672 for (i=0; i < option->count; i++) {
2673 option->types[i] = r->types[i];
2675 if (option->types[i].count) {
2676 option->types[i].fields = talloc_zero_array(option,
2677 union spoolss_Field, option->types[i].count);
2678 if (!option->types[i].fields) {
2679 talloc_free(option);
2682 for (k=0; k<option->types[i].count; k++) {
2683 option->types[i].fields[k] =
2684 r->types[i].fields[k];
2692 /****************************************************************
2693 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2695 * before replying OK: status=0 a rpc call is made to the workstation
2696 * asking ReplyOpenPrinter
2698 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2699 * called from api_spoolss_rffpcnex
2700 ****************************************************************/
2702 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2703 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2706 struct spoolss_NotifyOption *option = r->in.notify_options;
2707 struct sockaddr_storage client_ss;
2709 /* store the notify value in the printer struct */
2711 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2714 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2715 "Invalid handle (%s:%u:%u).\n",
2716 OUR_HANDLE(r->in.handle)));
2720 Printer->notify.flags = r->in.flags;
2721 Printer->notify.options = r->in.options;
2722 Printer->notify.printerlocal = r->in.printer_local;
2724 TALLOC_FREE(Printer->notify.option);
2725 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2727 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2729 /* Connect to the client machine and send a ReplyOpenPrinter */
2731 if ( Printer->printer_type == SPLHND_SERVER)
2733 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2734 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2737 if (!interpret_string_addr(&client_ss, p->client_address,
2739 return WERR_SERVER_UNAVAILABLE;
2742 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2743 Printer->notify.printerlocal, 1,
2744 &Printer->notify.client_hnd, &client_ss))
2745 return WERR_SERVER_UNAVAILABLE;
2747 Printer->notify.client_connected = true;
2752 /*******************************************************************
2753 * fill a notify_info_data with the servername
2754 ********************************************************************/
2756 void spoolss_notify_server_name(int snum,
2757 struct spoolss_Notify *data,
2758 print_queue_struct *queue,
2759 NT_PRINTER_INFO_LEVEL *printer,
2760 TALLOC_CTX *mem_ctx)
2762 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2765 /*******************************************************************
2766 * fill a notify_info_data with the printername (not including the servername).
2767 ********************************************************************/
2769 void spoolss_notify_printer_name(int snum,
2770 struct spoolss_Notify *data,
2771 print_queue_struct *queue,
2772 NT_PRINTER_INFO_LEVEL *printer,
2773 TALLOC_CTX *mem_ctx)
2775 /* the notify name should not contain the \\server\ part */
2776 char *p = strrchr(printer->info_2->printername, '\\');
2779 p = printer->info_2->printername;
2784 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2787 /*******************************************************************
2788 * fill a notify_info_data with the servicename
2789 ********************************************************************/
2791 void spoolss_notify_share_name(int snum,
2792 struct spoolss_Notify *data,
2793 print_queue_struct *queue,
2794 NT_PRINTER_INFO_LEVEL *printer,
2795 TALLOC_CTX *mem_ctx)
2797 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2800 /*******************************************************************
2801 * fill a notify_info_data with the port name
2802 ********************************************************************/
2804 void spoolss_notify_port_name(int snum,
2805 struct spoolss_Notify *data,
2806 print_queue_struct *queue,
2807 NT_PRINTER_INFO_LEVEL *printer,
2808 TALLOC_CTX *mem_ctx)
2810 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2813 /*******************************************************************
2814 * fill a notify_info_data with the printername
2815 * but it doesn't exist, have to see what to do
2816 ********************************************************************/
2818 void spoolss_notify_driver_name(int snum,
2819 struct spoolss_Notify *data,
2820 print_queue_struct *queue,
2821 NT_PRINTER_INFO_LEVEL *printer,
2822 TALLOC_CTX *mem_ctx)
2824 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2827 /*******************************************************************
2828 * fill a notify_info_data with the comment
2829 ********************************************************************/
2831 void spoolss_notify_comment(int snum,
2832 struct spoolss_Notify *data,
2833 print_queue_struct *queue,
2834 NT_PRINTER_INFO_LEVEL *printer,
2835 TALLOC_CTX *mem_ctx)
2839 if (*printer->info_2->comment == '\0') {
2840 p = lp_comment(snum);
2842 p = printer->info_2->comment;
2845 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2848 /*******************************************************************
2849 * fill a notify_info_data with the comment
2850 * location = "Room 1, floor 2, building 3"
2851 ********************************************************************/
2853 void spoolss_notify_location(int snum,
2854 struct spoolss_Notify *data,
2855 print_queue_struct *queue,
2856 NT_PRINTER_INFO_LEVEL *printer,
2857 TALLOC_CTX *mem_ctx)
2859 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2862 /*******************************************************************
2863 * fill a notify_info_data with the device mode
2864 * jfm:xxxx don't to it for know but that's a real problem !!!
2865 ********************************************************************/
2867 static void spoolss_notify_devmode(int snum,
2868 struct spoolss_Notify *data,
2869 print_queue_struct *queue,
2870 NT_PRINTER_INFO_LEVEL *printer,
2871 TALLOC_CTX *mem_ctx)
2873 /* for a dummy implementation we have to zero the fields */
2874 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2877 /*******************************************************************
2878 * fill a notify_info_data with the separator file name
2879 ********************************************************************/
2881 void spoolss_notify_sepfile(int snum,
2882 struct spoolss_Notify *data,
2883 print_queue_struct *queue,
2884 NT_PRINTER_INFO_LEVEL *printer,
2885 TALLOC_CTX *mem_ctx)
2887 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2890 /*******************************************************************
2891 * fill a notify_info_data with the print processor
2892 * jfm:xxxx return always winprint to indicate we don't do anything to it
2893 ********************************************************************/
2895 void spoolss_notify_print_processor(int snum,
2896 struct spoolss_Notify *data,
2897 print_queue_struct *queue,
2898 NT_PRINTER_INFO_LEVEL *printer,
2899 TALLOC_CTX *mem_ctx)
2901 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2904 /*******************************************************************
2905 * fill a notify_info_data with the print processor options
2906 * jfm:xxxx send an empty string
2907 ********************************************************************/
2909 void spoolss_notify_parameters(int snum,
2910 struct spoolss_Notify *data,
2911 print_queue_struct *queue,
2912 NT_PRINTER_INFO_LEVEL *printer,
2913 TALLOC_CTX *mem_ctx)
2915 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2918 /*******************************************************************
2919 * fill a notify_info_data with the data type
2920 * jfm:xxxx always send RAW as data type
2921 ********************************************************************/
2923 void spoolss_notify_datatype(int snum,
2924 struct spoolss_Notify *data,
2925 print_queue_struct *queue,
2926 NT_PRINTER_INFO_LEVEL *printer,
2927 TALLOC_CTX *mem_ctx)
2929 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2932 /*******************************************************************
2933 * fill a notify_info_data with the security descriptor
2934 * jfm:xxxx send an null pointer to say no security desc
2935 * have to implement security before !
2936 ********************************************************************/
2938 static void spoolss_notify_security_desc(int snum,
2939 struct spoolss_Notify *data,
2940 print_queue_struct *queue,
2941 NT_PRINTER_INFO_LEVEL *printer,
2942 TALLOC_CTX *mem_ctx)
2944 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2945 printer->info_2->secdesc_buf->sd_size,
2946 printer->info_2->secdesc_buf->sd);
2949 /*******************************************************************
2950 * fill a notify_info_data with the attributes
2951 * jfm:xxxx a samba printer is always shared
2952 ********************************************************************/
2954 void spoolss_notify_attributes(int snum,
2955 struct spoolss_Notify *data,
2956 print_queue_struct *queue,
2957 NT_PRINTER_INFO_LEVEL *printer,
2958 TALLOC_CTX *mem_ctx)
2960 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2963 /*******************************************************************
2964 * fill a notify_info_data with the priority
2965 ********************************************************************/
2967 static void spoolss_notify_priority(int snum,
2968 struct spoolss_Notify *data,
2969 print_queue_struct *queue,
2970 NT_PRINTER_INFO_LEVEL *printer,
2971 TALLOC_CTX *mem_ctx)
2973 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2976 /*******************************************************************
2977 * fill a notify_info_data with the default priority
2978 ********************************************************************/
2980 static void spoolss_notify_default_priority(int snum,
2981 struct spoolss_Notify *data,
2982 print_queue_struct *queue,
2983 NT_PRINTER_INFO_LEVEL *printer,
2984 TALLOC_CTX *mem_ctx)
2986 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2989 /*******************************************************************
2990 * fill a notify_info_data with the start time
2991 ********************************************************************/
2993 static void spoolss_notify_start_time(int snum,
2994 struct spoolss_Notify *data,
2995 print_queue_struct *queue,
2996 NT_PRINTER_INFO_LEVEL *printer,
2997 TALLOC_CTX *mem_ctx)
2999 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3002 /*******************************************************************
3003 * fill a notify_info_data with the until time
3004 ********************************************************************/
3006 static void spoolss_notify_until_time(int snum,
3007 struct spoolss_Notify *data,
3008 print_queue_struct *queue,
3009 NT_PRINTER_INFO_LEVEL *printer,
3010 TALLOC_CTX *mem_ctx)
3012 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3015 /*******************************************************************
3016 * fill a notify_info_data with the status
3017 ********************************************************************/
3019 static void spoolss_notify_status(int snum,
3020 struct spoolss_Notify *data,
3021 print_queue_struct *queue,
3022 NT_PRINTER_INFO_LEVEL *printer,
3023 TALLOC_CTX *mem_ctx)
3025 print_status_struct status;
3027 print_queue_length(snum, &status);
3028 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3031 /*******************************************************************
3032 * fill a notify_info_data with the number of jobs queued
3033 ********************************************************************/
3035 void spoolss_notify_cjobs(int snum,
3036 struct spoolss_Notify *data,
3037 print_queue_struct *queue,
3038 NT_PRINTER_INFO_LEVEL *printer,
3039 TALLOC_CTX *mem_ctx)
3041 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3044 /*******************************************************************
3045 * fill a notify_info_data with the average ppm
3046 ********************************************************************/
3048 static void spoolss_notify_average_ppm(int snum,
3049 struct spoolss_Notify *data,
3050 print_queue_struct *queue,
3051 NT_PRINTER_INFO_LEVEL *printer,
3052 TALLOC_CTX *mem_ctx)
3054 /* always respond 8 pages per minutes */
3055 /* a little hard ! */
3056 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3059 /*******************************************************************
3060 * fill a notify_info_data with username
3061 ********************************************************************/
3063 static void spoolss_notify_username(int snum,
3064 struct spoolss_Notify *data,
3065 print_queue_struct *queue,
3066 NT_PRINTER_INFO_LEVEL *printer,
3067 TALLOC_CTX *mem_ctx)
3069 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3072 /*******************************************************************
3073 * fill a notify_info_data with job status
3074 ********************************************************************/
3076 static void spoolss_notify_job_status(int snum,
3077 struct spoolss_Notify *data,
3078 print_queue_struct *queue,
3079 NT_PRINTER_INFO_LEVEL *printer,
3080 TALLOC_CTX *mem_ctx)
3082 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3085 /*******************************************************************
3086 * fill a notify_info_data with job name
3087 ********************************************************************/
3089 static void spoolss_notify_job_name(int snum,
3090 struct spoolss_Notify *data,
3091 print_queue_struct *queue,
3092 NT_PRINTER_INFO_LEVEL *printer,
3093 TALLOC_CTX *mem_ctx)
3095 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3098 /*******************************************************************
3099 * fill a notify_info_data with job status
3100 ********************************************************************/
3102 static void spoolss_notify_job_status_string(int snum,
3103 struct spoolss_Notify *data,
3104 print_queue_struct *queue,
3105 NT_PRINTER_INFO_LEVEL *printer,
3106 TALLOC_CTX *mem_ctx)
3109 * Now we're returning job status codes we just return a "" here. JRA.
3114 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3117 switch (queue->status) {
3122 p = ""; /* NT provides the paused string */
3131 #endif /* NO LONGER NEEDED. */
3133 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3136 /*******************************************************************
3137 * fill a notify_info_data with job time
3138 ********************************************************************/
3140 static void spoolss_notify_job_time(int snum,
3141 struct spoolss_Notify *data,
3142 print_queue_struct *queue,
3143 NT_PRINTER_INFO_LEVEL *printer,
3144 TALLOC_CTX *mem_ctx)
3146 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3149 /*******************************************************************
3150 * fill a notify_info_data with job size
3151 ********************************************************************/
3153 static void spoolss_notify_job_size(int snum,
3154 struct spoolss_Notify *data,
3155 print_queue_struct *queue,
3156 NT_PRINTER_INFO_LEVEL *printer,
3157 TALLOC_CTX *mem_ctx)
3159 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3162 /*******************************************************************
3163 * fill a notify_info_data with page info
3164 ********************************************************************/
3165 static void spoolss_notify_total_pages(int snum,
3166 struct spoolss_Notify *data,
3167 print_queue_struct *queue,
3168 NT_PRINTER_INFO_LEVEL *printer,
3169 TALLOC_CTX *mem_ctx)
3171 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3174 /*******************************************************************
3175 * fill a notify_info_data with pages printed info.
3176 ********************************************************************/
3177 static void spoolss_notify_pages_printed(int snum,
3178 struct spoolss_Notify *data,
3179 print_queue_struct *queue,
3180 NT_PRINTER_INFO_LEVEL *printer,
3181 TALLOC_CTX *mem_ctx)
3183 /* Add code when back-end tracks this */
3184 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3187 /*******************************************************************
3188 Fill a notify_info_data with job position.
3189 ********************************************************************/
3191 static void spoolss_notify_job_position(int snum,
3192 struct spoolss_Notify *data,
3193 print_queue_struct *queue,
3194 NT_PRINTER_INFO_LEVEL *printer,
3195 TALLOC_CTX *mem_ctx)
3197 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3200 /*******************************************************************
3201 Fill a notify_info_data with submitted time.
3202 ********************************************************************/
3204 static void spoolss_notify_submitted_time(int snum,
3205 struct spoolss_Notify *data,
3206 print_queue_struct *queue,
3207 NT_PRINTER_INFO_LEVEL *printer,
3208 TALLOC_CTX *mem_ctx)
3210 data->data.string.string = NULL;
3211 data->data.string.size = 0;
3213 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3214 &data->data.string.string,
3215 &data->data.string.size);
3219 struct s_notify_info_data_table
3221 enum spoolss_NotifyType type;
3224 enum spoolss_NotifyTable variable_type;
3225 void (*fn) (int snum, struct spoolss_Notify *data,
3226 print_queue_struct *queue,
3227 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3230 /* A table describing the various print notification constants and
3231 whether the notification data is a pointer to a variable sized
3232 buffer, a one value uint32_t or a two value uint32_t. */
3234 static const struct s_notify_info_data_table notify_info_data_table[] =
3236 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3237 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3238 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3239 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3240 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3241 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3242 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3243 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3244 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3245 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3246 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3247 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3248 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3249 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3250 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3251 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3252 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3253 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3254 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3262 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3263 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3264 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3265 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3266 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3267 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3268 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3269 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3270 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3271 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3272 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3273 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3274 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3275 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3276 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3277 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3278 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3279 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3280 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3281 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3282 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3283 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3284 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3287 /*******************************************************************
3288 Return the variable_type of info_data structure.
3289 ********************************************************************/
3291 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3296 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3297 if ( (notify_info_data_table[i].type == type) &&
3298 (notify_info_data_table[i].field == field) ) {
3299 return notify_info_data_table[i].variable_type;
3303 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3308 /****************************************************************************
3309 ****************************************************************************/
3311 static bool search_notify(enum spoolss_NotifyType type,
3317 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3318 if (notify_info_data_table[i].type == type &&
3319 notify_info_data_table[i].field == field &&
3320 notify_info_data_table[i].fn != NULL) {
3329 /****************************************************************************
3330 ****************************************************************************/
3332 void construct_info_data(struct spoolss_Notify *info_data,
3333 enum spoolss_NotifyType type,
3337 info_data->type = type;
3338 info_data->field.field = field;
3339 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3340 info_data->job_id = id;
3343 /*******************************************************************
3345 * fill a notify_info struct with info asked
3347 ********************************************************************/
3349 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3350 struct spoolss_NotifyInfo *info,
3352 const struct spoolss_NotifyOptionType *option_type,
3354 TALLOC_CTX *mem_ctx)
3357 enum spoolss_NotifyType type;
3360 struct spoolss_Notify *current_data;
3361 NT_PRINTER_INFO_LEVEL *printer = NULL;
3362 print_queue_struct *queue=NULL;
3364 type = option_type->type;
3366 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3367 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3368 option_type->count, lp_servicename(snum)));
3370 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3373 for(field_num=0; field_num < option_type->count; field_num++) {
3374 field = option_type->fields[field_num].field;
3376 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3378 if (!search_notify(type, field, &j) )
3381 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3382 struct spoolss_Notify,
3384 if (info->notifies == NULL) {
3385 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3386 free_a_printer(&printer, 2);
3390 current_data = &info->notifies[info->count];
3392 construct_info_data(current_data, type, field, id);
3394 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3395 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3397 notify_info_data_table[j].fn(snum, current_data, queue,
3403 free_a_printer(&printer, 2);
3407 /*******************************************************************
3409 * fill a notify_info struct with info asked
3411 ********************************************************************/
3413 static bool construct_notify_jobs_info(print_queue_struct *queue,
3414 struct spoolss_NotifyInfo *info,
3415 NT_PRINTER_INFO_LEVEL *printer,
3417 const struct spoolss_NotifyOptionType *option_type,
3419 TALLOC_CTX *mem_ctx)
3422 enum spoolss_NotifyType type;
3424 struct spoolss_Notify *current_data;
3426 DEBUG(4,("construct_notify_jobs_info\n"));
3428 type = option_type->type;
3430 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3431 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3432 option_type->count));
3434 for(field_num=0; field_num<option_type->count; field_num++) {
3435 field = option_type->fields[field_num].field;
3437 if (!search_notify(type, field, &j) )
3440 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3441 struct spoolss_Notify,
3443 if (info->notifies == NULL) {
3444 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3448 current_data=&(info->notifies[info->count]);
3450 construct_info_data(current_data, type, field, id);
3451 notify_info_data_table[j].fn(snum, current_data, queue,
3460 * JFM: The enumeration is not that simple, it's even non obvious.
3462 * let's take an example: I want to monitor the PRINTER SERVER for
3463 * the printer's name and the number of jobs currently queued.
3464 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3465 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3467 * I have 3 printers on the back of my server.
3469 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3472 * 1 printer 1 name 1
3473 * 2 printer 1 cjob 1
3474 * 3 printer 2 name 2
3475 * 4 printer 2 cjob 2
3476 * 5 printer 3 name 3
3477 * 6 printer 3 name 3
3479 * that's the print server case, the printer case is even worse.
3482 /*******************************************************************
3484 * enumerate all printers on the printserver
3485 * fill a notify_info struct with info asked
3487 ********************************************************************/
3489 static WERROR printserver_notify_info(pipes_struct *p,
3490 struct policy_handle *hnd,
3491 struct spoolss_NotifyInfo *info,
3492 TALLOC_CTX *mem_ctx)
3495 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3496 int n_services=lp_numservices();
3498 struct spoolss_NotifyOption *option;
3499 struct spoolss_NotifyOptionType option_type;
3501 DEBUG(4,("printserver_notify_info\n"));
3506 option = Printer->notify.option;
3509 info->notifies = NULL;
3512 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3513 sending a ffpcn() request first */
3518 for (i=0; i<option->count; i++) {
3519 option_type = option->types[i];
3521 if (option_type.type != PRINTER_NOTIFY_TYPE)
3524 for (snum=0; snum<n_services; snum++)
3526 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3527 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3533 * Debugging information, don't delete.
3536 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3537 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3538 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3540 for (i=0; i<info->count; i++) {
3541 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3542 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3543 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3550 /*******************************************************************
3552 * fill a notify_info struct with info asked
3554 ********************************************************************/
3556 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3557 struct spoolss_NotifyInfo *info,
3558 TALLOC_CTX *mem_ctx)
3561 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3564 struct spoolss_NotifyOption *option;
3565 struct spoolss_NotifyOptionType option_type;
3567 print_queue_struct *queue=NULL;
3568 print_status_struct status;
3570 DEBUG(4,("printer_notify_info\n"));
3575 option = Printer->notify.option;
3579 info->notifies = NULL;
3582 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3583 sending a ffpcn() request first */
3588 get_printer_snum(p, hnd, &snum, NULL);
3590 for (i=0; i<option->count; i++) {
3591 option_type = option->types[i];
3593 switch (option_type.type) {
3594 case PRINTER_NOTIFY_TYPE:
3595 if(construct_notify_printer_info(Printer, info, snum,
3601 case JOB_NOTIFY_TYPE: {
3602 NT_PRINTER_INFO_LEVEL *printer = NULL;
3604 count = print_queue_status(snum, &queue, &status);
3606 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3609 for (j=0; j<count; j++) {
3610 construct_notify_jobs_info(&queue[j], info,
3617 free_a_printer(&printer, 2);
3627 * Debugging information, don't delete.
3630 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3631 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3632 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3634 for (i=0; i<info->count; i++) {
3635 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3636 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3637 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3643 /****************************************************************
3644 _spoolss_RouterRefreshPrinterChangeNotify
3645 ****************************************************************/
3647 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3648 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3650 struct spoolss_NotifyInfo *info;
3652 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3653 WERROR result = WERR_BADFID;
3655 /* we always have a spoolss_NotifyInfo struct */
3656 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3658 result = WERR_NOMEM;
3662 *r->out.info = info;
3665 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3666 "Invalid handle (%s:%u:%u).\n",
3667 OUR_HANDLE(r->in.handle)));
3671 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3674 * We are now using the change value, and
3675 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3676 * I don't have a global notification system, I'm sending back all the
3677 * informations even when _NOTHING_ has changed.
3680 /* We need to keep track of the change value to send back in
3681 RRPCN replies otherwise our updates are ignored. */
3683 Printer->notify.fnpcn = true;
3685 if (Printer->notify.client_connected) {
3686 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3687 "Saving change value in request [%x]\n",
3689 Printer->notify.change = r->in.change_low;
3692 /* just ignore the spoolss_NotifyOption */
3694 switch (Printer->printer_type) {
3696 result = printserver_notify_info(p, r->in.handle,
3700 case SPLHND_PRINTER:
3701 result = printer_notify_info(p, r->in.handle,
3706 Printer->notify.fnpcn = false;
3712 /********************************************************************
3713 * construct_printer_info_0
3714 * fill a printer_info_0 struct
3715 ********************************************************************/
3717 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3718 const NT_PRINTER_INFO_LEVEL *ntprinter,
3719 struct spoolss_PrinterInfo0 *r,
3723 counter_printer_0 *session_counter;
3725 print_status_struct status;
3727 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3728 W_ERROR_HAVE_NO_MEMORY(r->printername);
3730 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3731 W_ERROR_HAVE_NO_MEMORY(r->servername);
3733 count = print_queue_length(snum, &status);
3735 /* check if we already have a counter for this printer */
3736 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3737 if (session_counter->snum == snum)
3741 /* it's the first time, add it to the list */
3742 if (session_counter == NULL) {
3743 session_counter = SMB_MALLOC_P(counter_printer_0);
3744 W_ERROR_HAVE_NO_MEMORY(session_counter);
3745 ZERO_STRUCTP(session_counter);
3746 session_counter->snum = snum;
3747 session_counter->counter = 0;
3748 DLIST_ADD(counter_list, session_counter);
3752 session_counter->counter++;
3758 setuptime = (time_t)ntprinter->info_2->setuptime;
3760 init_systemtime(&r->time, gmtime(&setuptime));
3763 * the global_counter should be stored in a TDB as it's common to all the clients
3764 * and should be zeroed on samba startup
3766 r->global_counter = session_counter->counter;
3768 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3769 r->version = 0x0005; /* NT 5 */
3770 r->free_build = 0x0893; /* build 2195 */
3772 r->max_spooling = 0;
3773 r->session_counter = session_counter->counter;
3774 r->num_error_out_of_paper = 0x0;
3775 r->num_error_not_ready = 0x0; /* number of print failure */
3777 r->number_of_processors = 0x1;
3778 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3779 r->high_part_total_bytes = 0x0;
3780 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3781 r->last_error = WERR_OK;
3782 r->status = nt_printq_status(status.status);
3783 r->enumerate_network_printers = 0x0;
3784 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3785 r->processor_architecture = 0x0;
3786 r->processor_level = 0x6; /* 6 ???*/
3794 /****************************************************************************
3795 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3796 should be valid upon entry
3797 ****************************************************************************/
3799 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3800 struct spoolss_DeviceMode *r,
3801 const NT_DEVICEMODE *ntdevmode)
3803 if (!r || !ntdevmode) {
3804 return WERR_INVALID_PARAM;
3807 r->devicename = talloc_strdup(mem_ctx, ntdevmode->devicename);
3808 W_ERROR_HAVE_NO_MEMORY(r->devicename);
3810 r->specversion = ntdevmode->specversion;
3811 r->driverversion = ntdevmode->driverversion;
3812 r->size = ntdevmode->size;
3813 r->__driverextra_length = ntdevmode->driverextra;
3814 r->fields = ntdevmode->fields;
3816 r->orientation = ntdevmode->orientation;
3817 r->papersize = ntdevmode->papersize;
3818 r->paperlength = ntdevmode->paperlength;
3819 r->paperwidth = ntdevmode->paperwidth;
3820 r->scale = ntdevmode->scale;
3821 r->copies = ntdevmode->copies;
3822 r->defaultsource = ntdevmode->defaultsource;
3823 r->printquality = ntdevmode->printquality;
3824 r->color = ntdevmode->color;
3825 r->duplex = ntdevmode->duplex;
3826 r->yresolution = ntdevmode->yresolution;
3827 r->ttoption = ntdevmode->ttoption;
3828 r->collate = ntdevmode->collate;
3830 r->formname = talloc_strdup(mem_ctx, ntdevmode->formname);
3831 W_ERROR_HAVE_NO_MEMORY(r->formname);
3833 /* all 0 below are values that have not been set in the old parsing/copy
3834 * function, maybe they should... - gd */
3840 r->displayflags = 0;
3841 r->displayfrequency = 0;
3842 r->icmmethod = ntdevmode->icmmethod;
3843 r->icmintent = ntdevmode->icmintent;
3844 r->mediatype = ntdevmode->mediatype;
3845 r->dithertype = ntdevmode->dithertype;
3848 r->panningwidth = 0;
3849 r->panningheight = 0;
3851 if (ntdevmode->nt_dev_private != NULL) {
3852 r->driverextra_data = data_blob_talloc(mem_ctx,
3853 ntdevmode->nt_dev_private,
3854 ntdevmode->driverextra);
3855 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3862 /****************************************************************************
3863 Create a spoolss_DeviceMode struct. Returns talloced memory.
3864 ****************************************************************************/
3866 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3867 const char *servicename)
3870 NT_PRINTER_INFO_LEVEL *printer = NULL;
3871 struct spoolss_DeviceMode *devmode = NULL;
3873 DEBUG(7,("construct_dev_mode\n"));
3875 DEBUGADD(8,("getting printer characteristics\n"));
3877 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3880 if (!printer->info_2->devmode) {
3881 DEBUG(5, ("BONG! There was no device mode!\n"));
3885 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3887 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3891 DEBUGADD(8,("loading DEVICEMODE\n"));
3893 result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3894 if (!W_ERROR_IS_OK(result)) {
3895 TALLOC_FREE(devmode);
3899 free_a_printer(&printer,2);
3904 /********************************************************************
3905 * construct_printer_info3
3906 * fill a spoolss_PrinterInfo3 struct
3907 ********************************************************************/
3909 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3910 const NT_PRINTER_INFO_LEVEL *ntprinter,
3911 struct spoolss_PrinterInfo3 *r,
3914 /* These are the components of the SD we are returning. */
3916 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3917 /* don't use talloc_steal() here unless you do a deep steal of all
3918 the SEC_DESC members */
3920 r->secdesc = dup_sec_desc(mem_ctx,
3921 ntprinter->info_2->secdesc_buf->sd);
3922 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3928 /********************************************************************
3929 * construct_printer_info4
3930 * fill a spoolss_PrinterInfo4 struct
3931 ********************************************************************/
3933 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3934 const NT_PRINTER_INFO_LEVEL *ntprinter,
3935 struct spoolss_PrinterInfo4 *r,
3938 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3939 W_ERROR_HAVE_NO_MEMORY(r->printername);
3940 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3941 W_ERROR_HAVE_NO_MEMORY(r->servername);
3943 r->attributes = ntprinter->info_2->attributes;
3948 /********************************************************************
3949 * construct_printer_info5
3950 * fill a spoolss_PrinterInfo5 struct
3951 ********************************************************************/
3953 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3954 const NT_PRINTER_INFO_LEVEL *ntprinter,
3955 struct spoolss_PrinterInfo5 *r,
3958 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3959 W_ERROR_HAVE_NO_MEMORY(r->printername);
3960 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3961 W_ERROR_HAVE_NO_MEMORY(r->portname);
3963 r->attributes = ntprinter->info_2->attributes;
3965 /* these two are not used by NT+ according to MSDN */
3967 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
3968 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
3973 /********************************************************************
3974 * construct_printer_info_6
3975 * fill a spoolss_PrinterInfo6 struct
3976 ********************************************************************/
3978 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3979 const NT_PRINTER_INFO_LEVEL *ntprinter,
3980 struct spoolss_PrinterInfo6 *r,
3984 print_status_struct status;
3986 count = print_queue_length(snum, &status);
3988 r->status = nt_printq_status(status.status);
3993 /********************************************************************
3994 * construct_printer_info7
3995 * fill a spoolss_PrinterInfo7 struct
3996 ********************************************************************/
3998 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3999 Printer_entry *print_hnd,
4000 struct spoolss_PrinterInfo7 *r,
4005 if (is_printer_published(print_hnd, snum, &guid)) {
4006 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4007 r->action = DSPRINT_PUBLISH;
4009 r->guid = talloc_strdup(mem_ctx, "");
4010 r->action = DSPRINT_UNPUBLISH;
4012 W_ERROR_HAVE_NO_MEMORY(r->guid);
4017 /********************************************************************
4018 * construct_printer_info8
4019 * fill a spoolss_PrinterInfo8 struct
4020 ********************************************************************/
4022 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4023 const NT_PRINTER_INFO_LEVEL *ntprinter,
4024 struct spoolss_DeviceModeInfo *r,
4027 struct spoolss_DeviceMode *devmode;
4030 if (!ntprinter->info_2->devmode) {
4035 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
4036 W_ERROR_HAVE_NO_MEMORY(devmode);
4038 result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
4039 if (!W_ERROR_IS_OK(result)) {
4040 TALLOC_FREE(devmode);
4044 r->devmode = devmode;
4050 /********************************************************************
4051 * construct_printer_info1
4052 * fill a spoolss_PrinterInfo1 struct
4053 ********************************************************************/
4055 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4056 const NT_PRINTER_INFO_LEVEL *ntprinter,
4058 struct spoolss_PrinterInfo1 *r,
4063 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
4064 ntprinter->info_2->printername,
4065 ntprinter->info_2->drivername,
4066 ntprinter->info_2->location);
4067 W_ERROR_HAVE_NO_MEMORY(r->description);
4069 if (*ntprinter->info_2->comment == '\0') {
4070 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4072 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4074 W_ERROR_HAVE_NO_MEMORY(r->comment);
4076 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4077 W_ERROR_HAVE_NO_MEMORY(r->name);
4082 /********************************************************************
4083 * construct_printer_info2
4084 * fill a spoolss_PrinterInfo2 struct
4085 ********************************************************************/
4087 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4088 const NT_PRINTER_INFO_LEVEL *ntprinter,
4089 struct spoolss_PrinterInfo2 *r,
4094 print_status_struct status;
4096 count = print_queue_length(snum, &status);
4098 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4099 W_ERROR_HAVE_NO_MEMORY(r->servername);
4100 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4101 W_ERROR_HAVE_NO_MEMORY(r->printername);
4102 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4103 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4104 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4105 W_ERROR_HAVE_NO_MEMORY(r->portname);
4106 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4107 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4109 if (*ntprinter->info_2->comment == '\0') {
4110 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4112 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4114 W_ERROR_HAVE_NO_MEMORY(r->comment);
4116 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4117 W_ERROR_HAVE_NO_MEMORY(r->location);
4118 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4119 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4120 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4121 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4122 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4123 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4124 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4125 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4127 r->attributes = ntprinter->info_2->attributes;
4129 r->priority = ntprinter->info_2->priority;
4130 r->defaultpriority = ntprinter->info_2->default_priority;
4131 r->starttime = ntprinter->info_2->starttime;
4132 r->untiltime = ntprinter->info_2->untiltime;
4133 r->status = nt_printq_status(status.status);
4135 r->averageppm = ntprinter->info_2->averageppm;
4137 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
4139 DEBUG(8,("Returning NULL Devicemode!\n"));
4144 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4145 /* don't use talloc_steal() here unless you do a deep steal of all
4146 the SEC_DESC members */
4148 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4154 /********************************************************************
4155 ********************************************************************/
4157 static bool snum_is_shared_printer(int snum)
4159 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4162 /********************************************************************
4163 Spoolss_enumprinters.
4164 ********************************************************************/
4166 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4169 union spoolss_PrinterInfo **info_p,
4173 int n_services = lp_numservices();
4174 union spoolss_PrinterInfo *info = NULL;
4176 WERROR result = WERR_OK;
4181 for (snum = 0; snum < n_services; snum++) {
4183 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4185 if (!snum_is_shared_printer(snum)) {
4189 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4190 lp_servicename(snum), snum));
4192 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4193 union spoolss_PrinterInfo,
4196 result = WERR_NOMEM;
4200 result = get_a_printer(NULL, &ntprinter, 2,
4201 lp_const_servicename(snum));
4202 if (!W_ERROR_IS_OK(result)) {
4208 result = construct_printer_info0(info, ntprinter,
4209 &info[count].info0, snum);
4212 result = construct_printer_info1(info, ntprinter, flags,
4213 &info[count].info1, snum);
4216 result = construct_printer_info2(info, ntprinter,
4217 &info[count].info2, snum);
4220 result = construct_printer_info4(info, ntprinter,
4221 &info[count].info4, snum);
4224 result = construct_printer_info5(info, ntprinter,
4225 &info[count].info5, snum);
4229 result = WERR_UNKNOWN_LEVEL;
4230 free_a_printer(&ntprinter, 2);
4234 free_a_printer(&ntprinter, 2);
4235 if (!W_ERROR_IS_OK(result)) {
4246 if (!W_ERROR_IS_OK(result)) {
4256 /********************************************************************
4257 * handle enumeration of printers at level 0
4258 ********************************************************************/
4260 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4262 const char *servername,
4263 union spoolss_PrinterInfo **info,
4266 DEBUG(4,("enum_all_printers_info_0\n"));
4268 return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4272 /********************************************************************
4273 ********************************************************************/
4275 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4277 union spoolss_PrinterInfo **info,
4280 DEBUG(4,("enum_all_printers_info_1\n"));
4282 return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4285 /********************************************************************
4286 enum_all_printers_info_1_local.
4287 *********************************************************************/
4289 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4290 union spoolss_PrinterInfo **info,
4293 DEBUG(4,("enum_all_printers_info_1_local\n"));
4295 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4298 /********************************************************************
4299 enum_all_printers_info_1_name.
4300 *********************************************************************/
4302 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4304 union spoolss_PrinterInfo **info,
4307 const char *s = name;
4309 DEBUG(4,("enum_all_printers_info_1_name\n"));
4311 if ((name[0] == '\\') && (name[1] == '\\')) {
4315 if (!is_myname_or_ipaddr(s)) {
4316 return WERR_INVALID_NAME;
4319 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4322 /********************************************************************
4323 enum_all_printers_info_1_network.
4324 *********************************************************************/
4326 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4328 union spoolss_PrinterInfo **info,
4331 const char *s = name;
4333 DEBUG(4,("enum_all_printers_info_1_network\n"));
4335 /* If we respond to a enum_printers level 1 on our name with flags
4336 set to PRINTER_ENUM_REMOTE with a list of printers then these
4337 printers incorrectly appear in the APW browse list.
4338 Specifically the printers for the server appear at the workgroup
4339 level where all the other servers in the domain are
4340 listed. Windows responds to this call with a
4341 WERR_CAN_NOT_COMPLETE so we should do the same. */
4343 if (name[0] == '\\' && name[1] == '\\') {
4347 if (is_myname_or_ipaddr(s)) {
4348 return WERR_CAN_NOT_COMPLETE;
4351 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4354 /********************************************************************
4355 * api_spoolss_enumprinters
4357 * called from api_spoolss_enumprinters (see this to understand)
4358 ********************************************************************/
4360 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4361 union spoolss_PrinterInfo **info,
4364 DEBUG(4,("enum_all_printers_info_2\n"));
4366 return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4369 /********************************************************************
4370 * handle enumeration of printers at level 1
4371 ********************************************************************/
4373 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4376 union spoolss_PrinterInfo **info,
4379 /* Not all the flags are equals */
4381 if (flags & PRINTER_ENUM_LOCAL) {
4382 return enum_all_printers_info_1_local(mem_ctx, info, count);
4385 if (flags & PRINTER_ENUM_NAME) {
4386 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4389 if (flags & PRINTER_ENUM_NETWORK) {
4390 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4393 return WERR_OK; /* NT4sp5 does that */
4396 /********************************************************************
4397 * handle enumeration of printers at level 2
4398 ********************************************************************/
4400 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4402 const char *servername,
4403 union spoolss_PrinterInfo **info,
4406 if (flags & PRINTER_ENUM_LOCAL) {
4407 return enum_all_printers_info_2(mem_ctx, info, count);
4410 if (flags & PRINTER_ENUM_NAME) {
4411 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4412 return WERR_INVALID_NAME;
4415 return enum_all_printers_info_2(mem_ctx, info, count);
4418 if (flags & PRINTER_ENUM_REMOTE) {
4419 return WERR_UNKNOWN_LEVEL;
4425 /********************************************************************
4426 * handle enumeration of printers at level 4
4427 ********************************************************************/
4429 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4431 const char *servername,
4432 union spoolss_PrinterInfo **info,
4435 DEBUG(4,("enum_all_printers_info_4\n"));
4437 return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4441 /********************************************************************
4442 * handle enumeration of printers at level 5
4443 ********************************************************************/
4445 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4447 const char *servername,
4448 union spoolss_PrinterInfo **info,
4451 DEBUG(4,("enum_all_printers_info_5\n"));
4453 return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4456 /****************************************************************
4457 _spoolss_EnumPrinters
4458 ****************************************************************/
4460 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4461 struct spoolss_EnumPrinters *r)
4463 const char *name = NULL;
4466 /* that's an [in out] buffer */
4468 if (!r->in.buffer && (r->in.offered != 0)) {
4469 return WERR_INVALID_PARAM;
4472 DEBUG(4,("_spoolss_EnumPrinters\n"));
4476 *r->out.info = NULL;
4480 * flags==PRINTER_ENUM_NAME
4481 * if name=="" then enumerates all printers
4482 * if name!="" then enumerate the printer
4483 * flags==PRINTER_ENUM_REMOTE
4484 * name is NULL, enumerate printers
4485 * Level 2: name!="" enumerates printers, name can't be NULL
4486 * Level 3: doesn't exist
4487 * Level 4: does a local registry lookup
4488 * Level 5: same as Level 2
4492 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4493 W_ERROR_HAVE_NO_MEMORY(name);
4496 switch (r->in.level) {
4498 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4499 r->out.info, r->out.count);
4502 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4503 r->out.info, r->out.count);
4506 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4507 r->out.info, r->out.count);
4510 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4511 r->out.info, r->out.count);
4514 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4515 r->out.info, r->out.count);
4518 return WERR_UNKNOWN_LEVEL;
4521 if (!W_ERROR_IS_OK(result)) {
4525 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4526 spoolss_EnumPrinters, NULL,
4527 *r->out.info, r->in.level,
4529 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4530 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4532 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4535 /****************************************************************
4537 ****************************************************************/
4539 WERROR _spoolss_GetPrinter(pipes_struct *p,
4540 struct spoolss_GetPrinter *r)
4542 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4543 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4544 WERROR result = WERR_OK;
4548 /* that's an [in out] buffer */
4550 if (!r->in.buffer && (r->in.offered != 0)) {
4551 return WERR_INVALID_PARAM;
4556 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4560 result = get_a_printer(Printer, &ntprinter, 2,
4561 lp_const_servicename(snum));
4562 if (!W_ERROR_IS_OK(result)) {
4566 switch (r->in.level) {
4568 result = construct_printer_info0(p->mem_ctx, ntprinter,
4569 &r->out.info->info0, snum);
4572 result = construct_printer_info1(p->mem_ctx, ntprinter,
4574 &r->out.info->info1, snum);
4577 result = construct_printer_info2(p->mem_ctx, ntprinter,
4578 &r->out.info->info2, snum);
4581 result = construct_printer_info3(p->mem_ctx, ntprinter,
4582 &r->out.info->info3, snum);
4585 result = construct_printer_info4(p->mem_ctx, ntprinter,
4586 &r->out.info->info4, snum);
4589 result = construct_printer_info5(p->mem_ctx, ntprinter,
4590 &r->out.info->info5, snum);
4593 result = construct_printer_info6(p->mem_ctx, ntprinter,
4594 &r->out.info->info6, snum);
4597 result = construct_printer_info7(p->mem_ctx, Printer,
4598 &r->out.info->info7, snum);
4601 result = construct_printer_info8(p->mem_ctx, ntprinter,
4602 &r->out.info->info8, snum);
4605 result = WERR_UNKNOWN_LEVEL;
4609 free_a_printer(&ntprinter, 2);
4611 if (!W_ERROR_IS_OK(result)) {
4612 TALLOC_FREE(r->out.info);
4616 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4617 r->out.info, r->in.level);
4618 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4620 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4623 /********************************************************************
4624 ********************************************************************/
4626 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4627 fstring *fstring_array,
4628 const char *cservername)
4630 int i, num_strings = 0;
4631 const char **array = NULL;
4633 for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4635 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4636 cservername, fstring_array[i]);
4643 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4650 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4651 &array, &num_strings);
4657 /********************************************************************
4658 * fill a spoolss_DriverInfo1 struct
4659 ********************************************************************/
4661 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4662 struct spoolss_DriverInfo1 *r,
4663 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4664 const char *servername,
4665 const char *architecture)
4667 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4668 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4673 /********************************************************************
4674 * fill a spoolss_DriverInfo2 struct
4675 ********************************************************************/
4677 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4678 struct spoolss_DriverInfo2 *r,
4679 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4680 const char *servername)
4683 const char *cservername = canon_servername(servername);
4685 r->version = driver->info_3->cversion;
4687 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4688 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4689 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4690 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4692 if (strlen(driver->info_3->driverpath)) {
4693 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4694 cservername, driver->info_3->driverpath);
4696 r->driver_path = talloc_strdup(mem_ctx, "");
4698 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4700 if (strlen(driver->info_3->datafile)) {
4701 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4702 cservername, driver->info_3->datafile);
4704 r->data_file = talloc_strdup(mem_ctx, "");
4706 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4708 if (strlen(driver->info_3->configfile)) {
4709 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4710 cservername, driver->info_3->configfile);
4712 r->config_file = talloc_strdup(mem_ctx, "");
4714 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4719 /********************************************************************
4720 * fill a spoolss_DriverInfo3 struct
4721 ********************************************************************/
4723 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4724 struct spoolss_DriverInfo3 *r,
4725 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4726 const char *servername)
4728 const char *cservername = canon_servername(servername);
4730 r->version = driver->info_3->cversion;
4732 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4733 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4734 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4735 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4737 if (strlen(driver->info_3->driverpath)) {
4738 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4739 cservername, driver->info_3->driverpath);
4741 r->driver_path = talloc_strdup(mem_ctx, "");
4743 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4745 if (strlen(driver->info_3->datafile)) {
4746 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4747 cservername, driver->info_3->datafile);
4749 r->data_file = talloc_strdup(mem_ctx, "");
4751 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4753 if (strlen(driver->info_3->configfile)) {
4754 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4755 cservername, driver->info_3->configfile);
4757 r->config_file = talloc_strdup(mem_ctx, "");
4759 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4761 if (strlen(driver->info_3->helpfile)) {
4762 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4763 cservername, driver->info_3->helpfile);
4765 r->help_file = talloc_strdup(mem_ctx, "");
4767 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4769 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4770 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4771 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4772 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4774 r->dependent_files = string_array_from_driver_info(mem_ctx,
4775 driver->info_3->dependentfiles,
4780 /********************************************************************
4781 * fill a spoolss_DriverInfo4 struct
4782 ********************************************************************/
4784 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4785 struct spoolss_DriverInfo4 *r,
4786 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4787 const char *servername)
4789 const char *cservername = canon_servername(servername);
4791 r->version = driver->info_3->cversion;
4793 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4794 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4795 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4796 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4798 if (strlen(driver->info_3->driverpath)) {
4799 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4800 cservername, driver->info_3->driverpath);
4802 r->driver_path = talloc_strdup(mem_ctx, "");
4804 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4806 if (strlen(driver->info_3->datafile)) {
4807 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4808 cservername, driver->info_3->datafile);
4810 r->data_file = talloc_strdup(mem_ctx, "");
4812 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4814 if (strlen(driver->info_3->configfile)) {
4815 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4816 cservername, driver->info_3->configfile);
4818 r->config_file = talloc_strdup(mem_ctx, "");
4820 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4822 if (strlen(driver->info_3->helpfile)) {
4823 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4824 cservername, driver->info_3->helpfile);
4826 r->help_file = talloc_strdup(mem_ctx, "");
4828 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4830 r->dependent_files = string_array_from_driver_info(mem_ctx,
4831 driver->info_3->dependentfiles,
4835 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4836 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4837 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4838 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4840 r->previous_names = string_array_from_driver_info(mem_ctx,
4847 /********************************************************************
4848 * fill a spoolss_DriverInfo5 struct
4849 ********************************************************************/
4851 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4852 struct spoolss_DriverInfo5 *r,
4853 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4854 const char *servername)
4856 const char *cservername = canon_servername(servername);
4858 r->version = driver->info_3->cversion;
4860 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4861 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4862 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4863 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4865 if (strlen(driver->info_3->driverpath)) {
4866 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4867 cservername, driver->info_3->driverpath);
4869 r->driver_path = talloc_strdup(mem_ctx, "");
4871 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4873 if (strlen(driver->info_3->datafile)) {
4874 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4875 cservername, driver->info_3->datafile);
4877 r->data_file = talloc_strdup(mem_ctx, "");
4879 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4881 if (strlen(driver->info_3->configfile)) {
4882 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4883 cservername, driver->info_3->configfile);
4885 r->config_file = talloc_strdup(mem_ctx, "");
4887 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4889 r->driver_attributes = 0;
4890 r->config_version = 0;
4891 r->driver_version = 0;
4895 /********************************************************************
4896 * fill a spoolss_DriverInfo6 struct
4897 ********************************************************************/
4899 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4900 struct spoolss_DriverInfo6 *r,
4901 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4902 const char *servername)
4904 const char *cservername = canon_servername(servername);
4906 r->version = driver->info_3->cversion;
4908 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4909 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4910 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4911 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4913 if (strlen(driver->info_3->driverpath)) {
4914 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4915 cservername, driver->info_3->driverpath);
4917 r->driver_path = talloc_strdup(mem_ctx, "");
4919 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4921 if (strlen(driver->info_3->datafile)) {
4922 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4923 cservername, driver->info_3->datafile);
4925 r->data_file = talloc_strdup(mem_ctx, "");
4927 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4929 if (strlen(driver->info_3->configfile)) {
4930 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4931 cservername, driver->info_3->configfile);
4933 r->config_file = talloc_strdup(mem_ctx, "");
4935 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4937 if (strlen(driver->info_3->helpfile)) {
4938 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4939 cservername, driver->info_3->helpfile);
4941 r->help_file = talloc_strdup(mem_ctx, "");
4943 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4945 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4946 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4947 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4948 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4950 r->dependent_files = string_array_from_driver_info(mem_ctx,
4951 driver->info_3->dependentfiles,
4953 r->previous_names = string_array_from_driver_info(mem_ctx,
4958 r->driver_version = 0;
4960 r->manufacturer_name = talloc_strdup(mem_ctx, "");
4961 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
4962 r->manufacturer_url = talloc_strdup(mem_ctx, "");
4963 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
4964 r->hardware_id = talloc_strdup(mem_ctx, "");
4965 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
4966 r->provider = talloc_strdup(mem_ctx, "");
4967 W_ERROR_HAVE_NO_MEMORY(r->provider);
4972 /********************************************************************
4973 ********************************************************************/
4974 #if 0 /* disabled until marshalling issues are resolved - gd */
4975 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4976 struct spoolss_DriverFileInfo *r,
4977 const char *cservername,
4978 const char *file_name,
4979 enum spoolss_DriverFileType file_type,
4980 uint32_t file_version)
4982 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
4983 cservername, file_name);
4984 W_ERROR_HAVE_NO_MEMORY(r->file_name);
4985 r->file_type = file_type;
4986 r->file_version = file_version;
4991 /********************************************************************
4992 ********************************************************************/
4994 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4995 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4996 const char *cservername,
4997 struct spoolss_DriverFileInfo **info_p,
5000 struct spoolss_DriverFileInfo *info = NULL;
5008 if (strlen(driver->info_3->driverpath)) {
5009 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5010 struct spoolss_DriverFileInfo,
5012 W_ERROR_HAVE_NO_MEMORY(info);
5013 result = fill_spoolss_DriverFileInfo(info,
5016 driver->info_3->driverpath,
5017 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5019 W_ERROR_NOT_OK_RETURN(result);
5023 if (strlen(driver->info_3->configfile)) {
5024 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5025 struct spoolss_DriverFileInfo,
5027 W_ERROR_HAVE_NO_MEMORY(info);
5028 result = fill_spoolss_DriverFileInfo(info,
5031 driver->info_3->configfile,
5032 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5034 W_ERROR_NOT_OK_RETURN(result);
5038 if (strlen(driver->info_3->datafile)) {
5039 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5040 struct spoolss_DriverFileInfo,
5042 W_ERROR_HAVE_NO_MEMORY(info);
5043 result = fill_spoolss_DriverFileInfo(info,
5046 driver->info_3->datafile,
5047 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5049 W_ERROR_NOT_OK_RETURN(result);
5053 if (strlen(driver->info_3->helpfile)) {
5054 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5055 struct spoolss_DriverFileInfo,
5057 W_ERROR_HAVE_NO_MEMORY(info);
5058 result = fill_spoolss_DriverFileInfo(info,
5061 driver->info_3->helpfile,
5062 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5064 W_ERROR_NOT_OK_RETURN(result);
5068 for (i=0; driver->info_3->dependentfiles[i][0] != '\0'; i++) {
5069 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5070 struct spoolss_DriverFileInfo,
5072 W_ERROR_HAVE_NO_MEMORY(info);
5073 result = fill_spoolss_DriverFileInfo(info,
5076 driver->info_3->dependentfiles[i],
5077 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5079 W_ERROR_NOT_OK_RETURN(result);
5089 /********************************************************************
5090 * fill a spoolss_DriverInfo101 struct
5091 ********************************************************************/
5093 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5094 struct spoolss_DriverInfo101 *r,
5095 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5096 const char *servername)
5098 const char *cservername = canon_servername(servername);
5101 r->version = driver->info_3->cversion;
5103 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
5104 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5105 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
5106 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5108 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5112 if (!W_ERROR_IS_OK(result)) {
5116 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5117 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5119 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5120 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5122 r->previous_names = string_array_from_driver_info(mem_ctx,
5126 r->driver_version = 0;
5128 r->manufacturer_name = talloc_strdup(mem_ctx, "");
5129 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5130 r->manufacturer_url = talloc_strdup(mem_ctx, "");
5131 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5132 r->hardware_id = talloc_strdup(mem_ctx, "");
5133 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5134 r->provider = talloc_strdup(mem_ctx, "");
5135 W_ERROR_HAVE_NO_MEMORY(r->provider);
5140 /********************************************************************
5141 * construct_printer_driver_info_1
5142 ********************************************************************/
5144 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
5145 struct spoolss_DriverInfo1 *r,
5147 const char *servername,
5148 const char *architecture,
5151 NT_PRINTER_INFO_LEVEL *printer = NULL;
5152 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5155 ZERO_STRUCT(driver);
5157 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5158 return WERR_INVALID_PRINTER_NAME;
5160 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5161 free_a_printer(&printer, 2);
5162 return WERR_UNKNOWN_PRINTER_DRIVER;
5165 result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
5167 free_a_printer(&printer,2);
5172 /********************************************************************
5173 * construct_printer_driver_info_2
5174 * fill a printer_info_2 struct
5175 ********************************************************************/
5177 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
5178 struct spoolss_DriverInfo2 *r,
5180 const char *servername,
5181 const char *architecture,
5184 NT_PRINTER_INFO_LEVEL *printer = NULL;
5185 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5188 ZERO_STRUCT(printer);
5189 ZERO_STRUCT(driver);
5191 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5192 return WERR_INVALID_PRINTER_NAME;
5194 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5195 free_a_printer(&printer, 2);
5196 return WERR_UNKNOWN_PRINTER_DRIVER;
5199 result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
5201 free_a_printer(&printer,2);
5206 /********************************************************************
5207 * construct_printer_info_3
5208 * fill a printer_info_3 struct
5209 ********************************************************************/
5211 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
5212 struct spoolss_DriverInfo3 *r,
5214 const char *servername,
5215 const char *architecture,
5218 NT_PRINTER_INFO_LEVEL *printer = NULL;
5219 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5221 ZERO_STRUCT(driver);
5223 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5224 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5225 if (!W_ERROR_IS_OK(status))
5226 return WERR_INVALID_PRINTER_NAME;
5228 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5229 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5234 * I put this code in during testing. Helpful when commenting out the
5235 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5236 * as win2k always queries the driver using an infor level of 6.
5237 * I've left it in (but ifdef'd out) because I'll probably
5238 * use it in experimentation again in the future. --jerry 22/01/2002
5241 if (!W_ERROR_IS_OK(status)) {
5243 * Is this a W2k client ?
5246 /* Yes - try again with a WinNT driver. */
5248 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5249 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5253 if (!W_ERROR_IS_OK(status)) {
5254 free_a_printer(&printer,2);
5255 return WERR_UNKNOWN_PRINTER_DRIVER;
5263 status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
5265 free_a_printer(&printer,2);
5270 /********************************************************************
5271 * construct_printer_info_6
5272 * fill a printer_info_6 struct
5273 ********************************************************************/
5275 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5276 struct spoolss_DriverInfo6 *r,
5278 const char *servername,
5279 const char *architecture,
5282 NT_PRINTER_INFO_LEVEL *printer = NULL;
5283 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5286 ZERO_STRUCT(driver);
5288 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5290 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5292 if (!W_ERROR_IS_OK(status))
5293 return WERR_INVALID_PRINTER_NAME;
5295 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5297 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5299 if (!W_ERROR_IS_OK(status))
5302 * Is this a W2k client ?
5306 free_a_printer(&printer,2);
5307 return WERR_UNKNOWN_PRINTER_DRIVER;
5310 /* Yes - try again with a WinNT driver. */
5312 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5313 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5314 if (!W_ERROR_IS_OK(status)) {
5315 free_a_printer(&printer,2);
5316 return WERR_UNKNOWN_PRINTER_DRIVER;
5320 status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5322 free_a_printer(&printer,2);
5323 free_a_printer_driver(driver, 3);
5327 #if 0 /* disabled until marshalling issues are resolved - gd */
5328 /********************************************************************
5329 * construct_printer_info_101
5330 * fill a printer_info_101 struct
5331 ********************************************************************/
5333 static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
5334 struct spoolss_DriverInfo101 *r,
5336 const char *servername,
5337 const char *architecture,
5340 NT_PRINTER_INFO_LEVEL *printer = NULL;
5341 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5344 ZERO_STRUCT(driver);
5346 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5348 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5349 win_errstr(result)));
5351 if (!W_ERROR_IS_OK(result)) {
5352 return WERR_INVALID_PRINTER_NAME;
5355 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5356 architecture, version);
5358 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5359 win_errstr(result)));
5361 if (!W_ERROR_IS_OK(result)) {
5363 * Is this a W2k client ?
5367 free_a_printer(&printer, 2);
5368 return WERR_UNKNOWN_PRINTER_DRIVER;
5371 /* Yes - try again with a WinNT driver. */
5373 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5374 architecture, version);
5375 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5376 win_errstr(result)));
5377 if (!W_ERROR_IS_OK(result)) {
5378 free_a_printer(&printer, 2);
5379 return WERR_UNKNOWN_PRINTER_DRIVER;
5383 result = fill_printer_driver_info101(mem_ctx, r, &driver, servername);
5385 free_a_printer(&printer, 2);
5386 free_a_printer_driver(driver, 3);
5391 /****************************************************************
5392 _spoolss_GetPrinterDriver2
5393 ****************************************************************/
5395 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5396 struct spoolss_GetPrinterDriver2 *r)
5398 Printer_entry *printer;
5401 const char *servername;
5404 /* that's an [in out] buffer */
5406 if (!r->in.buffer && (r->in.offered != 0)) {
5407 return WERR_INVALID_PARAM;
5410 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5412 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5413 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5414 return WERR_INVALID_PRINTER_NAME;
5418 *r->out.server_major_version = 0;
5419 *r->out.server_minor_version = 0;
5421 servername = get_server_name(printer);
5423 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5427 switch (r->in.level) {
5429 result = construct_printer_driver_info_1(p->mem_ctx,
5430 &r->out.info->info1,
5434 r->in.client_major_version);
5437 result = construct_printer_driver_info_2(p->mem_ctx,
5438 &r->out.info->info2,
5442 r->in.client_major_version);
5445 result = construct_printer_driver_info_3(p->mem_ctx,
5446 &r->out.info->info3,
5450 r->in.client_major_version);
5453 result = construct_printer_driver_info_6(p->mem_ctx,
5454 &r->out.info->info6,
5458 r->in.client_major_version);
5460 #if 0 /* disabled until marshalling issues are resolved - gd */
5462 result = construct_printer_driver_info_101(p->mem_ctx,
5463 &r->out.info->info101,
5467 r->in.client_major_version);
5471 result = WERR_UNKNOWN_LEVEL;
5475 if (!W_ERROR_IS_OK(result)) {
5476 TALLOC_FREE(r->out.info);
5480 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5481 r->out.info, r->in.level);
5482 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5484 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5488 /****************************************************************
5489 _spoolss_StartPagePrinter
5490 ****************************************************************/
5492 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5493 struct spoolss_StartPagePrinter *r)
5495 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5498 DEBUG(3,("_spoolss_StartPagePrinter: "
5499 "Error in startpageprinter printer handle\n"));
5503 Printer->page_started = true;
5507 /****************************************************************
5508 _spoolss_EndPagePrinter
5509 ****************************************************************/
5511 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5512 struct spoolss_EndPagePrinter *r)
5516 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5519 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5520 OUR_HANDLE(r->in.handle)));
5524 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5527 Printer->page_started = false;
5528 print_job_endpage(snum, Printer->jobid);
5533 /****************************************************************
5534 _spoolss_StartDocPrinter
5535 ****************************************************************/
5537 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5538 struct spoolss_StartDocPrinter *r)
5540 struct spoolss_DocumentInfo1 *info_1;
5542 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5545 DEBUG(2,("_spoolss_StartDocPrinter: "
5546 "Invalid handle (%s:%u:%u)\n",
5547 OUR_HANDLE(r->in.handle)));
5551 if (r->in.level != 1) {
5552 return WERR_UNKNOWN_LEVEL;
5555 info_1 = r->in.info.info1;
5558 * a nice thing with NT is it doesn't listen to what you tell it.
5559 * when asked to send _only_ RAW datas, it tries to send datas
5562 * So I add checks like in NT Server ...
5565 if (info_1->datatype) {
5566 if (strcmp(info_1->datatype, "RAW") != 0) {
5568 return WERR_INVALID_DATATYPE;
5572 /* get the share number of the printer */
5573 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5577 Printer->jobid = print_job_start(p->server_info, snum,
5578 info_1->document_name,
5579 Printer->nt_devmode);
5581 /* An error occured in print_job_start() so return an appropriate
5584 if (Printer->jobid == -1) {
5585 return map_werror_from_unix(errno);
5588 Printer->document_started = true;
5589 *r->out.job_id = Printer->jobid;
5594 /****************************************************************
5595 _spoolss_EndDocPrinter
5596 ****************************************************************/
5598 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5599 struct spoolss_EndDocPrinter *r)
5601 return _spoolss_enddocprinter_internal(p, r->in.handle);
5604 /****************************************************************
5605 _spoolss_WritePrinter
5606 ****************************************************************/
5608 WERROR _spoolss_WritePrinter(pipes_struct *p,
5609 struct spoolss_WritePrinter *r)
5611 uint32_t buffer_written;
5613 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5616 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5617 OUR_HANDLE(r->in.handle)));
5618 *r->out.num_written = r->in._data_size;
5622 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5625 buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5626 (const char *)r->in.data.data,
5628 (size_t)r->in._data_size);
5629 if (buffer_written == (uint32_t)-1) {
5630 *r->out.num_written = 0;
5631 if (errno == ENOSPC)
5632 return WERR_NO_SPOOL_SPACE;
5634 return WERR_ACCESS_DENIED;
5637 *r->out.num_written = r->in._data_size;
5642 /********************************************************************
5643 * api_spoolss_getprinter
5644 * called from the spoolss dispatcher
5646 ********************************************************************/
5648 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5652 WERROR errcode = WERR_BADFUNC;
5653 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5656 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5657 OUR_HANDLE(handle)));
5661 if (!get_printer_snum(p, handle, &snum, NULL))
5665 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5666 errcode = print_queue_pause(p->server_info, snum);
5668 case SPOOLSS_PRINTER_CONTROL_RESUME:
5669 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5670 errcode = print_queue_resume(p->server_info, snum);
5672 case SPOOLSS_PRINTER_CONTROL_PURGE:
5673 errcode = print_queue_purge(p->server_info, snum);
5676 return WERR_UNKNOWN_LEVEL;
5683 /****************************************************************
5684 _spoolss_AbortPrinter
5685 * From MSDN: "Deletes printer's spool file if printer is configured
5687 ****************************************************************/
5689 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5690 struct spoolss_AbortPrinter *r)
5692 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5694 WERROR errcode = WERR_OK;
5697 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5698 OUR_HANDLE(r->in.handle)));
5702 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5705 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5710 /********************************************************************
5711 * called by spoolss_api_setprinter
5712 * when updating a printer description
5713 ********************************************************************/
5715 static WERROR update_printer_sec(struct policy_handle *handle,
5716 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5718 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5722 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5724 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5725 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5726 OUR_HANDLE(handle)));
5728 result = WERR_BADFID;
5733 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5734 result = WERR_INVALID_PARAM;
5738 /* Check the user has permissions to change the security
5739 descriptor. By experimentation with two NT machines, the user
5740 requires Full Access to the printer to change security
5743 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5744 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5745 result = WERR_ACCESS_DENIED;
5749 /* NT seems to like setting the security descriptor even though
5750 nothing may have actually changed. */
5752 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5753 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5754 result = WERR_BADFID;
5758 if (DEBUGLEVEL >= 10) {
5762 the_acl = old_secdesc_ctr->sd->dacl;
5763 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5764 PRINTERNAME(snum), the_acl->num_aces));
5766 for (i = 0; i < the_acl->num_aces; i++) {
5767 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5768 &the_acl->aces[i].trustee),
5769 the_acl->aces[i].access_mask));
5772 the_acl = secdesc_ctr->sd->dacl;
5775 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5776 PRINTERNAME(snum), the_acl->num_aces));
5778 for (i = 0; i < the_acl->num_aces; i++) {
5779 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5780 &the_acl->aces[i].trustee),
5781 the_acl->aces[i].access_mask));
5784 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5788 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5789 if (!new_secdesc_ctr) {
5790 result = WERR_NOMEM;
5794 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5799 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5806 /********************************************************************
5807 Canonicalize printer info from a client
5809 ATTN: It does not matter what we set the servername to hear
5810 since we do the necessary work in get_a_printer() to set it to
5811 the correct value based on what the client sent in the
5812 _spoolss_open_printer_ex().
5813 ********************************************************************/
5815 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5817 fstring printername;
5820 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5821 "portname=%s drivername=%s comment=%s location=%s\n",
5822 info->servername, info->printername, info->sharename,
5823 info->portname, info->drivername, info->comment, info->location));
5825 /* we force some elements to "correct" values */
5826 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5827 fstrcpy(info->sharename, lp_servicename(snum));
5829 /* check to see if we allow printername != sharename */
5831 if ( lp_force_printername(snum) ) {
5832 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5833 global_myname(), info->sharename );
5836 /* make sure printername is in \\server\printername format */
5838 fstrcpy( printername, info->printername );
5840 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5841 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5845 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5846 global_myname(), p );
5849 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5850 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5857 /****************************************************************************
5858 ****************************************************************************/
5860 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
5862 char *cmd = lp_addport_cmd();
5863 char *command = NULL;
5865 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5866 bool is_print_op = false;
5869 return WERR_ACCESS_DENIED;
5872 command = talloc_asprintf(ctx,
5873 "%s \"%s\" \"%s\"", cmd, portname, uri );
5879 is_print_op = user_has_privileges( token, &se_printop );
5881 DEBUG(10,("Running [%s]\n", command));
5883 /********* BEGIN SePrintOperatorPrivilege **********/
5888 ret = smbrun(command, NULL);
5893 /********* END SePrintOperatorPrivilege **********/
5895 DEBUGADD(10,("returned [%d]\n", ret));
5897 TALLOC_FREE(command);
5900 return WERR_ACCESS_DENIED;
5906 /****************************************************************************
5907 ****************************************************************************/
5909 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5911 char *cmd = lp_addprinter_cmd();
5913 char *command = NULL;
5917 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5918 bool is_print_op = false;
5919 char *remote_machine = talloc_strdup(ctx, "%m");
5921 if (!remote_machine) {
5924 remote_machine = talloc_sub_basic(ctx,
5925 current_user_info.smb_name,
5926 current_user_info.domain,
5928 if (!remote_machine) {
5932 command = talloc_asprintf(ctx,
5933 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5934 cmd, printer->info_2->printername, printer->info_2->sharename,
5935 printer->info_2->portname, printer->info_2->drivername,
5936 printer->info_2->location, printer->info_2->comment, remote_machine);
5942 is_print_op = user_has_privileges( token, &se_printop );
5944 DEBUG(10,("Running [%s]\n", command));
5946 /********* BEGIN SePrintOperatorPrivilege **********/
5951 if ( (ret = smbrun(command, &fd)) == 0 ) {
5952 /* Tell everyone we updated smb.conf. */
5953 message_send_all(smbd_messaging_context(),
5954 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5960 /********* END SePrintOperatorPrivilege **********/
5962 DEBUGADD(10,("returned [%d]\n", ret));
5964 TALLOC_FREE(command);
5965 TALLOC_FREE(remote_machine);
5973 /* reload our services immediately */
5975 reload_services(false);
5979 /* Get lines and convert them back to dos-codepage */
5980 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5981 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5984 /* Set the portname to what the script says the portname should be. */
5985 /* but don't require anything to be return from the script exit a good error code */
5988 /* Set the portname to what the script says the portname should be. */
5989 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5990 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5993 TALLOC_FREE(qlines);
5998 /********************************************************************
5999 * Called by spoolss_api_setprinter
6000 * when updating a printer description.
6001 ********************************************************************/
6003 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
6004 struct spoolss_SetPrinterInfoCtr *info_ctr,
6005 struct spoolss_DeviceMode *devmode)
6008 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6009 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6014 DEBUG(8,("update_printer\n"));
6019 result = WERR_BADFID;
6023 if (!get_printer_snum(p, handle, &snum, NULL)) {
6024 result = WERR_BADFID;
6028 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6029 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6030 result = WERR_BADFID;
6034 DEBUGADD(8,("Converting info_2 struct\n"));
6037 * convert_printer_info converts the incoming
6038 * info from the client and overwrites the info
6039 * just read from the tdb in the pointer 'printer'.
6042 if (!convert_printer_info(info_ctr, printer)) {
6043 result = WERR_NOMEM;
6048 /* we have a valid devmode
6049 convert it and link it*/
6051 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6052 if (!convert_devicemode(printer->info_2->printername, devmode,
6053 &printer->info_2->devmode)) {
6054 result = WERR_NOMEM;
6059 /* Do sanity check on the requested changes for Samba */
6061 if (!check_printer_ok(printer->info_2, snum)) {
6062 result = WERR_INVALID_PARAM;
6066 /* FIXME!!! If the driver has changed we really should verify that
6067 it is installed before doing much else --jerry */
6069 /* Check calling user has permission to update printer description */
6071 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6072 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6073 result = WERR_ACCESS_DENIED;
6077 /* Call addprinter hook */
6078 /* Check changes to see if this is really needed */
6080 if ( *lp_addprinter_cmd()
6081 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6082 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6083 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6084 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6086 /* add_printer_hook() will call reload_services() */
6088 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6090 result = WERR_ACCESS_DENIED;
6096 * When a *new* driver is bound to a printer, the drivername is used to
6097 * lookup previously saved driver initialization info, which is then
6098 * bound to the printer, simulating what happens in the Windows arch.
6100 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6102 if (!set_driver_init(printer, 2))
6104 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6105 printer->info_2->drivername));
6108 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6109 printer->info_2->drivername));
6111 notify_printer_driver(snum, printer->info_2->drivername);
6115 * flag which changes actually occured. This is a small subset of
6116 * all the possible changes. We also have to update things in the
6120 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6121 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6122 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6123 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6125 notify_printer_comment(snum, printer->info_2->comment);
6128 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6129 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6130 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6131 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6133 notify_printer_sharename(snum, printer->info_2->sharename);
6136 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6139 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6142 pname = printer->info_2->printername;
6145 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6146 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6147 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6149 notify_printer_printername( snum, pname );
6152 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6153 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6154 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6155 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6157 notify_printer_port(snum, printer->info_2->portname);
6160 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6161 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6162 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6163 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6165 notify_printer_location(snum, printer->info_2->location);
6168 /* here we need to update some more DsSpooler keys */
6169 /* uNCName, serverName, shortServerName */
6171 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6172 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6173 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6174 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6175 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6177 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6178 global_myname(), printer->info_2->sharename );
6179 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6180 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6181 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6183 /* Update printer info */
6184 result = mod_a_printer(printer, 2);
6187 free_a_printer(&printer, 2);
6188 free_a_printer(&old_printer, 2);
6194 /****************************************************************************
6195 ****************************************************************************/
6196 static WERROR publish_or_unpublish_printer(pipes_struct *p,
6197 struct policy_handle *handle,
6198 struct spoolss_SetPrinterInfo7 *info7)
6202 Printer_entry *Printer;
6204 if ( lp_security() != SEC_ADS ) {
6205 return WERR_UNKNOWN_LEVEL;
6208 Printer = find_printer_index_by_hnd(p, handle);
6210 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6215 if (!get_printer_snum(p, handle, &snum, NULL))
6218 nt_printer_publish(Printer, snum, info7->action);
6222 return WERR_UNKNOWN_LEVEL;
6226 /****************************************************************
6228 ****************************************************************/
6230 WERROR _spoolss_SetPrinter(pipes_struct *p,
6231 struct spoolss_SetPrinter *r)
6235 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6238 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6239 OUR_HANDLE(r->in.handle)));
6243 /* check the level */
6244 switch (r->in.info_ctr->level) {
6246 return control_printer(r->in.handle, r->in.command, p);
6248 result = update_printer(p, r->in.handle,
6250 r->in.devmode_ctr->devmode);
6251 if (!W_ERROR_IS_OK(result))
6253 if (r->in.secdesc_ctr->sd)
6254 result = update_printer_sec(r->in.handle, p,
6258 return update_printer_sec(r->in.handle, p,
6261 return publish_or_unpublish_printer(p, r->in.handle,
6262 r->in.info_ctr->info.info7);
6264 return WERR_UNKNOWN_LEVEL;
6268 /****************************************************************
6269 _spoolss_FindClosePrinterNotify
6270 ****************************************************************/
6272 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6273 struct spoolss_FindClosePrinterNotify *r)
6275 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6278 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6279 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6283 if (Printer->notify.client_connected == true) {
6286 if ( Printer->printer_type == SPLHND_SERVER)
6288 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6289 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6292 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6295 Printer->notify.flags=0;
6296 Printer->notify.options=0;
6297 Printer->notify.localmachine[0]='\0';
6298 Printer->notify.printerlocal=0;
6299 TALLOC_FREE(Printer->notify.option);
6300 Printer->notify.client_connected = false;
6305 /****************************************************************
6307 ****************************************************************/
6309 WERROR _spoolss_AddJob(pipes_struct *p,
6310 struct spoolss_AddJob *r)
6312 if (!r->in.buffer && (r->in.offered != 0)) {
6313 return WERR_INVALID_PARAM;
6316 /* this is what a NT server returns for AddJob. AddJob must fail on
6317 * non-local printers */
6319 if (r->in.level != 1) {
6320 return WERR_UNKNOWN_LEVEL;
6323 return WERR_INVALID_PARAM;
6326 /****************************************************************************
6328 ****************************************************************************/
6330 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6331 struct spoolss_JobInfo1 *r,
6332 const print_queue_struct *queue,
6333 int position, int snum,
6334 const NT_PRINTER_INFO_LEVEL *ntprinter)
6338 t = gmtime(&queue->time);
6340 r->job_id = queue->job;
6342 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6343 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6344 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6345 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6346 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6347 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6348 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6349 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6350 r->data_type = talloc_strdup(mem_ctx, "RAW");
6351 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6352 r->text_status = talloc_strdup(mem_ctx, "");
6353 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6355 r->status = nt_printj_status(queue->status);
6356 r->priority = queue->priority;
6357 r->position = position;
6358 r->total_pages = queue->page_count;
6359 r->pages_printed = 0; /* ??? */
6361 init_systemtime(&r->submitted, t);
6366 /****************************************************************************
6368 ****************************************************************************/
6370 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6371 struct spoolss_JobInfo2 *r,
6372 const print_queue_struct *queue,
6373 int position, int snum,
6374 const NT_PRINTER_INFO_LEVEL *ntprinter,
6375 struct spoolss_DeviceMode *devmode)
6379 t = gmtime(&queue->time);
6381 r->job_id = queue->job;
6383 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6384 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6385 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6386 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6387 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6388 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6389 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6390 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6391 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6392 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6393 r->data_type = talloc_strdup(mem_ctx, "RAW");
6394 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6395 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6396 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6397 r->parameters = talloc_strdup(mem_ctx, "");
6398 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6399 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6400 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6402 r->devmode = devmode;
6404 r->text_status = talloc_strdup(mem_ctx, "");
6405 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6409 r->status = nt_printj_status(queue->status);
6410 r->priority = queue->priority;
6411 r->position = position;
6414 r->total_pages = queue->page_count;
6415 r->size = queue->size;
6416 init_systemtime(&r->submitted, t);
6418 r->pages_printed = 0; /* ??? */
6423 /****************************************************************************
6425 ****************************************************************************/
6427 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6428 struct spoolss_JobInfo3 *r,
6429 const print_queue_struct *queue,
6430 const print_queue_struct *next_queue,
6431 int position, int snum,
6432 const NT_PRINTER_INFO_LEVEL *ntprinter)
6434 r->job_id = queue->job;
6437 r->next_job_id = next_queue->job;
6444 /****************************************************************************
6445 Enumjobs at level 1.
6446 ****************************************************************************/
6448 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6449 const print_queue_struct *queue,
6450 uint32_t num_queues, int snum,
6451 const NT_PRINTER_INFO_LEVEL *ntprinter,
6452 union spoolss_JobInfo **info_p,
6455 union spoolss_JobInfo *info;
6457 WERROR result = WERR_OK;
6459 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6460 W_ERROR_HAVE_NO_MEMORY(info);
6462 *count = num_queues;
6464 for (i=0; i<*count; i++) {
6465 result = fill_job_info1(info,
6471 if (!W_ERROR_IS_OK(result)) {
6477 if (!W_ERROR_IS_OK(result)) {
6488 /****************************************************************************
6489 Enumjobs at level 2.
6490 ****************************************************************************/
6492 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6493 const print_queue_struct *queue,
6494 uint32_t num_queues, int snum,
6495 const NT_PRINTER_INFO_LEVEL *ntprinter,
6496 union spoolss_JobInfo **info_p,
6499 union spoolss_JobInfo *info;
6501 WERROR result = WERR_OK;
6503 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6504 W_ERROR_HAVE_NO_MEMORY(info);
6506 *count = num_queues;
6508 for (i=0; i<*count; i++) {
6510 struct spoolss_DeviceMode *devmode;
6512 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6514 result = WERR_NOMEM;
6518 result = fill_job_info2(info,
6525 if (!W_ERROR_IS_OK(result)) {
6531 if (!W_ERROR_IS_OK(result)) {
6542 /****************************************************************************
6543 Enumjobs at level 3.
6544 ****************************************************************************/
6546 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6547 const print_queue_struct *queue,
6548 uint32_t num_queues, int snum,
6549 const NT_PRINTER_INFO_LEVEL *ntprinter,
6550 union spoolss_JobInfo **info_p,
6553 union spoolss_JobInfo *info;
6555 WERROR result = WERR_OK;
6557 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6558 W_ERROR_HAVE_NO_MEMORY(info);
6560 *count = num_queues;
6562 for (i=0; i<*count; i++) {
6563 const print_queue_struct *next_queue = NULL;
6566 next_queue = &queue[i+1];
6569 result = fill_job_info3(info,
6576 if (!W_ERROR_IS_OK(result)) {
6582 if (!W_ERROR_IS_OK(result)) {
6593 /****************************************************************
6595 ****************************************************************/
6597 WERROR _spoolss_EnumJobs(pipes_struct *p,
6598 struct spoolss_EnumJobs *r)
6601 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6603 print_status_struct prt_status;
6604 print_queue_struct *queue = NULL;
6607 /* that's an [in out] buffer */
6609 if (!r->in.buffer && (r->in.offered != 0)) {
6610 return WERR_INVALID_PARAM;
6613 DEBUG(4,("_spoolss_EnumJobs\n"));
6617 *r->out.info = NULL;
6619 /* lookup the printer snum and tdb entry */
6621 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6625 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6626 if (!W_ERROR_IS_OK(result)) {
6630 count = print_queue_status(snum, &queue, &prt_status);
6631 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6632 count, prt_status.status, prt_status.message));
6636 free_a_printer(&ntprinter, 2);
6640 switch (r->in.level) {
6642 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6643 ntprinter, r->out.info, r->out.count);
6646 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6647 ntprinter, r->out.info, r->out.count);
6650 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6651 ntprinter, r->out.info, r->out.count);
6654 result = WERR_UNKNOWN_LEVEL;
6659 free_a_printer(&ntprinter, 2);
6661 if (!W_ERROR_IS_OK(result)) {
6665 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6666 spoolss_EnumJobs, NULL,
6667 *r->out.info, r->in.level,
6669 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6670 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6672 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6675 /****************************************************************
6676 _spoolss_ScheduleJob
6677 ****************************************************************/
6679 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6680 struct spoolss_ScheduleJob *r)
6685 /****************************************************************
6687 ****************************************************************/
6689 WERROR _spoolss_SetJob(pipes_struct *p,
6690 struct spoolss_SetJob *r)
6693 WERROR errcode = WERR_BADFUNC;
6695 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6699 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6700 return WERR_INVALID_PRINTER_NAME;
6703 switch (r->in.command) {
6704 case SPOOLSS_JOB_CONTROL_CANCEL:
6705 case SPOOLSS_JOB_CONTROL_DELETE:
6706 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6710 case SPOOLSS_JOB_CONTROL_PAUSE:
6711 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6715 case SPOOLSS_JOB_CONTROL_RESTART:
6716 case SPOOLSS_JOB_CONTROL_RESUME:
6717 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6722 return WERR_UNKNOWN_LEVEL;
6728 /****************************************************************************
6729 Enumerates all printer drivers by level.
6730 ****************************************************************************/
6732 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6733 const char *servername,
6734 const char *architecture,
6736 union spoolss_DriverInfo **info_p,
6742 fstring *list = NULL;
6743 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6744 union spoolss_DriverInfo *info = NULL;
6746 WERROR result = WERR_OK;
6751 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6753 ndrivers = get_ntdrivers(&list, architecture, version);
6754 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6755 ndrivers, architecture, version));
6757 if (ndrivers == -1) {
6758 result = WERR_NOMEM;
6762 if (ndrivers != 0) {
6763 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6764 union spoolss_DriverInfo,
6767 DEBUG(0,("enumprinterdrivers_level1: "
6768 "failed to enlarge driver info buffer!\n"));
6769 result = WERR_NOMEM;
6774 for (i=0; i<ndrivers; i++) {
6775 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6776 ZERO_STRUCT(driver);
6777 result = get_a_printer_driver(&driver, 3, list[i],
6778 architecture, version);
6779 if (!W_ERROR_IS_OK(result)) {
6785 result = fill_printer_driver_info1(info, &info[count+i].info1,
6786 &driver, servername,
6790 result = fill_printer_driver_info2(info, &info[count+i].info2,
6791 &driver, servername);
6794 result = fill_printer_driver_info3(info, &info[count+i].info3,
6795 &driver, servername);
6798 result = fill_printer_driver_info4(info, &info[count+i].info4,
6799 &driver, servername);
6802 result = fill_printer_driver_info5(info, &info[count+i].info5,
6803 &driver, servername);
6806 result = fill_printer_driver_info6(info, &info[count+i].info6,
6807 &driver, servername);
6810 result = WERR_UNKNOWN_LEVEL;
6814 if (!W_ERROR_IS_OK(result)) {
6815 free_a_printer_driver(driver, 3);
6818 free_a_printer_driver(driver, 3);
6828 if (!W_ERROR_IS_OK(result)) {
6839 /****************************************************************************
6840 Enumerates all printer drivers at level 1.
6841 ****************************************************************************/
6843 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6844 const char *servername,
6845 const char *architecture,
6846 union spoolss_DriverInfo **info_p,
6849 return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
6853 /****************************************************************************
6854 Enumerates all printer drivers at level 2.
6855 ****************************************************************************/
6857 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6858 const char *servername,
6859 const char *architecture,
6860 union spoolss_DriverInfo **info_p,
6863 return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
6867 /****************************************************************************
6868 Enumerates all printer drivers at level 3.
6869 ****************************************************************************/
6871 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6872 const char *servername,
6873 const char *architecture,
6874 union spoolss_DriverInfo **info_p,
6877 return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
6881 /****************************************************************************
6882 Enumerates all printer drivers at level 4.
6883 ****************************************************************************/
6885 static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
6886 const char *servername,
6887 const char *architecture,
6888 union spoolss_DriverInfo **info_p,
6891 return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
6895 /****************************************************************************
6896 Enumerates all printer drivers at level 5.
6897 ****************************************************************************/
6899 static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
6900 const char *servername,
6901 const char *architecture,
6902 union spoolss_DriverInfo **info_p,
6905 return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
6909 /****************************************************************************
6910 Enumerates all printer drivers at level 6.
6911 ****************************************************************************/
6913 static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
6914 const char *servername,
6915 const char *architecture,
6916 union spoolss_DriverInfo **info_p,
6919 return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
6924 /****************************************************************
6925 _spoolss_EnumPrinterDrivers
6926 ****************************************************************/
6928 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6929 struct spoolss_EnumPrinterDrivers *r)
6931 const char *cservername;
6934 /* that's an [in out] buffer */
6936 if (!r->in.buffer && (r->in.offered != 0)) {
6937 return WERR_INVALID_PARAM;
6940 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6944 *r->out.info = NULL;
6946 cservername = canon_servername(r->in.server);
6948 if (!is_myname_or_ipaddr(cservername)) {
6949 return WERR_UNKNOWN_PRINTER_DRIVER;
6952 switch (r->in.level) {
6954 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6956 r->out.info, r->out.count);
6959 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6961 r->out.info, r->out.count);
6964 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6966 r->out.info, r->out.count);
6969 result = enumprinterdrivers_level4(p->mem_ctx, cservername,
6971 r->out.info, r->out.count);
6974 result = enumprinterdrivers_level5(p->mem_ctx, cservername,
6976 r->out.info, r->out.count);
6979 result = enumprinterdrivers_level6(p->mem_ctx, cservername,
6981 r->out.info, r->out.count);
6984 return WERR_UNKNOWN_LEVEL;
6987 if (!W_ERROR_IS_OK(result)) {
6991 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6992 spoolss_EnumPrinterDrivers, NULL,
6993 *r->out.info, r->in.level,
6995 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6996 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6998 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7001 /****************************************************************************
7002 ****************************************************************************/
7004 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7005 struct spoolss_FormInfo1 *r,
7006 const nt_forms_struct *form)
7008 r->form_name = talloc_strdup(mem_ctx, form->name);
7009 W_ERROR_HAVE_NO_MEMORY(r->form_name);
7011 r->flags = form->flag;
7012 r->size.width = form->width;
7013 r->size.height = form->length;
7014 r->area.left = form->left;
7015 r->area.top = form->top;
7016 r->area.right = form->right;
7017 r->area.bottom = form->bottom;
7022 /****************************************************************
7023 spoolss_enumforms_level1
7024 ****************************************************************/
7026 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
7027 const nt_forms_struct *builtin_forms,
7028 uint32_t num_builtin_forms,
7029 const nt_forms_struct *user_forms,
7030 uint32_t num_user_forms,
7031 union spoolss_FormInfo **info_p,
7034 union spoolss_FormInfo *info;
7035 WERROR result = WERR_OK;
7038 *count = num_builtin_forms + num_user_forms;
7040 info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
7041 W_ERROR_HAVE_NO_MEMORY(info);
7043 /* construct the list of form structures */
7044 for (i=0; i<num_builtin_forms; i++) {
7045 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
7046 result = fill_form_info_1(info, &info[i].info1,
7048 if (!W_ERROR_IS_OK(result)) {
7053 for (i=0; i<num_user_forms; i++) {
7054 DEBUGADD(6,("Filling user form number [%d]\n",i));
7055 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
7057 if (!W_ERROR_IS_OK(result)) {
7063 if (!W_ERROR_IS_OK(result)) {
7074 /****************************************************************
7076 ****************************************************************/
7078 WERROR _spoolss_EnumForms(pipes_struct *p,
7079 struct spoolss_EnumForms *r)
7082 nt_forms_struct *user_forms = NULL;
7083 nt_forms_struct *builtin_forms = NULL;
7084 uint32_t num_user_forms;
7085 uint32_t num_builtin_forms;
7089 *r->out.info = NULL;
7091 /* that's an [in out] buffer */
7093 if (!r->in.buffer && (r->in.offered != 0) ) {
7094 return WERR_INVALID_PARAM;
7097 DEBUG(4,("_spoolss_EnumForms\n"));
7098 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7099 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7101 num_builtin_forms = get_builtin_ntforms(&builtin_forms);
7102 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
7103 num_user_forms = get_ntforms(&user_forms);
7104 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
7106 if (num_user_forms + num_builtin_forms == 0) {
7107 SAFE_FREE(builtin_forms);
7108 SAFE_FREE(user_forms);
7109 return WERR_NO_MORE_ITEMS;
7112 switch (r->in.level) {
7114 result = spoolss_enumforms_level1(p->mem_ctx,
7123 result = WERR_UNKNOWN_LEVEL;
7127 SAFE_FREE(user_forms);
7128 SAFE_FREE(builtin_forms);
7130 if (!W_ERROR_IS_OK(result)) {
7134 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7135 spoolss_EnumForms, NULL,
7136 *r->out.info, r->in.level,
7138 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7139 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7141 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7144 /****************************************************************
7145 ****************************************************************/
7147 static WERROR find_form_byname(const char *name,
7148 nt_forms_struct *form)
7150 nt_forms_struct *list = NULL;
7151 int num_forms = 0, i = 0;
7153 if (get_a_builtin_ntform_by_string(name, form)) {
7157 num_forms = get_ntforms(&list);
7158 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
7160 if (num_forms == 0) {
7164 /* Check if the requested name is in the list of form structures */
7165 for (i = 0; i < num_forms; i++) {
7167 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
7169 if (strequal(name, list[i].name)) {
7170 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7182 /****************************************************************
7184 ****************************************************************/
7186 WERROR _spoolss_GetForm(pipes_struct *p,
7187 struct spoolss_GetForm *r)
7190 nt_forms_struct form;
7192 /* that's an [in out] buffer */
7194 if (!r->in.buffer && (r->in.offered != 0)) {
7195 return WERR_INVALID_PARAM;
7198 DEBUG(4,("_spoolss_GetForm\n"));
7199 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7200 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7202 result = find_form_byname(r->in.form_name, &form);
7203 if (!W_ERROR_IS_OK(result)) {
7204 TALLOC_FREE(r->out.info);
7208 switch (r->in.level) {
7210 result = fill_form_info_1(p->mem_ctx,
7211 &r->out.info->info1,
7216 result = WERR_UNKNOWN_LEVEL;
7220 if (!W_ERROR_IS_OK(result)) {
7221 TALLOC_FREE(r->out.info);
7225 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7226 r->out.info, r->in.level);
7227 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7229 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7232 /****************************************************************************
7233 ****************************************************************************/
7235 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7236 struct spoolss_PortInfo1 *r,
7239 r->port_name = talloc_strdup(mem_ctx, name);
7240 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7245 /****************************************************************************
7246 TODO: This probably needs distinguish between TCP/IP and Local ports
7248 ****************************************************************************/
7250 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7251 struct spoolss_PortInfo2 *r,
7254 r->port_name = talloc_strdup(mem_ctx, name);
7255 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7257 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7258 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7260 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7261 W_ERROR_HAVE_NO_MEMORY(r->description);
7263 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7270 /****************************************************************************
7271 wrapper around the enumer ports command
7272 ****************************************************************************/
7274 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7276 char *cmd = lp_enumports_cmd();
7277 char **qlines = NULL;
7278 char *command = NULL;
7286 /* if no hook then just fill in the default port */
7289 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7292 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7293 TALLOC_FREE(qlines);
7300 /* we have a valid enumport command */
7302 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7307 DEBUG(10,("Running [%s]\n", command));
7308 ret = smbrun(command, &fd);
7309 DEBUG(10,("Returned [%d]\n", ret));
7310 TALLOC_FREE(command);
7315 return WERR_ACCESS_DENIED;
7319 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7320 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7330 /****************************************************************************
7332 ****************************************************************************/
7334 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7335 union spoolss_PortInfo **info_p,
7338 union spoolss_PortInfo *info = NULL;
7340 WERROR result = WERR_OK;
7341 char **qlines = NULL;
7344 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7345 if (!W_ERROR_IS_OK(result)) {
7350 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7352 DEBUG(10,("Returning WERR_NOMEM\n"));
7353 result = WERR_NOMEM;
7357 for (i=0; i<numlines; i++) {
7358 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7359 result = fill_port_1(info, &info[i].info1, qlines[i]);
7360 if (!W_ERROR_IS_OK(result)) {
7365 TALLOC_FREE(qlines);
7368 if (!W_ERROR_IS_OK(result)) {
7370 TALLOC_FREE(qlines);
7382 /****************************************************************************
7384 ****************************************************************************/
7386 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7387 union spoolss_PortInfo **info_p,
7390 union spoolss_PortInfo *info = NULL;
7392 WERROR result = WERR_OK;
7393 char **qlines = NULL;
7396 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7397 if (!W_ERROR_IS_OK(result)) {
7402 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7404 DEBUG(10,("Returning WERR_NOMEM\n"));
7405 result = WERR_NOMEM;
7409 for (i=0; i<numlines; i++) {
7410 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7411 result = fill_port_2(info, &info[i].info2, qlines[i]);
7412 if (!W_ERROR_IS_OK(result)) {
7417 TALLOC_FREE(qlines);
7420 if (!W_ERROR_IS_OK(result)) {
7422 TALLOC_FREE(qlines);
7434 /****************************************************************
7436 ****************************************************************/
7438 WERROR _spoolss_EnumPorts(pipes_struct *p,
7439 struct spoolss_EnumPorts *r)
7443 /* that's an [in out] buffer */
7445 if (!r->in.buffer && (r->in.offered != 0)) {
7446 return WERR_INVALID_PARAM;
7449 DEBUG(4,("_spoolss_EnumPorts\n"));
7453 *r->out.info = NULL;
7455 switch (r->in.level) {
7457 result = enumports_level_1(p->mem_ctx, r->out.info,
7461 result = enumports_level_2(p->mem_ctx, r->out.info,
7465 return WERR_UNKNOWN_LEVEL;
7468 if (!W_ERROR_IS_OK(result)) {
7472 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7473 spoolss_EnumPorts, NULL,
7474 *r->out.info, r->in.level,
7476 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7477 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7479 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7482 /****************************************************************************
7483 ****************************************************************************/
7485 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7487 struct spoolss_SetPrinterInfoCtr *info_ctr,
7488 struct spoolss_DeviceMode *devmode,
7489 struct security_descriptor *sec_desc,
7490 struct spoolss_UserLevelCtr *user_ctr,
7491 struct policy_handle *handle)
7493 NT_PRINTER_INFO_LEVEL *printer = NULL;
7496 WERROR err = WERR_OK;
7498 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7499 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7503 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7504 if (!convert_printer_info(info_ctr, printer)) {
7505 free_a_printer(&printer, 2);
7509 /* check to see if the printer already exists */
7511 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7512 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7513 printer->info_2->sharename));
7514 free_a_printer(&printer, 2);
7515 return WERR_PRINTER_ALREADY_EXISTS;
7518 /* FIXME!!! smbd should check to see if the driver is installed before
7519 trying to add a printer like this --jerry */
7521 if (*lp_addprinter_cmd() ) {
7522 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7524 free_a_printer(&printer,2);
7525 return WERR_ACCESS_DENIED;
7528 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7529 "smb.conf parameter \"addprinter command\" is defined. This"
7530 "parameter must exist for this call to succeed\n",
7531 printer->info_2->sharename ));
7534 /* use our primary netbios name since get_a_printer() will convert
7535 it to what the client expects on a case by case basis */
7537 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7538 printer->info_2->sharename);
7541 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7542 free_a_printer(&printer,2);
7543 return WERR_ACCESS_DENIED;
7546 /* you must be a printer admin to add a new printer */
7547 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7548 free_a_printer(&printer,2);
7549 return WERR_ACCESS_DENIED;
7553 * Do sanity check on the requested changes for Samba.
7556 if (!check_printer_ok(printer->info_2, snum)) {
7557 free_a_printer(&printer,2);
7558 return WERR_INVALID_PARAM;
7562 * When a printer is created, the drivername bound to the printer is used
7563 * to lookup previously saved driver initialization info, which is then
7564 * bound to the new printer, simulating what happens in the Windows arch.
7569 set_driver_init(printer, 2);
7573 /* A valid devmode was included, convert and link it
7575 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7577 if (!convert_devicemode(printer->info_2->printername, devmode,
7578 &printer->info_2->devmode)) {
7583 /* write the ASCII on disk */
7584 err = mod_a_printer(printer, 2);
7585 if (!W_ERROR_IS_OK(err)) {
7586 free_a_printer(&printer,2);
7590 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7591 /* Handle open failed - remove addition. */
7592 del_a_printer(printer->info_2->sharename);
7593 free_a_printer(&printer,2);
7594 ZERO_STRUCTP(handle);
7595 return WERR_ACCESS_DENIED;
7598 update_c_setprinter(false);
7599 free_a_printer(&printer,2);
7604 /****************************************************************
7605 _spoolss_AddPrinterEx
7606 ****************************************************************/
7608 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7609 struct spoolss_AddPrinterEx *r)
7611 switch (r->in.info_ctr->level) {
7613 /* we don't handle yet */
7614 /* but I know what to do ... */
7615 return WERR_UNKNOWN_LEVEL;
7617 return spoolss_addprinterex_level_2(p, r->in.server,
7619 r->in.devmode_ctr->devmode,
7620 r->in.secdesc_ctr->sd,
7621 r->in.userlevel_ctr,
7624 return WERR_UNKNOWN_LEVEL;
7628 /****************************************************************
7629 _spoolss_AddPrinterDriver
7630 ****************************************************************/
7632 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7633 struct spoolss_AddPrinterDriver *r)
7635 uint32_t level = r->in.info_ctr->level;
7636 struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7637 WERROR err = WERR_OK;
7638 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7639 const char *driver_name = NULL;
7643 switch (p->hdr_req.opnum) {
7644 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7645 fn = "_spoolss_AddPrinterDriver";
7647 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7648 fn = "_spoolss_AddPrinterDriverEx";
7651 return WERR_INVALID_PARAM;
7656 if (level != 3 && level != 6) {
7657 /* Clever hack from Martin Zielinski <mz@seh.de>
7658 * to allow downgrade from level 8 (Vista).
7660 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7661 return WERR_UNKNOWN_LEVEL;
7664 ZERO_STRUCT(driver);
7666 if (!convert_printer_driver_info(info, &driver, level)) {
7671 DEBUG(5,("Cleaning driver's information\n"));
7672 err = clean_up_driver_struct(p, driver, level);
7673 if (!W_ERROR_IS_OK(err))
7676 DEBUG(5,("Moving driver to final destination\n"));
7677 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7682 if (add_a_printer_driver(driver, level)!=0) {
7683 err = WERR_ACCESS_DENIED;
7689 driver_name = driver.info_3->name ? driver.info_3->name : "";
7692 driver_name = driver.info_6->name ? driver.info_6->name : "";
7697 * I think this is where he DrvUpgradePrinter() hook would be
7698 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7699 * server. Right now, we just need to send ourselves a message
7700 * to update each printer bound to this driver. --jerry
7703 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7704 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7709 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7710 * decide if the driver init data should be deleted. The rules are:
7711 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7712 * 2) delete init data only if there is no 2k/Xp driver
7713 * 3) always delete init data
7714 * The generalized rule is always use init data from the highest order driver.
7715 * It is necessary to follow the driver install by an initialization step to
7716 * finish off this process.
7719 version = driver.info_3->cversion;
7720 else if (level == 6)
7721 version = driver.info_6->version;
7726 * 9x printer driver - never delete init data
7729 DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7734 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7735 * there is no 2k/Xp driver init data for this driver name.
7739 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7741 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7743 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7745 if (!del_driver_init(driver_name))
7746 DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7750 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7752 free_a_printer_driver(driver1,3);
7753 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7760 * 2k or Xp printer driver - always delete init data
7763 if (!del_driver_init(driver_name))
7764 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7769 DEBUG(0,("%s: invalid level=%d\n", fn, level));
7775 free_a_printer_driver(driver, level);
7779 /****************************************************************
7780 _spoolss_AddPrinterDriverEx
7781 ****************************************************************/
7783 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7784 struct spoolss_AddPrinterDriverEx *r)
7786 struct spoolss_AddPrinterDriver a;
7789 * we only support the semantics of AddPrinterDriver()
7790 * i.e. only copy files that are newer than existing ones
7793 if (r->in.flags != APD_COPY_NEW_FILES) {
7794 return WERR_ACCESS_DENIED;
7797 a.in.servername = r->in.servername;
7798 a.in.info_ctr = r->in.info_ctr;
7800 return _spoolss_AddPrinterDriver(p, &a);
7803 /****************************************************************************
7804 ****************************************************************************/
7806 struct _spoolss_paths {
7812 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7814 static const struct _spoolss_paths spoolss_paths[]= {
7815 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7816 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7819 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7820 const char *servername,
7821 const char *environment,
7825 const char *pservername = NULL;
7826 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7827 const char *short_archi;
7831 /* environment may be empty */
7832 if (environment && strlen(environment)) {
7833 long_archi = environment;
7836 /* servername may be empty */
7837 if (servername && strlen(servername)) {
7838 pservername = canon_servername(servername);
7840 if (!is_myname_or_ipaddr(pservername)) {
7841 return WERR_INVALID_PARAM;
7845 if (!(short_archi = get_short_archi(long_archi))) {
7846 return WERR_INVALID_ENVIRONMENT;
7849 switch (component) {
7850 case SPOOLSS_PRTPROCS_PATH:
7851 case SPOOLSS_DRIVER_PATH:
7853 *path = talloc_asprintf(mem_ctx,
7856 spoolss_paths[component].share,
7859 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7860 SPOOLSS_DEFAULT_SERVER_PATH,
7861 spoolss_paths[component].dir,
7866 return WERR_INVALID_PARAM;
7876 /****************************************************************************
7877 ****************************************************************************/
7879 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7880 const char *servername,
7881 const char *environment,
7882 struct spoolss_DriverDirectoryInfo1 *r)
7887 werr = compose_spoolss_server_path(mem_ctx,
7890 SPOOLSS_DRIVER_PATH,
7892 if (!W_ERROR_IS_OK(werr)) {
7896 DEBUG(4,("printer driver directory: [%s]\n", path));
7898 r->directory_name = path;
7903 /****************************************************************
7904 _spoolss_GetPrinterDriverDirectory
7905 ****************************************************************/
7907 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7908 struct spoolss_GetPrinterDriverDirectory *r)
7912 /* that's an [in out] buffer */
7914 if (!r->in.buffer && (r->in.offered != 0)) {
7915 return WERR_INVALID_PARAM;
7918 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7923 /* r->in.level is ignored */
7925 werror = getprinterdriverdir_level_1(p->mem_ctx,
7928 &r->out.info->info1);
7929 if (!W_ERROR_IS_OK(werror)) {
7930 TALLOC_FREE(r->out.info);
7934 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7935 r->out.info, r->in.level);
7936 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7938 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7941 /****************************************************************
7942 _spoolss_EnumPrinterData
7943 ****************************************************************/
7945 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7946 struct spoolss_EnumPrinterData *r)
7948 NT_PRINTER_INFO_LEVEL *printer = NULL;
7949 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7952 REGISTRY_VALUE *val = NULL;
7953 NT_PRINTER_DATA *p_data;
7954 int i, key_index, num_values;
7957 *r->out.value_needed = 0;
7958 *r->out.type = REG_NONE;
7959 *r->out.data_needed = 0;
7961 DEBUG(5,("_spoolss_EnumPrinterData\n"));
7964 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7965 OUR_HANDLE(r->in.handle)));
7969 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7973 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7974 if (!W_ERROR_IS_OK(result)) {
7978 p_data = printer->info_2->data;
7979 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7984 * The NT machine wants to know the biggest size of value and data
7986 * cf: MSDN EnumPrinterData remark section
7989 if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7991 uint32_t biggest_valuesize = 0;
7992 uint32_t biggest_datasize = 0;
7994 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7996 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7998 for ( i=0; i<num_values; i++ )
8000 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8002 name_length = strlen(val->valuename);
8003 if ( strlen(val->valuename) > biggest_valuesize )
8004 biggest_valuesize = name_length;
8006 if ( val->size > biggest_datasize )
8007 biggest_datasize = val->size;
8009 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8013 /* the value is an UNICODE string but real_value_size is the length
8014 in bytes including the trailing 0 */
8016 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8017 *r->out.data_needed = biggest_datasize;
8019 DEBUG(6,("final values: [%d], [%d]\n",
8020 *r->out.value_needed, *r->out.data_needed));
8026 * the value len is wrong in NT sp3
8027 * that's the number of bytes not the number of unicode chars
8030 if (key_index != -1) {
8031 val = regval_ctr_specific_value(p_data->keys[key_index].values,
8037 /* out_value should default to "" or else NT4 has
8038 problems unmarshalling the response */
8040 if (r->in.value_offered) {
8041 *r->out.value_needed = 1;
8042 r->out.value_name = talloc_strdup(r, "");
8043 if (!r->out.value_name) {
8044 result = WERR_NOMEM;
8048 r->out.value_name = NULL;
8049 *r->out.value_needed = 0;
8052 /* the data is counted in bytes */
8054 *r->out.data_needed = r->in.data_offered;
8056 result = WERR_NO_MORE_ITEMS;
8060 * - counted in bytes in the request
8061 * - counted in UNICODE chars in the max reply
8062 * - counted in bytes in the real size
8064 * take a pause *before* coding not *during* coding
8068 if (r->in.value_offered) {
8069 r->out.value_name = talloc_strdup(r, regval_name(val));
8070 if (!r->out.value_name) {
8071 result = WERR_NOMEM;
8074 *r->out.value_needed = strlen_m_term(regval_name(val)) * 2;
8076 r->out.value_name = NULL;
8077 *r->out.value_needed = 0;
8082 *r->out.type = regval_type(val);
8084 /* data - counted in bytes */
8087 * See the section "Dynamically Typed Query Parameters"
8091 if (r->out.data && regval_data_p(val) &&
8092 regval_size(val) && r->in.data_offered) {
8093 memcpy(r->out.data, regval_data_p(val),
8094 MIN(regval_size(val),r->in.data_offered));
8097 *r->out.data_needed = regval_size(val);
8101 free_a_printer(&printer, 2);
8105 /****************************************************************
8106 _spoolss_SetPrinterData
8107 ****************************************************************/
8109 WERROR _spoolss_SetPrinterData(pipes_struct *p,
8110 struct spoolss_SetPrinterData *r)
8112 struct spoolss_SetPrinterDataEx r2;
8114 r2.in.handle = r->in.handle;
8115 r2.in.key_name = "PrinterDriverData";
8116 r2.in.value_name = r->in.value_name;
8117 r2.in.type = r->in.type;
8118 r2.in.data = r->in.data;
8119 r2.in.offered = r->in.offered;
8121 return _spoolss_SetPrinterDataEx(p, &r2);
8124 /****************************************************************
8125 _spoolss_ResetPrinter
8126 ****************************************************************/
8128 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8129 struct spoolss_ResetPrinter *r)
8131 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8134 DEBUG(5,("_spoolss_ResetPrinter\n"));
8137 * All we do is to check to see if the handle and queue is valid.
8138 * This call really doesn't mean anything to us because we only
8139 * support RAW printing. --jerry
8143 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8144 OUR_HANDLE(r->in.handle)));
8148 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8152 /* blindly return success */
8156 /****************************************************************
8157 _spoolss_DeletePrinterData
8158 ****************************************************************/
8160 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8161 struct spoolss_DeletePrinterData *r)
8163 struct spoolss_DeletePrinterDataEx r2;
8165 r2.in.handle = r->in.handle;
8166 r2.in.key_name = "PrinterDriverData";
8167 r2.in.value_name = r->in.value_name;
8169 return _spoolss_DeletePrinterDataEx(p, &r2);
8172 /****************************************************************
8174 ****************************************************************/
8176 WERROR _spoolss_AddForm(pipes_struct *p,
8177 struct spoolss_AddForm *r)
8179 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8180 nt_forms_struct tmpForm;
8182 WERROR status = WERR_OK;
8183 NT_PRINTER_INFO_LEVEL *printer = NULL;
8184 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8187 nt_forms_struct *list=NULL;
8188 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8190 DEBUG(5,("_spoolss_AddForm\n"));
8193 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8194 OUR_HANDLE(r->in.handle)));
8199 /* forms can be added on printer of on the print server handle */
8201 if ( Printer->printer_type == SPLHND_PRINTER )
8203 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8206 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8207 if (!W_ERROR_IS_OK(status))
8211 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8212 and not a printer admin, then fail */
8214 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8215 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8216 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8218 p->server_info->ptok,
8219 lp_printer_admin(snum))) {
8220 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8221 return WERR_ACCESS_DENIED;
8224 /* can't add if builtin */
8226 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8227 status = WERR_FILE_EXISTS;
8231 count = get_ntforms(&list);
8233 if(!add_a_form(&list, form, &count)) {
8234 status = WERR_NOMEM;
8239 write_ntforms(&list, count);
8243 * ChangeID must always be set if this is a printer
8246 if ( Printer->printer_type == SPLHND_PRINTER )
8247 status = mod_a_printer(printer, 2);
8251 free_a_printer(&printer, 2);
8257 /****************************************************************
8259 ****************************************************************/
8261 WERROR _spoolss_DeleteForm(pipes_struct *p,
8262 struct spoolss_DeleteForm *r)
8264 const char *form_name = r->in.form_name;
8265 nt_forms_struct tmpForm;
8267 nt_forms_struct *list=NULL;
8268 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8270 WERROR status = WERR_OK;
8271 NT_PRINTER_INFO_LEVEL *printer = NULL;
8272 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8275 DEBUG(5,("_spoolss_DeleteForm\n"));
8278 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8279 OUR_HANDLE(r->in.handle)));
8283 /* forms can be deleted on printer of on the print server handle */
8285 if ( Printer->printer_type == SPLHND_PRINTER )
8287 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8290 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8291 if (!W_ERROR_IS_OK(status))
8295 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8296 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8297 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8299 p->server_info->ptok,
8300 lp_printer_admin(snum))) {
8301 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8302 return WERR_ACCESS_DENIED;
8306 /* can't delete if builtin */
8308 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8309 status = WERR_INVALID_PARAM;
8313 count = get_ntforms(&list);
8316 ret = delete_a_form(&list, form_name, &count, &status);
8323 * ChangeID must always be set if this is a printer
8326 if ( Printer->printer_type == SPLHND_PRINTER )
8327 status = mod_a_printer(printer, 2);
8331 free_a_printer(&printer, 2);
8337 /****************************************************************
8339 ****************************************************************/
8341 WERROR _spoolss_SetForm(pipes_struct *p,
8342 struct spoolss_SetForm *r)
8344 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8345 nt_forms_struct tmpForm;
8347 WERROR status = WERR_OK;
8348 NT_PRINTER_INFO_LEVEL *printer = NULL;
8349 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8352 nt_forms_struct *list=NULL;
8353 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8355 DEBUG(5,("_spoolss_SetForm\n"));
8358 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8359 OUR_HANDLE(r->in.handle)));
8363 /* forms can be modified on printer of on the print server handle */
8365 if ( Printer->printer_type == SPLHND_PRINTER )
8367 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8370 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8371 if (!W_ERROR_IS_OK(status))
8375 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8376 and not a printer admin, then fail */
8378 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8379 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8380 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8382 p->server_info->ptok,
8383 lp_printer_admin(snum))) {
8384 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8385 return WERR_ACCESS_DENIED;
8388 /* can't set if builtin */
8389 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8390 status = WERR_INVALID_PARAM;
8394 count = get_ntforms(&list);
8395 update_a_form(&list, form, count);
8397 write_ntforms(&list, count);
8401 * ChangeID must always be set if this is a printer
8404 if ( Printer->printer_type == SPLHND_PRINTER )
8405 status = mod_a_printer(printer, 2);
8410 free_a_printer(&printer, 2);
8416 /****************************************************************************
8417 fill_print_processor1
8418 ****************************************************************************/
8420 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8421 struct spoolss_PrintProcessorInfo1 *r,
8422 const char *print_processor_name)
8424 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8425 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8430 /****************************************************************************
8431 enumprintprocessors level 1.
8432 ****************************************************************************/
8434 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8435 union spoolss_PrintProcessorInfo **info_p,
8438 union spoolss_PrintProcessorInfo *info;
8441 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8442 W_ERROR_HAVE_NO_MEMORY(info);
8446 result = fill_print_processor1(info, &info[0].info1, "winprint");
8447 if (!W_ERROR_IS_OK(result)) {
8452 if (!W_ERROR_IS_OK(result)) {
8463 /****************************************************************
8464 _spoolss_EnumPrintProcessors
8465 ****************************************************************/
8467 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8468 struct spoolss_EnumPrintProcessors *r)
8472 /* that's an [in out] buffer */
8474 if (!r->in.buffer && (r->in.offered != 0)) {
8475 return WERR_INVALID_PARAM;
8478 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8481 * Enumerate the print processors ...
8483 * Just reply with "winprint", to keep NT happy
8484 * and I can use my nice printer checker.
8489 *r->out.info = NULL;
8491 switch (r->in.level) {
8493 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8497 return WERR_UNKNOWN_LEVEL;
8500 if (!W_ERROR_IS_OK(result)) {
8504 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8505 spoolss_EnumPrintProcessors, NULL,
8506 *r->out.info, r->in.level,
8508 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8509 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8511 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8514 /****************************************************************************
8515 fill_printprocdatatype1
8516 ****************************************************************************/
8518 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8519 struct spoolss_PrintProcDataTypesInfo1 *r,
8520 const char *name_array)
8522 r->name_array = talloc_strdup(mem_ctx, name_array);
8523 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8528 /****************************************************************************
8529 enumprintprocdatatypes level 1.
8530 ****************************************************************************/
8532 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8533 union spoolss_PrintProcDataTypesInfo **info_p,
8537 union spoolss_PrintProcDataTypesInfo *info;
8539 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8540 W_ERROR_HAVE_NO_MEMORY(info);
8544 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8545 if (!W_ERROR_IS_OK(result)) {
8550 if (!W_ERROR_IS_OK(result)) {
8561 /****************************************************************
8562 _spoolss_EnumPrintProcDataTypes
8563 ****************************************************************/
8565 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8566 struct spoolss_EnumPrintProcDataTypes *r)
8570 /* that's an [in out] buffer */
8572 if (!r->in.buffer && (r->in.offered != 0)) {
8573 return WERR_INVALID_PARAM;
8576 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8580 *r->out.info = NULL;
8582 switch (r->in.level) {
8584 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8588 return WERR_UNKNOWN_LEVEL;
8591 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8592 spoolss_EnumPrintProcDataTypes, NULL,
8593 *r->out.info, r->in.level,
8595 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8596 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8598 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8601 /****************************************************************************
8603 ****************************************************************************/
8605 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8606 struct spoolss_MonitorInfo1 *r,
8607 const char *monitor_name)
8609 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8610 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8615 /****************************************************************************
8617 ****************************************************************************/
8619 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8620 struct spoolss_MonitorInfo2 *r,
8621 const char *monitor_name,
8622 const char *environment,
8623 const char *dll_name)
8625 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8626 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8627 r->environment = talloc_strdup(mem_ctx, environment);
8628 W_ERROR_HAVE_NO_MEMORY(r->environment);
8629 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8630 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8635 /****************************************************************************
8636 enumprintmonitors level 1.
8637 ****************************************************************************/
8639 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8640 union spoolss_MonitorInfo **info_p,
8643 union spoolss_MonitorInfo *info;
8644 WERROR result = WERR_OK;
8646 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8647 W_ERROR_HAVE_NO_MEMORY(info);
8651 result = fill_monitor_1(info, &info[0].info1,
8653 if (!W_ERROR_IS_OK(result)) {
8657 result = fill_monitor_1(info, &info[1].info1,
8659 if (!W_ERROR_IS_OK(result)) {
8664 if (!W_ERROR_IS_OK(result)) {
8675 /****************************************************************************
8676 enumprintmonitors level 2.
8677 ****************************************************************************/
8679 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8680 union spoolss_MonitorInfo **info_p,
8683 union spoolss_MonitorInfo *info;
8684 WERROR result = WERR_OK;
8686 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8687 W_ERROR_HAVE_NO_MEMORY(info);
8691 result = fill_monitor_2(info, &info[0].info2,
8693 "Windows NT X86", /* FIXME */
8695 if (!W_ERROR_IS_OK(result)) {
8699 result = fill_monitor_2(info, &info[1].info2,
8701 "Windows NT X86", /* FIXME */
8703 if (!W_ERROR_IS_OK(result)) {
8708 if (!W_ERROR_IS_OK(result)) {
8719 /****************************************************************
8720 _spoolss_EnumMonitors
8721 ****************************************************************/
8723 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8724 struct spoolss_EnumMonitors *r)
8728 /* that's an [in out] buffer */
8730 if (!r->in.buffer && (r->in.offered != 0)) {
8731 return WERR_INVALID_PARAM;
8734 DEBUG(5,("_spoolss_EnumMonitors\n"));
8737 * Enumerate the print monitors ...
8739 * Just reply with "Local Port", to keep NT happy
8740 * and I can use my nice printer checker.
8745 *r->out.info = NULL;
8747 switch (r->in.level) {
8749 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8753 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8757 return WERR_UNKNOWN_LEVEL;
8760 if (!W_ERROR_IS_OK(result)) {
8764 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8765 spoolss_EnumMonitors, NULL,
8766 *r->out.info, r->in.level,
8768 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8769 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8771 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8774 /****************************************************************************
8775 ****************************************************************************/
8777 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8778 const print_queue_struct *queue,
8779 int count, int snum,
8780 const NT_PRINTER_INFO_LEVEL *ntprinter,
8782 struct spoolss_JobInfo1 *r)
8787 for (i=0; i<count && found == false; i++) {
8788 if (queue[i].job == (int)jobid) {
8793 if (found == false) {
8794 /* NT treats not found as bad param... yet another bad choice */
8795 return WERR_INVALID_PARAM;
8798 return fill_job_info1(mem_ctx,
8806 /****************************************************************************
8807 ****************************************************************************/
8809 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8810 const print_queue_struct *queue,
8811 int count, int snum,
8812 const NT_PRINTER_INFO_LEVEL *ntprinter,
8814 struct spoolss_JobInfo2 *r)
8818 struct spoolss_DeviceMode *devmode;
8819 NT_DEVICEMODE *nt_devmode;
8822 for (i=0; i<count && found == false; i++) {
8823 if (queue[i].job == (int)jobid) {
8828 if (found == false) {
8829 /* NT treats not found as bad param... yet another bad
8831 return WERR_INVALID_PARAM;
8835 * if the print job does not have a DEVMODE associated with it,
8836 * just use the one for the printer. A NULL devicemode is not
8837 * a failure condition
8840 nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8842 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8843 W_ERROR_HAVE_NO_MEMORY(devmode);
8844 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8845 if (!W_ERROR_IS_OK(result)) {
8849 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8850 W_ERROR_HAVE_NO_MEMORY(devmode);
8853 return fill_job_info2(mem_ctx,
8862 /****************************************************************
8864 ****************************************************************/
8866 WERROR _spoolss_GetJob(pipes_struct *p,
8867 struct spoolss_GetJob *r)
8869 WERROR result = WERR_OK;
8870 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8873 print_queue_struct *queue = NULL;
8874 print_status_struct prt_status;
8876 /* that's an [in out] buffer */
8878 if (!r->in.buffer && (r->in.offered != 0)) {
8879 return WERR_INVALID_PARAM;
8882 DEBUG(5,("_spoolss_GetJob\n"));
8886 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8890 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8891 if (!W_ERROR_IS_OK(result)) {
8895 count = print_queue_status(snum, &queue, &prt_status);
8897 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8898 count, prt_status.status, prt_status.message));
8900 switch (r->in.level) {
8902 result = getjob_level_1(p->mem_ctx,
8903 queue, count, snum, ntprinter,
8904 r->in.job_id, &r->out.info->info1);
8907 result = getjob_level_2(p->mem_ctx,
8908 queue, count, snum, ntprinter,
8909 r->in.job_id, &r->out.info->info2);
8912 result = WERR_UNKNOWN_LEVEL;
8917 free_a_printer(&ntprinter, 2);
8919 if (!W_ERROR_IS_OK(result)) {
8920 TALLOC_FREE(r->out.info);
8924 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8925 r->out.info, r->in.level);
8926 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8928 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8931 /****************************************************************
8932 _spoolss_GetPrinterDataEx
8933 ****************************************************************/
8935 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8936 struct spoolss_GetPrinterDataEx *r)
8939 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8940 REGISTRY_VALUE *val = NULL;
8941 NT_PRINTER_INFO_LEVEL *printer = NULL;
8943 WERROR result = WERR_OK;
8946 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8948 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8949 r->in.key_name, r->in.value_name));
8951 /* in case of problem, return some default values */
8954 *r->out.type = REG_NONE;
8957 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8958 OUR_HANDLE(r->in.handle)));
8959 result = WERR_BADFID;
8963 /* Is the handle to a printer or to the server? */
8965 if (Printer->printer_type == SPLHND_SERVER) {
8967 union spoolss_PrinterData data;
8969 result = getprinterdata_printer_server(p->mem_ctx,
8973 if (!W_ERROR_IS_OK(result)) {
8977 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8978 *r->out.type, &data);
8979 if (!W_ERROR_IS_OK(result)) {
8983 *r->out.needed = blob.length;
8985 if (r->in.offered >= *r->out.needed) {
8986 memcpy(r->out.data, blob.data, blob.length);
8989 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8992 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8993 result = WERR_BADFID;
8997 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8998 if (!W_ERROR_IS_OK(result)) {
9002 /* check to see if the keyname is valid */
9003 if (!strlen(r->in.key_name)) {
9004 result = WERR_INVALID_PARAM;
9008 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
9010 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9011 strequal(r->in.value_name, "ChangeId")) {
9012 *r->out.type = REG_DWORD;
9014 if (r->in.offered >= *r->out.needed) {
9015 SIVAL(r->out.data, 0, printer->info_2->changeid);
9021 if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
9022 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9023 "Invalid keyname [%s]\n", r->in.key_name ));
9024 result = WERR_BADFILE;
9028 val = get_printer_data(printer->info_2,
9029 r->in.key_name, r->in.value_name);
9031 result = WERR_BADFILE;
9035 *r->out.needed = regval_size(val);
9036 *r->out.type = regval_type(val);
9038 if (r->in.offered >= *r->out.needed) {
9039 memcpy(r->out.data, regval_data_p(val), regval_size(val));
9043 free_a_printer(&printer, 2);
9046 if (!W_ERROR_IS_OK(result)) {
9050 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
9051 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9053 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9056 /****************************************************************
9057 _spoolss_SetPrinterDataEx
9058 ****************************************************************/
9060 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9061 struct spoolss_SetPrinterDataEx *r)
9063 NT_PRINTER_INFO_LEVEL *printer = NULL;
9065 WERROR result = WERR_OK;
9066 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9069 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9071 /* From MSDN documentation of SetPrinterDataEx: pass request to
9072 SetPrinterData if key is "PrinterDriverData" */
9075 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9076 OUR_HANDLE(r->in.handle)));
9080 if (Printer->printer_type == SPLHND_SERVER) {
9081 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9082 "Not implemented for server handles yet\n"));
9083 return WERR_INVALID_PARAM;
9086 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9091 * Access check : NT returns "access denied" if you make a
9092 * SetPrinterData call without the necessary privildge.
9093 * we were originally returning OK if nothing changed
9094 * which made Win2k issue **a lot** of SetPrinterData
9095 * when connecting to a printer --jerry
9098 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9099 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9100 "change denied by handle access permissions\n"));
9101 return WERR_ACCESS_DENIED;
9104 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9105 if (!W_ERROR_IS_OK(result)) {
9109 /* check for OID in valuename */
9111 oid_string = strchr(r->in.value_name, ',');
9118 * When client side code sets a magic printer data key, detect it and save
9119 * the current printer data and the magic key's data (its the DEVMODE) for
9120 * future printer/driver initializations.
9122 if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
9123 /* Set devmode and printer initialization info */
9124 result = save_driver_init(printer, 2, r->in.data, r->in.offered);
9126 srv_spoolss_reset_printerdata(printer->info_2->drivername);
9131 /* save the registry data */
9133 result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
9134 r->in.type, r->in.data, r->in.offered);
9136 if (W_ERROR_IS_OK(result)) {
9137 /* save the OID if one was specified */
9139 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9140 r->in.key_name, SPOOL_OID_KEY);
9142 result = WERR_NOMEM;
9147 * I'm not checking the status here on purpose. Don't know
9148 * if this is right, but I'm returning the status from the
9149 * previous set_printer_dataex() call. I have no idea if
9150 * this is right. --jerry
9153 set_printer_dataex(printer, str, r->in.value_name,
9154 REG_SZ, (uint8_t *)oid_string,
9155 strlen(oid_string)+1);
9158 result = mod_a_printer(printer, 2);
9162 free_a_printer(&printer, 2);
9167 /****************************************************************
9168 _spoolss_DeletePrinterDataEx
9169 ****************************************************************/
9171 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9172 struct spoolss_DeletePrinterDataEx *r)
9174 NT_PRINTER_INFO_LEVEL *printer = NULL;
9176 WERROR status = WERR_OK;
9177 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9179 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9182 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9183 "Invalid handle (%s:%u:%u).\n",
9184 OUR_HANDLE(r->in.handle)));
9188 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9191 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9192 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9193 "printer properties change denied by handle\n"));
9194 return WERR_ACCESS_DENIED;
9197 if (!r->in.value_name || !r->in.key_name) {
9201 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9202 if (!W_ERROR_IS_OK(status))
9205 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9207 if ( W_ERROR_IS_OK(status) )
9208 mod_a_printer( printer, 2 );
9210 free_a_printer(&printer, 2);
9215 /****************************************************************
9216 _spoolss_EnumPrinterKey
9217 ****************************************************************/
9219 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9220 struct spoolss_EnumPrinterKey *r)
9222 fstring *keynames = NULL;
9224 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9225 NT_PRINTER_DATA *data;
9226 NT_PRINTER_INFO_LEVEL *printer = NULL;
9228 WERROR result = WERR_BADFILE;
9230 const char **array = NULL;
9233 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9236 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9237 OUR_HANDLE(r->in.handle)));
9241 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9245 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9246 if (!W_ERROR_IS_OK(result)) {
9250 /* get the list of subkey names */
9252 data = printer->info_2->data;
9254 num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9255 if (num_keys == -1) {
9256 result = WERR_BADFILE;
9260 array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
9262 result = WERR_NOMEM;
9267 array[0] = talloc_strdup(array, "");
9269 result = WERR_NOMEM;
9274 for (i=0; i < num_keys; i++) {
9276 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
9279 array[i] = talloc_strdup(array, keynames[i]);
9281 result = WERR_NOMEM;
9286 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9287 result = WERR_NOMEM;
9291 *r->out._ndr_size = r->in.offered / 2;
9292 *r->out.needed = blob.length;
9294 if (r->in.offered < *r->out.needed) {
9295 result = WERR_MORE_DATA;
9298 r->out.key_buffer->string_array = array;
9302 if (!W_ERROR_IS_OK(result)) {
9304 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9309 free_a_printer(&printer, 2);
9310 SAFE_FREE(keynames);
9315 /****************************************************************
9316 _spoolss_DeletePrinterKey
9317 ****************************************************************/
9319 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9320 struct spoolss_DeletePrinterKey *r)
9322 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9323 NT_PRINTER_INFO_LEVEL *printer = NULL;
9327 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9330 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9331 OUR_HANDLE(r->in.handle)));
9335 /* if keyname == NULL, return error */
9337 if ( !r->in.key_name )
9338 return WERR_INVALID_PARAM;
9340 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9343 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9344 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9345 "printer properties change denied by handle\n"));
9346 return WERR_ACCESS_DENIED;
9349 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9350 if (!W_ERROR_IS_OK(status))
9353 /* delete the key and all subneys */
9355 status = delete_all_printer_data( printer->info_2, r->in.key_name );
9357 if ( W_ERROR_IS_OK(status) )
9358 status = mod_a_printer(printer, 2);
9360 free_a_printer( &printer, 2 );
9365 /****************************************************************
9366 ****************************************************************/
9368 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9370 struct spoolss_PrinterEnumValues *r)
9372 r->data = TALLOC_ZERO_P(mem_ctx, DATA_BLOB);
9373 W_ERROR_HAVE_NO_MEMORY(r->data);
9375 r->value_name = talloc_strdup(mem_ctx, regval_name(v));
9376 W_ERROR_HAVE_NO_MEMORY(r->value_name);
9378 r->type = regval_type(v);
9379 r->data_length = regval_size(v);
9381 if (r->data_length) {
9382 *r->data = data_blob_talloc(r->data, regval_data_p(v), regval_size(v));
9388 /****************************************************************
9389 _spoolss_EnumPrinterDataEx
9390 ****************************************************************/
9392 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9393 struct spoolss_EnumPrinterDataEx *r)
9396 NT_PRINTER_INFO_LEVEL *printer = NULL;
9397 struct spoolss_PrinterEnumValues *info = NULL;
9398 NT_PRINTER_DATA *p_data;
9399 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9405 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9409 *r->out.info = NULL;
9412 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9413 OUR_HANDLE(r->in.handle)));
9418 * first check for a keyname of NULL or "". Win2k seems to send
9419 * this a lot and we should send back WERR_INVALID_PARAM
9420 * no need to spend time looking up the printer in this case.
9424 if (!strlen(r->in.key_name)) {
9425 result = WERR_INVALID_PARAM;
9429 /* get the printer off of disk */
9431 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9435 ZERO_STRUCT(printer);
9436 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9437 if (!W_ERROR_IS_OK(result)) {
9441 /* now look for a match on the key name */
9443 p_data = printer->info_2->data;
9445 key_index = lookup_printerkey(p_data, r->in.key_name);
9446 if (key_index == -1) {
9447 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9449 result = WERR_INVALID_PARAM;
9453 /* allocate the memory for the array of pointers -- if necessary */
9455 count = regval_ctr_numvals(p_data->keys[key_index].values);
9457 result = WERR_OK; /* ??? */
9461 info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9462 struct spoolss_PrinterEnumValues,
9465 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9466 result = WERR_NOMEM;
9471 * loop through all params and build the array to pass
9472 * back to the client
9475 for (i=0; i < count; i++) {
9477 REGISTRY_VALUE *val;
9479 /* lookup the registry value */
9481 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9483 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9487 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9488 if (!W_ERROR_IS_OK(result)) {
9493 #if 0 /* FIXME - gd */
9494 /* housekeeping information in the reply */
9496 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9497 * the hand marshalled container size is a multiple
9498 * of 4 bytes for RPC alignment.
9502 needed += 4-(needed % 4);
9505 *r->out.count = count;
9506 *r->out.info = info;
9511 free_a_printer(&printer, 2);
9514 if (!W_ERROR_IS_OK(result)) {
9518 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9519 spoolss_EnumPrinterDataEx, NULL,
9522 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9523 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9525 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9528 /****************************************************************************
9529 ****************************************************************************/
9531 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9532 const char *servername,
9533 const char *environment,
9534 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9539 werr = compose_spoolss_server_path(mem_ctx,
9542 SPOOLSS_PRTPROCS_PATH,
9544 if (!W_ERROR_IS_OK(werr)) {
9548 DEBUG(4,("print processor directory: [%s]\n", path));
9550 r->directory_name = path;
9555 /****************************************************************
9556 _spoolss_GetPrintProcessorDirectory
9557 ****************************************************************/
9559 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9560 struct spoolss_GetPrintProcessorDirectory *r)
9564 /* that's an [in out] buffer */
9566 if (!r->in.buffer && (r->in.offered != 0)) {
9567 return WERR_INVALID_PARAM;
9570 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9575 /* r->in.level is ignored */
9577 /* We always should reply with a local print processor directory so that
9578 * users are not forced to have a [prnproc$] share on the Samba spoolss
9579 * server - Guenther */
9581 result = getprintprocessordirectory_level_1(p->mem_ctx,
9582 NULL, /* r->in.server */
9584 &r->out.info->info1);
9585 if (!W_ERROR_IS_OK(result)) {
9586 TALLOC_FREE(r->out.info);
9590 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9591 r->out.info, r->in.level);
9592 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9594 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9597 /*******************************************************************
9598 ********************************************************************/
9600 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9601 const char *dllname)
9603 enum ndr_err_code ndr_err;
9604 struct spoolss_MonitorUi ui;
9606 ui.dll_name = dllname;
9608 ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9609 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9610 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9611 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9613 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9616 /*******************************************************************
9617 Streams the monitor UI DLL name in UNICODE
9618 *******************************************************************/
9620 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9621 NT_USER_TOKEN *token, DATA_BLOB *in,
9622 DATA_BLOB *out, uint32_t *needed)
9624 const char *dllname = "tcpmonui.dll";
9626 *needed = (strlen(dllname)+1) * 2;
9628 if (out->length < *needed) {
9629 return WERR_INSUFFICIENT_BUFFER;
9632 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9639 /*******************************************************************
9640 ********************************************************************/
9642 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9643 struct spoolss_PortData1 *port1,
9644 const DATA_BLOB *buf)
9646 enum ndr_err_code ndr_err;
9647 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9648 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9649 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9650 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9652 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9655 /*******************************************************************
9656 ********************************************************************/
9658 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9659 struct spoolss_PortData2 *port2,
9660 const DATA_BLOB *buf)
9662 enum ndr_err_code ndr_err;
9663 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9664 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9665 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9666 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9668 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9671 /*******************************************************************
9672 Create a new TCP/IP port
9673 *******************************************************************/
9675 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9676 NT_USER_TOKEN *token, DATA_BLOB *in,
9677 DATA_BLOB *out, uint32_t *needed)
9679 struct spoolss_PortData1 port1;
9680 struct spoolss_PortData2 port2;
9681 char *device_uri = NULL;
9684 const char *portname;
9685 const char *hostaddress;
9687 uint32_t port_number;
9690 /* peek for spoolss_PortData version */
9692 if (!in || (in->length < (128 + 4))) {
9693 return WERR_GENERAL_FAILURE;
9696 version = IVAL(in->data, 128);
9702 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9706 portname = port1.portname;
9707 hostaddress = port1.hostaddress;
9708 queue = port1.queue;
9709 protocol = port1.protocol;
9710 port_number = port1.port_number;
9716 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9720 portname = port2.portname;
9721 hostaddress = port2.hostaddress;
9722 queue = port2.queue;
9723 protocol = port2.protocol;
9724 port_number = port2.port_number;
9728 DEBUG(1,("xcvtcp_addport: "
9729 "unknown version of port_data: %d\n", version));
9730 return WERR_UNKNOWN_PORT;
9733 /* create the device URI and call the add_port_hook() */
9736 case PROTOCOL_RAWTCP_TYPE:
9737 device_uri = talloc_asprintf(mem_ctx,
9738 "socket://%s:%d/", hostaddress,
9742 case PROTOCOL_LPR_TYPE:
9743 device_uri = talloc_asprintf(mem_ctx,
9744 "lpr://%s/%s", hostaddress, queue );
9748 return WERR_UNKNOWN_PORT;
9755 return add_port_hook(mem_ctx, token, portname, device_uri);
9758 /*******************************************************************
9759 *******************************************************************/
9761 struct xcv_api_table xcvtcp_cmds[] = {
9762 { "MonitorUI", xcvtcp_monitorui },
9763 { "AddPort", xcvtcp_addport},
9767 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9768 NT_USER_TOKEN *token, const char *command,
9775 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9777 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9778 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9779 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9782 return WERR_BADFUNC;
9785 /*******************************************************************
9786 *******************************************************************/
9787 #if 0 /* don't support management using the "Local Port" monitor */
9789 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9790 NT_USER_TOKEN *token, DATA_BLOB *in,
9791 DATA_BLOB *out, uint32_t *needed)
9793 const char *dllname = "localui.dll";
9795 *needed = (strlen(dllname)+1) * 2;
9797 if (out->length < *needed) {
9798 return WERR_INSUFFICIENT_BUFFER;
9801 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9808 /*******************************************************************
9809 *******************************************************************/
9811 struct xcv_api_table xcvlocal_cmds[] = {
9812 { "MonitorUI", xcvlocal_monitorui },
9816 struct xcv_api_table xcvlocal_cmds[] = {
9823 /*******************************************************************
9824 *******************************************************************/
9826 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9827 NT_USER_TOKEN *token, const char *command,
9828 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9833 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9835 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9836 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9837 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9839 return WERR_BADFUNC;
9842 /****************************************************************
9844 ****************************************************************/
9846 WERROR _spoolss_XcvData(pipes_struct *p,
9847 struct spoolss_XcvData *r)
9849 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9850 DATA_BLOB out_data = data_blob_null;
9854 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9855 OUR_HANDLE(r->in.handle)));
9859 /* Has to be a handle to the TCP/IP port monitor */
9861 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9862 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9866 /* requires administrative access to the server */
9868 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9869 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9870 return WERR_ACCESS_DENIED;
9873 /* Allocate the outgoing buffer */
9875 if (r->in.out_data_size) {
9876 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9877 if (out_data.data == NULL) {
9882 switch ( Printer->printer_type ) {
9883 case SPLHND_PORTMON_TCP:
9884 werror = process_xcvtcp_command(p->mem_ctx,
9885 p->server_info->ptok,
9886 r->in.function_name,
9887 &r->in.in_data, &out_data,
9890 case SPLHND_PORTMON_LOCAL:
9891 werror = process_xcvlocal_command(p->mem_ctx,
9892 p->server_info->ptok,
9893 r->in.function_name,
9894 &r->in.in_data, &out_data,
9898 werror = WERR_INVALID_PRINT_MONITOR;
9901 if (!W_ERROR_IS_OK(werror)) {
9905 *r->out.status_code = 0;
9907 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9908 memcpy(r->out.out_data, out_data.data,
9909 MIN(r->in.out_data_size, out_data.length));
9915 /****************************************************************
9916 _spoolss_AddPrintProcessor
9917 ****************************************************************/
9919 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9920 struct spoolss_AddPrintProcessor *r)
9922 /* for now, just indicate success and ignore the add. We'll
9923 automatically set the winprint processor for printer
9924 entries later. Used to debug the LexMark Optra S 1855 PCL
9930 /****************************************************************
9932 ****************************************************************/
9934 WERROR _spoolss_AddPort(pipes_struct *p,
9935 struct spoolss_AddPort *r)
9937 /* do what w2k3 does */
9939 return WERR_NOT_SUPPORTED;
9942 /****************************************************************
9944 ****************************************************************/
9946 WERROR _spoolss_AddPrinter(pipes_struct *p,
9947 struct spoolss_AddPrinter *r)
9949 p->rng_fault_state = true;
9950 return WERR_NOT_SUPPORTED;
9953 /****************************************************************
9954 _spoolss_GetPrinterDriver
9955 ****************************************************************/
9957 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9958 struct spoolss_GetPrinterDriver *r)
9960 p->rng_fault_state = true;
9961 return WERR_NOT_SUPPORTED;
9964 /****************************************************************
9965 _spoolss_ReadPrinter
9966 ****************************************************************/
9968 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9969 struct spoolss_ReadPrinter *r)
9971 p->rng_fault_state = true;
9972 return WERR_NOT_SUPPORTED;
9975 /****************************************************************
9976 _spoolss_WaitForPrinterChange
9977 ****************************************************************/
9979 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9980 struct spoolss_WaitForPrinterChange *r)
9982 p->rng_fault_state = true;
9983 return WERR_NOT_SUPPORTED;
9986 /****************************************************************
9987 _spoolss_ConfigurePort
9988 ****************************************************************/
9990 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9991 struct spoolss_ConfigurePort *r)
9993 p->rng_fault_state = true;
9994 return WERR_NOT_SUPPORTED;
9997 /****************************************************************
9999 ****************************************************************/
10001 WERROR _spoolss_DeletePort(pipes_struct *p,
10002 struct spoolss_DeletePort *r)
10004 p->rng_fault_state = true;
10005 return WERR_NOT_SUPPORTED;
10008 /****************************************************************
10009 _spoolss_CreatePrinterIC
10010 ****************************************************************/
10012 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10013 struct spoolss_CreatePrinterIC *r)
10015 p->rng_fault_state = true;
10016 return WERR_NOT_SUPPORTED;
10019 /****************************************************************
10020 _spoolss_PlayGDIScriptOnPrinterIC
10021 ****************************************************************/
10023 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10024 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10026 p->rng_fault_state = true;
10027 return WERR_NOT_SUPPORTED;
10030 /****************************************************************
10031 _spoolss_DeletePrinterIC
10032 ****************************************************************/
10034 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10035 struct spoolss_DeletePrinterIC *r)
10037 p->rng_fault_state = true;
10038 return WERR_NOT_SUPPORTED;
10041 /****************************************************************
10042 _spoolss_AddPrinterConnection
10043 ****************************************************************/
10045 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10046 struct spoolss_AddPrinterConnection *r)
10048 p->rng_fault_state = true;
10049 return WERR_NOT_SUPPORTED;
10052 /****************************************************************
10053 _spoolss_DeletePrinterConnection
10054 ****************************************************************/
10056 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10057 struct spoolss_DeletePrinterConnection *r)
10059 p->rng_fault_state = true;
10060 return WERR_NOT_SUPPORTED;
10063 /****************************************************************
10064 _spoolss_PrinterMessageBox
10065 ****************************************************************/
10067 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10068 struct spoolss_PrinterMessageBox *r)
10070 p->rng_fault_state = true;
10071 return WERR_NOT_SUPPORTED;
10074 /****************************************************************
10075 _spoolss_AddMonitor
10076 ****************************************************************/
10078 WERROR _spoolss_AddMonitor(pipes_struct *p,
10079 struct spoolss_AddMonitor *r)
10081 p->rng_fault_state = true;
10082 return WERR_NOT_SUPPORTED;
10085 /****************************************************************
10086 _spoolss_DeleteMonitor
10087 ****************************************************************/
10089 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10090 struct spoolss_DeleteMonitor *r)
10092 p->rng_fault_state = true;
10093 return WERR_NOT_SUPPORTED;
10096 /****************************************************************
10097 _spoolss_DeletePrintProcessor
10098 ****************************************************************/
10100 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10101 struct spoolss_DeletePrintProcessor *r)
10103 p->rng_fault_state = true;
10104 return WERR_NOT_SUPPORTED;
10107 /****************************************************************
10108 _spoolss_AddPrintProvidor
10109 ****************************************************************/
10111 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10112 struct spoolss_AddPrintProvidor *r)
10114 p->rng_fault_state = true;
10115 return WERR_NOT_SUPPORTED;
10118 /****************************************************************
10119 _spoolss_DeletePrintProvidor
10120 ****************************************************************/
10122 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10123 struct spoolss_DeletePrintProvidor *r)
10125 p->rng_fault_state = true;
10126 return WERR_NOT_SUPPORTED;
10129 /****************************************************************
10130 _spoolss_FindFirstPrinterChangeNotification
10131 ****************************************************************/
10133 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10134 struct spoolss_FindFirstPrinterChangeNotification *r)
10136 p->rng_fault_state = true;
10137 return WERR_NOT_SUPPORTED;
10140 /****************************************************************
10141 _spoolss_FindNextPrinterChangeNotification
10142 ****************************************************************/
10144 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10145 struct spoolss_FindNextPrinterChangeNotification *r)
10147 p->rng_fault_state = true;
10148 return WERR_NOT_SUPPORTED;
10151 /****************************************************************
10152 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10153 ****************************************************************/
10155 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10156 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10158 p->rng_fault_state = true;
10159 return WERR_NOT_SUPPORTED;
10162 /****************************************************************
10163 _spoolss_ReplyOpenPrinter
10164 ****************************************************************/
10166 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10167 struct spoolss_ReplyOpenPrinter *r)
10169 p->rng_fault_state = true;
10170 return WERR_NOT_SUPPORTED;
10173 /****************************************************************
10174 _spoolss_RouterReplyPrinter
10175 ****************************************************************/
10177 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10178 struct spoolss_RouterReplyPrinter *r)
10180 p->rng_fault_state = true;
10181 return WERR_NOT_SUPPORTED;
10184 /****************************************************************
10185 _spoolss_ReplyClosePrinter
10186 ****************************************************************/
10188 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10189 struct spoolss_ReplyClosePrinter *r)
10191 p->rng_fault_state = true;
10192 return WERR_NOT_SUPPORTED;
10195 /****************************************************************
10197 ****************************************************************/
10199 WERROR _spoolss_AddPortEx(pipes_struct *p,
10200 struct spoolss_AddPortEx *r)
10202 p->rng_fault_state = true;
10203 return WERR_NOT_SUPPORTED;
10206 /****************************************************************
10207 _spoolss_RouterFindFirstPrinterChangeNotification
10208 ****************************************************************/
10210 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10211 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10213 p->rng_fault_state = true;
10214 return WERR_NOT_SUPPORTED;
10217 /****************************************************************
10218 _spoolss_SpoolerInit
10219 ****************************************************************/
10221 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10222 struct spoolss_SpoolerInit *r)
10224 p->rng_fault_state = true;
10225 return WERR_NOT_SUPPORTED;
10228 /****************************************************************
10229 _spoolss_ResetPrinterEx
10230 ****************************************************************/
10232 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10233 struct spoolss_ResetPrinterEx *r)
10235 p->rng_fault_state = true;
10236 return WERR_NOT_SUPPORTED;
10239 /****************************************************************
10240 _spoolss_RouterReplyPrinterEx
10241 ****************************************************************/
10243 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10244 struct spoolss_RouterReplyPrinterEx *r)
10246 p->rng_fault_state = true;
10247 return WERR_NOT_SUPPORTED;
10250 /****************************************************************
10252 ****************************************************************/
10254 WERROR _spoolss_44(pipes_struct *p,
10255 struct spoolss_44 *r)
10257 p->rng_fault_state = true;
10258 return WERR_NOT_SUPPORTED;
10261 /****************************************************************
10263 ****************************************************************/
10265 WERROR _spoolss_47(pipes_struct *p,
10266 struct spoolss_47 *r)
10268 p->rng_fault_state = true;
10269 return WERR_NOT_SUPPORTED;
10272 /****************************************************************
10274 ****************************************************************/
10276 WERROR _spoolss_4a(pipes_struct *p,
10277 struct spoolss_4a *r)
10279 p->rng_fault_state = true;
10280 return WERR_NOT_SUPPORTED;
10283 /****************************************************************
10285 ****************************************************************/
10287 WERROR _spoolss_4b(pipes_struct *p,
10288 struct spoolss_4b *r)
10290 p->rng_fault_state = true;
10291 return WERR_NOT_SUPPORTED;
10294 /****************************************************************
10296 ****************************************************************/
10298 WERROR _spoolss_4c(pipes_struct *p,
10299 struct spoolss_4c *r)
10301 p->rng_fault_state = true;
10302 return WERR_NOT_SUPPORTED;
10305 /****************************************************************
10307 ****************************************************************/
10309 WERROR _spoolss_53(pipes_struct *p,
10310 struct spoolss_53 *r)
10312 p->rng_fault_state = true;
10313 return WERR_NOT_SUPPORTED;
10316 /****************************************************************
10318 ****************************************************************/
10320 WERROR _spoolss_55(pipes_struct *p,
10321 struct spoolss_55 *r)
10323 p->rng_fault_state = true;
10324 return WERR_NOT_SUPPORTED;
10327 /****************************************************************
10329 ****************************************************************/
10331 WERROR _spoolss_56(pipes_struct *p,
10332 struct spoolss_56 *r)
10334 p->rng_fault_state = true;
10335 return WERR_NOT_SUPPORTED;
10338 /****************************************************************
10340 ****************************************************************/
10342 WERROR _spoolss_57(pipes_struct *p,
10343 struct spoolss_57 *r)
10345 p->rng_fault_state = true;
10346 return WERR_NOT_SUPPORTED;
10349 /****************************************************************
10351 ****************************************************************/
10353 WERROR _spoolss_5a(pipes_struct *p,
10354 struct spoolss_5a *r)
10356 p->rng_fault_state = true;
10357 return WERR_NOT_SUPPORTED;
10360 /****************************************************************
10362 ****************************************************************/
10364 WERROR _spoolss_5b(pipes_struct *p,
10365 struct spoolss_5b *r)
10367 p->rng_fault_state = true;
10368 return WERR_NOT_SUPPORTED;
10371 /****************************************************************
10373 ****************************************************************/
10375 WERROR _spoolss_5c(pipes_struct *p,
10376 struct spoolss_5c *r)
10378 p->rng_fault_state = true;
10379 return WERR_NOT_SUPPORTED;
10382 /****************************************************************
10384 ****************************************************************/
10386 WERROR _spoolss_5d(pipes_struct *p,
10387 struct spoolss_5d *r)
10389 p->rng_fault_state = true;
10390 return WERR_NOT_SUPPORTED;
10393 /****************************************************************
10395 ****************************************************************/
10397 WERROR _spoolss_5e(pipes_struct *p,
10398 struct spoolss_5e *r)
10400 p->rng_fault_state = true;
10401 return WERR_NOT_SUPPORTED;
10404 /****************************************************************
10406 ****************************************************************/
10408 WERROR _spoolss_5f(pipes_struct *p,
10409 struct spoolss_5f *r)
10411 p->rng_fault_state = true;
10412 return WERR_NOT_SUPPORTED;