2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 extern userdom_struct current_user_info;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 /* Table to map the driver version */
46 static const char * drv_ver_to_os[] = {
47 "WIN9X", /* driver version/cversion 0 */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
53 static const char *get_drv_ver_to_os(int ver)
55 if (ver < 0 || ver > 3)
57 return drv_ver_to_os[ver];
61 const char *long_archi;
62 const char *short_archi;
66 static Printer_entry *printers_list;
68 typedef struct _counter_printer_0 {
69 struct _counter_printer_0 *next;
70 struct _counter_printer_0 *prev;
76 static counter_printer_0 *counter_list;
78 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
79 static uint32 smb_connections=0;
82 /* in printing/nt_printing.c */
84 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
86 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
87 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v)
96 return JOB_STATUS_PAUSED;
98 return JOB_STATUS_SPOOLING;
100 return JOB_STATUS_PRINTING;
102 return JOB_STATUS_ERROR;
104 return JOB_STATUS_DELETING;
106 return JOB_STATUS_OFFLINE;
108 return JOB_STATUS_PAPEROUT;
110 return JOB_STATUS_PRINTED;
112 return JOB_STATUS_DELETED;
114 return JOB_STATUS_BLOCKED;
115 case LPQ_USER_INTERVENTION:
116 return JOB_STATUS_USER_INTERVENTION;
121 static int nt_printq_status(int v)
125 return PRINTER_STATUS_PAUSED;
134 /****************************************************************************
135 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
136 ****************************************************************************/
138 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
143 SAFE_FREE((*pp)->ctr.type);
147 /***************************************************************************
148 Disconnect from the client
149 ****************************************************************************/
151 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
169 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
171 if (!W_ERROR_IS_OK(result))
172 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
173 dos_errstr(result)));
175 /* if it's the last connection, deconnect the IPC$ share */
176 if (smb_connections==1) {
178 cli_shutdown( notify_cli_pipe->cli );
179 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
181 message_deregister(MSG_PRINTER_NOTIFY2);
183 /* Tell the connections db we're no longer interested in
184 * printer notify messages. */
186 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
192 /****************************************************************************
193 Functions to free a printer entry datastruct.
194 ****************************************************************************/
196 static void free_printer_entry(void *ptr)
198 Printer_entry *Printer = (Printer_entry *)ptr;
200 if (Printer->notify.client_connected==True) {
203 if ( Printer->printer_type == SPLHND_SERVER) {
205 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
206 } else if (Printer->printer_type == SPLHND_PRINTER) {
207 snum = print_queue_snum(Printer->sharename);
209 srv_spoolss_replycloseprinter(snum,
210 &Printer->notify.client_hnd);
214 Printer->notify.flags=0;
215 Printer->notify.options=0;
216 Printer->notify.localmachine[0]='\0';
217 Printer->notify.printerlocal=0;
218 free_spool_notify_option(&Printer->notify.option);
219 Printer->notify.option=NULL;
220 Printer->notify.client_connected=False;
222 free_nt_devicemode( &Printer->nt_devmode );
223 free_a_printer( &Printer->printer_info, 2 );
225 talloc_destroy( Printer->ctx );
227 /* Remove from the internal list. */
228 DLIST_REMOVE(printers_list, Printer);
233 /****************************************************************************
234 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
235 ****************************************************************************/
237 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
239 SPOOL_NOTIFY_OPTION *new_sp = NULL;
244 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
251 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
253 if (!new_sp->ctr.type) {
262 /****************************************************************************
263 find printer index by handle
264 ****************************************************************************/
266 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
268 Printer_entry *find_printer = NULL;
270 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
271 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
278 /****************************************************************************
279 Close printer index by handle.
280 ****************************************************************************/
282 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
284 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
287 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
291 close_policy_hnd(p, hnd);
296 /****************************************************************************
297 Delete a printer given a handle.
298 ****************************************************************************/
299 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
301 char *cmd = lp_deleteprinter_cmd();
304 SE_PRIV se_printop = SE_PRINT_OPERATOR;
305 BOOL is_print_op = False;
307 /* can't fail if we don't try */
312 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
315 is_print_op = user_has_privileges( token, &se_printop );
317 DEBUG(10,("Running [%s]\n", command));
319 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
324 if ( (ret = smbrun(command, NULL)) == 0 ) {
325 /* Tell everyone we updated smb.conf. */
326 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
332 /********** END SePrintOperatorPrivlege BLOCK **********/
334 DEBUGADD(10,("returned [%d]\n", ret));
337 return WERR_BADFID; /* What to return here? */
339 /* go ahead and re-read the services immediately */
340 reload_services( False );
342 if ( lp_servicenumber( sharename ) < 0 )
343 return WERR_ACCESS_DENIED;
348 /****************************************************************************
349 Delete a printer given a handle.
350 ****************************************************************************/
352 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
354 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
357 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
362 * It turns out that Windows allows delete printer on a handle
363 * opened by an admin user, then used on a pipe handle created
364 * by an anonymous user..... but they're working on security.... riiight !
368 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
369 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
370 return WERR_ACCESS_DENIED;
373 /* this does not need a become root since the access check has been
374 done on the handle already */
376 if (del_a_printer( Printer->sharename ) != 0) {
377 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
381 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
384 /****************************************************************************
385 Return the snum of a printer corresponding to an handle.
386 ****************************************************************************/
388 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
390 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
393 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
397 switch (Printer->printer_type) {
399 DEBUG(4,("short name:%s\n", Printer->sharename));
400 *number = print_queue_snum(Printer->sharename);
401 return (*number != -1);
409 /****************************************************************************
410 Set printer handle type.
411 Check if it's \\server or \\server\printer
412 ****************************************************************************/
414 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
416 DEBUG(3,("Setting printer type=%s\n", handlename));
418 if ( strlen(handlename) < 3 ) {
419 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
423 /* it's a print server */
424 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
425 DEBUGADD(4,("Printer is a print server\n"));
426 Printer->printer_type = SPLHND_SERVER;
428 /* it's a printer (set_printer_hnd_name() will handle port monitors */
430 DEBUGADD(4,("Printer is a printer\n"));
431 Printer->printer_type = SPLHND_PRINTER;
437 /****************************************************************************
438 Set printer handle name.. Accept names like \\server, \\server\printer,
439 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
440 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
441 XcvDataPort() interface.
442 ****************************************************************************/
444 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
447 int n_services=lp_numservices();
448 char *aprinter, *printername;
449 const char *servername;
452 NT_PRINTER_INFO_LEVEL *printer;
455 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
457 aprinter = handlename;
458 if ( *handlename == '\\' ) {
459 servername = handlename + 2;
460 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
469 /* save the servername to fill in replies on this handle */
471 if ( !is_myname_or_ipaddr( servername ) )
474 fstrcpy( Printer->servername, servername );
476 if ( Printer->printer_type == SPLHND_SERVER )
479 if ( Printer->printer_type != SPLHND_PRINTER )
482 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
484 /* check for the Port Monitor Interface */
486 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
487 Printer->printer_type = SPLHND_PORTMON_TCP;
488 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
491 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
492 Printer->printer_type = SPLHND_PORTMON_LOCAL;
493 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
497 /* Search all sharenames first as this is easier than pulling
498 the printer_info_2 off of disk. Don't use find_service() since
499 that calls out to map_username() */
501 /* do another loop to look for printernames */
503 for (snum=0; !found && snum<n_services; snum++) {
505 /* no point going on if this is not a printer */
507 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
510 fstrcpy(sname, lp_servicename(snum));
511 if ( strequal( aprinter, sname ) ) {
516 /* no point looking up the printer object if
517 we aren't allowing printername != sharename */
519 if ( lp_force_printername(snum) )
522 fstrcpy(sname, lp_servicename(snum));
525 result = get_a_printer( NULL, &printer, 2, sname );
526 if ( !W_ERROR_IS_OK(result) ) {
527 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
528 sname, dos_errstr(result)));
532 /* printername is always returned as \\server\printername */
533 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
534 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
535 printer->info_2->printername));
536 free_a_printer( &printer, 2);
542 if ( strequal(printername, aprinter) ) {
547 DEBUGADD(10, ("printername: %s\n", printername));
549 free_a_printer( &printer, 2);
553 DEBUGADD(4,("Printer not found\n"));
557 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
559 fstrcpy(Printer->sharename, sname);
564 /****************************************************************************
565 Find first available printer slot. creates a printer handle for you.
566 ****************************************************************************/
568 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
570 Printer_entry *new_printer;
572 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
574 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
577 ZERO_STRUCTP(new_printer);
579 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
580 SAFE_FREE(new_printer);
584 /* Add to the internal list. */
585 DLIST_ADD(printers_list, new_printer);
587 new_printer->notify.option=NULL;
589 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
590 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
591 close_printer_handle(p, hnd);
595 if (!set_printer_hnd_printertype(new_printer, name)) {
596 close_printer_handle(p, hnd);
600 if (!set_printer_hnd_name(new_printer, name)) {
601 close_printer_handle(p, hnd);
605 new_printer->access_granted = access_granted;
607 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
612 /***************************************************************************
613 check to see if the client motify handle is monitoring the notification
614 given by (notify_type, notify_field).
615 **************************************************************************/
617 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
623 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
626 SPOOL_NOTIFY_OPTION *option = p->notify.option;
630 * Flags should always be zero when the change notify
631 * is registered by the client's spooler. A user Win32 app
632 * might use the flags though instead of the NOTIFY_OPTION_INFO
641 return is_monitoring_event_flags(
642 p->notify.flags, notify_type, notify_field);
644 for (i = 0; i < option->count; i++) {
646 /* Check match for notify_type */
648 if (option->ctr.type[i].type != notify_type)
651 /* Check match for field */
653 for (j = 0; j < option->ctr.type[i].count; j++) {
654 if (option->ctr.type[i].fields[j] == notify_field) {
660 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
661 p->servername, p->sharename, notify_type, notify_field));
666 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
668 static void notify_one_value(struct spoolss_notify_msg *msg,
669 SPOOL_NOTIFY_INFO_DATA *data,
672 data->notify_data.value[0] = msg->notify.value[0];
673 data->notify_data.value[1] = 0;
676 static void notify_string(struct spoolss_notify_msg *msg,
677 SPOOL_NOTIFY_INFO_DATA *data,
682 /* The length of the message includes the trailing \0 */
684 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
686 data->notify_data.data.length = msg->len * 2;
687 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
689 if (!data->notify_data.data.string) {
690 data->notify_data.data.length = 0;
694 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
697 static void notify_system_time(struct spoolss_notify_msg *msg,
698 SPOOL_NOTIFY_INFO_DATA *data,
704 if (msg->len != sizeof(time_t)) {
705 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
710 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
711 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
715 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
716 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
720 if (!spoolss_io_system_time("", &ps, 0, &systime))
723 data->notify_data.data.length = prs_offset(&ps);
724 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
726 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
731 struct notify2_message_table {
733 void (*fn)(struct spoolss_notify_msg *msg,
734 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
737 static struct notify2_message_table printer_notify_table[] = {
738 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
739 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
740 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
741 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
742 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
743 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
744 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
745 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
746 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
747 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
748 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
749 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
750 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
751 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
752 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
753 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
754 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
755 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
756 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
759 static struct notify2_message_table job_notify_table[] = {
760 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
761 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
762 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
763 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
764 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
765 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
766 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
767 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
768 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
769 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
770 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
771 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
772 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
773 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
774 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
775 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
776 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
777 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
778 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
779 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
780 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
781 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
782 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
783 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
787 /***********************************************************************
788 Allocate talloc context for container object
789 **********************************************************************/
791 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
796 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
801 /***********************************************************************
802 release all allocated memory and zero out structure
803 **********************************************************************/
805 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
811 talloc_destroy(ctr->ctx);
818 /***********************************************************************
819 **********************************************************************/
821 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
829 /***********************************************************************
830 **********************************************************************/
832 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
834 if ( !ctr || !ctr->msg_groups )
837 if ( idx >= ctr->num_groups )
840 return &ctr->msg_groups[idx];
844 /***********************************************************************
845 How many groups of change messages do we have ?
846 **********************************************************************/
848 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
853 return ctr->num_groups;
856 /***********************************************************************
857 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
858 **********************************************************************/
860 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
862 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
863 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
864 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
870 /* loop over all groups looking for a matching printer name */
872 for ( i=0; i<ctr->num_groups; i++ ) {
873 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
877 /* add a new group? */
879 if ( i == ctr->num_groups ) {
882 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
883 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
886 ctr->msg_groups = groups;
888 /* clear the new entry and set the printer name */
890 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
891 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
894 /* add the change messages; 'i' is the correct index now regardless */
896 msg_grp = &ctr->msg_groups[i];
900 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
901 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
904 msg_grp->msgs = msg_list;
906 new_slot = msg_grp->num_msgs-1;
907 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
909 /* need to allocate own copy of data */
912 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
914 return ctr->num_groups;
917 /***********************************************************************
918 Send a change notication message on all handles which have a call
920 **********************************************************************/
922 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
925 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
926 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
927 SPOOLSS_NOTIFY_MSG *messages;
928 int sending_msg_count;
931 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
935 messages = msg_group->msgs;
938 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
942 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
944 /* loop over all printers */
946 for (p = printers_list; p; p = p->next) {
947 SPOOL_NOTIFY_INFO_DATA *data;
952 /* Is there notification on this handle? */
954 if ( !p->notify.client_connected )
957 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
959 /* For this printer? Print servers always receive
962 if ( ( p->printer_type == SPLHND_PRINTER ) &&
963 ( !strequal(msg_group->printername, p->sharename) ) )
966 DEBUG(10,("Our printer\n"));
968 /* allocate the max entries possible */
970 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
973 /* build the array of change notifications */
975 sending_msg_count = 0;
977 for ( i=0; i<msg_group->num_msgs; i++ ) {
978 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
980 /* Are we monitoring this event? */
982 if (!is_monitoring_event(p, msg->type, msg->field))
988 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
989 msg->type, msg->field, p->sharename));
992 * if the is a printer notification handle and not a job notification
993 * type, then set the id to 0. Other wise just use what was specified
996 * When registering change notification on a print server handle
997 * we always need to send back the id (snum) matching the printer
998 * for which the change took place. For change notify registered
999 * on a printer handle, this does not matter and the id should be 0.
1004 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1010 /* Convert unix jobid to smb jobid */
1012 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1013 id = sysjob_to_jobid(msg->id);
1016 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1021 construct_info_data( &data[data_len], msg->type, msg->field, id );
1024 case PRINTER_NOTIFY_TYPE:
1025 if ( printer_notify_table[msg->field].fn )
1026 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1029 case JOB_NOTIFY_TYPE:
1030 if ( job_notify_table[msg->field].fn )
1031 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1035 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1042 if ( sending_msg_count ) {
1043 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1044 data_len, data, p->notify.change, 0 );
1049 DEBUG(8,("send_notify2_changes: Exit...\n"));
1053 /***********************************************************************
1054 **********************************************************************/
1056 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1059 uint32 tv_sec, tv_usec;
1062 /* Unpack message */
1064 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1067 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1069 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1072 tdb_unpack((char *)buf + offset, len - offset, "dd",
1073 &msg->notify.value[0], &msg->notify.value[1]);
1075 tdb_unpack((char *)buf + offset, len - offset, "B",
1076 &msg->len, &msg->notify.data);
1078 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1079 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1081 tv->tv_sec = tv_sec;
1082 tv->tv_usec = tv_usec;
1085 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1086 msg->notify.value[1]));
1088 dump_data(3, msg->notify.data, msg->len);
1093 /********************************************************************
1094 Receive a notify2 message list
1095 ********************************************************************/
1097 static void receive_notify2_message_list(int msg_type, struct process_id src,
1098 void *msg, size_t len)
1100 size_t msg_count, i;
1101 char *buf = (char *)msg;
1104 SPOOLSS_NOTIFY_MSG notify;
1105 SPOOLSS_NOTIFY_MSG_CTR messages;
1109 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1113 msg_count = IVAL(buf, 0);
1116 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1118 if (msg_count == 0) {
1119 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1123 /* initialize the container */
1125 ZERO_STRUCT( messages );
1126 notify_msg_ctr_init( &messages );
1129 * build message groups for each printer identified
1130 * in a change_notify msg. Remember that a PCN message
1131 * includes the handle returned for the srv_spoolss_replyopenprinter()
1132 * call. Therefore messages are grouped according to printer handle.
1135 for ( i=0; i<msg_count; i++ ) {
1136 struct timeval msg_tv;
1138 if (msg_ptr + 4 - buf > len) {
1139 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1143 msg_len = IVAL(msg_ptr,0);
1146 if (msg_ptr + msg_len - buf > len) {
1147 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1151 /* unpack messages */
1153 ZERO_STRUCT( notify );
1154 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1157 /* add to correct list in container */
1159 notify_msg_ctr_addmsg( &messages, ¬ify );
1161 /* free memory that might have been allocated by notify2_unpack_msg() */
1163 if ( notify.len != 0 )
1164 SAFE_FREE( notify.notify.data );
1167 /* process each group of messages */
1169 num_groups = notify_msg_ctr_numgroups( &messages );
1170 for ( i=0; i<num_groups; i++ )
1171 send_notify2_changes( &messages, i );
1176 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1178 notify_msg_ctr_destroy( &messages );
1183 /********************************************************************
1184 Send a message to ourself about new driver being installed
1185 so we can upgrade the information for each printer bound to this
1187 ********************************************************************/
1189 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1191 int len = strlen(drivername);
1196 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1199 message_send_pid(pid_to_procid(sys_getpid()),
1200 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1205 /**********************************************************************
1206 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1207 over all printers, upgrading ones as necessary
1208 **********************************************************************/
1210 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1214 int n_services = lp_numservices();
1216 len = MIN(len,sizeof(drivername)-1);
1217 strncpy(drivername, buf, len);
1219 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1221 /* Iterate the printer list */
1223 for (snum=0; snum<n_services; snum++)
1225 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1228 NT_PRINTER_INFO_LEVEL *printer = NULL;
1230 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1231 if (!W_ERROR_IS_OK(result))
1234 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1236 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1238 /* all we care about currently is the change_id */
1240 result = mod_a_printer(printer, 2);
1241 if (!W_ERROR_IS_OK(result)) {
1242 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1243 dos_errstr(result)));
1247 free_a_printer(&printer, 2);
1254 /********************************************************************
1255 Update the cache for all printq's with a registered client
1257 ********************************************************************/
1259 void update_monitored_printq_cache( void )
1261 Printer_entry *printer = printers_list;
1264 /* loop through all printers and update the cache where
1265 client_connected == True */
1268 if ( (printer->printer_type == SPLHND_PRINTER)
1269 && printer->notify.client_connected )
1271 snum = print_queue_snum(printer->sharename);
1272 print_queue_status( snum, NULL, NULL );
1275 printer = printer->next;
1280 /********************************************************************
1281 Send a message to ourself about new driver being installed
1282 so we can upgrade the information for each printer bound to this
1284 ********************************************************************/
1286 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1288 int len = strlen(drivername);
1293 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1296 message_send_pid(pid_to_procid(sys_getpid()),
1297 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1302 /**********************************************************************
1303 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1304 over all printers, resetting printer data as neessary
1305 **********************************************************************/
1307 void reset_all_printerdata(int msg_type, struct process_id src,
1308 void *buf, size_t len)
1312 int n_services = lp_numservices();
1314 len = MIN( len, sizeof(drivername)-1 );
1315 strncpy( drivername, buf, len );
1317 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1319 /* Iterate the printer list */
1321 for ( snum=0; snum<n_services; snum++ )
1323 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1326 NT_PRINTER_INFO_LEVEL *printer = NULL;
1328 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1329 if ( !W_ERROR_IS_OK(result) )
1333 * if the printer is bound to the driver,
1334 * then reset to the new driver initdata
1337 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1339 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1341 if ( !set_driver_init(printer, 2) ) {
1342 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1343 printer->info_2->printername, printer->info_2->drivername));
1346 result = mod_a_printer( printer, 2 );
1347 if ( !W_ERROR_IS_OK(result) ) {
1348 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1349 get_dos_error_msg(result)));
1353 free_a_printer( &printer, 2 );
1362 /********************************************************************
1363 Copy routines used by convert_to_openprinterex()
1364 *******************************************************************/
1366 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1374 DEBUG (8,("dup_devmode\n"));
1376 /* bulk copy first */
1378 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1382 /* dup the pointer members separately */
1384 len = unistrlen(devmode->devicename.buffer);
1386 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1387 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1392 len = unistrlen(devmode->formname.buffer);
1394 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1395 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1399 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1404 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1406 if (!new_ctr || !ctr)
1409 DEBUG(8,("copy_devmode_ctr\n"));
1411 new_ctr->size = ctr->size;
1412 new_ctr->devmode_ptr = ctr->devmode_ptr;
1414 if(ctr->devmode_ptr)
1415 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1418 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1420 if (!new_def || !def)
1423 DEBUG(8,("copy_printer_defaults\n"));
1425 new_def->datatype_ptr = def->datatype_ptr;
1427 if (def->datatype_ptr)
1428 copy_unistr2(&new_def->datatype, &def->datatype);
1430 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1432 new_def->access_required = def->access_required;
1435 /********************************************************************
1436 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1437 * SPOOL_Q_OPEN_PRINTER_EX structure
1438 ********************************************************************/
1440 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1442 if (!q_u_ex || !q_u)
1445 DEBUG(8,("convert_to_openprinterex\n"));
1447 if ( q_u->printername ) {
1448 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1449 if (q_u_ex->printername == NULL)
1451 copy_unistr2(q_u_ex->printername, q_u->printername);
1454 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1459 /********************************************************************
1460 * spoolss_open_printer
1462 * called from the spoolss dispatcher
1463 ********************************************************************/
1465 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1467 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1468 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1473 ZERO_STRUCT(q_u_ex);
1474 ZERO_STRUCT(r_u_ex);
1476 /* convert the OpenPrinter() call to OpenPrinterEx() */
1478 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1479 if (!W_ERROR_IS_OK(r_u_ex.status))
1480 return r_u_ex.status;
1482 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1484 /* convert back to OpenPrinter() */
1486 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1491 /********************************************************************
1492 ********************************************************************/
1494 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1496 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1497 POLICY_HND *handle = &r_u->handle;
1501 struct current_user user;
1502 Printer_entry *Printer=NULL;
1504 if ( !q_u->printername )
1505 return WERR_INVALID_PRINTER_NAME;
1507 /* some sanity check because you can open a printer or a print server */
1508 /* aka: \\server\printer or \\server */
1510 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1512 DEBUGADD(3,("checking name: %s\n",name));
1514 if (!open_printer_hnd(p, handle, name, 0))
1515 return WERR_INVALID_PRINTER_NAME;
1517 Printer=find_printer_index_by_hnd(p, handle);
1519 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1520 "handle we created for printer %s\n", name ));
1521 close_printer_handle(p,handle);
1522 return WERR_INVALID_PRINTER_NAME;
1525 get_current_user(&user, p);
1528 * First case: the user is opening the print server:
1530 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1531 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1533 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1534 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1535 * or if the user is listed in the smb.conf printer admin parameter.
1537 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1538 * client view printer folder, but does not show the MSAPW.
1540 * Note: this test needs code to check access rights here too. Jeremy
1541 * could you look at this?
1543 * Second case: the user is opening a printer:
1544 * NT doesn't let us connect to a printer if the connecting user
1545 * doesn't have print permission.
1547 * Third case: user is opening a Port Monitor
1548 * access checks same as opening a handle to the print server.
1551 switch (Printer->printer_type )
1554 case SPLHND_PORTMON_TCP:
1555 case SPLHND_PORTMON_LOCAL:
1556 /* Printserver handles use global struct... */
1560 /* Map standard access rights to object specific access rights */
1562 se_map_standard(&printer_default->access_required,
1563 &printserver_std_mapping);
1565 /* Deny any object specific bits that don't apply to print
1566 servers (i.e printer and job specific bits) */
1568 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1570 if (printer_default->access_required &
1571 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1572 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1573 close_printer_handle(p, handle);
1574 return WERR_ACCESS_DENIED;
1577 /* Allow admin access */
1579 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1581 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1583 if (!lp_ms_add_printer_wizard()) {
1584 close_printer_handle(p, handle);
1585 return WERR_ACCESS_DENIED;
1588 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1589 and not a printer admin, then fail */
1591 if ((user.ut.uid != 0) &&
1592 !user_has_privileges(user.nt_user_token,
1594 !token_contains_name_in_list(
1595 uidtoname(user.ut.uid), NULL,
1597 lp_printer_admin(snum))) {
1598 close_printer_handle(p, handle);
1599 return WERR_ACCESS_DENIED;
1602 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1606 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1609 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1610 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1612 /* We fall through to return WERR_OK */
1615 case SPLHND_PRINTER:
1616 /* NT doesn't let us connect to a printer if the connecting user
1617 doesn't have print permission. */
1619 if (!get_printer_snum(p, handle, &snum)) {
1620 close_printer_handle(p, handle);
1624 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1626 /* map an empty access mask to the minimum access mask */
1627 if (printer_default->access_required == 0x0)
1628 printer_default->access_required = PRINTER_ACCESS_USE;
1631 * If we are not serving the printer driver for this printer,
1632 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1633 * will keep NT clients happy --jerry
1636 if (lp_use_client_driver(snum)
1637 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1639 printer_default->access_required = PRINTER_ACCESS_USE;
1642 /* check smb.conf parameters and the the sec_desc */
1644 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1645 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1646 return WERR_ACCESS_DENIED;
1649 if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
1651 !print_access_check(&user, snum,
1652 printer_default->access_required)) {
1653 DEBUG(3, ("access DENIED for printer open\n"));
1654 close_printer_handle(p, handle);
1655 return WERR_ACCESS_DENIED;
1658 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1659 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1660 close_printer_handle(p, handle);
1661 return WERR_ACCESS_DENIED;
1664 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1665 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1667 printer_default->access_required = PRINTER_ACCESS_USE;
1669 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1670 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1675 /* sanity check to prevent programmer error */
1679 Printer->access_granted = printer_default->access_required;
1682 * If the client sent a devmode in the OpenPrinter() call, then
1683 * save it here in case we get a job submission on this handle
1686 if ( (Printer->printer_type != SPLHND_SERVER)
1687 && q_u->printer_default.devmode_cont.devmode_ptr )
1689 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1690 &Printer->nt_devmode );
1693 #if 0 /* JERRY -- I'm doubtful this is really effective */
1694 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1695 optimization in Windows 2000 clients --jerry */
1697 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1698 && (RA_WIN2K == get_remote_arch()) )
1700 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1701 sys_usleep( 500000 );
1708 /****************************************************************************
1709 ****************************************************************************/
1711 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1712 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1718 /* allocate memory if needed. Messy because
1719 convert_printer_info is used to update an existing
1720 printer or build a new one */
1722 if ( !printer->info_2 ) {
1723 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1724 if ( !printer->info_2 ) {
1725 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1730 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1731 printer->info_2->setuptime = time(NULL);
1739 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1740 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1746 printer->info_3=NULL;
1747 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1751 printer->info_6=NULL;
1752 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1762 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1763 NT_DEVICEMODE **pp_nt_devmode)
1765 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1768 * Ensure nt_devmode is a valid pointer
1769 * as we will be overwriting it.
1772 if (nt_devmode == NULL) {
1773 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1774 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1778 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1779 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1781 nt_devmode->specversion=devmode->specversion;
1782 nt_devmode->driverversion=devmode->driverversion;
1783 nt_devmode->size=devmode->size;
1784 nt_devmode->fields=devmode->fields;
1785 nt_devmode->orientation=devmode->orientation;
1786 nt_devmode->papersize=devmode->papersize;
1787 nt_devmode->paperlength=devmode->paperlength;
1788 nt_devmode->paperwidth=devmode->paperwidth;
1789 nt_devmode->scale=devmode->scale;
1790 nt_devmode->copies=devmode->copies;
1791 nt_devmode->defaultsource=devmode->defaultsource;
1792 nt_devmode->printquality=devmode->printquality;
1793 nt_devmode->color=devmode->color;
1794 nt_devmode->duplex=devmode->duplex;
1795 nt_devmode->yresolution=devmode->yresolution;
1796 nt_devmode->ttoption=devmode->ttoption;
1797 nt_devmode->collate=devmode->collate;
1799 nt_devmode->logpixels=devmode->logpixels;
1800 nt_devmode->bitsperpel=devmode->bitsperpel;
1801 nt_devmode->pelswidth=devmode->pelswidth;
1802 nt_devmode->pelsheight=devmode->pelsheight;
1803 nt_devmode->displayflags=devmode->displayflags;
1804 nt_devmode->displayfrequency=devmode->displayfrequency;
1805 nt_devmode->icmmethod=devmode->icmmethod;
1806 nt_devmode->icmintent=devmode->icmintent;
1807 nt_devmode->mediatype=devmode->mediatype;
1808 nt_devmode->dithertype=devmode->dithertype;
1809 nt_devmode->reserved1=devmode->reserved1;
1810 nt_devmode->reserved2=devmode->reserved2;
1811 nt_devmode->panningwidth=devmode->panningwidth;
1812 nt_devmode->panningheight=devmode->panningheight;
1815 * Only change private and driverextra if the incoming devmode
1816 * has a new one. JRA.
1819 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1820 SAFE_FREE(nt_devmode->nt_dev_private);
1821 nt_devmode->driverextra=devmode->driverextra;
1822 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1824 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1827 *pp_nt_devmode = nt_devmode;
1832 /********************************************************************
1833 * _spoolss_enddocprinter_internal.
1834 ********************************************************************/
1836 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1838 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1842 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1846 if (!get_printer_snum(p, handle, &snum))
1849 Printer->document_started=False;
1850 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1851 /* error codes unhandled so far ... */
1856 /********************************************************************
1857 * api_spoolss_closeprinter
1858 ********************************************************************/
1860 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1862 POLICY_HND *handle = &q_u->handle;
1864 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1866 if (Printer && Printer->document_started)
1867 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1869 if (!close_printer_handle(p, handle))
1872 /* clear the returned printer handle. Observed behavior
1873 from Win2k server. Don't think this really matters.
1874 Previous code just copied the value of the closed
1877 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1882 /********************************************************************
1883 * api_spoolss_deleteprinter
1885 ********************************************************************/
1887 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1889 POLICY_HND *handle = &q_u->handle;
1890 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1893 if (Printer && Printer->document_started)
1894 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1896 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1898 result = delete_printer_handle(p, handle);
1900 update_c_setprinter(False);
1905 /*******************************************************************
1906 * static function to lookup the version id corresponding to an
1907 * long architecture string
1908 ******************************************************************/
1910 static int get_version_id (char * arch)
1913 struct table_node archi_table[]= {
1915 {"Windows 4.0", "WIN40", 0 },
1916 {"Windows NT x86", "W32X86", 2 },
1917 {"Windows NT R4000", "W32MIPS", 2 },
1918 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1919 {"Windows NT PowerPC", "W32PPC", 2 },
1920 {"Windows IA64", "IA64", 3 },
1921 {"Windows x64", "x64", 3 },
1925 for (i=0; archi_table[i].long_archi != NULL; i++)
1927 if (strcmp(arch, archi_table[i].long_archi) == 0)
1928 return (archi_table[i].version);
1934 /********************************************************************
1935 * _spoolss_deleteprinterdriver
1936 ********************************************************************/
1938 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1942 NT_PRINTER_DRIVER_INFO_LEVEL info;
1943 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1945 struct current_user user;
1947 WERROR status_win2k = WERR_ACCESS_DENIED;
1948 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1950 get_current_user(&user, p);
1952 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1953 and not a printer admin, then fail */
1955 if ( (user.ut.uid != 0)
1956 && !user_has_privileges(user.nt_user_token, &se_printop )
1957 && !token_contains_name_in_list( uidtoname(user.ut.uid),
1958 NULL, user.nt_user_token, lp_printer_admin(-1)) )
1960 return WERR_ACCESS_DENIED;
1963 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1964 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1966 /* check that we have a valid driver name first */
1968 if ((version=get_version_id(arch)) == -1)
1969 return WERR_INVALID_ENVIRONMENT;
1972 ZERO_STRUCT(info_win2k);
1974 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1976 /* try for Win2k driver if "Windows NT x86" */
1978 if ( version == 2 ) {
1980 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1981 status = WERR_UNKNOWN_PRINTER_DRIVER;
1985 /* otherwise it was a failure */
1987 status = WERR_UNKNOWN_PRINTER_DRIVER;
1993 if (printer_driver_in_use(info.info_3)) {
1994 status = WERR_PRINTER_DRIVER_IN_USE;
2000 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2002 /* if we get to here, we now have 2 driver info structures to remove */
2003 /* remove the Win2k driver first*/
2005 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2006 free_a_printer_driver( info_win2k, 3 );
2008 /* this should not have failed---if it did, report to client */
2009 if ( !W_ERROR_IS_OK(status_win2k) )
2011 status = status_win2k;
2017 status = delete_printer_driver(info.info_3, &user, version, False);
2019 /* if at least one of the deletes succeeded return OK */
2021 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2025 free_a_printer_driver( info, 3 );
2030 /********************************************************************
2031 * spoolss_deleteprinterdriverex
2032 ********************************************************************/
2034 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2038 NT_PRINTER_DRIVER_INFO_LEVEL info;
2039 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2041 uint32 flags = q_u->delete_flags;
2043 struct current_user user;
2045 WERROR status_win2k = WERR_ACCESS_DENIED;
2046 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2048 get_current_user(&user, p);
2050 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2051 and not a printer admin, then fail */
2053 if ( (user.ut.uid != 0)
2054 && !user_has_privileges(user.nt_user_token, &se_printop )
2055 && !token_contains_name_in_list( uidtoname(user.ut.uid),
2056 NULL, user.nt_user_token, lp_printer_admin(-1)) )
2058 return WERR_ACCESS_DENIED;
2061 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2062 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2064 /* check that we have a valid driver name first */
2065 if ((version=get_version_id(arch)) == -1) {
2066 /* this is what NT returns */
2067 return WERR_INVALID_ENVIRONMENT;
2070 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2071 version = q_u->version;
2074 ZERO_STRUCT(info_win2k);
2076 status = get_a_printer_driver(&info, 3, driver, arch, version);
2078 if ( !W_ERROR_IS_OK(status) )
2081 * if the client asked for a specific version,
2082 * or this is something other than Windows NT x86,
2086 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2089 /* try for Win2k driver if "Windows NT x86" */
2092 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2093 status = WERR_UNKNOWN_PRINTER_DRIVER;
2098 if ( printer_driver_in_use(info.info_3) ) {
2099 status = WERR_PRINTER_DRIVER_IN_USE;
2104 * we have a couple of cases to consider.
2105 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2106 * then the delete should fail if **any** files overlap with
2108 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2109 * non-overlapping files
2110 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2111 * is set, the do not delete any files
2112 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2115 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2117 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2119 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2120 /* no idea of the correct error here */
2121 status = WERR_ACCESS_DENIED;
2126 /* also check for W32X86/3 if necessary; maybe we already have? */
2128 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2129 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2132 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2133 /* no idea of the correct error here */
2134 free_a_printer_driver( info_win2k, 3 );
2135 status = WERR_ACCESS_DENIED;
2139 /* if we get to here, we now have 2 driver info structures to remove */
2140 /* remove the Win2k driver first*/
2142 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2143 free_a_printer_driver( info_win2k, 3 );
2145 /* this should not have failed---if it did, report to client */
2147 if ( !W_ERROR_IS_OK(status_win2k) )
2152 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2154 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2157 free_a_printer_driver( info, 3 );
2163 /****************************************************************************
2164 Internal routine for retreiving printerdata
2165 ***************************************************************************/
2167 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2168 const char *key, const char *value, uint32 *type, uint8 **data,
2169 uint32 *needed, uint32 in_size )
2171 REGISTRY_VALUE *val;
2175 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2176 return WERR_BADFILE;
2178 *type = regval_type( val );
2180 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2182 size = regval_size( val );
2184 /* copy the min(in_size, len) */
2187 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2189 /* special case for 0 length values */
2191 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2195 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2204 DEBUG(5,("get_printer_dataex: copy done\n"));
2209 /****************************************************************************
2210 Internal routine for removing printerdata
2211 ***************************************************************************/
2213 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2215 return delete_printer_data( printer->info_2, key, value );
2218 /****************************************************************************
2219 Internal routine for storing printerdata
2220 ***************************************************************************/
2222 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2223 uint32 type, uint8 *data, int real_len )
2225 /* the registry objects enforce uniqueness based on value name */
2227 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2230 /********************************************************************
2231 GetPrinterData on a printer server Handle.
2232 ********************************************************************/
2234 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2238 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2240 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2242 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2248 if (!StrCaseCmp(value, "BeepEnabled")) {
2250 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2252 SIVAL(*data, 0, 0x00);
2257 if (!StrCaseCmp(value, "EventLog")) {
2259 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2261 /* formally was 0x1b */
2262 SIVAL(*data, 0, 0x0);
2267 if (!StrCaseCmp(value, "NetPopup")) {
2269 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2271 SIVAL(*data, 0, 0x00);
2276 if (!StrCaseCmp(value, "MajorVersion")) {
2278 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2281 /* Windows NT 4.0 seems to not allow uploading of drivers
2282 to a server that reports 0x3 as the MajorVersion.
2283 need to investigate more how Win2k gets around this .
2286 if ( RA_WINNT == get_remote_arch() )
2295 if (!StrCaseCmp(value, "MinorVersion")) {
2297 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2305 * uint32 size = 0x114
2307 * uint32 minor = [0|1]
2308 * uint32 build = [2195|2600]
2309 * extra unicode string = e.g. "Service Pack 3"
2311 if (!StrCaseCmp(value, "OSVersion")) {
2315 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2318 SIVAL(*data, 0, *needed); /* size */
2319 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2321 SIVAL(*data, 12, 2195); /* build */
2323 /* leave extra string empty */
2329 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2330 const char *string="C:\\PRINTERS";
2332 *needed = 2*(strlen(string)+1);
2333 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2335 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2337 /* it's done by hand ready to go on the wire */
2338 for (i=0; i<strlen(string); i++) {
2339 (*data)[2*i]=string[i];
2340 (*data)[2*i+1]='\0';
2345 if (!StrCaseCmp(value, "Architecture")) {
2346 const char *string="Windows NT x86";
2348 *needed = 2*(strlen(string)+1);
2349 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2351 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2352 for (i=0; i<strlen(string); i++) {
2353 (*data)[2*i]=string[i];
2354 (*data)[2*i+1]='\0';
2359 if (!StrCaseCmp(value, "DsPresent")) {
2361 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2364 /* only show the publish check box if we are a
2365 memeber of a AD domain */
2367 if ( lp_security() == SEC_ADS )
2368 SIVAL(*data, 0, 0x01);
2370 SIVAL(*data, 0, 0x00);
2376 if (!StrCaseCmp(value, "DNSMachineName")) {
2379 if (!get_mydnsfullname(hostname))
2380 return WERR_BADFILE;
2382 *needed = 2*(strlen(hostname)+1);
2383 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2385 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2386 for (i=0; i<strlen(hostname); i++) {
2387 (*data)[2*i]=hostname[i];
2388 (*data)[2*i+1]='\0';
2394 return WERR_BADFILE;
2397 /********************************************************************
2398 * spoolss_getprinterdata
2399 ********************************************************************/
2401 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2403 POLICY_HND *handle = &q_u->handle;
2404 UNISTR2 *valuename = &q_u->valuename;
2405 uint32 in_size = q_u->size;
2406 uint32 *type = &r_u->type;
2407 uint32 *out_size = &r_u->size;
2408 uint8 **data = &r_u->data;
2409 uint32 *needed = &r_u->needed;
2412 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2413 NT_PRINTER_INFO_LEVEL *printer = NULL;
2417 * Reminder: when it's a string, the length is in BYTES
2418 * even if UNICODE is negociated.
2423 *out_size = in_size;
2425 /* in case of problem, return some default values */
2430 DEBUG(4,("_spoolss_getprinterdata\n"));
2433 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2434 status = WERR_BADFID;
2438 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2440 if ( Printer->printer_type == SPLHND_SERVER )
2441 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2444 if ( !get_printer_snum(p,handle, &snum) ) {
2445 status = WERR_BADFID;
2449 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2450 if ( !W_ERROR_IS_OK(status) )
2453 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2455 if ( strequal(value, "ChangeId") ) {
2457 *needed = sizeof(uint32);
2458 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2459 status = WERR_NOMEM;
2462 SIVAL( *data, 0, printer->info_2->changeid );
2466 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2469 if (*needed > *out_size)
2470 status = WERR_MORE_DATA;
2473 if ( !W_ERROR_IS_OK(status) )
2475 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2477 /* reply this param doesn't exist */
2480 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2482 free_a_printer( &printer, 2 );
2491 /* cleanup & exit */
2494 free_a_printer( &printer, 2 );
2499 /*********************************************************
2500 Connect to the client machine.
2501 **********************************************************/
2503 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2504 struct in_addr *client_ip, const char *remote_machine)
2507 struct cli_state *the_cli;
2508 struct in_addr rm_addr;
2510 if ( is_zero_ip(*client_ip) ) {
2511 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2512 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2516 if ( ismyip( rm_addr )) {
2517 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2521 rm_addr.s_addr = client_ip->s_addr;
2522 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2523 inet_ntoa(*client_ip) ));
2526 /* setup the connection */
2528 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2529 &rm_addr, 0, "IPC$", "IPC",
2533 0, lp_client_signing(), NULL );
2535 if ( !NT_STATUS_IS_OK( ret ) ) {
2536 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2541 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2542 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2543 cli_shutdown(the_cli);
2548 * Ok - we have an anonymous connection to the IPC$ share.
2549 * Now start the NT Domain stuff :-).
2552 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2553 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2554 remote_machine, nt_errstr(ret)));
2555 cli_shutdown(the_cli);
2559 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2561 (*pp_pipe)->cli = the_cli;
2566 /***************************************************************************
2567 Connect to the client.
2568 ****************************************************************************/
2570 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2571 uint32 localprinter, uint32 type,
2572 POLICY_HND *handle, struct in_addr *client_ip)
2577 * If it's the first connection, contact the client
2578 * and connect to the IPC$ share anonymously
2580 if (smb_connections==0) {
2581 fstring unix_printer;
2583 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2585 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2588 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2589 /* Tell the connections db we're now interested in printer
2590 * notify messages. */
2591 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2595 * Tell the specific printing tdb we want messages for this printer
2596 * by registering our PID.
2599 if (!print_notify_register_pid(snum))
2600 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2604 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2607 if (!W_ERROR_IS_OK(result))
2608 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2609 dos_errstr(result)));
2611 return (W_ERROR_IS_OK(result));
2614 /********************************************************************
2616 * ReplyFindFirstPrinterChangeNotifyEx
2618 * before replying OK: status=0 a rpc call is made to the workstation
2619 * asking ReplyOpenPrinter
2621 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2622 * called from api_spoolss_rffpcnex
2623 ********************************************************************/
2625 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2627 POLICY_HND *handle = &q_u->handle;
2628 uint32 flags = q_u->flags;
2629 uint32 options = q_u->options;
2630 UNISTR2 *localmachine = &q_u->localmachine;
2631 uint32 printerlocal = q_u->printerlocal;
2633 SPOOL_NOTIFY_OPTION *option = q_u->option;
2634 struct in_addr client_ip;
2636 /* store the notify value in the printer struct */
2638 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2641 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2645 Printer->notify.flags=flags;
2646 Printer->notify.options=options;
2647 Printer->notify.printerlocal=printerlocal;
2649 if (Printer->notify.option)
2650 free_spool_notify_option(&Printer->notify.option);
2652 Printer->notify.option=dup_spool_notify_option(option);
2654 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2655 sizeof(Printer->notify.localmachine)-1);
2657 /* Connect to the client machine and send a ReplyOpenPrinter */
2659 if ( Printer->printer_type == SPLHND_SERVER)
2661 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2662 !get_printer_snum(p, handle, &snum) )
2665 client_ip.s_addr = inet_addr(p->conn->client_address);
2667 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2668 Printer->notify.printerlocal, 1,
2669 &Printer->notify.client_hnd, &client_ip))
2670 return WERR_SERVER_UNAVAILABLE;
2672 Printer->notify.client_connected=True;
2677 /*******************************************************************
2678 * fill a notify_info_data with the servername
2679 ********************************************************************/
2681 void spoolss_notify_server_name(int snum,
2682 SPOOL_NOTIFY_INFO_DATA *data,
2683 print_queue_struct *queue,
2684 NT_PRINTER_INFO_LEVEL *printer,
2685 TALLOC_CTX *mem_ctx)
2690 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2692 data->notify_data.data.length = len;
2693 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2695 if (!data->notify_data.data.string) {
2696 data->notify_data.data.length = 0;
2700 memcpy(data->notify_data.data.string, temp, len);
2703 /*******************************************************************
2704 * fill a notify_info_data with the printername (not including the servername).
2705 ********************************************************************/
2707 void spoolss_notify_printer_name(int snum,
2708 SPOOL_NOTIFY_INFO_DATA *data,
2709 print_queue_struct *queue,
2710 NT_PRINTER_INFO_LEVEL *printer,
2711 TALLOC_CTX *mem_ctx)
2716 /* the notify name should not contain the \\server\ part */
2717 char *p = strrchr(printer->info_2->printername, '\\');
2720 p = printer->info_2->printername;
2725 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2727 data->notify_data.data.length = len;
2728 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2730 if (!data->notify_data.data.string) {
2731 data->notify_data.data.length = 0;
2735 memcpy(data->notify_data.data.string, temp, len);
2738 /*******************************************************************
2739 * fill a notify_info_data with the servicename
2740 ********************************************************************/
2742 void spoolss_notify_share_name(int snum,
2743 SPOOL_NOTIFY_INFO_DATA *data,
2744 print_queue_struct *queue,
2745 NT_PRINTER_INFO_LEVEL *printer,
2746 TALLOC_CTX *mem_ctx)
2751 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2753 data->notify_data.data.length = len;
2754 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2756 if (!data->notify_data.data.string) {
2757 data->notify_data.data.length = 0;
2761 memcpy(data->notify_data.data.string, temp, len);
2764 /*******************************************************************
2765 * fill a notify_info_data with the port name
2766 ********************************************************************/
2768 void spoolss_notify_port_name(int snum,
2769 SPOOL_NOTIFY_INFO_DATA *data,
2770 print_queue_struct *queue,
2771 NT_PRINTER_INFO_LEVEL *printer,
2772 TALLOC_CTX *mem_ctx)
2777 /* even if it's strange, that's consistant in all the code */
2779 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2781 data->notify_data.data.length = len;
2782 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2784 if (!data->notify_data.data.string) {
2785 data->notify_data.data.length = 0;
2789 memcpy(data->notify_data.data.string, temp, len);
2792 /*******************************************************************
2793 * fill a notify_info_data with the printername
2794 * but it doesn't exist, have to see what to do
2795 ********************************************************************/
2797 void spoolss_notify_driver_name(int snum,
2798 SPOOL_NOTIFY_INFO_DATA *data,
2799 print_queue_struct *queue,
2800 NT_PRINTER_INFO_LEVEL *printer,
2801 TALLOC_CTX *mem_ctx)
2806 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2808 data->notify_data.data.length = len;
2809 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2811 if (!data->notify_data.data.string) {
2812 data->notify_data.data.length = 0;
2816 memcpy(data->notify_data.data.string, temp, len);
2819 /*******************************************************************
2820 * fill a notify_info_data with the comment
2821 ********************************************************************/
2823 void spoolss_notify_comment(int snum,
2824 SPOOL_NOTIFY_INFO_DATA *data,
2825 print_queue_struct *queue,
2826 NT_PRINTER_INFO_LEVEL *printer,
2827 TALLOC_CTX *mem_ctx)
2832 if (*printer->info_2->comment == '\0')
2833 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2835 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2837 data->notify_data.data.length = len;
2838 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2840 if (!data->notify_data.data.string) {
2841 data->notify_data.data.length = 0;
2845 memcpy(data->notify_data.data.string, temp, len);
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 SPOOL_NOTIFY_INFO_DATA *data,
2855 print_queue_struct *queue,
2856 NT_PRINTER_INFO_LEVEL *printer,
2857 TALLOC_CTX *mem_ctx)
2862 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2864 data->notify_data.data.length = len;
2865 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2867 if (!data->notify_data.data.string) {
2868 data->notify_data.data.length = 0;
2872 memcpy(data->notify_data.data.string, temp, len);
2875 /*******************************************************************
2876 * fill a notify_info_data with the device mode
2877 * jfm:xxxx don't to it for know but that's a real problem !!!
2878 ********************************************************************/
2880 static void spoolss_notify_devmode(int snum,
2881 SPOOL_NOTIFY_INFO_DATA *data,
2882 print_queue_struct *queue,
2883 NT_PRINTER_INFO_LEVEL *printer,
2884 TALLOC_CTX *mem_ctx)
2888 /*******************************************************************
2889 * fill a notify_info_data with the separator file name
2890 ********************************************************************/
2892 void spoolss_notify_sepfile(int snum,
2893 SPOOL_NOTIFY_INFO_DATA *data,
2894 print_queue_struct *queue,
2895 NT_PRINTER_INFO_LEVEL *printer,
2896 TALLOC_CTX *mem_ctx)
2901 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2903 data->notify_data.data.length = len;
2904 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2906 if (!data->notify_data.data.string) {
2907 data->notify_data.data.length = 0;
2911 memcpy(data->notify_data.data.string, temp, len);
2914 /*******************************************************************
2915 * fill a notify_info_data with the print processor
2916 * jfm:xxxx return always winprint to indicate we don't do anything to it
2917 ********************************************************************/
2919 void spoolss_notify_print_processor(int snum,
2920 SPOOL_NOTIFY_INFO_DATA *data,
2921 print_queue_struct *queue,
2922 NT_PRINTER_INFO_LEVEL *printer,
2923 TALLOC_CTX *mem_ctx)
2928 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2930 data->notify_data.data.length = len;
2931 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2933 if (!data->notify_data.data.string) {
2934 data->notify_data.data.length = 0;
2938 memcpy(data->notify_data.data.string, temp, len);
2941 /*******************************************************************
2942 * fill a notify_info_data with the print processor options
2943 * jfm:xxxx send an empty string
2944 ********************************************************************/
2946 void spoolss_notify_parameters(int snum,
2947 SPOOL_NOTIFY_INFO_DATA *data,
2948 print_queue_struct *queue,
2949 NT_PRINTER_INFO_LEVEL *printer,
2950 TALLOC_CTX *mem_ctx)
2955 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2957 data->notify_data.data.length = len;
2958 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2960 if (!data->notify_data.data.string) {
2961 data->notify_data.data.length = 0;
2965 memcpy(data->notify_data.data.string, temp, len);
2968 /*******************************************************************
2969 * fill a notify_info_data with the data type
2970 * jfm:xxxx always send RAW as data type
2971 ********************************************************************/
2973 void spoolss_notify_datatype(int snum,
2974 SPOOL_NOTIFY_INFO_DATA *data,
2975 print_queue_struct *queue,
2976 NT_PRINTER_INFO_LEVEL *printer,
2977 TALLOC_CTX *mem_ctx)
2982 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2984 data->notify_data.data.length = len;
2985 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2987 if (!data->notify_data.data.string) {
2988 data->notify_data.data.length = 0;
2992 memcpy(data->notify_data.data.string, temp, len);
2995 /*******************************************************************
2996 * fill a notify_info_data with the security descriptor
2997 * jfm:xxxx send an null pointer to say no security desc
2998 * have to implement security before !
2999 ********************************************************************/
3001 static void spoolss_notify_security_desc(int snum,
3002 SPOOL_NOTIFY_INFO_DATA *data,
3003 print_queue_struct *queue,
3004 NT_PRINTER_INFO_LEVEL *printer,
3005 TALLOC_CTX *mem_ctx)
3007 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3008 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3011 /*******************************************************************
3012 * fill a notify_info_data with the attributes
3013 * jfm:xxxx a samba printer is always shared
3014 ********************************************************************/
3016 void spoolss_notify_attributes(int snum,
3017 SPOOL_NOTIFY_INFO_DATA *data,
3018 print_queue_struct *queue,
3019 NT_PRINTER_INFO_LEVEL *printer,
3020 TALLOC_CTX *mem_ctx)
3022 data->notify_data.value[0] = printer->info_2->attributes;
3023 data->notify_data.value[1] = 0;
3026 /*******************************************************************
3027 * fill a notify_info_data with the priority
3028 ********************************************************************/
3030 static void spoolss_notify_priority(int snum,
3031 SPOOL_NOTIFY_INFO_DATA *data,
3032 print_queue_struct *queue,
3033 NT_PRINTER_INFO_LEVEL *printer,
3034 TALLOC_CTX *mem_ctx)
3036 data->notify_data.value[0] = printer->info_2->priority;
3037 data->notify_data.value[1] = 0;
3040 /*******************************************************************
3041 * fill a notify_info_data with the default priority
3042 ********************************************************************/
3044 static void spoolss_notify_default_priority(int snum,
3045 SPOOL_NOTIFY_INFO_DATA *data,
3046 print_queue_struct *queue,
3047 NT_PRINTER_INFO_LEVEL *printer,
3048 TALLOC_CTX *mem_ctx)
3050 data->notify_data.value[0] = printer->info_2->default_priority;
3051 data->notify_data.value[1] = 0;
3054 /*******************************************************************
3055 * fill a notify_info_data with the start time
3056 ********************************************************************/
3058 static void spoolss_notify_start_time(int snum,
3059 SPOOL_NOTIFY_INFO_DATA *data,
3060 print_queue_struct *queue,
3061 NT_PRINTER_INFO_LEVEL *printer,
3062 TALLOC_CTX *mem_ctx)
3064 data->notify_data.value[0] = printer->info_2->starttime;
3065 data->notify_data.value[1] = 0;
3068 /*******************************************************************
3069 * fill a notify_info_data with the until time
3070 ********************************************************************/
3072 static void spoolss_notify_until_time(int snum,
3073 SPOOL_NOTIFY_INFO_DATA *data,
3074 print_queue_struct *queue,
3075 NT_PRINTER_INFO_LEVEL *printer,
3076 TALLOC_CTX *mem_ctx)
3078 data->notify_data.value[0] = printer->info_2->untiltime;
3079 data->notify_data.value[1] = 0;
3082 /*******************************************************************
3083 * fill a notify_info_data with the status
3084 ********************************************************************/
3086 static void spoolss_notify_status(int snum,
3087 SPOOL_NOTIFY_INFO_DATA *data,
3088 print_queue_struct *queue,
3089 NT_PRINTER_INFO_LEVEL *printer,
3090 TALLOC_CTX *mem_ctx)
3092 print_status_struct status;
3094 print_queue_length(snum, &status);
3095 data->notify_data.value[0]=(uint32) status.status;
3096 data->notify_data.value[1] = 0;
3099 /*******************************************************************
3100 * fill a notify_info_data with the number of jobs queued
3101 ********************************************************************/
3103 void spoolss_notify_cjobs(int snum,
3104 SPOOL_NOTIFY_INFO_DATA *data,
3105 print_queue_struct *queue,
3106 NT_PRINTER_INFO_LEVEL *printer,
3107 TALLOC_CTX *mem_ctx)
3109 data->notify_data.value[0] = print_queue_length(snum, NULL);
3110 data->notify_data.value[1] = 0;
3113 /*******************************************************************
3114 * fill a notify_info_data with the average ppm
3115 ********************************************************************/
3117 static void spoolss_notify_average_ppm(int snum,
3118 SPOOL_NOTIFY_INFO_DATA *data,
3119 print_queue_struct *queue,
3120 NT_PRINTER_INFO_LEVEL *printer,
3121 TALLOC_CTX *mem_ctx)
3123 /* always respond 8 pages per minutes */
3124 /* a little hard ! */
3125 data->notify_data.value[0] = printer->info_2->averageppm;
3126 data->notify_data.value[1] = 0;
3129 /*******************************************************************
3130 * fill a notify_info_data with username
3131 ********************************************************************/
3133 static void spoolss_notify_username(int snum,
3134 SPOOL_NOTIFY_INFO_DATA *data,
3135 print_queue_struct *queue,
3136 NT_PRINTER_INFO_LEVEL *printer,
3137 TALLOC_CTX *mem_ctx)
3142 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3144 data->notify_data.data.length = len;
3145 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3147 if (!data->notify_data.data.string) {
3148 data->notify_data.data.length = 0;
3152 memcpy(data->notify_data.data.string, temp, len);
3155 /*******************************************************************
3156 * fill a notify_info_data with job status
3157 ********************************************************************/
3159 static void spoolss_notify_job_status(int snum,
3160 SPOOL_NOTIFY_INFO_DATA *data,
3161 print_queue_struct *queue,
3162 NT_PRINTER_INFO_LEVEL *printer,
3163 TALLOC_CTX *mem_ctx)
3165 data->notify_data.value[0]=nt_printj_status(queue->status);
3166 data->notify_data.value[1] = 0;
3169 /*******************************************************************
3170 * fill a notify_info_data with job name
3171 ********************************************************************/
3173 static void spoolss_notify_job_name(int snum,
3174 SPOOL_NOTIFY_INFO_DATA *data,
3175 print_queue_struct *queue,
3176 NT_PRINTER_INFO_LEVEL *printer,
3177 TALLOC_CTX *mem_ctx)
3182 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3184 data->notify_data.data.length = len;
3185 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3187 if (!data->notify_data.data.string) {
3188 data->notify_data.data.length = 0;
3192 memcpy(data->notify_data.data.string, temp, len);
3195 /*******************************************************************
3196 * fill a notify_info_data with job status
3197 ********************************************************************/
3199 static void spoolss_notify_job_status_string(int snum,
3200 SPOOL_NOTIFY_INFO_DATA *data,
3201 print_queue_struct *queue,
3202 NT_PRINTER_INFO_LEVEL *printer,
3203 TALLOC_CTX *mem_ctx)
3206 * Now we're returning job status codes we just return a "" here. JRA.
3213 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3216 switch (queue->status) {
3221 p = ""; /* NT provides the paused string */
3230 #endif /* NO LONGER NEEDED. */
3232 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3234 data->notify_data.data.length = len;
3235 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3237 if (!data->notify_data.data.string) {
3238 data->notify_data.data.length = 0;
3242 memcpy(data->notify_data.data.string, temp, len);
3245 /*******************************************************************
3246 * fill a notify_info_data with job time
3247 ********************************************************************/
3249 static void spoolss_notify_job_time(int snum,
3250 SPOOL_NOTIFY_INFO_DATA *data,
3251 print_queue_struct *queue,
3252 NT_PRINTER_INFO_LEVEL *printer,
3253 TALLOC_CTX *mem_ctx)
3255 data->notify_data.value[0]=0x0;
3256 data->notify_data.value[1]=0;
3259 /*******************************************************************
3260 * fill a notify_info_data with job size
3261 ********************************************************************/
3263 static void spoolss_notify_job_size(int snum,
3264 SPOOL_NOTIFY_INFO_DATA *data,
3265 print_queue_struct *queue,
3266 NT_PRINTER_INFO_LEVEL *printer,
3267 TALLOC_CTX *mem_ctx)
3269 data->notify_data.value[0]=queue->size;
3270 data->notify_data.value[1]=0;
3273 /*******************************************************************
3274 * fill a notify_info_data with page info
3275 ********************************************************************/
3276 static void spoolss_notify_total_pages(int snum,
3277 SPOOL_NOTIFY_INFO_DATA *data,
3278 print_queue_struct *queue,
3279 NT_PRINTER_INFO_LEVEL *printer,
3280 TALLOC_CTX *mem_ctx)
3282 data->notify_data.value[0]=queue->page_count;
3283 data->notify_data.value[1]=0;
3286 /*******************************************************************
3287 * fill a notify_info_data with pages printed info.
3288 ********************************************************************/
3289 static void spoolss_notify_pages_printed(int snum,
3290 SPOOL_NOTIFY_INFO_DATA *data,
3291 print_queue_struct *queue,
3292 NT_PRINTER_INFO_LEVEL *printer,
3293 TALLOC_CTX *mem_ctx)
3295 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3296 data->notify_data.value[1]=0;
3299 /*******************************************************************
3300 Fill a notify_info_data with job position.
3301 ********************************************************************/
3303 static void spoolss_notify_job_position(int snum,
3304 SPOOL_NOTIFY_INFO_DATA *data,
3305 print_queue_struct *queue,
3306 NT_PRINTER_INFO_LEVEL *printer,
3307 TALLOC_CTX *mem_ctx)
3309 data->notify_data.value[0]=queue->job;
3310 data->notify_data.value[1]=0;
3313 /*******************************************************************
3314 Fill a notify_info_data with submitted time.
3315 ********************************************************************/
3317 static void spoolss_notify_submitted_time(int snum,
3318 SPOOL_NOTIFY_INFO_DATA *data,
3319 print_queue_struct *queue,
3320 NT_PRINTER_INFO_LEVEL *printer,
3321 TALLOC_CTX *mem_ctx)
3328 t=gmtime(&queue->time);
3330 len = sizeof(SYSTEMTIME);
3332 data->notify_data.data.length = len;
3333 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3335 if (!data->notify_data.data.string) {
3336 data->notify_data.data.length = 0;
3340 make_systemtime(&st, t);
3343 * Systemtime must be linearized as a set of UINT16's.
3344 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3347 p = (char *)data->notify_data.data.string;
3348 SSVAL(p, 0, st.year);
3349 SSVAL(p, 2, st.month);
3350 SSVAL(p, 4, st.dayofweek);
3351 SSVAL(p, 6, st.day);
3352 SSVAL(p, 8, st.hour);
3353 SSVAL(p, 10, st.minute);
3354 SSVAL(p, 12, st.second);
3355 SSVAL(p, 14, st.milliseconds);
3358 struct s_notify_info_data_table
3364 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3365 print_queue_struct *queue,
3366 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3369 /* A table describing the various print notification constants and
3370 whether the notification data is a pointer to a variable sized
3371 buffer, a one value uint32 or a two value uint32. */
3373 static const struct s_notify_info_data_table notify_info_data_table[] =
3375 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3376 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3377 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3378 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3379 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3380 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3381 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3382 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3383 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3384 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3385 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3386 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3387 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3388 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3389 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3401 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3402 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3403 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3404 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3405 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3406 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3407 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3408 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3409 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3410 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3411 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3412 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3413 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3414 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3415 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3424 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3427 /*******************************************************************
3428 Return the size of info_data structure.
3429 ********************************************************************/
3431 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3435 for (i = 0; i < sizeof(notify_info_data_table); i++)
3437 if ( (notify_info_data_table[i].type == type)
3438 && (notify_info_data_table[i].field == field) )
3440 switch(notify_info_data_table[i].size)
3442 case NOTIFY_ONE_VALUE:
3443 case NOTIFY_TWO_VALUE:
3448 /* The only pointer notify data I have seen on
3449 the wire is the submitted time and this has
3450 the notify size set to 4. -tpot */
3452 case NOTIFY_POINTER:
3455 case NOTIFY_SECDESC:
3461 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3466 /*******************************************************************
3467 Return the type of notify_info_data.
3468 ********************************************************************/
3470 static int type_of_notify_info_data(uint16 type, uint16 field)
3474 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3475 if (notify_info_data_table[i].type == type &&
3476 notify_info_data_table[i].field == field)
3477 return notify_info_data_table[i].size;
3483 /****************************************************************************
3484 ****************************************************************************/
3486 static int search_notify(uint16 type, uint16 field, int *value)
3490 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3491 if (notify_info_data_table[i].type == type &&
3492 notify_info_data_table[i].field == field &&
3493 notify_info_data_table[i].fn != NULL) {
3502 /****************************************************************************
3503 ****************************************************************************/
3505 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3507 info_data->type = type;
3508 info_data->field = field;
3509 info_data->reserved = 0;
3511 info_data->size = size_of_notify_info_data(type, field);
3512 info_data->enc_type = type_of_notify_info_data(type, field);
3519 /*******************************************************************
3521 * fill a notify_info struct with info asked
3523 ********************************************************************/
3525 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3526 snum, SPOOL_NOTIFY_OPTION_TYPE
3527 *option_type, uint32 id,
3528 TALLOC_CTX *mem_ctx)
3534 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3535 NT_PRINTER_INFO_LEVEL *printer = NULL;
3536 print_queue_struct *queue=NULL;
3538 type=option_type->type;
3540 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3541 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3542 option_type->count, lp_servicename(snum)));
3544 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3547 for(field_num=0; field_num<option_type->count; field_num++) {
3548 field = option_type->fields[field_num];
3550 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3552 if (!search_notify(type, field, &j) )
3555 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3556 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3561 current_data = &info->data[info->count];
3563 construct_info_data(current_data, type, field, id);
3565 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3566 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3568 notify_info_data_table[j].fn(snum, current_data, queue,
3574 free_a_printer(&printer, 2);
3578 /*******************************************************************
3580 * fill a notify_info struct with info asked
3582 ********************************************************************/
3584 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3585 SPOOL_NOTIFY_INFO *info,
3586 NT_PRINTER_INFO_LEVEL *printer,
3587 int snum, SPOOL_NOTIFY_OPTION_TYPE
3588 *option_type, uint32 id,
3589 TALLOC_CTX *mem_ctx)
3595 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3597 DEBUG(4,("construct_notify_jobs_info\n"));
3599 type = option_type->type;
3601 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3602 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3603 option_type->count));
3605 for(field_num=0; field_num<option_type->count; field_num++) {
3606 field = option_type->fields[field_num];
3608 if (!search_notify(type, field, &j) )
3611 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3612 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3615 else info->data = tid;
3617 current_data=&(info->data[info->count]);
3619 construct_info_data(current_data, type, field, id);
3620 notify_info_data_table[j].fn(snum, current_data, queue,
3629 * JFM: The enumeration is not that simple, it's even non obvious.
3631 * let's take an example: I want to monitor the PRINTER SERVER for
3632 * the printer's name and the number of jobs currently queued.
3633 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3634 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3636 * I have 3 printers on the back of my server.
3638 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3641 * 1 printer 1 name 1
3642 * 2 printer 1 cjob 1
3643 * 3 printer 2 name 2
3644 * 4 printer 2 cjob 2
3645 * 5 printer 3 name 3
3646 * 6 printer 3 name 3
3648 * that's the print server case, the printer case is even worse.
3651 /*******************************************************************
3653 * enumerate all printers on the printserver
3654 * fill a notify_info struct with info asked
3656 ********************************************************************/
3658 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3659 SPOOL_NOTIFY_INFO *info,
3660 TALLOC_CTX *mem_ctx)
3663 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3664 int n_services=lp_numservices();
3666 SPOOL_NOTIFY_OPTION *option;
3667 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3669 DEBUG(4,("printserver_notify_info\n"));
3674 option=Printer->notify.option;
3679 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3680 sending a ffpcn() request first */
3685 for (i=0; i<option->count; i++) {
3686 option_type=&(option->ctr.type[i]);
3688 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3691 for (snum=0; snum<n_services; snum++)
3693 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3694 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3700 * Debugging information, don't delete.
3703 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3704 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3705 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3707 for (i=0; i<info->count; i++) {
3708 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3709 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3710 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3717 /*******************************************************************
3719 * fill a notify_info struct with info asked
3721 ********************************************************************/
3723 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3724 TALLOC_CTX *mem_ctx)
3727 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3730 SPOOL_NOTIFY_OPTION *option;
3731 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3733 print_queue_struct *queue=NULL;
3734 print_status_struct status;
3736 DEBUG(4,("printer_notify_info\n"));
3741 option=Printer->notify.option;
3747 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3748 sending a ffpcn() request first */
3753 get_printer_snum(p, hnd, &snum);
3755 for (i=0; i<option->count; i++) {
3756 option_type=&option->ctr.type[i];
3758 switch ( option_type->type ) {
3759 case PRINTER_NOTIFY_TYPE:
3760 if(construct_notify_printer_info(Printer, info, snum,
3766 case JOB_NOTIFY_TYPE: {
3767 NT_PRINTER_INFO_LEVEL *printer = NULL;
3769 count = print_queue_status(snum, &queue, &status);
3771 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3774 for (j=0; j<count; j++) {
3775 construct_notify_jobs_info(&queue[j], info,
3782 free_a_printer(&printer, 2);
3792 * Debugging information, don't delete.
3795 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3796 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3797 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3799 for (i=0; i<info->count; i++) {
3800 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3801 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3802 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3808 /********************************************************************
3810 ********************************************************************/
3812 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3814 POLICY_HND *handle = &q_u->handle;
3815 SPOOL_NOTIFY_INFO *info = &r_u->info;
3817 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3818 WERROR result = WERR_BADFID;
3820 /* we always have a NOTIFY_INFO struct */
3824 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3825 OUR_HANDLE(handle)));
3829 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3832 * We are now using the change value, and
3833 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3834 * I don't have a global notification system, I'm sending back all the
3835 * informations even when _NOTHING_ has changed.
3838 /* We need to keep track of the change value to send back in
3839 RRPCN replies otherwise our updates are ignored. */
3841 Printer->notify.fnpcn = True;
3843 if (Printer->notify.client_connected) {
3844 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3845 Printer->notify.change = q_u->change;
3848 /* just ignore the SPOOL_NOTIFY_OPTION */
3850 switch (Printer->printer_type) {
3852 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3855 case SPLHND_PRINTER:
3856 result = printer_notify_info(p, handle, info, p->mem_ctx);
3860 Printer->notify.fnpcn = False;
3866 /********************************************************************
3867 * construct_printer_info_0
3868 * fill a printer_info_0 struct
3869 ********************************************************************/
3871 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3875 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3876 counter_printer_0 *session_counter;
3877 uint32 global_counter;
3880 print_status_struct status;
3882 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3885 count = print_queue_length(snum, &status);
3887 /* check if we already have a counter for this printer */
3888 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3889 if (session_counter->snum == snum)
3893 /* it's the first time, add it to the list */
3894 if (session_counter==NULL) {
3895 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3896 free_a_printer(&ntprinter, 2);
3899 ZERO_STRUCTP(session_counter);
3900 session_counter->snum=snum;
3901 session_counter->counter=0;
3902 DLIST_ADD(counter_list, session_counter);
3906 session_counter->counter++;
3909 * the global_counter should be stored in a TDB as it's common to all the clients
3910 * and should be zeroed on samba startup
3912 global_counter=session_counter->counter;
3914 pstrcpy(chaine,ntprinter->info_2->printername);
3916 init_unistr(&printer->printername, chaine);
3918 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3919 init_unistr(&printer->servername, chaine);
3921 printer->cjobs = count;
3922 printer->total_jobs = 0;
3923 printer->total_bytes = 0;
3925 setuptime = (time_t)ntprinter->info_2->setuptime;
3926 t=gmtime(&setuptime);
3928 printer->year = t->tm_year+1900;
3929 printer->month = t->tm_mon+1;
3930 printer->dayofweek = t->tm_wday;
3931 printer->day = t->tm_mday;
3932 printer->hour = t->tm_hour;
3933 printer->minute = t->tm_min;
3934 printer->second = t->tm_sec;
3935 printer->milliseconds = 0;
3937 printer->global_counter = global_counter;
3938 printer->total_pages = 0;
3940 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3941 printer->major_version = 0x0005; /* NT 5 */
3942 printer->build_version = 0x0893; /* build 2195 */
3944 printer->unknown7 = 0x1;
3945 printer->unknown8 = 0x0;
3946 printer->unknown9 = 0x0;
3947 printer->session_counter = session_counter->counter;
3948 printer->unknown11 = 0x0;
3949 printer->printer_errors = 0x0; /* number of print failure */
3950 printer->unknown13 = 0x0;
3951 printer->unknown14 = 0x1;
3952 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3953 printer->unknown16 = 0x0;
3954 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3955 printer->unknown18 = 0x0;
3956 printer->status = nt_printq_status(status.status);
3957 printer->unknown20 = 0x0;
3958 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3959 printer->unknown22 = 0x0;
3960 printer->unknown23 = 0x6; /* 6 ???*/
3961 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3962 printer->unknown25 = 0;
3963 printer->unknown26 = 0;
3964 printer->unknown27 = 0;
3965 printer->unknown28 = 0;
3966 printer->unknown29 = 0;
3968 free_a_printer(&ntprinter,2);
3972 /********************************************************************
3973 * construct_printer_info_1
3974 * fill a printer_info_1 struct
3975 ********************************************************************/
3976 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3980 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3982 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3985 printer->flags=flags;
3987 if (*ntprinter->info_2->comment == '\0') {
3988 init_unistr(&printer->comment, lp_comment(snum));
3989 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3990 ntprinter->info_2->drivername, lp_comment(snum));
3993 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3994 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3995 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3998 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4000 init_unistr(&printer->description, chaine);
4001 init_unistr(&printer->name, chaine2);
4003 free_a_printer(&ntprinter,2);
4008 /****************************************************************************
4009 Free a DEVMODE struct.
4010 ****************************************************************************/
4012 static void free_dev_mode(DEVICEMODE *dev)
4017 SAFE_FREE(dev->dev_private);
4022 /****************************************************************************
4023 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4024 should be valid upon entry
4025 ****************************************************************************/
4027 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4029 if ( !devmode || !ntdevmode )
4032 init_unistr(&devmode->devicename, ntdevmode->devicename);
4034 init_unistr(&devmode->formname, ntdevmode->formname);
4036 devmode->specversion = ntdevmode->specversion;
4037 devmode->driverversion = ntdevmode->driverversion;
4038 devmode->size = ntdevmode->size;
4039 devmode->driverextra = ntdevmode->driverextra;
4040 devmode->fields = ntdevmode->fields;
4042 devmode->orientation = ntdevmode->orientation;
4043 devmode->papersize = ntdevmode->papersize;
4044 devmode->paperlength = ntdevmode->paperlength;
4045 devmode->paperwidth = ntdevmode->paperwidth;
4046 devmode->scale = ntdevmode->scale;
4047 devmode->copies = ntdevmode->copies;
4048 devmode->defaultsource = ntdevmode->defaultsource;
4049 devmode->printquality = ntdevmode->printquality;
4050 devmode->color = ntdevmode->color;
4051 devmode->duplex = ntdevmode->duplex;
4052 devmode->yresolution = ntdevmode->yresolution;
4053 devmode->ttoption = ntdevmode->ttoption;
4054 devmode->collate = ntdevmode->collate;
4055 devmode->icmmethod = ntdevmode->icmmethod;
4056 devmode->icmintent = ntdevmode->icmintent;
4057 devmode->mediatype = ntdevmode->mediatype;
4058 devmode->dithertype = ntdevmode->dithertype;
4060 if (ntdevmode->nt_dev_private != NULL) {
4061 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4068 /****************************************************************************
4069 Create a DEVMODE struct. Returns malloced memory.
4070 ****************************************************************************/
4072 DEVICEMODE *construct_dev_mode(int snum)
4074 NT_PRINTER_INFO_LEVEL *printer = NULL;
4075 DEVICEMODE *devmode = NULL;
4077 DEBUG(7,("construct_dev_mode\n"));
4079 DEBUGADD(8,("getting printer characteristics\n"));
4081 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4084 if ( !printer->info_2->devmode ) {
4085 DEBUG(5, ("BONG! There was no device mode!\n"));
4089 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4090 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4094 ZERO_STRUCTP(devmode);
4096 DEBUGADD(8,("loading DEVICEMODE\n"));
4098 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4099 free_dev_mode( devmode );
4104 free_a_printer(&printer,2);
4109 /********************************************************************
4110 * construct_printer_info_2
4111 * fill a printer_info_2 struct
4112 ********************************************************************/
4114 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4117 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4119 print_status_struct status;
4121 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4124 count = print_queue_length(snum, &status);
4126 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4127 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4128 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4129 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4130 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4132 if (*ntprinter->info_2->comment == '\0')
4133 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4135 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4137 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4138 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4139 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4140 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4141 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4143 printer->attributes = ntprinter->info_2->attributes;
4145 printer->priority = ntprinter->info_2->priority; /* priority */
4146 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4147 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4148 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4149 printer->status = nt_printq_status(status.status); /* status */
4150 printer->cjobs = count; /* jobs */
4151 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4153 if ( !(printer->devmode = construct_dev_mode(snum)) )
4154 DEBUG(8, ("Returning NULL Devicemode!\n"));
4156 printer->secdesc = NULL;
4158 if ( ntprinter->info_2->secdesc_buf
4159 && ntprinter->info_2->secdesc_buf->len != 0 )
4161 /* don't use talloc_steal() here unless you do a deep steal of all
4162 the SEC_DESC members */
4164 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4165 ntprinter->info_2->secdesc_buf->sec );
4168 free_a_printer(&ntprinter, 2);
4173 /********************************************************************
4174 * construct_printer_info_3
4175 * fill a printer_info_3 struct
4176 ********************************************************************/
4178 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4180 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4181 PRINTER_INFO_3 *printer = NULL;
4183 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4187 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4188 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4192 ZERO_STRUCTP(printer);
4194 /* These are the components of the SD we are returning. */
4196 printer->flags = 0x4;
4198 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4199 /* don't use talloc_steal() here unless you do a deep steal of all
4200 the SEC_DESC members */
4202 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4203 ntprinter->info_2->secdesc_buf->sec );
4206 free_a_printer(&ntprinter, 2);
4208 *pp_printer = printer;
4212 /********************************************************************
4213 * construct_printer_info_4
4214 * fill a printer_info_4 struct
4215 ********************************************************************/
4217 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4219 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4221 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4224 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4225 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4226 printer->attributes = ntprinter->info_2->attributes;
4228 free_a_printer(&ntprinter, 2);
4232 /********************************************************************
4233 * construct_printer_info_5
4234 * fill a printer_info_5 struct
4235 ********************************************************************/
4237 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4239 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4241 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4244 init_unistr(&printer->printername, ntprinter->info_2->printername);
4245 init_unistr(&printer->portname, ntprinter->info_2->portname);
4246 printer->attributes = ntprinter->info_2->attributes;
4248 /* these two are not used by NT+ according to MSDN */
4250 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4251 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4253 free_a_printer(&ntprinter, 2);
4258 /********************************************************************
4259 * construct_printer_info_7
4260 * fill a printer_info_7 struct
4261 ********************************************************************/
4263 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4265 char *guid_str = NULL;
4268 if (is_printer_published(print_hnd, snum, &guid)) {
4269 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4270 strupper_m(guid_str);
4271 init_unistr(&printer->guid, guid_str);
4272 printer->action = SPOOL_DS_PUBLISH;
4274 init_unistr(&printer->guid, "");
4275 printer->action = SPOOL_DS_UNPUBLISH;
4281 /********************************************************************
4282 Spoolss_enumprinters.
4283 ********************************************************************/
4285 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4289 int n_services=lp_numservices();
4290 PRINTER_INFO_1 *tp, *printers=NULL;
4291 PRINTER_INFO_1 current_prt;
4292 WERROR result = WERR_OK;
4294 DEBUG(4,("enum_all_printers_info_1\n"));
4296 for (snum=0; snum<n_services; snum++) {
4297 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4298 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4300 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4301 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4302 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4303 SAFE_FREE(printers);
4308 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4310 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4316 /* check the required size. */
4317 for (i=0; i<*returned; i++)
4318 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4320 if (*needed > offered) {
4321 result = WERR_INSUFFICIENT_BUFFER;
4325 if (!rpcbuf_alloc_size(buffer, *needed)) {
4326 result = WERR_NOMEM;
4330 /* fill the buffer with the structures */
4331 for (i=0; i<*returned; i++)
4332 smb_io_printer_info_1("", buffer, &printers[i], 0);
4337 SAFE_FREE(printers);
4339 if ( !W_ERROR_IS_OK(result) )
4345 /********************************************************************
4346 enum_all_printers_info_1_local.
4347 *********************************************************************/
4349 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4351 DEBUG(4,("enum_all_printers_info_1_local\n"));
4353 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4356 /********************************************************************
4357 enum_all_printers_info_1_name.
4358 *********************************************************************/
4360 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4364 DEBUG(4,("enum_all_printers_info_1_name\n"));
4366 if ((name[0] == '\\') && (name[1] == '\\'))
4369 if (is_myname_or_ipaddr(s)) {
4370 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4373 return WERR_INVALID_NAME;
4376 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4377 /********************************************************************
4378 enum_all_printers_info_1_remote.
4379 *********************************************************************/
4381 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4383 PRINTER_INFO_1 *printer;
4384 fstring printername;
4387 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4388 WERROR result = WERR_OK;
4390 /* JFM: currently it's more a place holder than anything else.
4391 * In the spooler world there is a notion of server registration.
4392 * the print servers are registered on the PDC (in the same domain)
4394 * We should have a TDB here. The registration is done thru an
4395 * undocumented RPC call.
4398 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4403 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4404 slprintf(desc, sizeof(desc)-1,"%s", name);
4405 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4407 init_unistr(&printer->description, desc);
4408 init_unistr(&printer->name, printername);
4409 init_unistr(&printer->comment, comment);
4410 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4412 /* check the required size. */
4413 *needed += spoolss_size_printer_info_1(printer);
4415 if (*needed > offered) {
4416 result = WERR_INSUFFICIENT_BUFFER;
4420 if (!rpcbuf_alloc_size(buffer, *needed)) {
4421 result = WERR_NOMEM;
4425 /* fill the buffer with the structures */
4426 smb_io_printer_info_1("", buffer, printer, 0);
4432 if ( !W_ERROR_IS_OK(result) )
4440 /********************************************************************
4441 enum_all_printers_info_1_network.
4442 *********************************************************************/
4444 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4448 DEBUG(4,("enum_all_printers_info_1_network\n"));
4450 /* If we respond to a enum_printers level 1 on our name with flags
4451 set to PRINTER_ENUM_REMOTE with a list of printers then these
4452 printers incorrectly appear in the APW browse list.
4453 Specifically the printers for the server appear at the workgroup
4454 level where all the other servers in the domain are
4455 listed. Windows responds to this call with a
4456 WERR_CAN_NOT_COMPLETE so we should do the same. */
4458 if (name[0] == '\\' && name[1] == '\\')
4461 if (is_myname_or_ipaddr(s))
4462 return WERR_CAN_NOT_COMPLETE;
4464 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4467 /********************************************************************
4468 * api_spoolss_enumprinters
4470 * called from api_spoolss_enumprinters (see this to understand)
4471 ********************************************************************/
4473 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4477 int n_services=lp_numservices();
4478 PRINTER_INFO_2 *tp, *printers=NULL;
4479 PRINTER_INFO_2 current_prt;
4480 WERROR result = WERR_OK;
4482 for (snum=0; snum<n_services; snum++) {
4483 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4484 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4486 if (construct_printer_info_2(NULL, ¤t_prt, snum))
4488 if ( !(tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4489 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4490 SAFE_FREE(printers);
4495 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4498 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4505 /* check the required size. */
4506 for (i=0; i<*returned; i++)
4507 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4509 if (*needed > offered) {
4510 result = WERR_INSUFFICIENT_BUFFER;
4514 if (!rpcbuf_alloc_size(buffer, *needed)) {
4515 result = WERR_NOMEM;
4519 /* fill the buffer with the structures */
4520 for (i=0; i<*returned; i++)
4521 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4526 for (i=0; i<*returned; i++)
4527 free_devmode(printers[i].devmode);
4529 SAFE_FREE(printers);
4531 if ( !W_ERROR_IS_OK(result) )
4537 /********************************************************************
4538 * handle enumeration of printers at level 1
4539 ********************************************************************/
4541 static WERROR enumprinters_level1( uint32 flags, fstring name,
4542 RPC_BUFFER *buffer, uint32 offered,
4543 uint32 *needed, uint32 *returned)
4545 /* Not all the flags are equals */
4547 if (flags & PRINTER_ENUM_LOCAL)
4548 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4550 if (flags & PRINTER_ENUM_NAME)
4551 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4553 #if 0 /* JERRY - disabled for now */
4554 if (flags & PRINTER_ENUM_REMOTE)
4555 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4558 if (flags & PRINTER_ENUM_NETWORK)
4559 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4561 return WERR_OK; /* NT4sp5 does that */
4564 /********************************************************************
4565 * handle enumeration of printers at level 2
4566 ********************************************************************/
4568 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4569 RPC_BUFFER *buffer, uint32 offered,
4570 uint32 *needed, uint32 *returned)
4572 char *s = servername;
4574 if (flags & PRINTER_ENUM_LOCAL) {
4575 return enum_all_printers_info_2(buffer, offered, needed, returned);
4578 if (flags & PRINTER_ENUM_NAME) {
4579 if ((servername[0] == '\\') && (servername[1] == '\\'))
4581 if (is_myname_or_ipaddr(s))
4582 return enum_all_printers_info_2(buffer, offered, needed, returned);
4584 return WERR_INVALID_NAME;
4587 if (flags & PRINTER_ENUM_REMOTE)
4588 return WERR_UNKNOWN_LEVEL;
4593 /********************************************************************
4594 * handle enumeration of printers at level 5
4595 ********************************************************************/
4597 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4598 RPC_BUFFER *buffer, uint32 offered,
4599 uint32 *needed, uint32 *returned)
4601 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4605 /********************************************************************
4606 * api_spoolss_enumprinters
4608 * called from api_spoolss_enumprinters (see this to understand)
4609 ********************************************************************/
4611 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4613 uint32 flags = q_u->flags;
4614 UNISTR2 *servername = &q_u->servername;
4615 uint32 level = q_u->level;
4616 RPC_BUFFER *buffer = NULL;
4617 uint32 offered = q_u->offered;
4618 uint32 *needed = &r_u->needed;
4619 uint32 *returned = &r_u->returned;
4623 /* that's an [in out] buffer */
4625 if ( q_u->buffer ) {
4626 rpcbuf_move(q_u->buffer, &r_u->buffer);
4627 buffer = r_u->buffer;
4630 DEBUG(4,("_spoolss_enumprinters\n"));
4637 * flags==PRINTER_ENUM_NAME
4638 * if name=="" then enumerates all printers
4639 * if name!="" then enumerate the printer
4640 * flags==PRINTER_ENUM_REMOTE
4641 * name is NULL, enumerate printers
4642 * Level 2: name!="" enumerates printers, name can't be NULL
4643 * Level 3: doesn't exist
4644 * Level 4: does a local registry lookup
4645 * Level 5: same as Level 2
4648 unistr2_to_ascii(name, servername, sizeof(name)-1);
4653 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4655 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4657 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4662 return WERR_UNKNOWN_LEVEL;
4665 /****************************************************************************
4666 ****************************************************************************/
4668 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4670 PRINTER_INFO_0 *printer=NULL;
4671 WERROR result = WERR_OK;
4673 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4676 construct_printer_info_0(print_hnd, printer, snum);
4678 /* check the required size. */
4679 *needed += spoolss_size_printer_info_0(printer);
4681 if (*needed > offered) {
4682 result = WERR_INSUFFICIENT_BUFFER;
4686 if (!rpcbuf_alloc_size(buffer, *needed)) {
4687 result = WERR_NOMEM;
4691 /* fill the buffer with the structures */
4692 smb_io_printer_info_0("", buffer, printer, 0);
4702 /****************************************************************************
4703 ****************************************************************************/
4705 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4707 PRINTER_INFO_1 *printer=NULL;
4708 WERROR result = WERR_OK;
4710 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4713 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4715 /* check the required size. */
4716 *needed += spoolss_size_printer_info_1(printer);
4718 if (*needed > offered) {
4719 result = WERR_INSUFFICIENT_BUFFER;
4723 if (!rpcbuf_alloc_size(buffer, *needed)) {
4724 result = WERR_NOMEM;
4728 /* fill the buffer with the structures */
4729 smb_io_printer_info_1("", buffer, printer, 0);
4738 /****************************************************************************
4739 ****************************************************************************/
4741 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4743 PRINTER_INFO_2 *printer=NULL;
4744 WERROR result = WERR_OK;
4746 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4749 construct_printer_info_2(print_hnd, printer, snum);
4751 /* check the required size. */
4752 *needed += spoolss_size_printer_info_2(printer);
4754 if (*needed > offered) {
4755 result = WERR_INSUFFICIENT_BUFFER;
4759 if (!rpcbuf_alloc_size(buffer, *needed)) {
4760 result = WERR_NOMEM;
4764 /* fill the buffer with the structures */
4765 if (!smb_io_printer_info_2("", buffer, printer, 0))
4766 result = WERR_NOMEM;
4770 free_printer_info_2(printer);
4775 /****************************************************************************
4776 ****************************************************************************/
4778 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4780 PRINTER_INFO_3 *printer=NULL;
4781 WERROR result = WERR_OK;
4783 if (!construct_printer_info_3(print_hnd, &printer, snum))
4786 /* check the required size. */
4787 *needed += spoolss_size_printer_info_3(printer);
4789 if (*needed > offered) {
4790 result = WERR_INSUFFICIENT_BUFFER;
4794 if (!rpcbuf_alloc_size(buffer, *needed)) {
4795 result = WERR_NOMEM;
4799 /* fill the buffer with the structures */
4800 smb_io_printer_info_3("", buffer, printer, 0);
4804 free_printer_info_3(printer);
4809 /****************************************************************************
4810 ****************************************************************************/
4812 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4814 PRINTER_INFO_4 *printer=NULL;
4815 WERROR result = WERR_OK;
4817 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4820 if (!construct_printer_info_4(print_hnd, printer, snum))
4823 /* check the required size. */
4824 *needed += spoolss_size_printer_info_4(printer);
4826 if (*needed > offered) {
4827 result = WERR_INSUFFICIENT_BUFFER;
4831 if (!rpcbuf_alloc_size(buffer, *needed)) {
4832 result = WERR_NOMEM;
4836 /* fill the buffer with the structures */
4837 smb_io_printer_info_4("", buffer, printer, 0);
4841 free_printer_info_4(printer);
4846 /****************************************************************************
4847 ****************************************************************************/
4849 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4851 PRINTER_INFO_5 *printer=NULL;
4852 WERROR result = WERR_OK;
4854 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4857 if (!construct_printer_info_5(print_hnd, printer, snum))
4860 /* check the required size. */
4861 *needed += spoolss_size_printer_info_5(printer);
4863 if (*needed > offered) {
4864 result = WERR_INSUFFICIENT_BUFFER;
4868 if (!rpcbuf_alloc_size(buffer, *needed)) {
4869 result = WERR_NOMEM;
4873 /* fill the buffer with the structures */
4874 smb_io_printer_info_5("", buffer, printer, 0);
4878 free_printer_info_5(printer);
4883 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4885 PRINTER_INFO_7 *printer=NULL;
4886 WERROR result = WERR_OK;
4888 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4891 if (!construct_printer_info_7(print_hnd, printer, snum))
4894 /* check the required size. */
4895 *needed += spoolss_size_printer_info_7(printer);
4897 if (*needed > offered) {
4898 result = WERR_INSUFFICIENT_BUFFER;
4902 if (!rpcbuf_alloc_size(buffer, *needed)) {
4903 result = WERR_NOMEM;
4908 /* fill the buffer with the structures */
4909 smb_io_printer_info_7("", buffer, printer, 0);
4913 free_printer_info_7(printer);
4918 /****************************************************************************
4919 ****************************************************************************/
4921 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4923 POLICY_HND *handle = &q_u->handle;
4924 uint32 level = q_u->level;
4925 RPC_BUFFER *buffer = NULL;
4926 uint32 offered = q_u->offered;
4927 uint32 *needed = &r_u->needed;
4928 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4932 /* that's an [in out] buffer */
4934 if ( q_u->buffer ) {
4935 rpcbuf_move(q_u->buffer, &r_u->buffer);
4936 buffer = r_u->buffer;
4941 if (!get_printer_snum(p, handle, &snum))
4946 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4948 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4950 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4952 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4954 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4956 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4958 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4960 return WERR_UNKNOWN_LEVEL;
4963 /********************************************************************
4964 * fill a DRIVER_INFO_1 struct
4965 ********************************************************************/
4967 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4969 init_unistr( &info->name, driver.info_3->name);
4972 /********************************************************************
4973 * construct_printer_driver_info_1
4974 ********************************************************************/
4976 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4978 NT_PRINTER_INFO_LEVEL *printer = NULL;
4979 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4981 ZERO_STRUCT(driver);
4983 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4984 return WERR_INVALID_PRINTER_NAME;
4986 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4987 return WERR_UNKNOWN_PRINTER_DRIVER;
4989 fill_printer_driver_info_1(info, driver, servername, architecture);
4991 free_a_printer(&printer,2);
4996 /********************************************************************
4997 * construct_printer_driver_info_2
4998 * fill a printer_info_2 struct
4999 ********************************************************************/
5001 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5005 info->version=driver.info_3->cversion;
5007 init_unistr( &info->name, driver.info_3->name );
5008 init_unistr( &info->architecture, driver.info_3->environment );
5011 if (strlen(driver.info_3->driverpath)) {
5012 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5013 init_unistr( &info->driverpath, temp );
5015 init_unistr( &info->driverpath, "" );
5017 if (strlen(driver.info_3->datafile)) {
5018 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5019 init_unistr( &info->datafile, temp );
5021 init_unistr( &info->datafile, "" );
5023 if (strlen(driver.info_3->configfile)) {
5024 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5025 init_unistr( &info->configfile, temp );
5027 init_unistr( &info->configfile, "" );
5030 /********************************************************************
5031 * construct_printer_driver_info_2
5032 * fill a printer_info_2 struct
5033 ********************************************************************/
5035 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5037 NT_PRINTER_INFO_LEVEL *printer = NULL;
5038 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5040 ZERO_STRUCT(printer);
5041 ZERO_STRUCT(driver);
5043 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5044 return WERR_INVALID_PRINTER_NAME;
5046 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5047 return WERR_UNKNOWN_PRINTER_DRIVER;
5049 fill_printer_driver_info_2(info, driver, servername);
5051 free_a_printer(&printer,2);
5056 /********************************************************************
5057 * copy a strings array and convert to UNICODE
5059 * convert an array of ascii string to a UNICODE string
5060 ********************************************************************/
5062 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5070 DEBUG(6,("init_unistr_array\n"));
5081 v = ""; /* hack to handle null lists */
5084 /* hack to allow this to be used in places other than when generating
5085 the list of dependent files */
5088 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5092 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5094 /* add one extra unit16 for the second terminating NULL */
5096 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5097 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5105 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5110 /* special case for ""; we need to add both NULL's here */
5112 (*uni_array)[j++]=0x0000;
5113 (*uni_array)[j]=0x0000;
5116 DEBUGADD(6,("last one:done\n"));
5118 /* return size of array in uint16's */
5123 /********************************************************************
5124 * construct_printer_info_3
5125 * fill a printer_info_3 struct
5126 ********************************************************************/
5128 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5134 info->version=driver.info_3->cversion;
5136 init_unistr( &info->name, driver.info_3->name );
5137 init_unistr( &info->architecture, driver.info_3->environment );
5139 if (strlen(driver.info_3->driverpath)) {
5140 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5141 init_unistr( &info->driverpath, temp );
5143 init_unistr( &info->driverpath, "" );
5145 if (strlen(driver.info_3->datafile)) {
5146 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5147 init_unistr( &info->datafile, temp );
5149 init_unistr( &info->datafile, "" );
5151 if (strlen(driver.info_3->configfile)) {
5152 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5153 init_unistr( &info->configfile, temp );
5155 init_unistr( &info->configfile, "" );
5157 if (strlen(driver.info_3->helpfile)) {
5158 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5159 init_unistr( &info->helpfile, temp );
5161 init_unistr( &info->helpfile, "" );
5163 init_unistr( &info->monitorname, driver.info_3->monitorname );
5164 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5166 info->dependentfiles=NULL;
5167 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5170 /********************************************************************
5171 * construct_printer_info_3
5172 * fill a printer_info_3 struct
5173 ********************************************************************/
5175 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5177 NT_PRINTER_INFO_LEVEL *printer = NULL;
5178 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5180 ZERO_STRUCT(driver);
5182 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5183 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5184 if (!W_ERROR_IS_OK(status))
5185 return WERR_INVALID_PRINTER_NAME;
5187 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5188 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5193 * I put this code in during testing. Helpful when commenting out the
5194 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5195 * as win2k always queries the driver using an infor level of 6.
5196 * I've left it in (but ifdef'd out) because I'll probably
5197 * use it in experimentation again in the future. --jerry 22/01/2002
5200 if (!W_ERROR_IS_OK(status)) {
5202 * Is this a W2k client ?
5205 /* Yes - try again with a WinNT driver. */
5207 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5208 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5212 if (!W_ERROR_IS_OK(status)) {
5213 free_a_printer(&printer,2);
5214 return WERR_UNKNOWN_PRINTER_DRIVER;
5222 fill_printer_driver_info_3(info, driver, servername);
5224 free_a_printer(&printer,2);
5229 /********************************************************************
5230 * construct_printer_info_6
5231 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5232 ********************************************************************/
5234 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5240 memset(&nullstr, '\0', sizeof(fstring));
5242 info->version=driver.info_3->cversion;
5244 init_unistr( &info->name, driver.info_3->name );
5245 init_unistr( &info->architecture, driver.info_3->environment );
5247 if (strlen(driver.info_3->driverpath)) {
5248 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5249 init_unistr( &info->driverpath, temp );
5251 init_unistr( &info->driverpath, "" );
5253 if (strlen(driver.info_3->datafile)) {
5254 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5255 init_unistr( &info->datafile, temp );
5257 init_unistr( &info->datafile, "" );
5259 if (strlen(driver.info_3->configfile)) {
5260 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5261 init_unistr( &info->configfile, temp );
5263 init_unistr( &info->configfile, "" );
5265 if (strlen(driver.info_3->helpfile)) {
5266 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5267 init_unistr( &info->helpfile, temp );
5269 init_unistr( &info->helpfile, "" );
5271 init_unistr( &info->monitorname, driver.info_3->monitorname );
5272 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5274 info->dependentfiles = NULL;
5275 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5277 info->previousdrivernames=NULL;
5278 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5280 info->driver_date.low=0;
5281 info->driver_date.high=0;
5284 info->driver_version_low=0;
5285 info->driver_version_high=0;
5287 init_unistr( &info->mfgname, "");
5288 init_unistr( &info->oem_url, "");
5289 init_unistr( &info->hardware_id, "");
5290 init_unistr( &info->provider, "");
5293 /********************************************************************
5294 * construct_printer_info_6
5295 * fill a printer_info_6 struct
5296 ********************************************************************/
5298 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5299 fstring servername, fstring architecture, uint32 version)
5301 NT_PRINTER_INFO_LEVEL *printer = NULL;
5302 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5305 ZERO_STRUCT(driver);
5307 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5309 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5311 if (!W_ERROR_IS_OK(status))
5312 return WERR_INVALID_PRINTER_NAME;
5314 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5316 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5318 if (!W_ERROR_IS_OK(status))
5321 * Is this a W2k client ?
5325 free_a_printer(&printer,2);
5326 return WERR_UNKNOWN_PRINTER_DRIVER;
5329 /* Yes - try again with a WinNT driver. */
5331 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5332 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5333 if (!W_ERROR_IS_OK(status)) {
5334 free_a_printer(&printer,2);
5335 return WERR_UNKNOWN_PRINTER_DRIVER;
5339 fill_printer_driver_info_6(info, driver, servername);
5341 free_a_printer(&printer,2);
5342 free_a_printer_driver(driver, 3);
5347 /****************************************************************************
5348 ****************************************************************************/
5350 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5352 SAFE_FREE(info->dependentfiles);
5355 /****************************************************************************
5356 ****************************************************************************/
5358 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5360 SAFE_FREE(info->dependentfiles);
5363 /****************************************************************************
5364 ****************************************************************************/
5366 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5368 DRIVER_INFO_1 *info=NULL;
5371 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5374 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5375 if (!W_ERROR_IS_OK(result))
5378 /* check the required size. */
5379 *needed += spoolss_size_printer_driver_info_1(info);
5381 if (*needed > offered) {
5382 result = WERR_INSUFFICIENT_BUFFER;
5386 if (!rpcbuf_alloc_size(buffer, *needed)) {
5387 result = WERR_NOMEM;
5391 /* fill the buffer with the structures */
5392 smb_io_printer_driver_info_1("", buffer, info, 0);
5401 /****************************************************************************
5402 ****************************************************************************/
5404 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5406 DRIVER_INFO_2 *info=NULL;
5409 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5412 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5413 if (!W_ERROR_IS_OK(result))
5416 /* check the required size. */
5417 *needed += spoolss_size_printer_driver_info_2(info);
5419 if (*needed > offered) {
5420 result = WERR_INSUFFICIENT_BUFFER;
5424 if (!rpcbuf_alloc_size(buffer, *needed)) {
5425 result = WERR_NOMEM;
5429 /* fill the buffer with the structures */
5430 smb_io_printer_driver_info_2("", buffer, info, 0);
5439 /****************************************************************************
5440 ****************************************************************************/
5442 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5449 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5450 if (!W_ERROR_IS_OK(result))
5453 /* check the required size. */
5454 *needed += spoolss_size_printer_driver_info_3(&info);
5456 if (*needed > offered) {
5457 result = WERR_INSUFFICIENT_BUFFER;
5461 if (!rpcbuf_alloc_size(buffer, *needed)) {
5462 result = WERR_NOMEM;
5466 /* fill the buffer with the structures */
5467 smb_io_printer_driver_info_3("", buffer, &info, 0);
5470 free_printer_driver_info_3(&info);
5475 /****************************************************************************
5476 ****************************************************************************/
5478 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5485 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5486 if (!W_ERROR_IS_OK(result))
5489 /* check the required size. */
5490 *needed += spoolss_size_printer_driver_info_6(&info);
5492 if (*needed > offered) {
5493 result = WERR_INSUFFICIENT_BUFFER;
5497 if (!rpcbuf_alloc_size(buffer, *needed)) {
5498 result = WERR_NOMEM;
5502 /* fill the buffer with the structures */
5503 smb_io_printer_driver_info_6("", buffer, &info, 0);
5506 free_printer_driver_info_6(&info);
5511 /****************************************************************************
5512 ****************************************************************************/
5514 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5516 POLICY_HND *handle = &q_u->handle;
5517 UNISTR2 *uni_arch = &q_u->architecture;
5518 uint32 level = q_u->level;
5519 uint32 clientmajorversion = q_u->clientmajorversion;
5520 RPC_BUFFER *buffer = NULL;
5521 uint32 offered = q_u->offered;
5522 uint32 *needed = &r_u->needed;
5523 uint32 *servermajorversion = &r_u->servermajorversion;
5524 uint32 *serverminorversion = &r_u->serverminorversion;
5525 Printer_entry *printer;
5528 fstring architecture;
5531 /* that's an [in out] buffer */
5533 if ( q_u->buffer ) {
5534 rpcbuf_move(q_u->buffer, &r_u->buffer);
5535 buffer = r_u->buffer;
5538 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5540 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5541 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5542 return WERR_INVALID_PRINTER_NAME;
5546 *servermajorversion = 0;
5547 *serverminorversion = 0;
5549 fstrcpy(servername, get_server_name( printer ));
5550 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5552 if (!get_printer_snum(p, handle, &snum))
5557 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5559 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5561 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5563 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5566 /* apparently this call is the equivalent of
5567 EnumPrinterDataEx() for the DsDriver key */
5572 return WERR_UNKNOWN_LEVEL;
5575 /****************************************************************************
5576 ****************************************************************************/
5578 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5580 POLICY_HND *handle = &q_u->handle;
5582 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5585 DEBUG(3,("Error in startpageprinter printer handle\n"));
5589 Printer->page_started=True;
5593 /****************************************************************************
5594 ****************************************************************************/
5596 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5598 POLICY_HND *handle = &q_u->handle;
5601 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5604 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5608 if (!get_printer_snum(p, handle, &snum))
5611 Printer->page_started=False;
5612 print_job_endpage(snum, Printer->jobid);
5617 /********************************************************************
5618 * api_spoolss_getprinter
5619 * called from the spoolss dispatcher
5621 ********************************************************************/
5623 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5625 POLICY_HND *handle = &q_u->handle;
5626 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5627 uint32 *jobid = &r_u->jobid;
5629 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5633 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5634 struct current_user user;
5637 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5641 get_current_user(&user, p);
5644 * a nice thing with NT is it doesn't listen to what you tell it.
5645 * when asked to send _only_ RAW datas, it tries to send datas
5648 * So I add checks like in NT Server ...
5651 if (info_1->p_datatype != 0) {
5652 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5653 if (strcmp(datatype, "RAW") != 0) {
5655 return WERR_INVALID_DATATYPE;
5659 /* get the share number of the printer */
5660 if (!get_printer_snum(p, handle, &snum)) {
5664 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5666 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5668 /* An error occured in print_job_start() so return an appropriate
5671 if (Printer->jobid == -1) {
5672 return map_werror_from_unix(errno);
5675 Printer->document_started=True;
5676 (*jobid) = Printer->jobid;
5681 /********************************************************************
5682 * api_spoolss_getprinter
5683 * called from the spoolss dispatcher
5685 ********************************************************************/
5687 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5689 POLICY_HND *handle = &q_u->handle;
5691 return _spoolss_enddocprinter_internal(p, handle);
5694 /****************************************************************************
5695 ****************************************************************************/
5697 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5699 POLICY_HND *handle = &q_u->handle;
5700 uint32 buffer_size = q_u->buffer_size;
5701 uint8 *buffer = q_u->buffer;
5702 uint32 *buffer_written = &q_u->buffer_size2;
5704 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5707 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5708 r_u->buffer_written = q_u->buffer_size2;
5712 if (!get_printer_snum(p, handle, &snum))
5715 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5716 (SMB_OFF_T)-1, (size_t)buffer_size);
5717 if (*buffer_written == (uint32)-1) {
5718 r_u->buffer_written = 0;
5719 if (errno == ENOSPC)
5720 return WERR_NO_SPOOL_SPACE;
5722 return WERR_ACCESS_DENIED;
5725 r_u->buffer_written = q_u->buffer_size2;
5730 /********************************************************************
5731 * api_spoolss_getprinter
5732 * called from the spoolss dispatcher
5734 ********************************************************************/
5736 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5739 struct current_user user;
5741 WERROR errcode = WERR_BADFUNC;
5742 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5744 get_current_user(&user, p);
5747 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5751 if (!get_printer_snum(p, handle, &snum))
5755 case PRINTER_CONTROL_PAUSE:
5756 if (print_queue_pause(&user, snum, &errcode)) {
5760 case PRINTER_CONTROL_RESUME:
5761 case PRINTER_CONTROL_UNPAUSE:
5762 if (print_queue_resume(&user, snum, &errcode)) {
5766 case PRINTER_CONTROL_PURGE:
5767 if (print_queue_purge(&user, snum, &errcode)) {
5772 return WERR_UNKNOWN_LEVEL;
5778 /********************************************************************
5779 * api_spoolss_abortprinter
5780 * From MSDN: "Deletes printer's spool file if printer is configured
5782 ********************************************************************/
5784 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5786 POLICY_HND *handle = &q_u->handle;
5787 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5789 struct current_user user;
5790 WERROR errcode = WERR_OK;
5793 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5797 if (!get_printer_snum(p, handle, &snum))
5800 get_current_user( &user, p );
5802 print_job_delete( &user, snum, Printer->jobid, &errcode );
5807 /********************************************************************
5808 * called by spoolss_api_setprinter
5809 * when updating a printer description
5810 ********************************************************************/
5812 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5813 const SPOOL_PRINTER_INFO_LEVEL *info,
5814 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5816 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5820 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5822 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5823 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5824 OUR_HANDLE(handle)));
5826 result = WERR_BADFID;
5830 /* Check the user has permissions to change the security
5831 descriptor. By experimentation with two NT machines, the user
5832 requires Full Access to the printer to change security
5835 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5836 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5837 result = WERR_ACCESS_DENIED;
5841 /* NT seems to like setting the security descriptor even though
5842 nothing may have actually changed. */
5844 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5846 if (DEBUGLEVEL >= 10) {
5850 the_acl = old_secdesc_ctr->sec->dacl;
5851 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5852 PRINTERNAME(snum), the_acl->num_aces));
5854 for (i = 0; i < the_acl->num_aces; i++) {
5857 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5859 DEBUG(10, ("%s 0x%08x\n", sid_str,
5860 the_acl->ace[i].info.mask));
5863 the_acl = secdesc_ctr->sec->dacl;
5866 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5867 PRINTERNAME(snum), the_acl->num_aces));
5869 for (i = 0; i < the_acl->num_aces; i++) {
5872 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5874 DEBUG(10, ("%s 0x%08x\n", sid_str,
5875 the_acl->ace[i].info.mask));
5878 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5882 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5884 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5889 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5896 /********************************************************************
5897 Canonicalize printer info from a client
5899 ATTN: It does not matter what we set the servername to hear
5900 since we do the necessary work in get_a_printer() to set it to
5901 the correct value based on what the client sent in the
5902 _spoolss_open_printer_ex().
5903 ********************************************************************/
5905 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5907 fstring printername;
5910 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5911 "portname=%s drivername=%s comment=%s location=%s\n",
5912 info->servername, info->printername, info->sharename,
5913 info->portname, info->drivername, info->comment, info->location));
5915 /* we force some elements to "correct" values */
5916 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5917 fstrcpy(info->sharename, lp_servicename(snum));
5919 /* check to see if we allow printername != sharename */
5921 if ( lp_force_printername(snum) ) {
5922 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5923 global_myname(), info->sharename );
5926 /* make sure printername is in \\server\printername format */
5928 fstrcpy( printername, info->printername );
5930 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5931 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5935 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5936 global_myname(), p );
5939 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5940 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5947 /****************************************************************************
5948 ****************************************************************************/
5950 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5952 char *cmd = lp_addprinter_cmd();
5958 fstring remote_machine = "%m";
5959 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5960 BOOL is_print_op = False;
5962 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5964 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5965 cmd, printer->info_2->printername, printer->info_2->sharename,
5966 printer->info_2->portname, printer->info_2->drivername,
5967 printer->info_2->location, printer->info_2->comment, remote_machine);
5970 is_print_op = user_has_privileges( token, &se_printop );
5972 DEBUG(10,("Running [%s]\n", command));
5974 /********* BEGIN SePrintOperatorPrivilege **********/
5979 if ( (ret = smbrun(command, &fd)) == 0 ) {
5980 /* Tell everyone we updated smb.conf. */
5981 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
5987 /********* END SePrintOperatorPrivilege **********/
5989 DEBUGADD(10,("returned [%d]\n", ret));
5997 /* reload our services immediately */
5998 reload_services( False );
6001 /* Get lines and convert them back to dos-codepage */
6002 qlines = fd_lines_load(fd, &numlines, 0);
6003 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6006 /* Set the portname to what the script says the portname should be. */
6007 /* but don't require anything to be return from the script exit a good error code */
6010 /* Set the portname to what the script says the portname should be. */
6011 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6012 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6015 file_lines_free(qlines);
6019 /********************************************************************
6020 * Called by spoolss_api_setprinter
6021 * when updating a printer description.
6022 ********************************************************************/
6024 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6025 const SPOOL_PRINTER_INFO_LEVEL *info,
6026 DEVICEMODE *devmode)
6029 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6030 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6035 DEBUG(8,("update_printer\n"));
6040 result = WERR_BADFID;
6044 if (!get_printer_snum(p, handle, &snum)) {
6045 result = WERR_BADFID;
6049 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6050 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6051 result = WERR_BADFID;
6055 DEBUGADD(8,("Converting info_2 struct\n"));
6058 * convert_printer_info converts the incoming
6059 * info from the client and overwrites the info
6060 * just read from the tdb in the pointer 'printer'.
6063 if (!convert_printer_info(info, printer, level)) {
6064 result = WERR_NOMEM;
6069 /* we have a valid devmode
6070 convert it and link it*/
6072 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6073 if (!convert_devicemode(printer->info_2->printername, devmode,
6074 &printer->info_2->devmode)) {
6075 result = WERR_NOMEM;
6080 /* Do sanity check on the requested changes for Samba */
6082 if (!check_printer_ok(printer->info_2, snum)) {
6083 result = WERR_INVALID_PARAM;
6087 /* FIXME!!! If the driver has changed we really should verify that
6088 it is installed before doing much else --jerry */
6090 /* Check calling user has permission to update printer description */
6092 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6093 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6094 result = WERR_ACCESS_DENIED;
6098 /* Call addprinter hook */
6099 /* Check changes to see if this is really needed */
6101 if ( *lp_addprinter_cmd()
6102 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6103 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6104 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6105 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6107 /* add_printer_hook() will call reload_services() */
6109 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6110 result = WERR_ACCESS_DENIED;
6116 * When a *new* driver is bound to a printer, the drivername is used to
6117 * lookup previously saved driver initialization info, which is then
6118 * bound to the printer, simulating what happens in the Windows arch.
6120 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6122 if (!set_driver_init(printer, 2))
6124 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6125 printer->info_2->drivername));
6128 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6129 printer->info_2->drivername));
6131 notify_printer_driver(snum, printer->info_2->drivername);
6135 * flag which changes actually occured. This is a small subset of
6136 * all the possible changes. We also have to update things in the
6140 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6141 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6142 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6143 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6145 notify_printer_comment(snum, printer->info_2->comment);
6148 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6149 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6150 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6151 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6153 notify_printer_sharename(snum, printer->info_2->sharename);
6156 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6159 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6162 pname = printer->info_2->printername;
6165 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6166 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6167 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6169 notify_printer_printername( snum, pname );
6172 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6173 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6174 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6175 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6177 notify_printer_port(snum, printer->info_2->portname);
6180 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6181 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6182 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6183 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6185 notify_printer_location(snum, printer->info_2->location);
6188 /* here we need to update some more DsSpooler keys */
6189 /* uNCName, serverName, shortServerName */
6191 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6192 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6193 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6194 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6195 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6197 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6198 global_myname(), printer->info_2->sharename );
6199 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6200 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6201 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6203 /* Update printer info */
6204 result = mod_a_printer(printer, 2);
6207 free_a_printer(&printer, 2);
6208 free_a_printer(&old_printer, 2);
6214 /****************************************************************************
6215 ****************************************************************************/
6216 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6217 const SPOOL_PRINTER_INFO_LEVEL *info)
6220 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6222 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6224 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6229 if (!get_printer_snum(p, handle, &snum))
6232 nt_printer_publish(Printer, snum, info7->action);
6236 return WERR_UNKNOWN_LEVEL;
6239 /****************************************************************************
6240 ****************************************************************************/
6242 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6244 POLICY_HND *handle = &q_u->handle;
6245 uint32 level = q_u->level;
6246 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6247 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6248 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6249 uint32 command = q_u->command;
6252 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6255 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6259 /* check the level */
6262 return control_printer(handle, command, p);
6264 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6265 if (!W_ERROR_IS_OK(result))
6268 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6271 return update_printer_sec(handle, level, info, p,
6274 return publish_or_unpublish_printer(p, handle, info);
6276 return WERR_UNKNOWN_LEVEL;
6280 /****************************************************************************
6281 ****************************************************************************/
6283 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6285 POLICY_HND *handle = &q_u->handle;
6286 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6289 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6293 if (Printer->notify.client_connected==True) {
6296 if ( Printer->printer_type == SPLHND_SERVER)
6298 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6299 !get_printer_snum(p, handle, &snum) )
6302 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6305 Printer->notify.flags=0;
6306 Printer->notify.options=0;
6307 Printer->notify.localmachine[0]='\0';
6308 Printer->notify.printerlocal=0;
6309 if (Printer->notify.option)
6310 free_spool_notify_option(&Printer->notify.option);
6311 Printer->notify.client_connected=False;
6316 /****************************************************************************
6317 ****************************************************************************/
6319 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6321 /* that's an [in out] buffer */
6324 rpcbuf_move(q_u->buffer, &r_u->buffer);
6327 return WERR_INVALID_PARAM; /* this is what a NT server
6328 returns for AddJob. AddJob
6329 must fail on non-local
6333 /****************************************************************************
6334 ****************************************************************************/
6336 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6337 int position, int snum,
6338 NT_PRINTER_INFO_LEVEL *ntprinter)
6342 t=gmtime(&queue->time);
6344 job_info->jobid=queue->job;
6345 init_unistr(&job_info->printername, lp_servicename(snum));
6346 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6347 init_unistr(&job_info->username, queue->fs_user);
6348 init_unistr(&job_info->document, queue->fs_file);
6349 init_unistr(&job_info->datatype, "RAW");
6350 init_unistr(&job_info->text_status, "");
6351 job_info->status=nt_printj_status(queue->status);
6352 job_info->priority=queue->priority;
6353 job_info->position=position;
6354 job_info->totalpages=queue->page_count;
6355 job_info->pagesprinted=0;
6357 make_systemtime(&job_info->submitted, t);
6360 /****************************************************************************
6361 ****************************************************************************/
6363 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6364 int position, int snum,
6365 NT_PRINTER_INFO_LEVEL *ntprinter,
6366 DEVICEMODE *devmode)
6370 t=gmtime(&queue->time);
6372 job_info->jobid=queue->job;
6374 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6376 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6377 init_unistr(&job_info->username, queue->fs_user);
6378 init_unistr(&job_info->document, queue->fs_file);
6379 init_unistr(&job_info->notifyname, queue->fs_user);
6380 init_unistr(&job_info->datatype, "RAW");
6381 init_unistr(&job_info->printprocessor, "winprint");
6382 init_unistr(&job_info->parameters, "");
6383 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6384 init_unistr(&job_info->text_status, "");
6386 /* and here the security descriptor */
6388 job_info->status=nt_printj_status(queue->status);
6389 job_info->priority=queue->priority;
6390 job_info->position=position;
6391 job_info->starttime=0;
6392 job_info->untiltime=0;
6393 job_info->totalpages=queue->page_count;
6394 job_info->size=queue->size;
6395 make_systemtime(&(job_info->submitted), t);
6396 job_info->timeelapsed=0;
6397 job_info->pagesprinted=0;
6399 job_info->devmode = devmode;
6404 /****************************************************************************
6405 Enumjobs at level 1.
6406 ****************************************************************************/
6408 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6409 NT_PRINTER_INFO_LEVEL *ntprinter,
6410 RPC_BUFFER *buffer, uint32 offered,
6411 uint32 *needed, uint32 *returned)
6415 WERROR result = WERR_OK;
6417 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6424 for (i=0; i<*returned; i++)
6425 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6429 /* check the required size. */
6430 for (i=0; i<*returned; i++)
6431 (*needed) += spoolss_size_job_info_1(&info[i]);
6433 if (*needed > offered) {
6434 result = WERR_INSUFFICIENT_BUFFER;
6438 if (!rpcbuf_alloc_size(buffer, *needed)) {
6439 result = WERR_NOMEM;
6443 /* fill the buffer with the structures */
6444 for (i=0; i<*returned; i++)
6445 smb_io_job_info_1("", buffer, &info[i], 0);
6451 if ( !W_ERROR_IS_OK(result) )
6457 /****************************************************************************
6458 Enumjobs at level 2.
6459 ****************************************************************************/
6461 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6462 NT_PRINTER_INFO_LEVEL *ntprinter,
6463 RPC_BUFFER *buffer, uint32 offered,
6464 uint32 *needed, uint32 *returned)
6466 JOB_INFO_2 *info = NULL;
6468 WERROR result = WERR_OK;
6469 DEVICEMODE *devmode = NULL;
6471 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6476 /* this should not be a failure condition if the devmode is NULL */
6478 devmode = construct_dev_mode(snum);
6480 for (i=0; i<*returned; i++)
6481 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6483 free_a_printer(&ntprinter, 2);
6486 /* check the required size. */
6487 for (i=0; i<*returned; i++)
6488 (*needed) += spoolss_size_job_info_2(&info[i]);
6490 if (*needed > offered) {
6491 result = WERR_INSUFFICIENT_BUFFER;
6495 if (!rpcbuf_alloc_size(buffer, *needed)) {
6496 result = WERR_NOMEM;
6500 /* fill the buffer with the structures */
6501 for (i=0; i<*returned; i++)
6502 smb_io_job_info_2("", buffer, &info[i], 0);
6505 free_devmode(devmode);
6508 if ( !W_ERROR_IS_OK(result) )
6515 /****************************************************************************
6517 ****************************************************************************/
6519 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6521 POLICY_HND *handle = &q_u->handle;
6522 uint32 level = q_u->level;
6523 RPC_BUFFER *buffer = NULL;
6524 uint32 offered = q_u->offered;
6525 uint32 *needed = &r_u->needed;
6526 uint32 *returned = &r_u->returned;
6528 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6530 print_status_struct prt_status;
6531 print_queue_struct *queue=NULL;
6533 /* that's an [in out] buffer */
6535 if ( q_u->buffer ) {
6536 rpcbuf_move(q_u->buffer, &r_u->buffer);
6537 buffer = r_u->buffer;
6540 DEBUG(4,("_spoolss_enumjobs\n"));
6545 /* lookup the printer snum and tdb entry */
6547 if (!get_printer_snum(p, handle, &snum))
6550 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6551 if ( !W_ERROR_IS_OK(wret) )
6554 *returned = print_queue_status(snum, &queue, &prt_status);
6555 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6557 if (*returned == 0) {
6564 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6567 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6572 wret = WERR_UNKNOWN_LEVEL;
6575 free_a_printer( &ntprinter, 2 );
6579 /****************************************************************************
6580 ****************************************************************************/
6582 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6587 /****************************************************************************
6588 ****************************************************************************/
6590 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6592 POLICY_HND *handle = &q_u->handle;
6593 uint32 jobid = q_u->jobid;
6594 uint32 command = q_u->command;
6596 struct current_user user;
6598 WERROR errcode = WERR_BADFUNC;
6600 if (!get_printer_snum(p, handle, &snum)) {
6604 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6605 return WERR_INVALID_PRINTER_NAME;
6608 get_current_user(&user, p);
6611 case JOB_CONTROL_CANCEL:
6612 case JOB_CONTROL_DELETE:
6613 if (print_job_delete(&user, snum, jobid, &errcode)) {
6617 case JOB_CONTROL_PAUSE:
6618 if (print_job_pause(&user, snum, jobid, &errcode)) {
6622 case JOB_CONTROL_RESTART:
6623 case JOB_CONTROL_RESUME:
6624 if (print_job_resume(&user, snum, jobid, &errcode)) {
6629 return WERR_UNKNOWN_LEVEL;
6635 /****************************************************************************
6636 Enumerates all printer drivers at level 1.
6637 ****************************************************************************/
6639 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6644 fstring *list = NULL;
6645 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6646 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6647 WERROR result = WERR_OK;
6651 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6653 ndrivers=get_ntdrivers(&list, architecture, version);
6654 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6660 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6661 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6662 SAFE_FREE(driver_info_1);
6666 else driver_info_1 = tdi1;
6669 for (i=0; i<ndrivers; i++) {
6671 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6672 ZERO_STRUCT(driver);
6673 status = get_a_printer_driver(&driver, 3, list[i],
6674 architecture, version);
6675 if (!W_ERROR_IS_OK(status)) {
6679 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6680 free_a_printer_driver(driver, 3);
6683 *returned+=ndrivers;
6687 /* check the required size. */
6688 for (i=0; i<*returned; i++) {
6689 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6690 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6693 if (*needed > offered) {
6694 result = WERR_INSUFFICIENT_BUFFER;
6698 if (!rpcbuf_alloc_size(buffer, *needed)) {
6699 result = WERR_NOMEM;
6703 /* fill the buffer with the driver structures */
6704 for (i=0; i<*returned; i++) {
6705 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6706 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6710 SAFE_FREE(driver_info_1);
6712 if ( !W_ERROR_IS_OK(result) )
6718 /****************************************************************************
6719 Enumerates all printer drivers at level 2.
6720 ****************************************************************************/
6722 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6727 fstring *list = NULL;
6728 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6729 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6730 WERROR result = WERR_OK;
6734 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6736 ndrivers=get_ntdrivers(&list, architecture, version);
6737 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6743 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6744 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6745 SAFE_FREE(driver_info_2);
6749 else driver_info_2 = tdi2;
6752 for (i=0; i<ndrivers; i++) {
6755 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6756 ZERO_STRUCT(driver);
6757 status = get_a_printer_driver(&driver, 3, list[i],
6758 architecture, version);
6759 if (!W_ERROR_IS_OK(status)) {
6763 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6764 free_a_printer_driver(driver, 3);
6767 *returned+=ndrivers;
6771 /* check the required size. */
6772 for (i=0; i<*returned; i++) {
6773 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6774 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6777 if (*needed > offered) {
6778 result = WERR_INSUFFICIENT_BUFFER;
6782 if (!rpcbuf_alloc_size(buffer, *needed)) {
6783 result = WERR_NOMEM;
6787 /* fill the buffer with the form structures */
6788 for (i=0; i<*returned; i++) {
6789 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6790 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6794 SAFE_FREE(driver_info_2);
6796 if ( !W_ERROR_IS_OK(result) )
6802 /****************************************************************************
6803 Enumerates all printer drivers at level 3.
6804 ****************************************************************************/
6806 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6811 fstring *list = NULL;
6812 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6813 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6814 WERROR result = WERR_OK;
6818 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6820 ndrivers=get_ntdrivers(&list, architecture, version);
6821 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6827 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6828 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6829 SAFE_FREE(driver_info_3);
6833 else driver_info_3 = tdi3;
6836 for (i=0; i<ndrivers; i++) {
6839 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6840 ZERO_STRUCT(driver);
6841 status = get_a_printer_driver(&driver, 3, list[i],
6842 architecture, version);
6843 if (!W_ERROR_IS_OK(status)) {
6847 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6848 free_a_printer_driver(driver, 3);
6851 *returned+=ndrivers;
6855 /* check the required size. */
6856 for (i=0; i<*returned; i++) {
6857 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6858 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6861 if (*needed > offered) {
6862 result = WERR_INSUFFICIENT_BUFFER;
6866 if (!rpcbuf_alloc_size(buffer, *needed)) {
6867 result = WERR_NOMEM;
6871 /* fill the buffer with the driver structures */
6872 for (i=0; i<*returned; i++) {
6873 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6874 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6878 for (i=0; i<*returned; i++)
6879 SAFE_FREE(driver_info_3[i].dependentfiles);
6881 SAFE_FREE(driver_info_3);
6883 if ( !W_ERROR_IS_OK(result) )
6889 /****************************************************************************
6890 Enumerates all printer drivers.
6891 ****************************************************************************/
6893 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6895 uint32 level = q_u->level;
6896 RPC_BUFFER *buffer = NULL;
6897 uint32 offered = q_u->offered;
6898 uint32 *needed = &r_u->needed;
6899 uint32 *returned = &r_u->returned;
6902 fstring architecture;
6904 /* that's an [in out] buffer */
6906 if ( q_u->buffer ) {
6907 rpcbuf_move(q_u->buffer, &r_u->buffer);
6908 buffer = r_u->buffer;
6911 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6916 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6917 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6919 if ( !is_myname_or_ipaddr( servername ) )
6920 return WERR_UNKNOWN_PRINTER_DRIVER;
6924 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6926 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6928 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6930 return WERR_UNKNOWN_LEVEL;
6934 /****************************************************************************
6935 ****************************************************************************/
6937 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6939 form->flag=list->flag;
6940 init_unistr(&form->name, list->name);
6941 form->width=list->width;
6942 form->length=list->length;
6943 form->left=list->left;
6944 form->top=list->top;
6945 form->right=list->right;
6946 form->bottom=list->bottom;
6949 /****************************************************************************
6950 ****************************************************************************/
6952 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6954 uint32 level = q_u->level;
6955 RPC_BUFFER *buffer = NULL;
6956 uint32 offered = q_u->offered;
6957 uint32 *needed = &r_u->needed;
6958 uint32 *numofforms = &r_u->numofforms;
6959 uint32 numbuiltinforms;
6961 nt_forms_struct *list=NULL;
6962 nt_forms_struct *builtinlist=NULL;
6967 /* that's an [in out] buffer */
6969 if ( q_u->buffer ) {
6970 rpcbuf_move(q_u->buffer, &r_u->buffer);
6971 buffer = r_u->buffer;
6974 DEBUG(4,("_spoolss_enumforms\n"));
6975 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6976 DEBUGADD(5,("Info level [%d]\n", level));
6978 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6979 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6980 *numofforms = get_ntforms(&list);
6981 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6982 *numofforms += numbuiltinforms;
6984 if (*numofforms == 0)
6985 return WERR_NO_MORE_ITEMS;
6989 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
6994 /* construct the list of form structures */
6995 for (i=0; i<numbuiltinforms; i++) {
6996 DEBUGADD(6,("Filling form number [%d]\n",i));
6997 fill_form_1(&forms_1[i], &builtinlist[i]);
7000 SAFE_FREE(builtinlist);
7002 for (; i<*numofforms; i++) {
7003 DEBUGADD(6,("Filling form number [%d]\n",i));
7004 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7009 /* check the required size. */
7010 for (i=0; i<numbuiltinforms; i++) {
7011 DEBUGADD(6,("adding form [%d]'s size\n",i));
7012 buffer_size += spoolss_size_form_1(&forms_1[i]);
7014 for (; i<*numofforms; i++) {
7015 DEBUGADD(6,("adding form [%d]'s size\n",i));
7016 buffer_size += spoolss_size_form_1(&forms_1[i]);
7019 *needed=buffer_size;
7021 if (*needed > offered) {
7024 return WERR_INSUFFICIENT_BUFFER;
7027 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7033 /* fill the buffer with the form structures */
7034 for (i=0; i<numbuiltinforms; i++) {
7035 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7036 smb_io_form_1("", buffer, &forms_1[i], 0);
7038 for (; i<*numofforms; i++) {
7039 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7040 smb_io_form_1("", buffer, &forms_1[i], 0);
7049 SAFE_FREE(builtinlist);
7050 return WERR_UNKNOWN_LEVEL;
7055 /****************************************************************************
7056 ****************************************************************************/
7058 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7060 uint32 level = q_u->level;
7061 UNISTR2 *uni_formname = &q_u->formname;
7062 RPC_BUFFER *buffer = NULL;
7063 uint32 offered = q_u->offered;
7064 uint32 *needed = &r_u->needed;
7066 nt_forms_struct *list=NULL;
7067 nt_forms_struct builtin_form;
7072 int numofforms=0, i=0;
7074 /* that's an [in out] buffer */
7076 if ( q_u->buffer ) {
7077 rpcbuf_move(q_u->buffer, &r_u->buffer);
7078 buffer = r_u->buffer;
7081 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7083 DEBUG(4,("_spoolss_getform\n"));
7084 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7085 DEBUGADD(5,("Info level [%d]\n", level));
7087 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7088 if (!foundBuiltin) {
7089 numofforms = get_ntforms(&list);
7090 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7092 if (numofforms == 0)
7099 fill_form_1(&form_1, &builtin_form);
7102 /* Check if the requested name is in the list of form structures */
7103 for (i=0; i<numofforms; i++) {
7105 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7107 if (strequal(form_name, list[i].name)) {
7108 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7109 fill_form_1(&form_1, &list[i]);
7115 if (i == numofforms) {
7119 /* check the required size. */
7121 *needed=spoolss_size_form_1(&form_1);
7123 if (*needed > offered)
7124 return WERR_INSUFFICIENT_BUFFER;
7126 if (!rpcbuf_alloc_size(buffer, buffer_size))
7129 /* fill the buffer with the form structures */
7130 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7131 smb_io_form_1("", buffer, &form_1, 0);
7137 return WERR_UNKNOWN_LEVEL;
7141 /****************************************************************************
7142 ****************************************************************************/
7144 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7146 init_unistr(&port->port_name, name);
7149 /****************************************************************************
7150 ****************************************************************************/
7152 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7154 init_unistr(&port->port_name, name);
7155 init_unistr(&port->monitor_name, "Local Monitor");
7156 init_unistr(&port->description, "Local Port");
7157 port->port_type=PORT_TYPE_WRITE;
7162 /****************************************************************************
7163 wrapper around the enumer ports command
7164 ****************************************************************************/
7166 WERROR enumports_hook( int *count, char ***lines )
7168 char *cmd = lp_enumports_cmd();
7176 /* if no hook then just fill in the default port */
7179 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7180 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7185 /* we have a valid enumport command */
7187 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7189 DEBUG(10,("Running [%s]\n", command));
7190 ret = smbrun(command, &fd);
7191 DEBUG(10,("Returned [%d]\n", ret));
7196 return WERR_ACCESS_DENIED;
7200 qlines = fd_lines_load(fd, &numlines, 0);
7201 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7211 /****************************************************************************
7213 ****************************************************************************/
7215 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7217 PORT_INFO_1 *ports=NULL;
7219 WERROR result = WERR_OK;
7223 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7227 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7228 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7229 dos_errstr(WERR_NOMEM)));
7230 file_lines_free(qlines);
7234 for (i=0; i<numlines; i++) {
7235 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7236 fill_port_1(&ports[i], qlines[i]);
7239 file_lines_free(qlines);
7242 *returned = numlines;
7244 /* check the required size. */
7245 for (i=0; i<*returned; i++) {
7246 DEBUGADD(6,("adding port [%d]'s size\n", i));
7247 *needed += spoolss_size_port_info_1(&ports[i]);
7250 if (*needed > offered) {
7251 result = WERR_INSUFFICIENT_BUFFER;
7255 if (!rpcbuf_alloc_size(buffer, *needed)) {
7256 result = WERR_NOMEM;
7260 /* fill the buffer with the ports structures */
7261 for (i=0; i<*returned; i++) {
7262 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7263 smb_io_port_1("", buffer, &ports[i], 0);
7269 if ( !W_ERROR_IS_OK(result) )
7275 /****************************************************************************
7277 ****************************************************************************/
7279 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7281 PORT_INFO_2 *ports=NULL;
7283 WERROR result = WERR_OK;
7287 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7292 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7293 file_lines_free(qlines);
7297 for (i=0; i<numlines; i++) {
7298 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7299 fill_port_2(&(ports[i]), qlines[i]);
7302 file_lines_free(qlines);
7305 *returned = numlines;
7307 /* check the required size. */
7308 for (i=0; i<*returned; i++) {
7309 DEBUGADD(6,("adding port [%d]'s size\n", i));
7310 *needed += spoolss_size_port_info_2(&ports[i]);
7313 if (*needed > offered) {
7314 result = WERR_INSUFFICIENT_BUFFER;
7318 if (!rpcbuf_alloc_size(buffer, *needed)) {
7319 result = WERR_NOMEM;
7323 /* fill the buffer with the ports structures */
7324 for (i=0; i<*returned; i++) {
7325 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7326 smb_io_port_2("", buffer, &ports[i], 0);
7332 if ( !W_ERROR_IS_OK(result) )
7338 /****************************************************************************
7340 ****************************************************************************/
7342 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7344 uint32 level = q_u->level;
7345 RPC_BUFFER *buffer = NULL;
7346 uint32 offered = q_u->offered;
7347 uint32 *needed = &r_u->needed;
7348 uint32 *returned = &r_u->returned;
7350 /* that's an [in out] buffer */
7352 if ( q_u->buffer ) {
7353 rpcbuf_move(q_u->buffer, &r_u->buffer);
7354 buffer = r_u->buffer;
7357 DEBUG(4,("_spoolss_enumports\n"));
7364 return enumports_level_1(buffer, offered, needed, returned);
7366 return enumports_level_2(buffer, offered, needed, returned);
7368 return WERR_UNKNOWN_LEVEL;
7372 /****************************************************************************
7373 ****************************************************************************/
7375 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7376 const SPOOL_PRINTER_INFO_LEVEL *info,
7377 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7378 uint32 user_switch, const SPOOL_USER_CTR *user,
7381 NT_PRINTER_INFO_LEVEL *printer = NULL;
7384 WERROR err = WERR_OK;
7386 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7387 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7391 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7392 if (!convert_printer_info(info, printer, 2)) {
7393 free_a_printer(&printer, 2);
7397 /* check to see if the printer already exists */
7399 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7400 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7401 printer->info_2->sharename));
7402 free_a_printer(&printer, 2);
7403 return WERR_PRINTER_ALREADY_EXISTS;
7406 /* FIXME!!! smbd should check to see if the driver is installed before
7407 trying to add a printer like this --jerry */
7409 if (*lp_addprinter_cmd() ) {
7410 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7411 free_a_printer(&printer,2);
7412 return WERR_ACCESS_DENIED;
7415 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7416 "smb.conf parameter \"addprinter command\" is defined. This"
7417 "parameter must exist for this call to succeed\n",
7418 printer->info_2->sharename ));
7421 /* use our primary netbios name since get_a_printer() will convert
7422 it to what the client expects on a case by case basis */
7424 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7425 printer->info_2->sharename);
7428 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7429 free_a_printer(&printer,2);
7430 return WERR_ACCESS_DENIED;
7433 /* you must be a printer admin to add a new printer */
7434 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7435 free_a_printer(&printer,2);
7436 return WERR_ACCESS_DENIED;
7440 * Do sanity check on the requested changes for Samba.
7443 if (!check_printer_ok(printer->info_2, snum)) {
7444 free_a_printer(&printer,2);
7445 return WERR_INVALID_PARAM;
7449 * When a printer is created, the drivername bound to the printer is used
7450 * to lookup previously saved driver initialization info, which is then
7451 * bound to the new printer, simulating what happens in the Windows arch.
7456 set_driver_init(printer, 2);
7460 /* A valid devmode was included, convert and link it
7462 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7464 if (!convert_devicemode(printer->info_2->printername, devmode,
7465 &printer->info_2->devmode))
7469 /* write the ASCII on disk */
7470 err = mod_a_printer(printer, 2);
7471 if (!W_ERROR_IS_OK(err)) {
7472 free_a_printer(&printer,2);
7476 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7477 /* Handle open failed - remove addition. */
7478 del_a_printer(printer->info_2->sharename);
7479 free_a_printer(&printer,2);
7480 return WERR_ACCESS_DENIED;
7483 update_c_setprinter(False);
7484 free_a_printer(&printer,2);
7489 /****************************************************************************
7490 ****************************************************************************/
7492 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7494 UNISTR2 *uni_srv_name = q_u->server_name;
7495 uint32 level = q_u->level;
7496 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7497 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7498 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7499 uint32 user_switch = q_u->user_switch;
7500 SPOOL_USER_CTR *user = &q_u->user_ctr;
7501 POLICY_HND *handle = &r_u->handle;
7505 /* we don't handle yet */
7506 /* but I know what to do ... */
7507 return WERR_UNKNOWN_LEVEL;
7509 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7511 user_switch, user, handle);
7513 return WERR_UNKNOWN_LEVEL;
7517 /****************************************************************************
7518 ****************************************************************************/
7520 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7522 uint32 level = q_u->level;
7523 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7524 WERROR err = WERR_OK;
7525 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7526 struct current_user user;
7527 fstring driver_name;
7530 ZERO_STRUCT(driver);
7532 get_current_user(&user, p);
7534 if (!convert_printer_driver_info(info, &driver, level)) {
7539 DEBUG(5,("Cleaning driver's information\n"));
7540 err = clean_up_driver_struct(driver, level, &user);
7541 if (!W_ERROR_IS_OK(err))
7544 DEBUG(5,("Moving driver to final destination\n"));
7545 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7549 if (add_a_printer_driver(driver, level)!=0) {
7550 err = WERR_ACCESS_DENIED;
7554 /* BEGIN_ADMIN_LOG */
7557 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7558 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7559 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.ut.uid));
7562 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7563 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7564 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.ut.uid));
7570 * I think this is where he DrvUpgradePrinter() hook would be
7571 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7572 * server. Right now, we just need to send ourselves a message
7573 * to update each printer bound to this driver. --jerry
7576 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7577 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7582 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7583 * decide if the driver init data should be deleted. The rules are:
7584 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7585 * 2) delete init data only if there is no 2k/Xp driver
7586 * 3) always delete init data
7587 * The generalized rule is always use init data from the highest order driver.
7588 * It is necessary to follow the driver install by an initialization step to
7589 * finish off this process.
7592 version = driver.info_3->cversion;
7593 else if (level == 6)
7594 version = driver.info_6->version;
7599 * 9x printer driver - never delete init data
7602 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7607 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7608 * there is no 2k/Xp driver init data for this driver name.
7612 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7614 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7616 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7618 if (!del_driver_init(driver_name))
7619 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7622 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7624 free_a_printer_driver(driver1,3);
7625 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7632 * 2k or Xp printer driver - always delete init data
7635 if (!del_driver_init(driver_name))
7636 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7640 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7646 free_a_printer_driver(driver, level);
7650 /********************************************************************
7651 * spoolss_addprinterdriverex
7652 ********************************************************************/
7654 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7656 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7657 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7660 * we only support the semantics of AddPrinterDriver()
7661 * i.e. only copy files that are newer than existing ones
7664 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7665 return WERR_ACCESS_DENIED;
7667 ZERO_STRUCT(q_u_local);
7668 ZERO_STRUCT(r_u_local);
7670 /* just pass the information off to _spoolss_addprinterdriver() */
7671 q_u_local.server_name_ptr = q_u->server_name_ptr;
7672 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7673 q_u_local.level = q_u->level;
7674 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7676 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7679 /****************************************************************************
7680 ****************************************************************************/
7682 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7684 init_unistr(&info->name, name);
7687 /****************************************************************************
7688 ****************************************************************************/
7690 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7696 const char *short_archi;
7697 DRIVER_DIRECTORY_1 *info=NULL;
7698 WERROR result = WERR_OK;
7700 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7701 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7703 /* check for beginning double '\'s and that the server
7706 pservername = servername;
7707 if ( *pservername == '\\' && strlen(servername)>2 ) {
7711 if ( !is_myname_or_ipaddr( pservername ) )
7712 return WERR_INVALID_PARAM;
7714 if (!(short_archi = get_short_archi(long_archi)))
7715 return WERR_INVALID_ENVIRONMENT;
7717 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7720 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7722 DEBUG(4,("printer driver directory: [%s]\n", path));
7724 fill_driverdir_1(info, path);
7726 *needed += spoolss_size_driverdir_info_1(info);
7728 if (*needed > offered) {
7729 result = WERR_INSUFFICIENT_BUFFER;
7733 if (!rpcbuf_alloc_size(buffer, *needed)) {
7734 result = WERR_NOMEM;
7738 smb_io_driverdir_1("", buffer, info, 0);
7746 /****************************************************************************
7747 ****************************************************************************/
7749 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7751 UNISTR2 *name = &q_u->name;
7752 UNISTR2 *uni_environment = &q_u->environment;
7753 uint32 level = q_u->level;
7754 RPC_BUFFER *buffer = NULL;
7755 uint32 offered = q_u->offered;
7756 uint32 *needed = &r_u->needed;
7758 /* that's an [in out] buffer */
7760 if ( q_u->buffer ) {
7761 rpcbuf_move(q_u->buffer, &r_u->buffer);
7762 buffer = r_u->buffer;
7765 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7771 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7773 return WERR_UNKNOWN_LEVEL;
7777 /****************************************************************************
7778 ****************************************************************************/
7780 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7782 POLICY_HND *handle = &q_u->handle;
7783 uint32 idx = q_u->index;
7784 uint32 in_value_len = q_u->valuesize;
7785 uint32 in_data_len = q_u->datasize;
7786 uint32 *out_max_value_len = &r_u->valuesize;
7787 uint16 **out_value = &r_u->value;
7788 uint32 *out_value_len = &r_u->realvaluesize;
7789 uint32 *out_type = &r_u->type;
7790 uint32 *out_max_data_len = &r_u->datasize;
7791 uint8 **data_out = &r_u->data;
7792 uint32 *out_data_len = &r_u->realdatasize;
7794 NT_PRINTER_INFO_LEVEL *printer = NULL;
7796 uint32 biggest_valuesize;
7797 uint32 biggest_datasize;
7799 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7802 REGISTRY_VALUE *val = NULL;
7803 NT_PRINTER_DATA *p_data;
7804 int i, key_index, num_values;
7809 *out_max_data_len = 0;
7813 DEBUG(5,("spoolss_enumprinterdata\n"));
7816 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7820 if (!get_printer_snum(p,handle, &snum))
7823 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7824 if (!W_ERROR_IS_OK(result))
7827 p_data = printer->info_2->data;
7828 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7833 * The NT machine wants to know the biggest size of value and data
7835 * cf: MSDN EnumPrinterData remark section
7838 if ( !in_value_len && !in_data_len && (key_index != -1) )
7840 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7842 biggest_valuesize = 0;
7843 biggest_datasize = 0;
7845 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7847 for ( i=0; i<num_values; i++ )
7849 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7851 name_length = strlen(val->valuename);
7852 if ( strlen(val->valuename) > biggest_valuesize )
7853 biggest_valuesize = name_length;
7855 if ( val->size > biggest_datasize )
7856 biggest_datasize = val->size;
7858 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7862 /* the value is an UNICODE string but real_value_size is the length
7863 in bytes including the trailing 0 */
7865 *out_value_len = 2 * (1+biggest_valuesize);
7866 *out_data_len = biggest_datasize;
7868 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7874 * the value len is wrong in NT sp3
7875 * that's the number of bytes not the number of unicode chars
7878 if ( key_index != -1 )
7879 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7884 /* out_value should default to "" or else NT4 has
7885 problems unmarshalling the response */
7887 *out_max_value_len=(in_value_len/sizeof(uint16));
7889 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7891 result = WERR_NOMEM;
7895 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7897 /* the data is counted in bytes */
7899 *out_max_data_len = in_data_len;
7900 *out_data_len = in_data_len;
7902 /* only allocate when given a non-zero data_len */
7904 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7906 result = WERR_NOMEM;
7910 result = WERR_NO_MORE_ITEMS;
7916 * - counted in bytes in the request
7917 * - counted in UNICODE chars in the max reply
7918 * - counted in bytes in the real size
7920 * take a pause *before* coding not *during* coding
7924 *out_max_value_len=(in_value_len/sizeof(uint16));
7925 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7927 result = WERR_NOMEM;
7931 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7935 *out_type = regval_type( val );
7937 /* data - counted in bytes */
7939 *out_max_data_len = in_data_len;
7940 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7942 result = WERR_NOMEM;
7945 data_len = regval_size(val);
7947 memcpy( *data_out, regval_data_p(val), data_len );
7948 *out_data_len = data_len;
7952 free_a_printer(&printer, 2);
7956 /****************************************************************************
7957 ****************************************************************************/
7959 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7961 POLICY_HND *handle = &q_u->handle;
7962 UNISTR2 *value = &q_u->value;
7963 uint32 type = q_u->type;
7964 uint8 *data = q_u->data;
7965 uint32 real_len = q_u->real_len;
7967 NT_PRINTER_INFO_LEVEL *printer = NULL;
7969 WERROR status = WERR_OK;
7970 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7973 DEBUG(5,("spoolss_setprinterdata\n"));
7976 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7980 if ( Printer->printer_type == SPLHND_SERVER ) {
7981 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7982 return WERR_INVALID_PARAM;
7985 if (!get_printer_snum(p,handle, &snum))
7989 * Access check : NT returns "access denied" if you make a
7990 * SetPrinterData call without the necessary privildge.
7991 * we were originally returning OK if nothing changed
7992 * which made Win2k issue **a lot** of SetPrinterData
7993 * when connecting to a printer --jerry
7996 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7998 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7999 status = WERR_ACCESS_DENIED;
8003 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8004 if (!W_ERROR_IS_OK(status))
8007 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8010 * When client side code sets a magic printer data key, detect it and save
8011 * the current printer data and the magic key's data (its the DEVMODE) for
8012 * future printer/driver initializations.
8014 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8016 /* Set devmode and printer initialization info */
8017 status = save_driver_init( printer, 2, data, real_len );
8019 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8023 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8024 type, data, real_len );
8025 if ( W_ERROR_IS_OK(status) )
8026 status = mod_a_printer(printer, 2);
8030 free_a_printer(&printer, 2);
8035 /****************************************************************************
8036 ****************************************************************************/
8038 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8040 POLICY_HND *handle = &q_u->handle;
8041 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8044 DEBUG(5,("_spoolss_resetprinter\n"));
8047 * All we do is to check to see if the handle and queue is valid.
8048 * This call really doesn't mean anything to us because we only
8049 * support RAW printing. --jerry
8053 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8057 if (!get_printer_snum(p,handle, &snum))
8061 /* blindly return success */
8066 /****************************************************************************
8067 ****************************************************************************/
8069 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8071 POLICY_HND *handle = &q_u->handle;
8072 UNISTR2 *value = &q_u->valuename;
8074 NT_PRINTER_INFO_LEVEL *printer = NULL;
8076 WERROR status = WERR_OK;
8077 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8080 DEBUG(5,("spoolss_deleteprinterdata\n"));
8083 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8087 if (!get_printer_snum(p, handle, &snum))
8090 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8091 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8092 return WERR_ACCESS_DENIED;
8095 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8096 if (!W_ERROR_IS_OK(status))
8099 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8101 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8103 if ( W_ERROR_IS_OK(status) )
8104 mod_a_printer( printer, 2 );
8106 free_a_printer(&printer, 2);
8111 /****************************************************************************
8112 ****************************************************************************/
8114 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8116 POLICY_HND *handle = &q_u->handle;
8117 FORM *form = &q_u->form;
8118 nt_forms_struct tmpForm;
8120 WERROR status = WERR_OK;
8121 NT_PRINTER_INFO_LEVEL *printer = NULL;
8124 nt_forms_struct *list=NULL;
8125 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8127 DEBUG(5,("spoolss_addform\n"));
8130 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8135 /* forms can be added on printer of on the print server handle */
8137 if ( Printer->printer_type == SPLHND_PRINTER )
8139 if (!get_printer_snum(p,handle, &snum))
8142 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8143 if (!W_ERROR_IS_OK(status))
8147 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8148 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8149 status = WERR_ACCESS_DENIED;
8153 /* can't add if builtin */
8155 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8156 status = WERR_ALREADY_EXISTS;
8160 count = get_ntforms(&list);
8162 if(!add_a_form(&list, form, &count)) {
8163 status = WERR_NOMEM;
8167 write_ntforms(&list, count);
8170 * ChangeID must always be set if this is a printer
8173 if ( Printer->printer_type == SPLHND_PRINTER )
8174 status = mod_a_printer(printer, 2);
8178 free_a_printer(&printer, 2);
8184 /****************************************************************************
8185 ****************************************************************************/
8187 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8189 POLICY_HND *handle = &q_u->handle;
8190 UNISTR2 *form_name = &q_u->name;
8191 nt_forms_struct tmpForm;
8193 nt_forms_struct *list=NULL;
8194 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8196 WERROR status = WERR_OK;
8197 NT_PRINTER_INFO_LEVEL *printer = NULL;
8199 DEBUG(5,("spoolss_deleteform\n"));
8202 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8206 /* forms can be deleted on printer of on the print server handle */
8208 if ( Printer->printer_type == SPLHND_PRINTER )
8210 if (!get_printer_snum(p,handle, &snum))
8213 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8214 if (!W_ERROR_IS_OK(status))
8218 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8219 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8220 status = WERR_ACCESS_DENIED;
8224 /* can't delete if builtin */
8226 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8227 status = WERR_INVALID_PARAM;
8231 count = get_ntforms(&list);
8233 if ( !delete_a_form(&list, form_name, &count, &status ))
8237 * ChangeID must always be set if this is a printer
8240 if ( Printer->printer_type == SPLHND_PRINTER )
8241 status = mod_a_printer(printer, 2);
8245 free_a_printer(&printer, 2);
8251 /****************************************************************************
8252 ****************************************************************************/
8254 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8256 POLICY_HND *handle = &q_u->handle;
8257 FORM *form = &q_u->form;
8258 nt_forms_struct tmpForm;
8260 WERROR status = WERR_OK;
8261 NT_PRINTER_INFO_LEVEL *printer = NULL;
8264 nt_forms_struct *list=NULL;
8265 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8267 DEBUG(5,("spoolss_setform\n"));
8270 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8274 /* forms can be modified on printer of on the print server handle */
8276 if ( Printer->printer_type == SPLHND_PRINTER )
8278 if (!get_printer_snum(p,handle, &snum))
8281 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8282 if (!W_ERROR_IS_OK(status))
8286 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8287 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8288 status = WERR_ACCESS_DENIED;
8292 /* can't set if builtin */
8293 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8294 status = WERR_INVALID_PARAM;
8298 count = get_ntforms(&list);
8299 update_a_form(&list, form, count);
8300 write_ntforms(&list, count);
8303 * ChangeID must always be set if this is a printer
8306 if ( Printer->printer_type == SPLHND_PRINTER )
8307 status = mod_a_printer(printer, 2);
8312 free_a_printer(&printer, 2);
8318 /****************************************************************************
8319 enumprintprocessors level 1.
8320 ****************************************************************************/
8322 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8324 PRINTPROCESSOR_1 *info_1=NULL;
8325 WERROR result = WERR_OK;
8327 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8332 init_unistr(&info_1->name, "winprint");
8334 *needed += spoolss_size_printprocessor_info_1(info_1);
8336 if (*needed > offered) {
8337 result = WERR_INSUFFICIENT_BUFFER;
8341 if (!rpcbuf_alloc_size(buffer, *needed)) {
8342 result = WERR_NOMEM;
8346 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8351 if ( !W_ERROR_IS_OK(result) )
8357 /****************************************************************************
8358 ****************************************************************************/
8360 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8362 uint32 level = q_u->level;
8363 RPC_BUFFER *buffer = NULL;
8364 uint32 offered = q_u->offered;
8365 uint32 *needed = &r_u->needed;
8366 uint32 *returned = &r_u->returned;
8368 /* that's an [in out] buffer */
8370 if ( q_u->buffer ) {
8371 rpcbuf_move(q_u->buffer, &r_u->buffer);
8372 buffer = r_u->buffer;
8375 DEBUG(5,("spoolss_enumprintprocessors\n"));
8378 * Enumerate the print processors ...
8380 * Just reply with "winprint", to keep NT happy
8381 * and I can use my nice printer checker.
8389 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8391 return WERR_UNKNOWN_LEVEL;
8395 /****************************************************************************
8396 enumprintprocdatatypes level 1.
8397 ****************************************************************************/
8399 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8401 PRINTPROCDATATYPE_1 *info_1=NULL;
8402 WERROR result = WERR_NOMEM;
8404 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8409 init_unistr(&info_1->name, "RAW");
8411 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8413 if (*needed > offered) {
8414 result = WERR_INSUFFICIENT_BUFFER;
8418 if (!rpcbuf_alloc_size(buffer, *needed)) {
8419 result = WERR_NOMEM;
8423 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8428 if ( !W_ERROR_IS_OK(result) )
8434 /****************************************************************************
8435 ****************************************************************************/
8437 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8439 uint32 level = q_u->level;
8440 RPC_BUFFER *buffer = NULL;
8441 uint32 offered = q_u->offered;
8442 uint32 *needed = &r_u->needed;
8443 uint32 *returned = &r_u->returned;
8445 /* that's an [in out] buffer */
8447 if ( q_u->buffer ) {
8448 rpcbuf_move(q_u->buffer, &r_u->buffer);
8449 buffer = r_u->buffer;
8452 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8459 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8461 return WERR_UNKNOWN_LEVEL;
8465 /****************************************************************************
8466 enumprintmonitors level 1.
8467 ****************************************************************************/
8469 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8471 PRINTMONITOR_1 *info_1;
8472 WERROR result = WERR_OK;
8475 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8480 init_unistr(&(info_1[0].name), "Local Port");
8481 init_unistr(&(info_1[1].name), "Standard TCP/IP Port");
8483 for ( i=0; i<*returned; i++ ) {
8484 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8487 if (*needed > offered) {
8488 result = WERR_INSUFFICIENT_BUFFER;
8492 if (!rpcbuf_alloc_size(buffer, *needed)) {
8493 result = WERR_NOMEM;
8497 for ( i=0; i<*returned; i++ ) {
8498 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8504 if ( !W_ERROR_IS_OK(result) )
8510 /****************************************************************************
8511 enumprintmonitors level 2.
8512 ****************************************************************************/
8514 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8516 PRINTMONITOR_2 *info_2;
8517 WERROR result = WERR_OK;
8520 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8525 init_unistr(&(info_2[0].name), "Local Port");
8526 init_unistr(&(info_2[0].environment), "Windows NT X86");
8527 init_unistr(&(info_2[0].dll_name), "localmon.dll");
8529 init_unistr(&(info_2[1].name), "Standard TCP/IP Port");
8530 init_unistr(&(info_2[1].environment), "Windows NT X86");
8531 init_unistr(&(info_2[1].dll_name), "tcpmon.dll");
8533 for ( i=0; i<*returned; i++ ) {
8534 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8537 if (*needed > offered) {
8538 result = WERR_INSUFFICIENT_BUFFER;
8542 if (!rpcbuf_alloc_size(buffer, *needed)) {
8543 result = WERR_NOMEM;
8547 for ( i=0; i<*returned; i++ ) {
8548 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8554 if ( !W_ERROR_IS_OK(result) )
8560 /****************************************************************************
8561 ****************************************************************************/
8563 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8565 uint32 level = q_u->level;
8566 RPC_BUFFER *buffer = NULL;
8567 uint32 offered = q_u->offered;
8568 uint32 *needed = &r_u->needed;
8569 uint32 *returned = &r_u->returned;
8571 /* that's an [in out] buffer */
8573 if ( q_u->buffer ) {
8574 rpcbuf_move(q_u->buffer, &r_u->buffer);
8575 buffer = r_u->buffer;
8578 DEBUG(5,("spoolss_enumprintmonitors\n"));
8581 * Enumerate the print monitors ...
8583 * Just reply with "Local Port", to keep NT happy
8584 * and I can use my nice printer checker.
8592 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8594 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8596 return WERR_UNKNOWN_LEVEL;
8600 /****************************************************************************
8601 ****************************************************************************/
8603 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8604 NT_PRINTER_INFO_LEVEL *ntprinter,
8605 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8610 JOB_INFO_1 *info_1=NULL;
8611 WERROR result = WERR_OK;
8613 info_1=SMB_MALLOC_P(JOB_INFO_1);
8615 if (info_1 == NULL) {
8619 for (i=0; i<count && found==False; i++) {
8620 if ((*queue)[i].job==(int)jobid)
8626 /* NT treats not found as bad param... yet another bad choice */
8627 return WERR_INVALID_PARAM;
8630 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8632 *needed += spoolss_size_job_info_1(info_1);
8634 if (*needed > offered) {
8635 result = WERR_INSUFFICIENT_BUFFER;
8639 if (!rpcbuf_alloc_size(buffer, *needed)) {
8640 result = WERR_NOMEM;
8644 smb_io_job_info_1("", buffer, info_1, 0);
8652 /****************************************************************************
8653 ****************************************************************************/
8655 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8656 NT_PRINTER_INFO_LEVEL *ntprinter,
8657 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8664 DEVICEMODE *devmode = NULL;
8665 NT_DEVICEMODE *nt_devmode = NULL;
8667 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8670 ZERO_STRUCTP(info_2);
8672 for ( i=0; i<count && found==False; i++ )
8674 if ((*queue)[i].job == (int)jobid)
8679 /* NT treats not found as bad param... yet another bad
8681 result = WERR_INVALID_PARAM;
8686 * if the print job does not have a DEVMODE associated with it,
8687 * just use the one for the printer. A NULL devicemode is not
8688 * a failure condition
8691 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8692 devmode = construct_dev_mode(snum);
8694 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8695 ZERO_STRUCTP( devmode );
8696 convert_nt_devicemode( devmode, nt_devmode );
8700 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8702 *needed += spoolss_size_job_info_2(info_2);
8704 if (*needed > offered) {
8705 result = WERR_INSUFFICIENT_BUFFER;
8709 if (!rpcbuf_alloc_size(buffer, *needed)) {
8710 result = WERR_NOMEM;
8714 smb_io_job_info_2("", buffer, info_2, 0);
8719 /* Cleanup allocated memory */
8721 free_job_info_2(info_2); /* Also frees devmode */
8727 /****************************************************************************
8728 ****************************************************************************/
8730 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8732 POLICY_HND *handle = &q_u->handle;
8733 uint32 jobid = q_u->jobid;
8734 uint32 level = q_u->level;
8735 RPC_BUFFER *buffer = NULL;
8736 uint32 offered = q_u->offered;
8737 uint32 *needed = &r_u->needed;
8738 WERROR wstatus = WERR_OK;
8739 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8742 print_queue_struct *queue = NULL;
8743 print_status_struct prt_status;
8745 /* that's an [in out] buffer */
8747 if ( q_u->buffer ) {
8748 rpcbuf_move(q_u->buffer, &r_u->buffer);
8749 buffer = r_u->buffer;
8752 DEBUG(5,("spoolss_getjob\n"));
8756 if (!get_printer_snum(p, handle, &snum))
8759 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8760 if ( !W_ERROR_IS_OK(wstatus) )
8763 count = print_queue_status(snum, &queue, &prt_status);
8765 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8766 count, prt_status.status, prt_status.message));
8770 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8771 buffer, offered, needed);
8774 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8775 buffer, offered, needed);
8778 wstatus = WERR_UNKNOWN_LEVEL;
8783 free_a_printer( &ntprinter, 2 );
8788 /********************************************************************
8789 spoolss_getprinterdataex
8791 From MSDN documentation of GetPrinterDataEx: pass request
8792 to GetPrinterData if key is "PrinterDriverData".
8793 ********************************************************************/
8795 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8797 POLICY_HND *handle = &q_u->handle;
8798 uint32 in_size = q_u->size;
8799 uint32 *type = &r_u->type;
8800 uint32 *out_size = &r_u->size;
8801 uint8 **data = &r_u->data;
8802 uint32 *needed = &r_u->needed;
8803 fstring keyname, valuename;
8805 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8807 NT_PRINTER_INFO_LEVEL *printer = NULL;
8809 WERROR status = WERR_OK;
8811 DEBUG(4,("_spoolss_getprinterdataex\n"));
8813 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8814 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8816 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8817 keyname, valuename));
8819 /* in case of problem, return some default values */
8823 *out_size = in_size;
8826 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8827 status = WERR_BADFID;
8831 /* Is the handle to a printer or to the server? */
8833 if (Printer->printer_type == SPLHND_SERVER) {
8834 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8835 status = WERR_INVALID_PARAM;
8839 if ( !get_printer_snum(p,handle, &snum) )
8842 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8843 if ( !W_ERROR_IS_OK(status) )
8846 /* check to see if the keyname is valid */
8847 if ( !strlen(keyname) ) {
8848 status = WERR_INVALID_PARAM;
8852 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8853 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8854 free_a_printer( &printer, 2 );
8855 status = WERR_BADFILE;
8859 /* When given a new keyname, we should just create it */
8861 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8863 if (*needed > *out_size)
8864 status = WERR_MORE_DATA;
8867 if ( !W_ERROR_IS_OK(status) )
8869 DEBUG(5, ("error: allocating %d\n", *out_size));
8871 /* reply this param doesn't exist */
8875 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8876 status = WERR_NOMEM;
8886 free_a_printer( &printer, 2 );
8891 /********************************************************************
8892 * spoolss_setprinterdataex
8893 ********************************************************************/
8895 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8897 POLICY_HND *handle = &q_u->handle;
8898 uint32 type = q_u->type;
8899 uint8 *data = q_u->data;
8900 uint32 real_len = q_u->real_len;
8902 NT_PRINTER_INFO_LEVEL *printer = NULL;
8904 WERROR status = WERR_OK;
8905 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8910 DEBUG(4,("_spoolss_setprinterdataex\n"));
8912 /* From MSDN documentation of SetPrinterDataEx: pass request to
8913 SetPrinterData if key is "PrinterDriverData" */
8916 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8920 if ( Printer->printer_type == SPLHND_SERVER ) {
8921 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8922 return WERR_INVALID_PARAM;
8925 if ( !get_printer_snum(p,handle, &snum) )
8929 * Access check : NT returns "access denied" if you make a
8930 * SetPrinterData call without the necessary privildge.
8931 * we were originally returning OK if nothing changed
8932 * which made Win2k issue **a lot** of SetPrinterData
8933 * when connecting to a printer --jerry
8936 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8938 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8939 return WERR_ACCESS_DENIED;
8942 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8943 if (!W_ERROR_IS_OK(status))
8946 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8947 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8949 /* check for OID in valuename */
8951 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8957 /* save the registry data */
8959 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8961 if ( W_ERROR_IS_OK(status) )
8963 /* save the OID if one was specified */
8965 fstrcat( keyname, "\\" );
8966 fstrcat( keyname, SPOOL_OID_KEY );
8969 * I'm not checking the status here on purpose. Don't know
8970 * if this is right, but I'm returning the status from the
8971 * previous set_printer_dataex() call. I have no idea if
8972 * this is right. --jerry
8975 set_printer_dataex( printer, keyname, valuename,
8976 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8979 status = mod_a_printer(printer, 2);
8982 free_a_printer(&printer, 2);
8988 /********************************************************************
8989 * spoolss_deleteprinterdataex
8990 ********************************************************************/
8992 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8994 POLICY_HND *handle = &q_u->handle;
8995 UNISTR2 *value = &q_u->valuename;
8996 UNISTR2 *key = &q_u->keyname;
8998 NT_PRINTER_INFO_LEVEL *printer = NULL;
9000 WERROR status = WERR_OK;
9001 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9002 pstring valuename, keyname;
9004 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9007 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9011 if (!get_printer_snum(p, handle, &snum))
9014 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9015 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9016 return WERR_ACCESS_DENIED;
9019 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9020 if (!W_ERROR_IS_OK(status))
9023 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9024 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9026 status = delete_printer_dataex( printer, keyname, valuename );
9028 if ( W_ERROR_IS_OK(status) )
9029 mod_a_printer( printer, 2 );
9031 free_a_printer(&printer, 2);
9036 /********************************************************************
9037 * spoolss_enumprinterkey
9038 ********************************************************************/
9041 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9044 fstring *keynames = NULL;
9045 uint16 *enumkeys = NULL;
9048 POLICY_HND *handle = &q_u->handle;
9049 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9050 NT_PRINTER_DATA *data;
9051 NT_PRINTER_INFO_LEVEL *printer = NULL;
9053 WERROR status = WERR_BADFILE;
9056 DEBUG(4,("_spoolss_enumprinterkey\n"));
9059 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9063 if ( !get_printer_snum(p,handle, &snum) )
9066 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9067 if (!W_ERROR_IS_OK(status))
9070 /* get the list of subkey names */
9072 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9073 data = printer->info_2->data;
9075 num_keys = get_printer_subkeys( data, key, &keynames );
9077 if ( num_keys == -1 ) {
9078 status = WERR_BADFILE;
9082 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9084 r_u->needed = printerkey_len*2;
9086 if ( q_u->size < r_u->needed ) {
9087 status = WERR_MORE_DATA;
9091 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9092 status = WERR_NOMEM;
9098 if ( q_u->size < r_u->needed )
9099 status = WERR_MORE_DATA;
9102 free_a_printer( &printer, 2 );
9103 SAFE_FREE( keynames );
9108 /********************************************************************
9109 * spoolss_deleteprinterkey
9110 ********************************************************************/
9112 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9114 POLICY_HND *handle = &q_u->handle;
9115 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9117 NT_PRINTER_INFO_LEVEL *printer = NULL;
9121 DEBUG(5,("spoolss_deleteprinterkey\n"));
9124 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9128 /* if keyname == NULL, return error */
9130 if ( !q_u->keyname.buffer )
9131 return WERR_INVALID_PARAM;
9133 if (!get_printer_snum(p, handle, &snum))
9136 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9137 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9138 return WERR_ACCESS_DENIED;
9141 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9142 if (!W_ERROR_IS_OK(status))
9145 /* delete the key and all subneys */
9147 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9149 status = delete_all_printer_data( printer->info_2, key );
9151 if ( W_ERROR_IS_OK(status) )
9152 status = mod_a_printer(printer, 2);
9154 free_a_printer( &printer, 2 );
9160 /********************************************************************
9161 * spoolss_enumprinterdataex
9162 ********************************************************************/
9164 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9166 POLICY_HND *handle = &q_u->handle;
9167 uint32 in_size = q_u->size;
9170 NT_PRINTER_INFO_LEVEL *printer = NULL;
9171 PRINTER_ENUM_VALUES *enum_values = NULL;
9172 NT_PRINTER_DATA *p_data;
9174 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9179 REGISTRY_VALUE *val;
9184 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9187 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9192 * first check for a keyname of NULL or "". Win2k seems to send
9193 * this a lot and we should send back WERR_INVALID_PARAM
9194 * no need to spend time looking up the printer in this case.
9198 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9199 if ( !strlen(key) ) {
9200 result = WERR_INVALID_PARAM;
9204 /* get the printer off of disk */
9206 if (!get_printer_snum(p,handle, &snum))
9209 ZERO_STRUCT(printer);
9210 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9211 if (!W_ERROR_IS_OK(result))
9214 /* now look for a match on the key name */
9216 p_data = printer->info_2->data;
9218 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9219 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9221 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9222 result = WERR_INVALID_PARAM;
9229 /* allocate the memory for the array of pointers -- if necessary */
9231 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9234 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9236 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9237 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9238 result = WERR_NOMEM;
9242 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9246 * loop through all params and build the array to pass
9247 * back to the client
9250 for ( i=0; i<num_entries; i++ )
9252 /* lookup the registry value */
9254 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9255 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9259 value_name = regval_name( val );
9260 init_unistr( &enum_values[i].valuename, value_name );
9261 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9262 enum_values[i].type = regval_type( val );
9264 data_len = regval_size( val );
9266 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9268 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9270 result = WERR_NOMEM;
9274 enum_values[i].data_len = data_len;
9276 /* keep track of the size of the array in bytes */
9278 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9281 /* housekeeping information in the reply */
9283 r_u->needed = needed;
9284 r_u->returned = num_entries;
9286 if (needed > in_size) {
9287 result = WERR_MORE_DATA;
9291 /* copy data into the reply */
9293 r_u->ctr.size = r_u->needed;
9294 r_u->ctr.size_of_array = r_u->returned;
9295 r_u->ctr.values = enum_values;
9301 free_a_printer(&printer, 2);
9306 /****************************************************************************
9307 ****************************************************************************/
9309 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9311 init_unistr(&info->name, name);
9314 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9315 UNISTR2 *environment,
9322 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9323 WERROR result = WERR_OK;
9325 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9327 if (!get_short_archi(long_archi))
9328 return WERR_INVALID_ENVIRONMENT;
9330 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9333 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9335 fill_printprocessordirectory_1(info, path);
9337 *needed += spoolss_size_printprocessordirectory_info_1(info);
9339 if (*needed > offered) {
9340 result = WERR_INSUFFICIENT_BUFFER;
9344 if (!rpcbuf_alloc_size(buffer, *needed)) {
9345 result = WERR_INSUFFICIENT_BUFFER;
9349 smb_io_printprocessordirectory_1("", buffer, info, 0);
9357 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9359 uint32 level = q_u->level;
9360 RPC_BUFFER *buffer = NULL;
9361 uint32 offered = q_u->offered;
9362 uint32 *needed = &r_u->needed;
9365 /* that's an [in out] buffer */
9367 if ( q_u->buffer ) {
9368 rpcbuf_move(q_u->buffer, &r_u->buffer);
9369 buffer = r_u->buffer;
9372 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9378 result = getprintprocessordirectory_level_1
9379 (&q_u->name, &q_u->environment, buffer, offered, needed);
9382 result = WERR_UNKNOWN_LEVEL;
9388 /*******************************************************************
9389 *******************************************************************/
9391 static WERROR process_xcvtcp_command( const char *command, RPC_BUFFER *inbuf, RPC_BUFFER *outbuf )
9393 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9398 /*******************************************************************
9399 *******************************************************************/
9401 static WERROR process_xcvlocal_command( const char *command, RPC_BUFFER *inbuf, RPC_BUFFER *outbuf )
9403 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9408 /*******************************************************************
9409 *******************************************************************/
9411 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9413 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9417 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9421 /* Has to be a handle to the TCP/IP port monitor */
9423 if ( Printer->printer_type != SPLHND_PORTMON_TCP ) {
9424 DEBUG(2,("_spoolss_xcvdataport: Call only valid for the TCP/IP Port Monitor\n"));
9428 /* requires administrative access to the server */
9430 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9431 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9432 return WERR_ACCESS_DENIED;
9435 /* Get the command name. There's numerous commands supported by the
9436 TCPMON interface. */
9438 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command), q_u->dataname.uni_str_len*2, 0);
9440 switch ( Printer->printer_type ) {
9441 case SPLHND_PORTMON_TCP:
9442 return process_xcvtcp_command( command, &q_u->indata, &r_u->outdata );
9443 case SPLHND_PORTMON_LOCAL:
9444 return process_xcvlocal_command( command, &q_u->indata, &r_u->outdata );
9447 return WERR_INVALID_PRINT_MONITOR;