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. */
32 #define DBGC_CLASS DBGC_RPC_SRV
34 #ifndef MAX_OPEN_PRINTER_EXS
35 #define MAX_OPEN_PRINTER_EXS 50
38 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
39 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42 /* Table to map the driver version */
44 static const char * drv_ver_to_os[] = {
45 "WIN9X", /* driver version/cversion 0 */
47 "WINNT", /* driver version/cversion 2 */
48 "WIN2K", /* driver version/cversion 3 */
51 static const char *get_drv_ver_to_os(int ver)
53 if (ver < 0 || ver > 3)
55 return drv_ver_to_os[ver];
59 const char *long_archi;
60 const char *short_archi;
64 static Printer_entry *printers_list;
66 typedef struct _counter_printer_0 {
67 struct _counter_printer_0 *next;
68 struct _counter_printer_0 *prev;
74 static counter_printer_0 *counter_list;
76 static struct cli_state notify_cli; /* print notify back-channel */
77 static uint32 smb_connections=0;
80 /* in printing/nt_printing.c */
82 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
84 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
85 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
87 /* translate between internal status numbers and NT status numbers */
88 static int nt_printj_status(int v)
94 return JOB_STATUS_PAUSED;
96 return JOB_STATUS_SPOOLING;
98 return JOB_STATUS_PRINTING;
100 return JOB_STATUS_ERROR;
102 return JOB_STATUS_DELETING;
104 return JOB_STATUS_OFFLINE;
106 return JOB_STATUS_PAPEROUT;
108 return JOB_STATUS_PRINTED;
110 return JOB_STATUS_DELETED;
112 return JOB_STATUS_BLOCKED;
113 case LPQ_USER_INTERVENTION:
114 return JOB_STATUS_USER_INTERVENTION;
119 static int nt_printq_status(int v)
123 return PRINTER_STATUS_PAUSED;
132 /****************************************************************************
133 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
134 ****************************************************************************/
136 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
141 SAFE_FREE((*pp)->ctr.type);
145 /***************************************************************************
146 Disconnect from the client
147 ****************************************************************************/
149 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
154 * Tell the specific printing tdb we no longer want messages for this printer
155 * by deregistering our PID.
158 if (!print_notify_deregister_pid(snum))
159 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
161 /* weird if the test succeds !!! */
162 if (smb_connections==0) {
163 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
167 result = cli_spoolss_reply_close_printer(¬ify_cli, notify_cli.mem_ctx, handle);
169 if (!W_ERROR_IS_OK(result))
170 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171 dos_errstr(result)));
173 /* if it's the last connection, deconnect the IPC$ share */
174 if (smb_connections==1) {
175 cli_nt_session_close(¬ify_cli);
176 cli_ulogoff(¬ify_cli);
177 cli_shutdown(¬ify_cli);
178 message_deregister(MSG_PRINTER_NOTIFY2);
180 /* Tell the connections db we're no longer interested in
181 * printer notify messages. */
183 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
189 /****************************************************************************
190 Functions to free a printer entry datastruct.
191 ****************************************************************************/
193 static void free_printer_entry(void *ptr)
195 Printer_entry *Printer = (Printer_entry *)ptr;
197 if (Printer->notify.client_connected==True) {
200 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
202 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
204 snum = print_queue_snum(Printer->sharename);
206 srv_spoolss_replycloseprinter(snum,
207 &Printer->notify.client_hnd);
211 Printer->notify.flags=0;
212 Printer->notify.options=0;
213 Printer->notify.localmachine[0]='\0';
214 Printer->notify.printerlocal=0;
215 free_spool_notify_option(&Printer->notify.option);
216 Printer->notify.option=NULL;
217 Printer->notify.client_connected=False;
219 free_nt_devicemode( &Printer->nt_devmode );
220 free_a_printer( &Printer->printer_info, 2 );
222 talloc_destroy( Printer->ctx );
224 /* Remove from the internal list. */
225 DLIST_REMOVE(printers_list, Printer);
230 /****************************************************************************
231 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
232 ****************************************************************************/
234 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
236 SPOOL_NOTIFY_OPTION *new_sp = NULL;
241 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
248 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
250 if (!new_sp->ctr.type) {
259 /****************************************************************************
260 find printer index by handle
261 ****************************************************************************/
263 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
265 Printer_entry *find_printer = NULL;
267 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
268 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
275 /****************************************************************************
276 look for a printer object cached on an open printer handle
277 ****************************************************************************/
279 WERROR find_printer_in_print_hnd_cache( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 **info2,
280 const char *servername, const char *printername )
284 DEBUG(10,("find_printer_in_print_hnd_cache: printer [\\\\%s\\%s]\n",
285 servername, printername));
287 for ( p=printers_list; p; p=p->next )
289 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
291 && strequal( p->sharename, printername )
292 && strequal( p->servername, servername ) )
294 DEBUG(10,("Found printer\n"));
295 *info2 = dup_printer_2( ctx, p->printer_info->info_2 );
301 return WERR_INVALID_PRINTER_NAME;
304 /****************************************************************************
305 destroy any cached printer_info_2 structures on open handles
306 ****************************************************************************/
308 void invalidate_printer_hnd_cache( char *printername )
312 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
314 for ( p=printers_list; p; p=p->next )
316 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
318 && StrCaseCmp(p->sharename, printername)==0)
320 DEBUG(10,("invalidating printer_info cache for handl:\n"));
321 free_a_printer( &p->printer_info, 2 );
322 p->printer_info = NULL;
328 /****************************************************************************
329 Close printer index by handle.
330 ****************************************************************************/
332 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
334 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
337 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
341 close_policy_hnd(p, hnd);
346 /****************************************************************************
347 Delete a printer given a handle.
348 ****************************************************************************/
350 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
352 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
355 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
360 * It turns out that Windows allows delete printer on a handle
361 * opened by an admin user, then used on a pipe handle created
362 * by an anonymous user..... but they're working on security.... riiight !
366 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
367 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
368 return WERR_ACCESS_DENIED;
372 /* Check calling user has permission to delete printer. Note that
373 since we set the snum parameter to -1 only administrators can
374 delete the printer. This stops people with the Full Control
375 permission from deleting the printer. */
377 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
378 DEBUG(3, ("printer delete denied by security descriptor\n"));
379 return WERR_ACCESS_DENIED;
383 if (del_a_printer( Printer->sharename ) != 0) {
384 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
388 if (*lp_deleteprinter_cmd()) {
390 char *cmd = lp_deleteprinter_cmd();
394 pstr_sprintf(command, "%s \"%s\"", cmd, Printer->sharename);
396 DEBUG(10,("Running [%s]\n", command));
397 ret = smbrun(command, NULL);
399 return WERR_BADFID; /* What to return here? */
401 DEBUGADD(10,("returned [%d]\n", ret));
403 /* Send SIGHUP to process group... is there a better way? */
406 /* go ahead and re-read the services immediately */
407 reload_services( False );
409 if ( lp_servicenumber( Printer->sharename ) < 0 )
410 return WERR_ACCESS_DENIED;
416 /****************************************************************************
417 Return the snum of a printer corresponding to an handle.
418 ****************************************************************************/
420 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
422 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
425 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
429 switch (Printer->printer_type) {
430 case PRINTER_HANDLE_IS_PRINTER:
431 DEBUG(4,("short name:%s\n", Printer->sharename));
432 *number = print_queue_snum(Printer->sharename);
433 return (*number != -1);
434 case PRINTER_HANDLE_IS_PRINTSERVER:
441 /****************************************************************************
442 Set printer handle type.
443 Check if it's \\server or \\server\printer
444 ****************************************************************************/
446 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
448 DEBUG(3,("Setting printer type=%s\n", handlename));
450 if ( strlen(handlename) < 3 ) {
451 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
455 /* it's a print server */
456 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
457 DEBUGADD(4,("Printer is a print server\n"));
458 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
462 DEBUGADD(4,("Printer is a printer\n"));
463 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
469 /****************************************************************************
470 Set printer handle name.
471 ****************************************************************************/
473 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
476 int n_services=lp_numservices();
477 char *aprinter, *printername;
478 const char *servername;
481 NT_PRINTER_INFO_LEVEL *printer;
484 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
486 aprinter = handlename;
487 if ( *handlename == '\\' ) {
488 servername = handlename + 2;
489 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
498 /* save the servername to fill in replies on this handle */
500 if ( !is_myname_or_ipaddr( servername ) )
503 fstrcpy( Printer->servername, servername );
505 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
508 if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
511 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
513 /* Search all sharenames first as this is easier than pulling
514 the printer_info_2 off of disk */
516 snum = find_service(aprinter);
518 if ( lp_snum_ok(snum) && lp_print_ok(snum) ) {
520 fstrcpy( sname, aprinter );
523 /* do another loop to look for printernames */
525 for (snum=0; !found && snum<n_services; snum++) {
527 /* no point in checking if this is not a printer or
528 we aren't allowing printername != sharename */
530 if ( !(lp_snum_ok(snum)
532 && !lp_force_printername(snum)) )
537 fstrcpy(sname, lp_servicename(snum));
540 result = get_a_printer( NULL, &printer, 2, sname );
541 if ( !W_ERROR_IS_OK(result) ) {
542 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
543 sname, dos_errstr(result)));
547 /* printername is always returned as \\server\printername */
548 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
549 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
550 printer->info_2->printername));
551 free_a_printer( &printer, 2);
557 if ( strequal(printername, aprinter) ) {
561 DEBUGADD(10, ("printername: %s\n", printername));
563 free_a_printer( &printer, 2);
567 DEBUGADD(4,("Printer not found\n"));
571 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
573 fstrcpy(Printer->sharename, sname);
578 /****************************************************************************
579 Find first available printer slot. creates a printer handle for you.
580 ****************************************************************************/
582 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
584 Printer_entry *new_printer;
586 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
588 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
591 ZERO_STRUCTP(new_printer);
593 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
594 SAFE_FREE(new_printer);
598 /* Add to the internal list. */
599 DLIST_ADD(printers_list, new_printer);
601 new_printer->notify.option=NULL;
603 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
604 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
605 close_printer_handle(p, hnd);
609 if (!set_printer_hnd_printertype(new_printer, name)) {
610 close_printer_handle(p, hnd);
614 if (!set_printer_hnd_name(new_printer, name)) {
615 close_printer_handle(p, hnd);
619 new_printer->access_granted = access_granted;
621 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
626 /****************************************************************************
627 Allocate more memory for a BUFFER.
628 ****************************************************************************/
630 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
638 /* damn, I'm doing the reverse operation of prs_grow() :) */
639 if (buffer_size < prs_data_size(ps))
642 extra_space = buffer_size - prs_data_size(ps);
645 * save the offset and move to the end of the buffer
646 * prs_grow() checks the extra_space against the offset
648 old_offset=prs_offset(ps);
649 prs_set_offset(ps, prs_data_size(ps));
651 if (!prs_grow(ps, extra_space))
654 prs_set_offset(ps, old_offset);
656 buffer->string_at_end=prs_data_size(ps);
661 /***************************************************************************
662 check to see if the client motify handle is monitoring the notification
663 given by (notify_type, notify_field).
664 **************************************************************************/
666 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
672 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
675 SPOOL_NOTIFY_OPTION *option = p->notify.option;
679 * Flags should always be zero when the change notify
680 * is registered by the client's spooler. A user Win32 app
681 * might use the flags though instead of the NOTIFY_OPTION_INFO
690 return is_monitoring_event_flags(
691 p->notify.flags, notify_type, notify_field);
693 for (i = 0; i < option->count; i++) {
695 /* Check match for notify_type */
697 if (option->ctr.type[i].type != notify_type)
700 /* Check match for field */
702 for (j = 0; j < option->ctr.type[i].count; j++) {
703 if (option->ctr.type[i].fields[j] == notify_field) {
709 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
710 p->servername, p->sharename, notify_type, notify_field));
715 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
717 static void notify_one_value(struct spoolss_notify_msg *msg,
718 SPOOL_NOTIFY_INFO_DATA *data,
721 data->notify_data.value[0] = msg->notify.value[0];
722 data->notify_data.value[1] = 0;
725 static void notify_string(struct spoolss_notify_msg *msg,
726 SPOOL_NOTIFY_INFO_DATA *data,
731 /* The length of the message includes the trailing \0 */
733 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
735 data->notify_data.data.length = msg->len * 2;
736 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
738 if (!data->notify_data.data.string) {
739 data->notify_data.data.length = 0;
743 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
746 static void notify_system_time(struct spoolss_notify_msg *msg,
747 SPOOL_NOTIFY_INFO_DATA *data,
753 if (msg->len != sizeof(time_t)) {
754 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
759 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
760 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
764 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
765 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
769 if (!spoolss_io_system_time("", &ps, 0, &systime))
772 data->notify_data.data.length = prs_offset(&ps);
773 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
775 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
780 struct notify2_message_table {
782 void (*fn)(struct spoolss_notify_msg *msg,
783 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
786 static struct notify2_message_table printer_notify_table[] = {
787 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
788 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
789 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
790 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
791 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
792 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
793 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
794 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
795 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
796 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
797 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
798 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
799 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
800 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
801 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
802 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
803 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
804 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
805 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
808 static struct notify2_message_table job_notify_table[] = {
809 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
810 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
811 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
812 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
813 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
814 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
815 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
816 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
817 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
818 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
819 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
820 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
821 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
822 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
823 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
824 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
825 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
826 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
827 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
828 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
829 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
830 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
831 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
832 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
836 /***********************************************************************
837 Allocate talloc context for container object
838 **********************************************************************/
840 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
845 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
850 /***********************************************************************
851 release all allocated memory and zero out structure
852 **********************************************************************/
854 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
860 talloc_destroy(ctr->ctx);
867 /***********************************************************************
868 **********************************************************************/
870 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
878 /***********************************************************************
879 **********************************************************************/
881 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
883 if ( !ctr || !ctr->msg_groups )
886 if ( idx >= ctr->num_groups )
889 return &ctr->msg_groups[idx];
893 /***********************************************************************
894 How many groups of change messages do we have ?
895 **********************************************************************/
897 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
902 return ctr->num_groups;
905 /***********************************************************************
906 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
907 **********************************************************************/
909 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
911 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
912 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
913 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
919 /* loop over all groups looking for a matching printer name */
921 for ( i=0; i<ctr->num_groups; i++ ) {
922 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
926 /* add a new group? */
928 if ( i == ctr->num_groups ) {
931 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
932 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
935 ctr->msg_groups = groups;
937 /* clear the new entry and set the printer name */
939 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
940 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
943 /* add the change messages; 'i' is the correct index now regardless */
945 msg_grp = &ctr->msg_groups[i];
949 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
950 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
953 msg_grp->msgs = msg_list;
955 new_slot = msg_grp->num_msgs-1;
956 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
958 /* need to allocate own copy of data */
961 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
963 return ctr->num_groups;
966 /***********************************************************************
967 Send a change notication message on all handles which have a call
969 **********************************************************************/
971 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
974 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
975 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
976 SPOOLSS_NOTIFY_MSG *messages;
977 int sending_msg_count;
980 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
984 messages = msg_group->msgs;
987 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
991 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
993 /* loop over all printers */
995 for (p = printers_list; p; p = p->next) {
996 SPOOL_NOTIFY_INFO_DATA *data;
1001 /* Is there notification on this handle? */
1003 if ( !p->notify.client_connected )
1006 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
1008 /* For this printer? Print servers always receive
1011 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
1012 ( !strequal(msg_group->printername, p->sharename) ) )
1015 DEBUG(10,("Our printer\n"));
1017 /* allocate the max entries possible */
1019 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
1022 /* build the array of change notifications */
1024 sending_msg_count = 0;
1026 for ( i=0; i<msg_group->num_msgs; i++ ) {
1027 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1029 /* Are we monitoring this event? */
1031 if (!is_monitoring_event(p, msg->type, msg->field))
1034 sending_msg_count++;
1037 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1038 msg->type, msg->field, p->sharename));
1041 * if the is a printer notification handle and not a job notification
1042 * type, then set the id to 0. Other wise just use what was specified
1045 * When registering change notification on a print server handle
1046 * we always need to send back the id (snum) matching the printer
1047 * for which the change took place. For change notify registered
1048 * on a printer handle, this does not matter and the id should be 0.
1053 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1059 /* Convert unix jobid to smb jobid */
1061 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1062 id = sysjob_to_jobid(msg->id);
1065 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1070 construct_info_data( &data[data_len], msg->type, msg->field, id );
1073 case PRINTER_NOTIFY_TYPE:
1074 if ( printer_notify_table[msg->field].fn )
1075 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1078 case JOB_NOTIFY_TYPE:
1079 if ( job_notify_table[msg->field].fn )
1080 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1084 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1091 if ( sending_msg_count ) {
1092 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
1093 data_len, data, p->notify.change, 0 );
1098 DEBUG(8,("send_notify2_changes: Exit...\n"));
1102 /***********************************************************************
1103 **********************************************************************/
1105 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1108 uint32 tv_sec, tv_usec;
1111 /* Unpack message */
1113 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1116 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1118 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1121 tdb_unpack((char *)buf + offset, len - offset, "dd",
1122 &msg->notify.value[0], &msg->notify.value[1]);
1124 tdb_unpack((char *)buf + offset, len - offset, "B",
1125 &msg->len, &msg->notify.data);
1127 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1128 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1130 tv->tv_sec = tv_sec;
1131 tv->tv_usec = tv_usec;
1134 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1135 msg->notify.value[1]));
1137 dump_data(3, msg->notify.data, msg->len);
1142 /********************************************************************
1143 Receive a notify2 message list
1144 ********************************************************************/
1146 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1148 size_t msg_count, i;
1149 char *buf = (char *)msg;
1152 SPOOLSS_NOTIFY_MSG notify;
1153 SPOOLSS_NOTIFY_MSG_CTR messages;
1157 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1161 msg_count = IVAL(buf, 0);
1164 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1166 if (msg_count == 0) {
1167 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1171 /* initialize the container */
1173 ZERO_STRUCT( messages );
1174 notify_msg_ctr_init( &messages );
1177 * build message groups for each printer identified
1178 * in a change_notify msg. Remember that a PCN message
1179 * includes the handle returned for the srv_spoolss_replyopenprinter()
1180 * call. Therefore messages are grouped according to printer handle.
1183 for ( i=0; i<msg_count; i++ ) {
1184 struct timeval msg_tv;
1186 if (msg_ptr + 4 - buf > len) {
1187 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1191 msg_len = IVAL(msg_ptr,0);
1194 if (msg_ptr + msg_len - buf > len) {
1195 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1199 /* unpack messages */
1201 ZERO_STRUCT( notify );
1202 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1205 /* add to correct list in container */
1207 notify_msg_ctr_addmsg( &messages, ¬ify );
1209 /* free memory that might have been allocated by notify2_unpack_msg() */
1211 if ( notify.len != 0 )
1212 SAFE_FREE( notify.notify.data );
1215 /* process each group of messages */
1217 num_groups = notify_msg_ctr_numgroups( &messages );
1218 for ( i=0; i<num_groups; i++ )
1219 send_notify2_changes( &messages, i );
1224 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1226 notify_msg_ctr_destroy( &messages );
1231 /********************************************************************
1232 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1233 one smbd, all of processes must clear their printer cache immediately.
1234 ********************************************************************/
1236 void receive_printer_mod_msg(int msg_type, pid_t src, void *buf, size_t len)
1238 fstring printername;
1240 fstrcpy( printername, buf );
1242 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername ));
1244 invalidate_printer_hnd_cache( printername );
1247 /********************************************************************
1248 Send a message to ourself about new driver being installed
1249 so we can upgrade the information for each printer bound to this
1251 ********************************************************************/
1253 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1255 int len = strlen(drivername);
1260 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1263 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1268 /**********************************************************************
1269 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1270 over all printers, upgrading ones as necessary
1271 **********************************************************************/
1273 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1277 int n_services = lp_numservices();
1279 len = MIN(len,sizeof(drivername)-1);
1280 strncpy(drivername, buf, len);
1282 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1284 /* Iterate the printer list */
1286 for (snum=0; snum<n_services; snum++)
1288 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1291 NT_PRINTER_INFO_LEVEL *printer = NULL;
1293 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1294 if (!W_ERROR_IS_OK(result))
1297 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1299 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1301 /* all we care about currently is the change_id */
1303 result = mod_a_printer(printer, 2);
1304 if (!W_ERROR_IS_OK(result)) {
1305 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1306 dos_errstr(result)));
1310 free_a_printer(&printer, 2);
1317 /********************************************************************
1318 Update the cache for all printq's with a registered client
1320 ********************************************************************/
1322 void update_monitored_printq_cache( void )
1324 Printer_entry *printer = printers_list;
1327 /* loop through all printers and update the cache where
1328 client_connected == True */
1331 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1332 && printer->notify.client_connected )
1334 snum = print_queue_snum(printer->sharename);
1335 print_queue_status( snum, NULL, NULL );
1338 printer = printer->next;
1343 /********************************************************************
1344 Send a message to ourself about new driver being installed
1345 so we can upgrade the information for each printer bound to this
1347 ********************************************************************/
1349 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1351 int len = strlen(drivername);
1356 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1359 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1364 /**********************************************************************
1365 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1366 over all printers, resetting printer data as neessary
1367 **********************************************************************/
1369 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1373 int n_services = lp_numservices();
1375 len = MIN( len, sizeof(drivername)-1 );
1376 strncpy( drivername, buf, len );
1378 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1380 /* Iterate the printer list */
1382 for ( snum=0; snum<n_services; snum++ )
1384 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1387 NT_PRINTER_INFO_LEVEL *printer = NULL;
1389 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1390 if ( !W_ERROR_IS_OK(result) )
1394 * if the printer is bound to the driver,
1395 * then reset to the new driver initdata
1398 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1400 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1402 if ( !set_driver_init(printer, 2) ) {
1403 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1404 printer->info_2->printername, printer->info_2->drivername));
1407 result = mod_a_printer( printer, 2 );
1408 if ( !W_ERROR_IS_OK(result) ) {
1409 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1410 get_dos_error_msg(result)));
1414 free_a_printer( &printer, 2 );
1423 /********************************************************************
1424 Copy routines used by convert_to_openprinterex()
1425 *******************************************************************/
1427 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1435 DEBUG (8,("dup_devmode\n"));
1437 /* bulk copy first */
1439 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1443 /* dup the pointer members separately */
1445 len = unistrlen(devmode->devicename.buffer);
1447 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1448 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1453 len = unistrlen(devmode->formname.buffer);
1455 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1456 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1460 d->private = TALLOC_MEMDUP(ctx, devmode->private, devmode->driverextra);
1465 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1467 if (!new_ctr || !ctr)
1470 DEBUG(8,("copy_devmode_ctr\n"));
1472 new_ctr->size = ctr->size;
1473 new_ctr->devmode_ptr = ctr->devmode_ptr;
1475 if(ctr->devmode_ptr)
1476 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1479 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1481 if (!new_def || !def)
1484 DEBUG(8,("copy_printer_defaults\n"));
1486 new_def->datatype_ptr = def->datatype_ptr;
1488 if (def->datatype_ptr)
1489 copy_unistr2(&new_def->datatype, &def->datatype);
1491 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1493 new_def->access_required = def->access_required;
1496 /********************************************************************
1497 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1498 * SPOOL_Q_OPEN_PRINTER_EX structure
1499 ********************************************************************/
1501 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1503 if (!q_u_ex || !q_u)
1506 DEBUG(8,("convert_to_openprinterex\n"));
1508 q_u_ex->printername_ptr = q_u->printername_ptr;
1510 if (q_u->printername_ptr)
1511 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1513 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1516 /********************************************************************
1517 * spoolss_open_printer
1519 * called from the spoolss dispatcher
1520 ********************************************************************/
1522 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1524 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1525 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1530 ZERO_STRUCT(q_u_ex);
1531 ZERO_STRUCT(r_u_ex);
1533 /* convert the OpenPrinter() call to OpenPrinterEx() */
1535 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1537 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1539 /* convert back to OpenPrinter() */
1541 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1546 /********************************************************************
1547 * spoolss_open_printer
1549 * If the openprinterex rpc call contains a devmode,
1550 * it's a per-user one. This per-user devmode is derivated
1551 * from the global devmode. Openprinterex() contains a per-user
1552 * devmode for when you do EMF printing and spooling.
1553 * In the EMF case, the NT workstation is only doing half the job
1554 * of rendering the page. The other half is done by running the printer
1555 * driver on the server.
1556 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1557 * The EMF file only contains what is to be printed on the page.
1558 * So in order for the server to know how to print, the NT client sends
1559 * a devicemode attached to the openprinterex call.
1560 * But this devicemode is short lived, it's only valid for the current print job.
1562 * If Samba would have supported EMF spooling, this devicemode would
1563 * have been attached to the handle, to sent it to the driver to correctly
1564 * rasterize the EMF file.
1566 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1567 * we just act as a pass-thru between windows and the printer.
1569 * In order to know that Samba supports only RAW spooling, NT has to call
1570 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1571 * and until NT sends a RAW job, we refuse it.
1573 * But to call getprinter() or startdoc(), you first need a valid handle,
1574 * and to get an handle you have to call openprintex(). Hence why you have
1575 * a devicemode in the openprinterex() call.
1578 * Differences between NT4 and NT 2000.
1581 * On NT4, you only have a global devicemode. This global devicemode can be changed
1582 * by the administrator (or by a user with enough privs). Everytime a user
1583 * wants to print, the devicemode is resetted to the default. In Word, everytime
1584 * you print, the printer's characteristics are always reset to the global devicemode.
1588 * In W2K, there is the notion of per-user devicemode. The first time you use
1589 * a printer, a per-user devicemode is build from the global devicemode.
1590 * If you change your per-user devicemode, it is saved in the registry, under the
1591 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1592 * printer preferences available.
1594 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1595 * on the General Tab of the printer properties windows.
1597 * To change the global devicemode: it's the "Printing Defaults..." button
1598 * on the Advanced Tab of the printer properties window.
1601 ********************************************************************/
1603 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1605 UNISTR2 *printername = NULL;
1606 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1607 POLICY_HND *handle = &r_u->handle;
1611 struct current_user user;
1612 Printer_entry *Printer=NULL;
1614 if (q_u->printername_ptr != 0)
1615 printername = &q_u->printername;
1617 if (printername == NULL)
1618 return WERR_INVALID_PRINTER_NAME;
1620 /* some sanity check because you can open a printer or a print server */
1621 /* aka: \\server\printer or \\server */
1622 unistr2_to_ascii(name, printername, sizeof(name)-1);
1624 DEBUGADD(3,("checking name: %s\n",name));
1626 if (!open_printer_hnd(p, handle, name, 0))
1627 return WERR_INVALID_PRINTER_NAME;
1629 Printer=find_printer_index_by_hnd(p, handle);
1631 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1632 "handle we created for printer %s\n", name ));
1633 close_printer_handle(p,handle);
1634 return WERR_INVALID_PRINTER_NAME;
1637 get_current_user(&user, p);
1640 * First case: the user is opening the print server:
1642 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1643 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1645 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1646 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1647 * or if the user is listed in the smb.conf printer admin parameter.
1649 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1650 * client view printer folder, but does not show the MSAPW.
1652 * Note: this test needs code to check access rights here too. Jeremy
1653 * could you look at this?
1655 * Second case: the user is opening a printer:
1656 * NT doesn't let us connect to a printer if the connecting user
1657 * doesn't have print permission.
1660 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1662 /* Printserver handles use global struct... */
1666 /* Map standard access rights to object specific access rights */
1668 se_map_standard(&printer_default->access_required,
1669 &printserver_std_mapping);
1671 /* Deny any object specific bits that don't apply to print
1672 servers (i.e printer and job specific bits) */
1674 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1676 if (printer_default->access_required &
1677 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1678 DEBUG(3, ("access DENIED for non-printserver bits"));
1679 close_printer_handle(p, handle);
1680 return WERR_ACCESS_DENIED;
1683 /* Allow admin access */
1685 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1687 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1689 if (!lp_ms_add_printer_wizard()) {
1690 close_printer_handle(p, handle);
1691 return WERR_ACCESS_DENIED;
1694 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1695 and not a printer admin, then fail */
1698 && !user_has_privileges( user.nt_user_token, &se_printop )
1699 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1701 close_printer_handle(p, handle);
1702 return WERR_ACCESS_DENIED;
1705 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1709 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1712 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1713 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1715 /* We fall through to return WERR_OK */
1720 /* NT doesn't let us connect to a printer if the connecting user
1721 doesn't have print permission. */
1723 if (!get_printer_snum(p, handle, &snum)) {
1724 close_printer_handle(p, handle);
1728 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1730 /* map an empty access mask to the minimum access mask */
1731 if (printer_default->access_required == 0x0)
1732 printer_default->access_required = PRINTER_ACCESS_USE;
1735 * If we are not serving the printer driver for this printer,
1736 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1737 * will keep NT clients happy --jerry
1740 if (lp_use_client_driver(snum)
1741 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1743 printer_default->access_required = PRINTER_ACCESS_USE;
1746 /* check smb.conf parameters and the the sec_desc */
1748 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1749 DEBUG(3, ("access DENIED for printer open\n"));
1750 close_printer_handle(p, handle);
1751 return WERR_ACCESS_DENIED;
1754 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1755 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1756 close_printer_handle(p, handle);
1757 return WERR_ACCESS_DENIED;
1760 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1761 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1763 printer_default->access_required = PRINTER_ACCESS_USE;
1765 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1766 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1770 Printer->access_granted = printer_default->access_required;
1773 * If the client sent a devmode in the OpenPrinter() call, then
1774 * save it here in case we get a job submission on this handle
1777 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1778 && q_u->printer_default.devmode_cont.devmode_ptr )
1780 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1781 &Printer->nt_devmode );
1784 #if 0 /* JERRY -- I'm doubtful this is really effective */
1785 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1786 optimization in Windows 2000 clients --jerry */
1788 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1789 && (RA_WIN2K == get_remote_arch()) )
1791 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1792 sys_usleep( 500000 );
1799 /****************************************************************************
1800 ****************************************************************************/
1802 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1803 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1809 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1818 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1819 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1825 printer->info_3=NULL;
1826 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1830 printer->info_6=NULL;
1831 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1841 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1842 NT_DEVICEMODE **pp_nt_devmode)
1844 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1847 * Ensure nt_devmode is a valid pointer
1848 * as we will be overwriting it.
1851 if (nt_devmode == NULL) {
1852 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1853 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1857 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1858 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1860 nt_devmode->specversion=devmode->specversion;
1861 nt_devmode->driverversion=devmode->driverversion;
1862 nt_devmode->size=devmode->size;
1863 nt_devmode->fields=devmode->fields;
1864 nt_devmode->orientation=devmode->orientation;
1865 nt_devmode->papersize=devmode->papersize;
1866 nt_devmode->paperlength=devmode->paperlength;
1867 nt_devmode->paperwidth=devmode->paperwidth;
1868 nt_devmode->scale=devmode->scale;
1869 nt_devmode->copies=devmode->copies;
1870 nt_devmode->defaultsource=devmode->defaultsource;
1871 nt_devmode->printquality=devmode->printquality;
1872 nt_devmode->color=devmode->color;
1873 nt_devmode->duplex=devmode->duplex;
1874 nt_devmode->yresolution=devmode->yresolution;
1875 nt_devmode->ttoption=devmode->ttoption;
1876 nt_devmode->collate=devmode->collate;
1878 nt_devmode->logpixels=devmode->logpixels;
1879 nt_devmode->bitsperpel=devmode->bitsperpel;
1880 nt_devmode->pelswidth=devmode->pelswidth;
1881 nt_devmode->pelsheight=devmode->pelsheight;
1882 nt_devmode->displayflags=devmode->displayflags;
1883 nt_devmode->displayfrequency=devmode->displayfrequency;
1884 nt_devmode->icmmethod=devmode->icmmethod;
1885 nt_devmode->icmintent=devmode->icmintent;
1886 nt_devmode->mediatype=devmode->mediatype;
1887 nt_devmode->dithertype=devmode->dithertype;
1888 nt_devmode->reserved1=devmode->reserved1;
1889 nt_devmode->reserved2=devmode->reserved2;
1890 nt_devmode->panningwidth=devmode->panningwidth;
1891 nt_devmode->panningheight=devmode->panningheight;
1894 * Only change private and driverextra if the incoming devmode
1895 * has a new one. JRA.
1898 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1899 SAFE_FREE(nt_devmode->private);
1900 nt_devmode->driverextra=devmode->driverextra;
1901 if((nt_devmode->private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1903 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1906 *pp_nt_devmode = nt_devmode;
1911 /********************************************************************
1912 * _spoolss_enddocprinter_internal.
1913 ********************************************************************/
1915 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1917 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1921 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1925 if (!get_printer_snum(p, handle, &snum))
1928 Printer->document_started=False;
1929 print_job_end(snum, Printer->jobid,True);
1930 /* error codes unhandled so far ... */
1935 /********************************************************************
1936 * api_spoolss_closeprinter
1937 ********************************************************************/
1939 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1941 POLICY_HND *handle = &q_u->handle;
1943 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1945 if (Printer && Printer->document_started)
1946 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1948 if (!close_printer_handle(p, handle))
1951 /* clear the returned printer handle. Observed behavior
1952 from Win2k server. Don't think this really matters.
1953 Previous code just copied the value of the closed
1956 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1961 /********************************************************************
1962 * api_spoolss_deleteprinter
1964 ********************************************************************/
1966 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1968 POLICY_HND *handle = &q_u->handle;
1969 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1972 if (Printer && Printer->document_started)
1973 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1975 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1977 result = delete_printer_handle(p, handle);
1979 update_c_setprinter(False);
1984 /*******************************************************************
1985 * static function to lookup the version id corresponding to an
1986 * long architecture string
1987 ******************************************************************/
1989 static int get_version_id (char * arch)
1992 struct table_node archi_table[]= {
1994 {"Windows 4.0", "WIN40", 0 },
1995 {"Windows NT x86", "W32X86", 2 },
1996 {"Windows NT R4000", "W32MIPS", 2 },
1997 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1998 {"Windows NT PowerPC", "W32PPC", 2 },
1999 {"Windows IA64", "IA64", 3 },
2000 {"Windows x64", "x64", 3 },
2004 for (i=0; archi_table[i].long_archi != NULL; i++)
2006 if (strcmp(arch, archi_table[i].long_archi) == 0)
2007 return (archi_table[i].version);
2013 /********************************************************************
2014 * _spoolss_deleteprinterdriver
2015 ********************************************************************/
2017 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2021 NT_PRINTER_DRIVER_INFO_LEVEL info;
2022 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2024 struct current_user user;
2026 WERROR status_win2k = WERR_ACCESS_DENIED;
2028 get_current_user(&user, p);
2030 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2031 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2033 /* check that we have a valid driver name first */
2035 if ((version=get_version_id(arch)) == -1)
2036 return WERR_INVALID_ENVIRONMENT;
2039 ZERO_STRUCT(info_win2k);
2041 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2043 /* try for Win2k driver if "Windows NT x86" */
2045 if ( version == 2 ) {
2047 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2048 status = WERR_UNKNOWN_PRINTER_DRIVER;
2052 /* otherwise it was a failure */
2054 status = WERR_UNKNOWN_PRINTER_DRIVER;
2060 if (printer_driver_in_use(info.info_3)) {
2061 status = WERR_PRINTER_DRIVER_IN_USE;
2067 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2069 /* if we get to here, we now have 2 driver info structures to remove */
2070 /* remove the Win2k driver first*/
2072 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2073 free_a_printer_driver( info_win2k, 3 );
2075 /* this should not have failed---if it did, report to client */
2076 if ( !W_ERROR_IS_OK(status_win2k) )
2081 status = delete_printer_driver(info.info_3, &user, version, False);
2083 /* if at least one of the deletes succeeded return OK */
2085 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2089 free_a_printer_driver( info, 3 );
2094 /********************************************************************
2095 * spoolss_deleteprinterdriverex
2096 ********************************************************************/
2098 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2102 NT_PRINTER_DRIVER_INFO_LEVEL info;
2103 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2105 uint32 flags = q_u->delete_flags;
2107 struct current_user user;
2109 WERROR status_win2k = WERR_ACCESS_DENIED;
2111 get_current_user(&user, p);
2113 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2114 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2116 /* check that we have a valid driver name first */
2117 if ((version=get_version_id(arch)) == -1) {
2118 /* this is what NT returns */
2119 return WERR_INVALID_ENVIRONMENT;
2122 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2123 version = q_u->version;
2126 ZERO_STRUCT(info_win2k);
2128 status = get_a_printer_driver(&info, 3, driver, arch, version);
2130 if ( !W_ERROR_IS_OK(status) )
2133 * if the client asked for a specific version,
2134 * or this is something other than Windows NT x86,
2138 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2141 /* try for Win2k driver if "Windows NT x86" */
2144 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2145 status = WERR_UNKNOWN_PRINTER_DRIVER;
2150 if ( printer_driver_in_use(info.info_3) ) {
2151 status = WERR_PRINTER_DRIVER_IN_USE;
2156 * we have a couple of cases to consider.
2157 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2158 * then the delete should fail if **any** files overlap with
2160 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2161 * non-overlapping files
2162 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2163 * is set, the do not delete any files
2164 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2167 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2169 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2171 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2172 /* no idea of the correct error here */
2173 status = WERR_ACCESS_DENIED;
2178 /* also check for W32X86/3 if necessary; maybe we already have? */
2180 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2181 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2184 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2185 /* no idea of the correct error here */
2186 free_a_printer_driver( info_win2k, 3 );
2187 status = WERR_ACCESS_DENIED;
2191 /* if we get to here, we now have 2 driver info structures to remove */
2192 /* remove the Win2k driver first*/
2194 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2195 free_a_printer_driver( info_win2k, 3 );
2197 /* this should not have failed---if it did, report to client */
2199 if ( !W_ERROR_IS_OK(status_win2k) )
2204 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2206 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2209 free_a_printer_driver( info, 3 );
2215 /****************************************************************************
2216 Internal routine for retreiving printerdata
2217 ***************************************************************************/
2219 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2220 const char *key, const char *value, uint32 *type, uint8 **data,
2221 uint32 *needed, uint32 in_size )
2223 REGISTRY_VALUE *val;
2226 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2227 return WERR_BADFILE;
2229 *type = regval_type( val );
2231 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2233 size = regval_size( val );
2235 /* copy the min(in_size, len) */
2238 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2240 /* special case for 0 length values */
2242 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2246 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2255 DEBUG(5,("get_printer_dataex: copy done\n"));
2260 /****************************************************************************
2261 Internal routine for removing printerdata
2262 ***************************************************************************/
2264 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2266 return delete_printer_data( printer->info_2, key, value );
2269 /****************************************************************************
2270 Internal routine for storing printerdata
2271 ***************************************************************************/
2273 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2274 uint32 type, uint8 *data, int real_len )
2276 delete_printer_data( printer->info_2, key, value );
2278 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2281 /********************************************************************
2282 GetPrinterData on a printer server Handle.
2283 ********************************************************************/
2285 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2289 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2291 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2293 if((*data = (uint8 *)TALLOC_ZERO(ctx, 4*sizeof(uint8) )) == NULL)
2299 if (!StrCaseCmp(value, "BeepEnabled")) {
2301 if((*data = (uint8 *)TALLOC(ctx, 4*sizeof(uint8) )) == NULL)
2303 SIVAL(*data, 0, 0x00);
2308 if (!StrCaseCmp(value, "EventLog")) {
2310 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2312 /* formally was 0x1b */
2313 SIVAL(*data, 0, 0x0);
2318 if (!StrCaseCmp(value, "NetPopup")) {
2320 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2322 SIVAL(*data, 0, 0x00);
2327 if (!StrCaseCmp(value, "MajorVersion")) {
2329 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2332 /* Windows NT 4.0 seems to not allow uploading of drivers
2333 to a server that reports 0x3 as the MajorVersion.
2334 need to investigate more how Win2k gets around this .
2337 if ( RA_WINNT == get_remote_arch() )
2346 if (!StrCaseCmp(value, "MinorVersion")) {
2348 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2356 * uint32 size = 0x114
2358 * uint32 minor = [0|1]
2359 * uint32 build = [2195|2600]
2360 * extra unicode string = e.g. "Service Pack 3"
2362 if (!StrCaseCmp(value, "OSVersion")) {
2366 if((*data = (uint8 *)TALLOC(ctx, *needed)) == NULL)
2368 ZERO_STRUCTP( *data );
2370 SIVAL(*data, 0, *needed); /* size */
2371 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2373 SIVAL(*data, 12, 2195); /* build */
2375 /* leave extra string empty */
2381 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2382 const char *string="C:\\PRINTERS";
2384 *needed = 2*(strlen(string)+1);
2385 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2387 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2389 /* it's done by hand ready to go on the wire */
2390 for (i=0; i<strlen(string); i++) {
2391 (*data)[2*i]=string[i];
2392 (*data)[2*i+1]='\0';
2397 if (!StrCaseCmp(value, "Architecture")) {
2398 const char *string="Windows NT x86";
2400 *needed = 2*(strlen(string)+1);
2401 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2403 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2404 for (i=0; i<strlen(string); i++) {
2405 (*data)[2*i]=string[i];
2406 (*data)[2*i+1]='\0';
2411 if (!StrCaseCmp(value, "DsPresent")) {
2413 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2415 SIVAL(*data, 0, 0x01);
2420 if (!StrCaseCmp(value, "DNSMachineName")) {
2423 if (!get_mydnsfullname(hostname))
2424 return WERR_BADFILE;
2426 *needed = 2*(strlen(hostname)+1);
2427 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2429 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2430 for (i=0; i<strlen(hostname); i++) {
2431 (*data)[2*i]=hostname[i];
2432 (*data)[2*i+1]='\0';
2438 return WERR_BADFILE;
2441 /********************************************************************
2442 * spoolss_getprinterdata
2443 ********************************************************************/
2445 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2447 POLICY_HND *handle = &q_u->handle;
2448 UNISTR2 *valuename = &q_u->valuename;
2449 uint32 in_size = q_u->size;
2450 uint32 *type = &r_u->type;
2451 uint32 *out_size = &r_u->size;
2452 uint8 **data = &r_u->data;
2453 uint32 *needed = &r_u->needed;
2456 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2457 NT_PRINTER_INFO_LEVEL *printer = NULL;
2461 * Reminder: when it's a string, the length is in BYTES
2462 * even if UNICODE is negociated.
2467 *out_size = in_size;
2469 /* in case of problem, return some default values */
2474 DEBUG(4,("_spoolss_getprinterdata\n"));
2477 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2478 status = WERR_BADFID;
2482 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2484 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2485 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2488 if ( !get_printer_snum(p,handle, &snum) ) {
2489 status = WERR_BADFID;
2493 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2494 if ( !W_ERROR_IS_OK(status) )
2497 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2499 if ( strequal(value, "ChangeId") ) {
2501 *needed = sizeof(uint32);
2502 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2503 status = WERR_NOMEM;
2506 SIVAL( *data, 0, printer->info_2->changeid );
2510 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2513 if (*needed > *out_size)
2514 status = WERR_MORE_DATA;
2517 if ( !W_ERROR_IS_OK(status) )
2519 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2521 /* reply this param doesn't exist */
2524 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2526 free_a_printer( &printer, 2 );
2535 /* cleanup & exit */
2538 free_a_printer( &printer, 2 );
2543 /*********************************************************
2544 Connect to the client machine.
2545 **********************************************************/
2547 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2548 struct in_addr *client_ip, const char *remote_machine)
2550 ZERO_STRUCTP(the_cli);
2552 if(cli_initialise(the_cli) == NULL) {
2553 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2557 if ( is_zero_ip(*client_ip) ) {
2558 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2559 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2560 cli_shutdown(the_cli);
2564 if (ismyip(the_cli->dest_ip)) {
2565 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2566 cli_shutdown(the_cli);
2571 the_cli->dest_ip.s_addr = client_ip->s_addr;
2572 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2573 inet_ntoa(*client_ip) ));
2576 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2577 DEBUG(0,("spoolss_connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2578 cli_shutdown(the_cli);
2582 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2583 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2585 cli_shutdown(the_cli);
2589 the_cli->protocol = PROTOCOL_NT1;
2590 cli_setup_signing_state(the_cli, lp_client_signing());
2592 if (!cli_negprot(the_cli)) {
2593 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2594 cli_shutdown(the_cli);
2598 if (the_cli->protocol != PROTOCOL_NT1) {
2599 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2600 cli_shutdown(the_cli);
2605 * Do an anonymous session setup.
2608 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2609 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2610 cli_shutdown(the_cli);
2614 if (!(the_cli->sec_mode & 1)) {
2615 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2616 cli_shutdown(the_cli);
2620 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2621 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2622 cli_shutdown(the_cli);
2627 * Ok - we have an anonymous connection to the IPC$ share.
2628 * Now start the NT Domain stuff :-).
2631 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2632 DEBUG(0,("spoolss_connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
2633 cli_nt_session_close(the_cli);
2634 cli_ulogoff(the_cli);
2635 cli_shutdown(the_cli);
2642 /***************************************************************************
2643 Connect to the client.
2644 ****************************************************************************/
2646 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2647 uint32 localprinter, uint32 type,
2648 POLICY_HND *handle, struct in_addr *client_ip)
2653 * If it's the first connection, contact the client
2654 * and connect to the IPC$ share anonymously
2656 if (smb_connections==0) {
2657 fstring unix_printer;
2659 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2661 ZERO_STRUCT(notify_cli);
2663 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2666 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2667 /* Tell the connections db we're now interested in printer
2668 * notify messages. */
2669 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2673 * Tell the specific printing tdb we want messages for this printer
2674 * by registering our PID.
2677 if (!print_notify_register_pid(snum))
2678 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2682 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2685 if (!W_ERROR_IS_OK(result))
2686 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2687 dos_errstr(result)));
2689 return (W_ERROR_IS_OK(result));
2692 /********************************************************************
2694 * ReplyFindFirstPrinterChangeNotifyEx
2696 * before replying OK: status=0 a rpc call is made to the workstation
2697 * asking ReplyOpenPrinter
2699 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2700 * called from api_spoolss_rffpcnex
2701 ********************************************************************/
2703 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2705 POLICY_HND *handle = &q_u->handle;
2706 uint32 flags = q_u->flags;
2707 uint32 options = q_u->options;
2708 UNISTR2 *localmachine = &q_u->localmachine;
2709 uint32 printerlocal = q_u->printerlocal;
2711 SPOOL_NOTIFY_OPTION *option = q_u->option;
2712 struct in_addr client_ip;
2714 /* store the notify value in the printer struct */
2716 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2719 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2723 Printer->notify.flags=flags;
2724 Printer->notify.options=options;
2725 Printer->notify.printerlocal=printerlocal;
2727 if (Printer->notify.option)
2728 free_spool_notify_option(&Printer->notify.option);
2730 Printer->notify.option=dup_spool_notify_option(option);
2732 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2733 sizeof(Printer->notify.localmachine)-1);
2735 /* Connect to the client machine and send a ReplyOpenPrinter */
2737 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2739 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2740 !get_printer_snum(p, handle, &snum) )
2743 client_ip.s_addr = inet_addr(p->conn->client_address);
2745 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2746 Printer->notify.printerlocal, 1,
2747 &Printer->notify.client_hnd, &client_ip))
2748 return WERR_SERVER_UNAVAILABLE;
2750 Printer->notify.client_connected=True;
2755 /*******************************************************************
2756 * fill a notify_info_data with the servername
2757 ********************************************************************/
2759 void spoolss_notify_server_name(int snum,
2760 SPOOL_NOTIFY_INFO_DATA *data,
2761 print_queue_struct *queue,
2762 NT_PRINTER_INFO_LEVEL *printer,
2763 TALLOC_CTX *mem_ctx)
2768 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2770 data->notify_data.data.length = len;
2771 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2773 if (!data->notify_data.data.string) {
2774 data->notify_data.data.length = 0;
2778 memcpy(data->notify_data.data.string, temp, len);
2781 /*******************************************************************
2782 * fill a notify_info_data with the printername (not including the servername).
2783 ********************************************************************/
2785 void spoolss_notify_printer_name(int snum,
2786 SPOOL_NOTIFY_INFO_DATA *data,
2787 print_queue_struct *queue,
2788 NT_PRINTER_INFO_LEVEL *printer,
2789 TALLOC_CTX *mem_ctx)
2794 /* the notify name should not contain the \\server\ part */
2795 char *p = strrchr(printer->info_2->printername, '\\');
2798 p = printer->info_2->printername;
2803 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2805 data->notify_data.data.length = len;
2806 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2808 if (!data->notify_data.data.string) {
2809 data->notify_data.data.length = 0;
2813 memcpy(data->notify_data.data.string, temp, len);
2816 /*******************************************************************
2817 * fill a notify_info_data with the servicename
2818 ********************************************************************/
2820 void spoolss_notify_share_name(int snum,
2821 SPOOL_NOTIFY_INFO_DATA *data,
2822 print_queue_struct *queue,
2823 NT_PRINTER_INFO_LEVEL *printer,
2824 TALLOC_CTX *mem_ctx)
2829 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2831 data->notify_data.data.length = len;
2832 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2834 if (!data->notify_data.data.string) {
2835 data->notify_data.data.length = 0;
2839 memcpy(data->notify_data.data.string, temp, len);
2842 /*******************************************************************
2843 * fill a notify_info_data with the port name
2844 ********************************************************************/
2846 void spoolss_notify_port_name(int snum,
2847 SPOOL_NOTIFY_INFO_DATA *data,
2848 print_queue_struct *queue,
2849 NT_PRINTER_INFO_LEVEL *printer,
2850 TALLOC_CTX *mem_ctx)
2855 /* even if it's strange, that's consistant in all the code */
2857 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2859 data->notify_data.data.length = len;
2860 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2862 if (!data->notify_data.data.string) {
2863 data->notify_data.data.length = 0;
2867 memcpy(data->notify_data.data.string, temp, len);
2870 /*******************************************************************
2871 * fill a notify_info_data with the printername
2872 * but it doesn't exist, have to see what to do
2873 ********************************************************************/
2875 void spoolss_notify_driver_name(int snum,
2876 SPOOL_NOTIFY_INFO_DATA *data,
2877 print_queue_struct *queue,
2878 NT_PRINTER_INFO_LEVEL *printer,
2879 TALLOC_CTX *mem_ctx)
2884 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2886 data->notify_data.data.length = len;
2887 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2889 if (!data->notify_data.data.string) {
2890 data->notify_data.data.length = 0;
2894 memcpy(data->notify_data.data.string, temp, len);
2897 /*******************************************************************
2898 * fill a notify_info_data with the comment
2899 ********************************************************************/
2901 void spoolss_notify_comment(int snum,
2902 SPOOL_NOTIFY_INFO_DATA *data,
2903 print_queue_struct *queue,
2904 NT_PRINTER_INFO_LEVEL *printer,
2905 TALLOC_CTX *mem_ctx)
2910 if (*printer->info_2->comment == '\0')
2911 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2913 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2915 data->notify_data.data.length = len;
2916 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2918 if (!data->notify_data.data.string) {
2919 data->notify_data.data.length = 0;
2923 memcpy(data->notify_data.data.string, temp, len);
2926 /*******************************************************************
2927 * fill a notify_info_data with the comment
2928 * location = "Room 1, floor 2, building 3"
2929 ********************************************************************/
2931 void spoolss_notify_location(int snum,
2932 SPOOL_NOTIFY_INFO_DATA *data,
2933 print_queue_struct *queue,
2934 NT_PRINTER_INFO_LEVEL *printer,
2935 TALLOC_CTX *mem_ctx)
2940 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2942 data->notify_data.data.length = len;
2943 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2945 if (!data->notify_data.data.string) {
2946 data->notify_data.data.length = 0;
2950 memcpy(data->notify_data.data.string, temp, len);
2953 /*******************************************************************
2954 * fill a notify_info_data with the device mode
2955 * jfm:xxxx don't to it for know but that's a real problem !!!
2956 ********************************************************************/
2958 static void spoolss_notify_devmode(int snum,
2959 SPOOL_NOTIFY_INFO_DATA *data,
2960 print_queue_struct *queue,
2961 NT_PRINTER_INFO_LEVEL *printer,
2962 TALLOC_CTX *mem_ctx)
2966 /*******************************************************************
2967 * fill a notify_info_data with the separator file name
2968 ********************************************************************/
2970 void spoolss_notify_sepfile(int snum,
2971 SPOOL_NOTIFY_INFO_DATA *data,
2972 print_queue_struct *queue,
2973 NT_PRINTER_INFO_LEVEL *printer,
2974 TALLOC_CTX *mem_ctx)
2979 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2981 data->notify_data.data.length = len;
2982 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2984 if (!data->notify_data.data.string) {
2985 data->notify_data.data.length = 0;
2989 memcpy(data->notify_data.data.string, temp, len);
2992 /*******************************************************************
2993 * fill a notify_info_data with the print processor
2994 * jfm:xxxx return always winprint to indicate we don't do anything to it
2995 ********************************************************************/
2997 void spoolss_notify_print_processor(int snum,
2998 SPOOL_NOTIFY_INFO_DATA *data,
2999 print_queue_struct *queue,
3000 NT_PRINTER_INFO_LEVEL *printer,
3001 TALLOC_CTX *mem_ctx)
3006 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3008 data->notify_data.data.length = len;
3009 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3011 if (!data->notify_data.data.string) {
3012 data->notify_data.data.length = 0;
3016 memcpy(data->notify_data.data.string, temp, len);
3019 /*******************************************************************
3020 * fill a notify_info_data with the print processor options
3021 * jfm:xxxx send an empty string
3022 ********************************************************************/
3024 void spoolss_notify_parameters(int snum,
3025 SPOOL_NOTIFY_INFO_DATA *data,
3026 print_queue_struct *queue,
3027 NT_PRINTER_INFO_LEVEL *printer,
3028 TALLOC_CTX *mem_ctx)
3033 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3035 data->notify_data.data.length = len;
3036 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3038 if (!data->notify_data.data.string) {
3039 data->notify_data.data.length = 0;
3043 memcpy(data->notify_data.data.string, temp, len);
3046 /*******************************************************************
3047 * fill a notify_info_data with the data type
3048 * jfm:xxxx always send RAW as data type
3049 ********************************************************************/
3051 void spoolss_notify_datatype(int snum,
3052 SPOOL_NOTIFY_INFO_DATA *data,
3053 print_queue_struct *queue,
3054 NT_PRINTER_INFO_LEVEL *printer,
3055 TALLOC_CTX *mem_ctx)
3060 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3062 data->notify_data.data.length = len;
3063 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3065 if (!data->notify_data.data.string) {
3066 data->notify_data.data.length = 0;
3070 memcpy(data->notify_data.data.string, temp, len);
3073 /*******************************************************************
3074 * fill a notify_info_data with the security descriptor
3075 * jfm:xxxx send an null pointer to say no security desc
3076 * have to implement security before !
3077 ********************************************************************/
3079 static void spoolss_notify_security_desc(int snum,
3080 SPOOL_NOTIFY_INFO_DATA *data,
3081 print_queue_struct *queue,
3082 NT_PRINTER_INFO_LEVEL *printer,
3083 TALLOC_CTX *mem_ctx)
3085 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3086 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3089 /*******************************************************************
3090 * fill a notify_info_data with the attributes
3091 * jfm:xxxx a samba printer is always shared
3092 ********************************************************************/
3094 void spoolss_notify_attributes(int snum,
3095 SPOOL_NOTIFY_INFO_DATA *data,
3096 print_queue_struct *queue,
3097 NT_PRINTER_INFO_LEVEL *printer,
3098 TALLOC_CTX *mem_ctx)
3100 data->notify_data.value[0] = printer->info_2->attributes;
3101 data->notify_data.value[1] = 0;
3104 /*******************************************************************
3105 * fill a notify_info_data with the priority
3106 ********************************************************************/
3108 static void spoolss_notify_priority(int snum,
3109 SPOOL_NOTIFY_INFO_DATA *data,
3110 print_queue_struct *queue,
3111 NT_PRINTER_INFO_LEVEL *printer,
3112 TALLOC_CTX *mem_ctx)
3114 data->notify_data.value[0] = printer->info_2->priority;
3115 data->notify_data.value[1] = 0;
3118 /*******************************************************************
3119 * fill a notify_info_data with the default priority
3120 ********************************************************************/
3122 static void spoolss_notify_default_priority(int snum,
3123 SPOOL_NOTIFY_INFO_DATA *data,
3124 print_queue_struct *queue,
3125 NT_PRINTER_INFO_LEVEL *printer,
3126 TALLOC_CTX *mem_ctx)
3128 data->notify_data.value[0] = printer->info_2->default_priority;
3129 data->notify_data.value[1] = 0;
3132 /*******************************************************************
3133 * fill a notify_info_data with the start time
3134 ********************************************************************/
3136 static void spoolss_notify_start_time(int snum,
3137 SPOOL_NOTIFY_INFO_DATA *data,
3138 print_queue_struct *queue,
3139 NT_PRINTER_INFO_LEVEL *printer,
3140 TALLOC_CTX *mem_ctx)
3142 data->notify_data.value[0] = printer->info_2->starttime;
3143 data->notify_data.value[1] = 0;
3146 /*******************************************************************
3147 * fill a notify_info_data with the until time
3148 ********************************************************************/
3150 static void spoolss_notify_until_time(int snum,
3151 SPOOL_NOTIFY_INFO_DATA *data,
3152 print_queue_struct *queue,
3153 NT_PRINTER_INFO_LEVEL *printer,
3154 TALLOC_CTX *mem_ctx)
3156 data->notify_data.value[0] = printer->info_2->untiltime;
3157 data->notify_data.value[1] = 0;
3160 /*******************************************************************
3161 * fill a notify_info_data with the status
3162 ********************************************************************/
3164 static void spoolss_notify_status(int snum,
3165 SPOOL_NOTIFY_INFO_DATA *data,
3166 print_queue_struct *queue,
3167 NT_PRINTER_INFO_LEVEL *printer,
3168 TALLOC_CTX *mem_ctx)
3170 print_status_struct status;
3172 print_queue_length(snum, &status);
3173 data->notify_data.value[0]=(uint32) status.status;
3174 data->notify_data.value[1] = 0;
3177 /*******************************************************************
3178 * fill a notify_info_data with the number of jobs queued
3179 ********************************************************************/
3181 void spoolss_notify_cjobs(int snum,
3182 SPOOL_NOTIFY_INFO_DATA *data,
3183 print_queue_struct *queue,
3184 NT_PRINTER_INFO_LEVEL *printer,
3185 TALLOC_CTX *mem_ctx)
3187 data->notify_data.value[0] = print_queue_length(snum, NULL);
3188 data->notify_data.value[1] = 0;
3191 /*******************************************************************
3192 * fill a notify_info_data with the average ppm
3193 ********************************************************************/
3195 static void spoolss_notify_average_ppm(int snum,
3196 SPOOL_NOTIFY_INFO_DATA *data,
3197 print_queue_struct *queue,
3198 NT_PRINTER_INFO_LEVEL *printer,
3199 TALLOC_CTX *mem_ctx)
3201 /* always respond 8 pages per minutes */
3202 /* a little hard ! */
3203 data->notify_data.value[0] = printer->info_2->averageppm;
3204 data->notify_data.value[1] = 0;
3207 /*******************************************************************
3208 * fill a notify_info_data with username
3209 ********************************************************************/
3211 static void spoolss_notify_username(int snum,
3212 SPOOL_NOTIFY_INFO_DATA *data,
3213 print_queue_struct *queue,
3214 NT_PRINTER_INFO_LEVEL *printer,
3215 TALLOC_CTX *mem_ctx)
3220 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3222 data->notify_data.data.length = len;
3223 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3225 if (!data->notify_data.data.string) {
3226 data->notify_data.data.length = 0;
3230 memcpy(data->notify_data.data.string, temp, len);
3233 /*******************************************************************
3234 * fill a notify_info_data with job status
3235 ********************************************************************/
3237 static void spoolss_notify_job_status(int snum,
3238 SPOOL_NOTIFY_INFO_DATA *data,
3239 print_queue_struct *queue,
3240 NT_PRINTER_INFO_LEVEL *printer,
3241 TALLOC_CTX *mem_ctx)
3243 data->notify_data.value[0]=nt_printj_status(queue->status);
3244 data->notify_data.value[1] = 0;
3247 /*******************************************************************
3248 * fill a notify_info_data with job name
3249 ********************************************************************/
3251 static void spoolss_notify_job_name(int snum,
3252 SPOOL_NOTIFY_INFO_DATA *data,
3253 print_queue_struct *queue,
3254 NT_PRINTER_INFO_LEVEL *printer,
3255 TALLOC_CTX *mem_ctx)
3260 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3262 data->notify_data.data.length = len;
3263 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3265 if (!data->notify_data.data.string) {
3266 data->notify_data.data.length = 0;
3270 memcpy(data->notify_data.data.string, temp, len);
3273 /*******************************************************************
3274 * fill a notify_info_data with job status
3275 ********************************************************************/
3277 static void spoolss_notify_job_status_string(int snum,
3278 SPOOL_NOTIFY_INFO_DATA *data,
3279 print_queue_struct *queue,
3280 NT_PRINTER_INFO_LEVEL *printer,
3281 TALLOC_CTX *mem_ctx)
3284 * Now we're returning job status codes we just return a "" here. JRA.
3291 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3294 switch (queue->status) {
3299 p = ""; /* NT provides the paused string */
3308 #endif /* NO LONGER NEEDED. */
3310 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3312 data->notify_data.data.length = len;
3313 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3315 if (!data->notify_data.data.string) {
3316 data->notify_data.data.length = 0;
3320 memcpy(data->notify_data.data.string, temp, len);
3323 /*******************************************************************
3324 * fill a notify_info_data with job time
3325 ********************************************************************/
3327 static void spoolss_notify_job_time(int snum,
3328 SPOOL_NOTIFY_INFO_DATA *data,
3329 print_queue_struct *queue,
3330 NT_PRINTER_INFO_LEVEL *printer,
3331 TALLOC_CTX *mem_ctx)
3333 data->notify_data.value[0]=0x0;
3334 data->notify_data.value[1]=0;
3337 /*******************************************************************
3338 * fill a notify_info_data with job size
3339 ********************************************************************/
3341 static void spoolss_notify_job_size(int snum,
3342 SPOOL_NOTIFY_INFO_DATA *data,
3343 print_queue_struct *queue,
3344 NT_PRINTER_INFO_LEVEL *printer,
3345 TALLOC_CTX *mem_ctx)
3347 data->notify_data.value[0]=queue->size;
3348 data->notify_data.value[1]=0;
3351 /*******************************************************************
3352 * fill a notify_info_data with page info
3353 ********************************************************************/
3354 static void spoolss_notify_total_pages(int snum,
3355 SPOOL_NOTIFY_INFO_DATA *data,
3356 print_queue_struct *queue,
3357 NT_PRINTER_INFO_LEVEL *printer,
3358 TALLOC_CTX *mem_ctx)
3360 data->notify_data.value[0]=queue->page_count;
3361 data->notify_data.value[1]=0;
3364 /*******************************************************************
3365 * fill a notify_info_data with pages printed info.
3366 ********************************************************************/
3367 static void spoolss_notify_pages_printed(int snum,
3368 SPOOL_NOTIFY_INFO_DATA *data,
3369 print_queue_struct *queue,
3370 NT_PRINTER_INFO_LEVEL *printer,
3371 TALLOC_CTX *mem_ctx)
3373 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3374 data->notify_data.value[1]=0;
3377 /*******************************************************************
3378 Fill a notify_info_data with job position.
3379 ********************************************************************/
3381 static void spoolss_notify_job_position(int snum,
3382 SPOOL_NOTIFY_INFO_DATA *data,
3383 print_queue_struct *queue,
3384 NT_PRINTER_INFO_LEVEL *printer,
3385 TALLOC_CTX *mem_ctx)
3387 data->notify_data.value[0]=queue->job;
3388 data->notify_data.value[1]=0;
3391 /*******************************************************************
3392 Fill a notify_info_data with submitted time.
3393 ********************************************************************/
3395 static void spoolss_notify_submitted_time(int snum,
3396 SPOOL_NOTIFY_INFO_DATA *data,
3397 print_queue_struct *queue,
3398 NT_PRINTER_INFO_LEVEL *printer,
3399 TALLOC_CTX *mem_ctx)
3406 t=gmtime(&queue->time);
3408 len = sizeof(SYSTEMTIME);
3410 data->notify_data.data.length = len;
3411 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3413 if (!data->notify_data.data.string) {
3414 data->notify_data.data.length = 0;
3418 make_systemtime(&st, t);
3421 * Systemtime must be linearized as a set of UINT16's.
3422 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3425 p = (char *)data->notify_data.data.string;
3426 SSVAL(p, 0, st.year);
3427 SSVAL(p, 2, st.month);
3428 SSVAL(p, 4, st.dayofweek);
3429 SSVAL(p, 6, st.day);
3430 SSVAL(p, 8, st.hour);
3431 SSVAL(p, 10, st.minute);
3432 SSVAL(p, 12, st.second);
3433 SSVAL(p, 14, st.milliseconds);
3436 struct s_notify_info_data_table
3442 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3443 print_queue_struct *queue,
3444 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3447 /* A table describing the various print notification constants and
3448 whether the notification data is a pointer to a variable sized
3449 buffer, a one value uint32 or a two value uint32. */
3451 static const struct s_notify_info_data_table notify_info_data_table[] =
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3502 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3505 /*******************************************************************
3506 Return the size of info_data structure.
3507 ********************************************************************/
3509 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3513 for (i = 0; i < sizeof(notify_info_data_table); i++)
3515 if ( (notify_info_data_table[i].type == type)
3516 && (notify_info_data_table[i].field == field) )
3518 switch(notify_info_data_table[i].size)
3520 case NOTIFY_ONE_VALUE:
3521 case NOTIFY_TWO_VALUE:
3526 /* The only pointer notify data I have seen on
3527 the wire is the submitted time and this has
3528 the notify size set to 4. -tpot */
3530 case NOTIFY_POINTER:
3533 case NOTIFY_SECDESC:
3539 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3544 /*******************************************************************
3545 Return the type of notify_info_data.
3546 ********************************************************************/
3548 static int type_of_notify_info_data(uint16 type, uint16 field)
3552 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3553 if (notify_info_data_table[i].type == type &&
3554 notify_info_data_table[i].field == field)
3555 return notify_info_data_table[i].size;
3561 /****************************************************************************
3562 ****************************************************************************/
3564 static int search_notify(uint16 type, uint16 field, int *value)
3568 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3569 if (notify_info_data_table[i].type == type &&
3570 notify_info_data_table[i].field == field &&
3571 notify_info_data_table[i].fn != NULL) {
3580 /****************************************************************************
3581 ****************************************************************************/
3583 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3585 info_data->type = type;
3586 info_data->field = field;
3587 info_data->reserved = 0;
3589 info_data->size = size_of_notify_info_data(type, field);
3590 info_data->enc_type = type_of_notify_info_data(type, field);
3597 /*******************************************************************
3599 * fill a notify_info struct with info asked
3601 ********************************************************************/
3603 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3604 snum, SPOOL_NOTIFY_OPTION_TYPE
3605 *option_type, uint32 id,
3606 TALLOC_CTX *mem_ctx)
3612 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3613 NT_PRINTER_INFO_LEVEL *printer = NULL;
3614 print_queue_struct *queue=NULL;
3616 type=option_type->type;
3618 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3619 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3620 option_type->count, lp_servicename(snum)));
3622 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3625 for(field_num=0; field_num<option_type->count; field_num++) {
3626 field = option_type->fields[field_num];
3628 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3630 if (!search_notify(type, field, &j) )
3633 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3634 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3639 current_data = &info->data[info->count];
3641 construct_info_data(current_data, type, field, id);
3643 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3644 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3646 notify_info_data_table[j].fn(snum, current_data, queue,
3652 free_a_printer(&printer, 2);
3656 /*******************************************************************
3658 * fill a notify_info struct with info asked
3660 ********************************************************************/
3662 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3663 SPOOL_NOTIFY_INFO *info,
3664 NT_PRINTER_INFO_LEVEL *printer,
3665 int snum, SPOOL_NOTIFY_OPTION_TYPE
3666 *option_type, uint32 id,
3667 TALLOC_CTX *mem_ctx)
3673 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3675 DEBUG(4,("construct_notify_jobs_info\n"));
3677 type = option_type->type;
3679 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3680 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3681 option_type->count));
3683 for(field_num=0; field_num<option_type->count; field_num++) {
3684 field = option_type->fields[field_num];
3686 if (!search_notify(type, field, &j) )
3689 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3690 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3693 else info->data = tid;
3695 current_data=&(info->data[info->count]);
3697 construct_info_data(current_data, type, field, id);
3698 notify_info_data_table[j].fn(snum, current_data, queue,
3707 * JFM: The enumeration is not that simple, it's even non obvious.
3709 * let's take an example: I want to monitor the PRINTER SERVER for
3710 * the printer's name and the number of jobs currently queued.
3711 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3712 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3714 * I have 3 printers on the back of my server.
3716 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3719 * 1 printer 1 name 1
3720 * 2 printer 1 cjob 1
3721 * 3 printer 2 name 2
3722 * 4 printer 2 cjob 2
3723 * 5 printer 3 name 3
3724 * 6 printer 3 name 3
3726 * that's the print server case, the printer case is even worse.
3729 /*******************************************************************
3731 * enumerate all printers on the printserver
3732 * fill a notify_info struct with info asked
3734 ********************************************************************/
3736 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3737 SPOOL_NOTIFY_INFO *info,
3738 TALLOC_CTX *mem_ctx)
3741 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3742 int n_services=lp_numservices();
3744 SPOOL_NOTIFY_OPTION *option;
3745 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3747 DEBUG(4,("printserver_notify_info\n"));
3752 option=Printer->notify.option;
3757 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3758 sending a ffpcn() request first */
3763 for (i=0; i<option->count; i++) {
3764 option_type=&(option->ctr.type[i]);
3766 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3769 for (snum=0; snum<n_services; snum++)
3771 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3772 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3778 * Debugging information, don't delete.
3781 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3782 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3783 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3785 for (i=0; i<info->count; i++) {
3786 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3787 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3788 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3795 /*******************************************************************
3797 * fill a notify_info struct with info asked
3799 ********************************************************************/
3801 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3802 TALLOC_CTX *mem_ctx)
3805 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3808 SPOOL_NOTIFY_OPTION *option;
3809 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3811 print_queue_struct *queue=NULL;
3812 print_status_struct status;
3814 DEBUG(4,("printer_notify_info\n"));
3819 option=Printer->notify.option;
3825 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3826 sending a ffpcn() request first */
3831 get_printer_snum(p, hnd, &snum);
3833 for (i=0; i<option->count; i++) {
3834 option_type=&option->ctr.type[i];
3836 switch ( option_type->type ) {
3837 case PRINTER_NOTIFY_TYPE:
3838 if(construct_notify_printer_info(Printer, info, snum,
3844 case JOB_NOTIFY_TYPE: {
3845 NT_PRINTER_INFO_LEVEL *printer = NULL;
3847 count = print_queue_status(snum, &queue, &status);
3849 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3852 for (j=0; j<count; j++) {
3853 construct_notify_jobs_info(&queue[j], info,
3860 free_a_printer(&printer, 2);
3870 * Debugging information, don't delete.
3873 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3874 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3875 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3877 for (i=0; i<info->count; i++) {
3878 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3879 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3880 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3886 /********************************************************************
3888 ********************************************************************/
3890 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3892 POLICY_HND *handle = &q_u->handle;
3893 SPOOL_NOTIFY_INFO *info = &r_u->info;
3895 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3896 WERROR result = WERR_BADFID;
3898 /* we always have a NOTIFY_INFO struct */
3902 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3903 OUR_HANDLE(handle)));
3907 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3910 * We are now using the change value, and
3911 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3912 * I don't have a global notification system, I'm sending back all the
3913 * informations even when _NOTHING_ has changed.
3916 /* We need to keep track of the change value to send back in
3917 RRPCN replies otherwise our updates are ignored. */
3919 Printer->notify.fnpcn = True;
3921 if (Printer->notify.client_connected) {
3922 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3923 Printer->notify.change = q_u->change;
3926 /* just ignore the SPOOL_NOTIFY_OPTION */
3928 switch (Printer->printer_type) {
3929 case PRINTER_HANDLE_IS_PRINTSERVER:
3930 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3933 case PRINTER_HANDLE_IS_PRINTER:
3934 result = printer_notify_info(p, handle, info, p->mem_ctx);
3938 Printer->notify.fnpcn = False;
3944 /********************************************************************
3945 * construct_printer_info_0
3946 * fill a printer_info_0 struct
3947 ********************************************************************/
3949 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3953 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3954 counter_printer_0 *session_counter;
3955 uint32 global_counter;
3958 print_status_struct status;
3960 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3963 count = print_queue_length(snum, &status);
3965 /* check if we already have a counter for this printer */
3966 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3967 if (session_counter->snum == snum)
3971 /* it's the first time, add it to the list */
3972 if (session_counter==NULL) {
3973 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3974 free_a_printer(&ntprinter, 2);
3977 ZERO_STRUCTP(session_counter);
3978 session_counter->snum=snum;
3979 session_counter->counter=0;
3980 DLIST_ADD(counter_list, session_counter);
3984 session_counter->counter++;
3987 * the global_counter should be stored in a TDB as it's common to all the clients
3988 * and should be zeroed on samba startup
3990 global_counter=session_counter->counter;
3992 pstrcpy(chaine,ntprinter->info_2->printername);
3994 init_unistr(&printer->printername, chaine);
3996 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3997 init_unistr(&printer->servername, chaine);
3999 printer->cjobs = count;
4000 printer->total_jobs = 0;
4001 printer->total_bytes = 0;
4003 setuptime = (time_t)ntprinter->info_2->setuptime;
4004 t=gmtime(&setuptime);
4006 printer->year = t->tm_year+1900;
4007 printer->month = t->tm_mon+1;
4008 printer->dayofweek = t->tm_wday;
4009 printer->day = t->tm_mday;
4010 printer->hour = t->tm_hour;
4011 printer->minute = t->tm_min;
4012 printer->second = t->tm_sec;
4013 printer->milliseconds = 0;
4015 printer->global_counter = global_counter;
4016 printer->total_pages = 0;
4018 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4019 printer->major_version = 0x0005; /* NT 5 */
4020 printer->build_version = 0x0893; /* build 2195 */
4022 printer->unknown7 = 0x1;
4023 printer->unknown8 = 0x0;
4024 printer->unknown9 = 0x0;
4025 printer->session_counter = session_counter->counter;
4026 printer->unknown11 = 0x0;
4027 printer->printer_errors = 0x0; /* number of print failure */
4028 printer->unknown13 = 0x0;
4029 printer->unknown14 = 0x1;
4030 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4031 printer->unknown16 = 0x0;
4032 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4033 printer->unknown18 = 0x0;
4034 printer->status = nt_printq_status(status.status);
4035 printer->unknown20 = 0x0;
4036 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4037 printer->unknown22 = 0x0;
4038 printer->unknown23 = 0x6; /* 6 ???*/
4039 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4040 printer->unknown25 = 0;
4041 printer->unknown26 = 0;
4042 printer->unknown27 = 0;
4043 printer->unknown28 = 0;
4044 printer->unknown29 = 0;
4046 free_a_printer(&ntprinter,2);
4050 /********************************************************************
4051 * construct_printer_info_1
4052 * fill a printer_info_1 struct
4053 ********************************************************************/
4054 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4058 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4060 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4063 printer->flags=flags;
4065 if (*ntprinter->info_2->comment == '\0') {
4066 init_unistr(&printer->comment, lp_comment(snum));
4067 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4068 ntprinter->info_2->drivername, lp_comment(snum));
4071 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4072 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4073 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4076 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4078 init_unistr(&printer->description, chaine);
4079 init_unistr(&printer->name, chaine2);
4081 free_a_printer(&ntprinter,2);
4086 /****************************************************************************
4087 Free a DEVMODE struct.
4088 ****************************************************************************/
4090 static void free_dev_mode(DEVICEMODE *dev)
4095 SAFE_FREE(dev->private);
4100 /****************************************************************************
4101 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4102 should be valid upon entry
4103 ****************************************************************************/
4105 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4107 if ( !devmode || !ntdevmode )
4110 init_unistr(&devmode->devicename, ntdevmode->devicename);
4112 init_unistr(&devmode->formname, ntdevmode->formname);
4114 devmode->specversion = ntdevmode->specversion;
4115 devmode->driverversion = ntdevmode->driverversion;
4116 devmode->size = ntdevmode->size;
4117 devmode->driverextra = ntdevmode->driverextra;
4118 devmode->fields = ntdevmode->fields;
4120 devmode->orientation = ntdevmode->orientation;
4121 devmode->papersize = ntdevmode->papersize;
4122 devmode->paperlength = ntdevmode->paperlength;
4123 devmode->paperwidth = ntdevmode->paperwidth;
4124 devmode->scale = ntdevmode->scale;
4125 devmode->copies = ntdevmode->copies;
4126 devmode->defaultsource = ntdevmode->defaultsource;
4127 devmode->printquality = ntdevmode->printquality;
4128 devmode->color = ntdevmode->color;
4129 devmode->duplex = ntdevmode->duplex;
4130 devmode->yresolution = ntdevmode->yresolution;
4131 devmode->ttoption = ntdevmode->ttoption;
4132 devmode->collate = ntdevmode->collate;
4133 devmode->icmmethod = ntdevmode->icmmethod;
4134 devmode->icmintent = ntdevmode->icmintent;
4135 devmode->mediatype = ntdevmode->mediatype;
4136 devmode->dithertype = ntdevmode->dithertype;
4138 if (ntdevmode->private != NULL) {
4139 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4146 /****************************************************************************
4147 Create a DEVMODE struct. Returns malloced memory.
4148 ****************************************************************************/
4150 DEVICEMODE *construct_dev_mode(int snum)
4152 NT_PRINTER_INFO_LEVEL *printer = NULL;
4153 DEVICEMODE *devmode = NULL;
4155 DEBUG(7,("construct_dev_mode\n"));
4157 DEBUGADD(8,("getting printer characteristics\n"));
4159 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4162 if ( !printer->info_2->devmode ) {
4163 DEBUG(5, ("BONG! There was no device mode!\n"));
4167 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4168 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4172 ZERO_STRUCTP(devmode);
4174 DEBUGADD(8,("loading DEVICEMODE\n"));
4176 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4177 free_dev_mode( devmode );
4182 free_a_printer(&printer,2);
4187 /********************************************************************
4188 * construct_printer_info_2
4189 * fill a printer_info_2 struct
4190 ********************************************************************/
4192 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4195 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4197 print_status_struct status;
4199 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4202 count = print_queue_length(snum, &status);
4204 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4205 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4206 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4207 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4208 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4210 if (*ntprinter->info_2->comment == '\0')
4211 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4213 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4215 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4216 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4217 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4218 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4219 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4221 printer->attributes = ntprinter->info_2->attributes;
4223 printer->priority = ntprinter->info_2->priority; /* priority */
4224 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4225 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4226 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4227 printer->status = nt_printq_status(status.status); /* status */
4228 printer->cjobs = count; /* jobs */
4229 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4231 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4232 DEBUG(8, ("Returning NULL Devicemode!\n"));
4235 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4236 /* steal the printer info sec_desc structure. [badly done]. */
4237 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4238 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4239 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4240 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4243 printer->secdesc = NULL;
4246 free_a_printer(&ntprinter, 2);
4250 /********************************************************************
4251 * construct_printer_info_3
4252 * fill a printer_info_3 struct
4253 ********************************************************************/
4255 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4257 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4258 PRINTER_INFO_3 *printer = NULL;
4260 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4264 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4265 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4269 ZERO_STRUCTP(printer);
4271 printer->flags = 4; /* These are the components of the SD we are returning. */
4272 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4273 /* steal the printer info sec_desc structure. [badly done]. */
4274 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4278 * Set the flags for the components we are returning.
4281 if (printer->secdesc->owner_sid)
4282 printer->flags |= OWNER_SECURITY_INFORMATION;
4284 if (printer->secdesc->grp_sid)
4285 printer->flags |= GROUP_SECURITY_INFORMATION;
4287 if (printer->secdesc->dacl)
4288 printer->flags |= DACL_SECURITY_INFORMATION;
4290 if (printer->secdesc->sacl)
4291 printer->flags |= SACL_SECURITY_INFORMATION;
4294 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4295 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4296 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4299 free_a_printer(&ntprinter, 2);
4301 *pp_printer = printer;
4305 /********************************************************************
4306 * construct_printer_info_4
4307 * fill a printer_info_4 struct
4308 ********************************************************************/
4310 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4312 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4314 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4317 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4318 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4319 printer->attributes = ntprinter->info_2->attributes;
4321 free_a_printer(&ntprinter, 2);
4325 /********************************************************************
4326 * construct_printer_info_5
4327 * fill a printer_info_5 struct
4328 ********************************************************************/
4330 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4332 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4334 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4337 init_unistr(&printer->printername, ntprinter->info_2->printername);
4338 init_unistr(&printer->portname, ntprinter->info_2->portname);
4339 printer->attributes = ntprinter->info_2->attributes;
4341 /* these two are not used by NT+ according to MSDN */
4343 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4344 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4346 free_a_printer(&ntprinter, 2);
4351 /********************************************************************
4352 * construct_printer_info_7
4353 * fill a printer_info_7 struct
4354 ********************************************************************/
4356 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4358 char *guid_str = NULL;
4361 if (is_printer_published(print_hnd, snum, &guid)) {
4362 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4363 strupper_m(guid_str);
4364 init_unistr(&printer->guid, guid_str);
4365 printer->action = SPOOL_DS_PUBLISH;
4367 init_unistr(&printer->guid, "");
4368 printer->action = SPOOL_DS_UNPUBLISH;
4374 /********************************************************************
4375 Spoolss_enumprinters.
4376 ********************************************************************/
4378 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4382 int n_services=lp_numservices();
4383 PRINTER_INFO_1 *tp, *printers=NULL;
4384 PRINTER_INFO_1 current_prt;
4386 DEBUG(4,("enum_all_printers_info_1\n"));
4388 for (snum=0; snum<n_services; snum++) {
4389 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4390 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4392 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4393 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4394 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4395 SAFE_FREE(printers);
4400 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4402 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4408 /* check the required size. */
4409 for (i=0; i<*returned; i++)
4410 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4412 if (!alloc_buffer_size(buffer, *needed))
4413 return WERR_INSUFFICIENT_BUFFER;
4415 /* fill the buffer with the structures */
4416 for (i=0; i<*returned; i++)
4417 smb_io_printer_info_1("", buffer, &printers[i], 0);
4420 SAFE_FREE(printers);
4422 if (*needed > offered) {
4424 return WERR_INSUFFICIENT_BUFFER;
4430 /********************************************************************
4431 enum_all_printers_info_1_local.
4432 *********************************************************************/
4434 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4436 DEBUG(4,("enum_all_printers_info_1_local\n"));
4438 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4441 /********************************************************************
4442 enum_all_printers_info_1_name.
4443 *********************************************************************/
4445 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4449 DEBUG(4,("enum_all_printers_info_1_name\n"));
4451 if ((name[0] == '\\') && (name[1] == '\\'))
4454 if (is_myname_or_ipaddr(s)) {
4455 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4458 return WERR_INVALID_NAME;
4461 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4462 /********************************************************************
4463 enum_all_printers_info_1_remote.
4464 *********************************************************************/
4466 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4468 PRINTER_INFO_1 *printer;
4469 fstring printername;
4472 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4474 /* JFM: currently it's more a place holder than anything else.
4475 * In the spooler world there is a notion of server registration.
4476 * the print servers are registered on the PDC (in the same domain)
4478 * We should have a TDB here. The registration is done thru an
4479 * undocumented RPC call.
4482 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4487 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4488 slprintf(desc, sizeof(desc)-1,"%s", name);
4489 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4491 init_unistr(&printer->description, desc);
4492 init_unistr(&printer->name, printername);
4493 init_unistr(&printer->comment, comment);
4494 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4496 /* check the required size. */
4497 *needed += spoolss_size_printer_info_1(printer);
4499 if (!alloc_buffer_size(buffer, *needed)) {
4501 return WERR_INSUFFICIENT_BUFFER;
4504 /* fill the buffer with the structures */
4505 smb_io_printer_info_1("", buffer, printer, 0);
4510 if (*needed > offered) {
4512 return WERR_INSUFFICIENT_BUFFER;
4520 /********************************************************************
4521 enum_all_printers_info_1_network.
4522 *********************************************************************/
4524 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4528 DEBUG(4,("enum_all_printers_info_1_network\n"));
4530 /* If we respond to a enum_printers level 1 on our name with flags
4531 set to PRINTER_ENUM_REMOTE with a list of printers then these
4532 printers incorrectly appear in the APW browse list.
4533 Specifically the printers for the server appear at the workgroup
4534 level where all the other servers in the domain are
4535 listed. Windows responds to this call with a
4536 WERR_CAN_NOT_COMPLETE so we should do the same. */
4538 if (name[0] == '\\' && name[1] == '\\')
4541 if (is_myname_or_ipaddr(s))
4542 return WERR_CAN_NOT_COMPLETE;
4544 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4547 /********************************************************************
4548 * api_spoolss_enumprinters
4550 * called from api_spoolss_enumprinters (see this to understand)
4551 ********************************************************************/
4553 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4557 int n_services=lp_numservices();
4558 PRINTER_INFO_2 *tp, *printers=NULL;
4559 PRINTER_INFO_2 current_prt;
4561 for (snum=0; snum<n_services; snum++) {
4562 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4563 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4565 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4566 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) == NULL) {
4567 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4568 SAFE_FREE(printers);
4573 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4574 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4580 /* check the required size. */
4581 for (i=0; i<*returned; i++)
4582 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4584 if (!alloc_buffer_size(buffer, *needed)) {
4585 for (i=0; i<*returned; i++) {
4586 free_devmode(printers[i].devmode);
4588 SAFE_FREE(printers);
4589 return WERR_INSUFFICIENT_BUFFER;
4592 /* fill the buffer with the structures */
4593 for (i=0; i<*returned; i++)
4594 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4597 for (i=0; i<*returned; i++) {
4598 free_devmode(printers[i].devmode);
4600 SAFE_FREE(printers);
4602 if (*needed > offered) {
4604 return WERR_INSUFFICIENT_BUFFER;
4610 /********************************************************************
4611 * handle enumeration of printers at level 1
4612 ********************************************************************/
4614 static WERROR enumprinters_level1( uint32 flags, fstring name,
4615 NEW_BUFFER *buffer, uint32 offered,
4616 uint32 *needed, uint32 *returned)
4618 /* Not all the flags are equals */
4620 if (flags & PRINTER_ENUM_LOCAL)
4621 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4623 if (flags & PRINTER_ENUM_NAME)
4624 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4626 #if 0 /* JERRY - disabled for now */
4627 if (flags & PRINTER_ENUM_REMOTE)
4628 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4631 if (flags & PRINTER_ENUM_NETWORK)
4632 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4634 return WERR_OK; /* NT4sp5 does that */
4637 /********************************************************************
4638 * handle enumeration of printers at level 2
4639 ********************************************************************/
4641 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4642 NEW_BUFFER *buffer, uint32 offered,
4643 uint32 *needed, uint32 *returned)
4645 char *s = servername;
4647 if (flags & PRINTER_ENUM_LOCAL) {
4648 return enum_all_printers_info_2(buffer, offered, needed, returned);
4651 if (flags & PRINTER_ENUM_NAME) {
4652 if ((servername[0] == '\\') && (servername[1] == '\\'))
4654 if (is_myname_or_ipaddr(s))
4655 return enum_all_printers_info_2(buffer, offered, needed, returned);
4657 return WERR_INVALID_NAME;
4660 if (flags & PRINTER_ENUM_REMOTE)
4661 return WERR_UNKNOWN_LEVEL;
4666 /********************************************************************
4667 * handle enumeration of printers at level 5
4668 ********************************************************************/
4670 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4671 NEW_BUFFER *buffer, uint32 offered,
4672 uint32 *needed, uint32 *returned)
4674 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4678 /********************************************************************
4679 * api_spoolss_enumprinters
4681 * called from api_spoolss_enumprinters (see this to understand)
4682 ********************************************************************/
4684 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4686 uint32 flags = q_u->flags;
4687 UNISTR2 *servername = &q_u->servername;
4688 uint32 level = q_u->level;
4689 NEW_BUFFER *buffer = NULL;
4690 uint32 offered = q_u->offered;
4691 uint32 *needed = &r_u->needed;
4692 uint32 *returned = &r_u->returned;
4696 /* that's an [in out] buffer */
4697 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4698 buffer = r_u->buffer;
4700 DEBUG(4,("_spoolss_enumprinters\n"));
4707 * flags==PRINTER_ENUM_NAME
4708 * if name=="" then enumerates all printers
4709 * if name!="" then enumerate the printer
4710 * flags==PRINTER_ENUM_REMOTE
4711 * name is NULL, enumerate printers
4712 * Level 2: name!="" enumerates printers, name can't be NULL
4713 * Level 3: doesn't exist
4714 * Level 4: does a local registry lookup
4715 * Level 5: same as Level 2
4718 unistr2_to_ascii(name, servername, sizeof(name)-1);
4723 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4725 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4727 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4732 return WERR_UNKNOWN_LEVEL;
4735 /****************************************************************************
4736 ****************************************************************************/
4738 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4740 PRINTER_INFO_0 *printer=NULL;
4742 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4745 construct_printer_info_0(print_hnd, printer, snum);
4747 /* check the required size. */
4748 *needed += spoolss_size_printer_info_0(printer);
4750 if (!alloc_buffer_size(buffer, *needed)) {
4752 return WERR_INSUFFICIENT_BUFFER;
4755 /* fill the buffer with the structures */
4756 smb_io_printer_info_0("", buffer, printer, 0);
4761 if (*needed > offered) {
4762 return WERR_INSUFFICIENT_BUFFER;
4768 /****************************************************************************
4769 ****************************************************************************/
4771 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4773 PRINTER_INFO_1 *printer=NULL;
4775 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4778 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4780 /* check the required size. */
4781 *needed += spoolss_size_printer_info_1(printer);
4783 if (!alloc_buffer_size(buffer, *needed)) {
4785 return WERR_INSUFFICIENT_BUFFER;
4788 /* fill the buffer with the structures */
4789 smb_io_printer_info_1("", buffer, printer, 0);
4794 if (*needed > offered) {
4795 return WERR_INSUFFICIENT_BUFFER;
4801 /****************************************************************************
4802 ****************************************************************************/
4804 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4806 PRINTER_INFO_2 *printer=NULL;
4808 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4811 construct_printer_info_2(print_hnd, printer, snum);
4813 /* check the required size. */
4814 *needed += spoolss_size_printer_info_2(printer);
4816 if (!alloc_buffer_size(buffer, *needed)) {
4817 free_printer_info_2(printer);
4818 return WERR_INSUFFICIENT_BUFFER;
4821 /* fill the buffer with the structures */
4822 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4823 free_printer_info_2(printer);
4828 free_printer_info_2(printer);
4830 if (*needed > offered) {
4831 return WERR_INSUFFICIENT_BUFFER;
4837 /****************************************************************************
4838 ****************************************************************************/
4840 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4842 PRINTER_INFO_3 *printer=NULL;
4844 if (!construct_printer_info_3(print_hnd, &printer, snum))
4847 /* check the required size. */
4848 *needed += spoolss_size_printer_info_3(printer);
4850 if (!alloc_buffer_size(buffer, *needed)) {
4851 free_printer_info_3(printer);
4852 return WERR_INSUFFICIENT_BUFFER;
4855 /* fill the buffer with the structures */
4856 smb_io_printer_info_3("", buffer, printer, 0);
4859 free_printer_info_3(printer);
4861 if (*needed > offered) {
4862 return WERR_INSUFFICIENT_BUFFER;
4868 /****************************************************************************
4869 ****************************************************************************/
4871 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4873 PRINTER_INFO_4 *printer=NULL;
4875 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4878 if (!construct_printer_info_4(print_hnd, printer, snum))
4881 /* check the required size. */
4882 *needed += spoolss_size_printer_info_4(printer);
4884 if (!alloc_buffer_size(buffer, *needed)) {
4885 free_printer_info_4(printer);
4886 return WERR_INSUFFICIENT_BUFFER;
4889 /* fill the buffer with the structures */
4890 smb_io_printer_info_4("", buffer, printer, 0);
4893 free_printer_info_4(printer);
4895 if (*needed > offered) {
4896 return WERR_INSUFFICIENT_BUFFER;
4902 /****************************************************************************
4903 ****************************************************************************/
4905 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4907 PRINTER_INFO_5 *printer=NULL;
4909 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4912 if (!construct_printer_info_5(print_hnd, printer, snum))
4915 /* check the required size. */
4916 *needed += spoolss_size_printer_info_5(printer);
4918 if (!alloc_buffer_size(buffer, *needed)) {
4919 free_printer_info_5(printer);
4920 return WERR_INSUFFICIENT_BUFFER;
4923 /* fill the buffer with the structures */
4924 smb_io_printer_info_5("", buffer, printer, 0);
4927 free_printer_info_5(printer);
4929 if (*needed > offered) {
4930 return WERR_INSUFFICIENT_BUFFER;
4936 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4938 PRINTER_INFO_7 *printer=NULL;
4940 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4943 if (!construct_printer_info_7(print_hnd, printer, snum))
4946 /* check the required size. */
4947 *needed += spoolss_size_printer_info_7(printer);
4949 if (!alloc_buffer_size(buffer, *needed)) {
4950 free_printer_info_7(printer);
4951 return WERR_INSUFFICIENT_BUFFER;
4954 /* fill the buffer with the structures */
4955 smb_io_printer_info_7("", buffer, printer, 0);
4958 free_printer_info_7(printer);
4960 if (*needed > offered) {
4961 return WERR_INSUFFICIENT_BUFFER;
4967 /****************************************************************************
4968 ****************************************************************************/
4970 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4972 POLICY_HND *handle = &q_u->handle;
4973 uint32 level = q_u->level;
4974 NEW_BUFFER *buffer = NULL;
4975 uint32 offered = q_u->offered;
4976 uint32 *needed = &r_u->needed;
4977 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4981 /* that's an [in out] buffer */
4982 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4983 buffer = r_u->buffer;
4987 if (!get_printer_snum(p, handle, &snum))
4992 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4994 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4996 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4998 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5000 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5002 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5004 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5006 return WERR_UNKNOWN_LEVEL;
5009 /********************************************************************
5010 * fill a DRIVER_INFO_1 struct
5011 ********************************************************************/
5013 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5015 init_unistr( &info->name, driver.info_3->name);
5018 /********************************************************************
5019 * construct_printer_driver_info_1
5020 ********************************************************************/
5022 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5024 NT_PRINTER_INFO_LEVEL *printer = NULL;
5025 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5027 ZERO_STRUCT(driver);
5029 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5030 return WERR_INVALID_PRINTER_NAME;
5032 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5033 return WERR_UNKNOWN_PRINTER_DRIVER;
5035 fill_printer_driver_info_1(info, driver, servername, architecture);
5037 free_a_printer(&printer,2);
5042 /********************************************************************
5043 * construct_printer_driver_info_2
5044 * fill a printer_info_2 struct
5045 ********************************************************************/
5047 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5051 info->version=driver.info_3->cversion;
5053 init_unistr( &info->name, driver.info_3->name );
5054 init_unistr( &info->architecture, driver.info_3->environment );
5057 if (strlen(driver.info_3->driverpath)) {
5058 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5059 init_unistr( &info->driverpath, temp );
5061 init_unistr( &info->driverpath, "" );
5063 if (strlen(driver.info_3->datafile)) {
5064 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5065 init_unistr( &info->datafile, temp );
5067 init_unistr( &info->datafile, "" );
5069 if (strlen(driver.info_3->configfile)) {
5070 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5071 init_unistr( &info->configfile, temp );
5073 init_unistr( &info->configfile, "" );
5076 /********************************************************************
5077 * construct_printer_driver_info_2
5078 * fill a printer_info_2 struct
5079 ********************************************************************/
5081 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5083 NT_PRINTER_INFO_LEVEL *printer = NULL;
5084 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5086 ZERO_STRUCT(printer);
5087 ZERO_STRUCT(driver);
5089 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5090 return WERR_INVALID_PRINTER_NAME;
5092 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5093 return WERR_UNKNOWN_PRINTER_DRIVER;
5095 fill_printer_driver_info_2(info, driver, servername);
5097 free_a_printer(&printer,2);
5102 /********************************************************************
5103 * copy a strings array and convert to UNICODE
5105 * convert an array of ascii string to a UNICODE string
5106 ********************************************************************/
5108 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5116 DEBUG(6,("init_unistr_array\n"));
5127 v = ""; /* hack to handle null lists */
5130 /* hack to allow this to be used in places other than when generating
5131 the list of dependent files */
5134 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5138 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5140 /* add one extra unit16 for the second terminating NULL */
5142 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5143 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5151 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5156 /* special case for ""; we need to add both NULL's here */
5158 (*uni_array)[j++]=0x0000;
5159 (*uni_array)[j]=0x0000;
5162 DEBUGADD(6,("last one:done\n"));
5164 /* return size of array in uint16's */
5169 /********************************************************************
5170 * construct_printer_info_3
5171 * fill a printer_info_3 struct
5172 ********************************************************************/
5174 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5180 info->version=driver.info_3->cversion;
5182 init_unistr( &info->name, driver.info_3->name );
5183 init_unistr( &info->architecture, driver.info_3->environment );
5185 if (strlen(driver.info_3->driverpath)) {
5186 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5187 init_unistr( &info->driverpath, temp );
5189 init_unistr( &info->driverpath, "" );
5191 if (strlen(driver.info_3->datafile)) {
5192 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5193 init_unistr( &info->datafile, temp );
5195 init_unistr( &info->datafile, "" );
5197 if (strlen(driver.info_3->configfile)) {
5198 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5199 init_unistr( &info->configfile, temp );
5201 init_unistr( &info->configfile, "" );
5203 if (strlen(driver.info_3->helpfile)) {
5204 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5205 init_unistr( &info->helpfile, temp );
5207 init_unistr( &info->helpfile, "" );
5209 init_unistr( &info->monitorname, driver.info_3->monitorname );
5210 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5212 info->dependentfiles=NULL;
5213 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5216 /********************************************************************
5217 * construct_printer_info_3
5218 * fill a printer_info_3 struct
5219 ********************************************************************/
5221 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5223 NT_PRINTER_INFO_LEVEL *printer = NULL;
5224 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5226 ZERO_STRUCT(driver);
5228 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5229 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5230 if (!W_ERROR_IS_OK(status))
5231 return WERR_INVALID_PRINTER_NAME;
5233 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5234 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5239 * I put this code in during testing. Helpful when commenting out the
5240 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5241 * as win2k always queries the driver using an infor level of 6.
5242 * I've left it in (but ifdef'd out) because I'll probably
5243 * use it in experimentation again in the future. --jerry 22/01/2002
5246 if (!W_ERROR_IS_OK(status)) {
5248 * Is this a W2k client ?
5251 /* Yes - try again with a WinNT driver. */
5253 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5254 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5258 if (!W_ERROR_IS_OK(status)) {
5259 free_a_printer(&printer,2);
5260 return WERR_UNKNOWN_PRINTER_DRIVER;
5268 fill_printer_driver_info_3(info, driver, servername);
5270 free_a_printer(&printer,2);
5275 /********************************************************************
5276 * construct_printer_info_6
5277 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5278 ********************************************************************/
5280 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5286 memset(&nullstr, '\0', sizeof(fstring));
5288 info->version=driver.info_3->cversion;
5290 init_unistr( &info->name, driver.info_3->name );
5291 init_unistr( &info->architecture, driver.info_3->environment );
5293 if (strlen(driver.info_3->driverpath)) {
5294 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5295 init_unistr( &info->driverpath, temp );
5297 init_unistr( &info->driverpath, "" );
5299 if (strlen(driver.info_3->datafile)) {
5300 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5301 init_unistr( &info->datafile, temp );
5303 init_unistr( &info->datafile, "" );
5305 if (strlen(driver.info_3->configfile)) {
5306 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5307 init_unistr( &info->configfile, temp );
5309 init_unistr( &info->configfile, "" );
5311 if (strlen(driver.info_3->helpfile)) {
5312 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5313 init_unistr( &info->helpfile, temp );
5315 init_unistr( &info->helpfile, "" );
5317 init_unistr( &info->monitorname, driver.info_3->monitorname );
5318 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5320 info->dependentfiles = NULL;
5321 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5323 info->previousdrivernames=NULL;
5324 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5326 info->driver_date.low=0;
5327 info->driver_date.high=0;
5330 info->driver_version_low=0;
5331 info->driver_version_high=0;
5333 init_unistr( &info->mfgname, "");
5334 init_unistr( &info->oem_url, "");
5335 init_unistr( &info->hardware_id, "");
5336 init_unistr( &info->provider, "");
5339 /********************************************************************
5340 * construct_printer_info_6
5341 * fill a printer_info_6 struct
5342 ********************************************************************/
5344 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5345 fstring servername, fstring architecture, uint32 version)
5347 NT_PRINTER_INFO_LEVEL *printer = NULL;
5348 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5351 ZERO_STRUCT(driver);
5353 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5355 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5357 if (!W_ERROR_IS_OK(status))
5358 return WERR_INVALID_PRINTER_NAME;
5360 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5362 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5364 if (!W_ERROR_IS_OK(status))
5367 * Is this a W2k client ?
5371 free_a_printer(&printer,2);
5372 return WERR_UNKNOWN_PRINTER_DRIVER;
5375 /* Yes - try again with a WinNT driver. */
5377 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5378 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5379 if (!W_ERROR_IS_OK(status)) {
5380 free_a_printer(&printer,2);
5381 return WERR_UNKNOWN_PRINTER_DRIVER;
5385 fill_printer_driver_info_6(info, driver, servername);
5387 free_a_printer(&printer,2);
5388 free_a_printer_driver(driver, 3);
5393 /****************************************************************************
5394 ****************************************************************************/
5396 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5398 SAFE_FREE(info->dependentfiles);
5401 /****************************************************************************
5402 ****************************************************************************/
5404 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5406 SAFE_FREE(info->dependentfiles);
5410 /****************************************************************************
5411 ****************************************************************************/
5413 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5415 DRIVER_INFO_1 *info=NULL;
5418 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5421 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5422 if (!W_ERROR_IS_OK(status)) {
5427 /* check the required size. */
5428 *needed += spoolss_size_printer_driver_info_1(info);
5430 if (!alloc_buffer_size(buffer, *needed)) {
5432 return WERR_INSUFFICIENT_BUFFER;
5435 /* fill the buffer with the structures */
5436 smb_io_printer_driver_info_1("", buffer, info, 0);
5441 if (*needed > offered)
5442 return WERR_INSUFFICIENT_BUFFER;
5447 /****************************************************************************
5448 ****************************************************************************/
5450 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5452 DRIVER_INFO_2 *info=NULL;
5455 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5458 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5459 if (!W_ERROR_IS_OK(status)) {
5464 /* check the required size. */
5465 *needed += spoolss_size_printer_driver_info_2(info);
5467 if (!alloc_buffer_size(buffer, *needed)) {
5469 return WERR_INSUFFICIENT_BUFFER;
5472 /* fill the buffer with the structures */
5473 smb_io_printer_driver_info_2("", buffer, info, 0);
5478 if (*needed > offered)
5479 return WERR_INSUFFICIENT_BUFFER;
5484 /****************************************************************************
5485 ****************************************************************************/
5487 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5494 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5495 if (!W_ERROR_IS_OK(status)) {
5499 /* check the required size. */
5500 *needed += spoolss_size_printer_driver_info_3(&info);
5502 if (!alloc_buffer_size(buffer, *needed)) {
5503 free_printer_driver_info_3(&info);
5504 return WERR_INSUFFICIENT_BUFFER;
5507 /* fill the buffer with the structures */
5508 smb_io_printer_driver_info_3("", buffer, &info, 0);
5510 free_printer_driver_info_3(&info);
5512 if (*needed > offered)
5513 return WERR_INSUFFICIENT_BUFFER;
5518 /****************************************************************************
5519 ****************************************************************************/
5521 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5528 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5529 if (!W_ERROR_IS_OK(status)) {
5533 /* check the required size. */
5534 *needed += spoolss_size_printer_driver_info_6(&info);
5536 if (!alloc_buffer_size(buffer, *needed)) {
5537 free_printer_driver_info_6(&info);
5538 return WERR_INSUFFICIENT_BUFFER;
5541 /* fill the buffer with the structures */
5542 smb_io_printer_driver_info_6("", buffer, &info, 0);
5544 free_printer_driver_info_6(&info);
5546 if (*needed > offered)
5547 return WERR_INSUFFICIENT_BUFFER;
5552 /****************************************************************************
5553 ****************************************************************************/
5555 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5557 POLICY_HND *handle = &q_u->handle;
5558 UNISTR2 *uni_arch = &q_u->architecture;
5559 uint32 level = q_u->level;
5560 uint32 clientmajorversion = q_u->clientmajorversion;
5561 NEW_BUFFER *buffer = NULL;
5562 uint32 offered = q_u->offered;
5563 uint32 *needed = &r_u->needed;
5564 uint32 *servermajorversion = &r_u->servermajorversion;
5565 uint32 *serverminorversion = &r_u->serverminorversion;
5566 Printer_entry *printer;
5569 fstring architecture;
5572 /* that's an [in out] buffer */
5573 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5574 buffer = r_u->buffer;
5576 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5578 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5579 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5580 return WERR_INVALID_PRINTER_NAME;
5584 *servermajorversion = 0;
5585 *serverminorversion = 0;
5587 fstrcpy(servername, get_server_name( printer ));
5588 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5590 if (!get_printer_snum(p, handle, &snum))
5595 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5597 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5599 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5601 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5604 /* apparently this call is the equivalent of
5605 EnumPrinterDataEx() for the DsDriver key */
5610 return WERR_UNKNOWN_LEVEL;
5613 /****************************************************************************
5614 ****************************************************************************/
5616 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5618 POLICY_HND *handle = &q_u->handle;
5620 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5623 DEBUG(3,("Error in startpageprinter printer handle\n"));
5627 Printer->page_started=True;
5631 /****************************************************************************
5632 ****************************************************************************/
5634 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5636 POLICY_HND *handle = &q_u->handle;
5639 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5642 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5646 if (!get_printer_snum(p, handle, &snum))
5649 Printer->page_started=False;
5650 print_job_endpage(snum, Printer->jobid);
5655 /********************************************************************
5656 * api_spoolss_getprinter
5657 * called from the spoolss dispatcher
5659 ********************************************************************/
5661 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5663 POLICY_HND *handle = &q_u->handle;
5664 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5665 uint32 *jobid = &r_u->jobid;
5667 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5671 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5672 struct current_user user;
5675 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5679 get_current_user(&user, p);
5682 * a nice thing with NT is it doesn't listen to what you tell it.
5683 * when asked to send _only_ RAW datas, it tries to send datas
5686 * So I add checks like in NT Server ...
5689 if (info_1->p_datatype != 0) {
5690 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5691 if (strcmp(datatype, "RAW") != 0) {
5693 return WERR_INVALID_DATATYPE;
5697 /* get the share number of the printer */
5698 if (!get_printer_snum(p, handle, &snum)) {
5702 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5704 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5706 /* An error occured in print_job_start() so return an appropriate
5709 if (Printer->jobid == -1) {
5710 return map_werror_from_unix(errno);
5713 Printer->document_started=True;
5714 (*jobid) = Printer->jobid;
5719 /********************************************************************
5720 * api_spoolss_getprinter
5721 * called from the spoolss dispatcher
5723 ********************************************************************/
5725 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5727 POLICY_HND *handle = &q_u->handle;
5729 return _spoolss_enddocprinter_internal(p, handle);
5732 /****************************************************************************
5733 ****************************************************************************/
5735 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5737 POLICY_HND *handle = &q_u->handle;
5738 uint32 buffer_size = q_u->buffer_size;
5739 uint8 *buffer = q_u->buffer;
5740 uint32 *buffer_written = &q_u->buffer_size2;
5742 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5745 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5746 r_u->buffer_written = q_u->buffer_size2;
5750 if (!get_printer_snum(p, handle, &snum))
5753 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5754 if (*buffer_written == -1) {
5755 r_u->buffer_written = 0;
5756 if (errno == ENOSPC)
5757 return WERR_NO_SPOOL_SPACE;
5759 return WERR_ACCESS_DENIED;
5762 r_u->buffer_written = q_u->buffer_size2;
5767 /********************************************************************
5768 * api_spoolss_getprinter
5769 * called from the spoolss dispatcher
5771 ********************************************************************/
5773 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5776 struct current_user user;
5778 WERROR errcode = WERR_BADFUNC;
5779 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5781 get_current_user(&user, p);
5784 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5788 if (!get_printer_snum(p, handle, &snum))
5792 case PRINTER_CONTROL_PAUSE:
5793 if (print_queue_pause(&user, snum, &errcode)) {
5797 case PRINTER_CONTROL_RESUME:
5798 case PRINTER_CONTROL_UNPAUSE:
5799 if (print_queue_resume(&user, snum, &errcode)) {
5803 case PRINTER_CONTROL_PURGE:
5804 if (print_queue_purge(&user, snum, &errcode)) {
5809 return WERR_UNKNOWN_LEVEL;
5815 /********************************************************************
5816 * api_spoolss_abortprinter
5817 * From MSDN: "Deletes printer's spool file if printer is configured
5819 ********************************************************************/
5821 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5823 POLICY_HND *handle = &q_u->handle;
5824 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5826 struct current_user user;
5827 WERROR errcode = WERR_OK;
5830 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5834 if (!get_printer_snum(p, handle, &snum))
5837 get_current_user( &user, p );
5839 print_job_delete( &user, snum, Printer->jobid, &errcode );
5844 /********************************************************************
5845 * called by spoolss_api_setprinter
5846 * when updating a printer description
5847 ********************************************************************/
5849 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5850 const SPOOL_PRINTER_INFO_LEVEL *info,
5851 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5853 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5857 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5859 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5860 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5861 OUR_HANDLE(handle)));
5863 result = WERR_BADFID;
5867 /* Check the user has permissions to change the security
5868 descriptor. By experimentation with two NT machines, the user
5869 requires Full Access to the printer to change security
5872 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5873 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5874 result = WERR_ACCESS_DENIED;
5878 /* NT seems to like setting the security descriptor even though
5879 nothing may have actually changed. */
5881 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5883 if (DEBUGLEVEL >= 10) {
5887 the_acl = old_secdesc_ctr->sec->dacl;
5888 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5889 PRINTERNAME(snum), the_acl->num_aces));
5891 for (i = 0; i < the_acl->num_aces; i++) {
5894 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5896 DEBUG(10, ("%s 0x%08x\n", sid_str,
5897 the_acl->ace[i].info.mask));
5900 the_acl = secdesc_ctr->sec->dacl;
5903 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5904 PRINTERNAME(snum), the_acl->num_aces));
5906 for (i = 0; i < the_acl->num_aces; i++) {
5909 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5911 DEBUG(10, ("%s 0x%08x\n", sid_str,
5912 the_acl->ace[i].info.mask));
5915 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5919 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5921 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5926 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5933 /********************************************************************
5934 Canonicalize printer info from a client
5936 ATTN: It does not matter what we set the servername to hear
5937 since we do the necessary work in get_a_printer() to set it to
5938 the correct value based on what the client sent in the
5939 _spoolss_open_printer_ex().
5940 ********************************************************************/
5942 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5944 fstring printername;
5947 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5948 "portname=%s drivername=%s comment=%s location=%s\n",
5949 info->servername, info->printername, info->sharename,
5950 info->portname, info->drivername, info->comment, info->location));
5952 /* we force some elements to "correct" values */
5953 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5954 fstrcpy(info->sharename, lp_servicename(snum));
5956 /* check to see if we allow printername != sharename */
5958 if ( lp_force_printername(snum) ) {
5959 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5960 global_myname(), info->sharename );
5963 /* make sure printername is in \\server\printername format */
5965 fstrcpy( printername, info->printername );
5967 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5968 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5972 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5973 global_myname(), p );
5976 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5977 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5984 /****************************************************************************
5985 ****************************************************************************/
5987 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5989 extern userdom_struct current_user_info;
5990 char *cmd = lp_addprinter_cmd();
5996 fstring remote_machine = "%m";
5998 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6000 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6001 cmd, printer->info_2->printername, printer->info_2->sharename,
6002 printer->info_2->portname, printer->info_2->drivername,
6003 printer->info_2->location, printer->info_2->comment, remote_machine);
6005 DEBUG(10,("Running [%s]\n", command));
6006 ret = smbrun(command, &fd);
6007 DEBUGADD(10,("returned [%d]\n", ret));
6016 /* Get lines and convert them back to dos-codepage */
6017 qlines = fd_lines_load(fd, &numlines);
6018 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6022 /* Set the portname to what the script says the portname should be. */
6023 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6024 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6026 /* Send SIGHUP to process group... is there a better way? */
6029 /* reload our services immediately */
6030 reload_services( False );
6033 file_lines_free(qlines);
6037 /********************************************************************
6038 * Called by spoolss_api_setprinter
6039 * when updating a printer description.
6040 ********************************************************************/
6042 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6043 const SPOOL_PRINTER_INFO_LEVEL *info,
6044 DEVICEMODE *devmode)
6047 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6048 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6053 DEBUG(8,("update_printer\n"));
6058 result = WERR_BADFID;
6062 if (!get_printer_snum(p, handle, &snum)) {
6063 result = WERR_BADFID;
6067 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6068 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6069 result = WERR_BADFID;
6073 DEBUGADD(8,("Converting info_2 struct\n"));
6076 * convert_printer_info converts the incoming
6077 * info from the client and overwrites the info
6078 * just read from the tdb in the pointer 'printer'.
6081 if (!convert_printer_info(info, printer, level)) {
6082 result = WERR_NOMEM;
6087 /* we have a valid devmode
6088 convert it and link it*/
6090 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6091 if (!convert_devicemode(printer->info_2->printername, devmode,
6092 &printer->info_2->devmode)) {
6093 result = WERR_NOMEM;
6098 /* Do sanity check on the requested changes for Samba */
6100 if (!check_printer_ok(printer->info_2, snum)) {
6101 result = WERR_INVALID_PARAM;
6105 /* FIXME!!! If the driver has changed we really should verify that
6106 it is installed before doing much else --jerry */
6108 /* Check calling user has permission to update printer description */
6110 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6111 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6112 result = WERR_ACCESS_DENIED;
6116 /* Call addprinter hook */
6117 /* Check changes to see if this is really needed */
6119 if ( *lp_addprinter_cmd()
6120 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6121 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6122 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6123 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6125 if ( !add_printer_hook(printer) ) {
6126 result = WERR_ACCESS_DENIED;
6131 * make sure we actually reload the services after
6132 * this as smb.conf could have a new section in it
6133 * .... shouldn't .... but could
6135 reload_services(False);
6139 * When a *new* driver is bound to a printer, the drivername is used to
6140 * lookup previously saved driver initialization info, which is then
6141 * bound to the printer, simulating what happens in the Windows arch.
6143 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6145 if (!set_driver_init(printer, 2))
6147 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6148 printer->info_2->drivername));
6151 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6152 printer->info_2->drivername));
6154 notify_printer_driver(snum, printer->info_2->drivername);
6158 * flag which changes actually occured. This is a small subset of
6159 * all the possible changes. We also have to update things in the
6163 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6164 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6165 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6166 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6168 notify_printer_comment(snum, printer->info_2->comment);
6171 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6172 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6173 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6174 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6176 notify_printer_sharename(snum, printer->info_2->sharename);
6179 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6182 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6185 pname = printer->info_2->printername;
6188 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6189 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6190 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6192 notify_printer_printername( snum, pname );
6195 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6196 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6197 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6198 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6200 notify_printer_port(snum, printer->info_2->portname);
6203 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6204 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6205 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6206 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6208 notify_printer_location(snum, printer->info_2->location);
6211 /* here we need to update some more DsSpooler keys */
6212 /* uNCName, serverName, shortServerName */
6214 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6215 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6216 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6217 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6218 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6220 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6221 global_myname(), printer->info_2->sharename );
6222 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6223 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6224 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6226 /* Update printer info */
6227 result = mod_a_printer(printer, 2);
6230 free_a_printer(&printer, 2);
6231 free_a_printer(&old_printer, 2);
6237 /****************************************************************************
6238 ****************************************************************************/
6239 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6240 const SPOOL_PRINTER_INFO_LEVEL *info)
6243 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6245 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6247 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6252 if (!get_printer_snum(p, handle, &snum))
6255 nt_printer_publish(Printer, snum, info7->action);
6259 return WERR_UNKNOWN_LEVEL;
6262 /****************************************************************************
6263 ****************************************************************************/
6265 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6267 POLICY_HND *handle = &q_u->handle;
6268 uint32 level = q_u->level;
6269 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6270 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6271 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6272 uint32 command = q_u->command;
6275 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6278 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6282 /* check the level */
6285 return control_printer(handle, command, p);
6287 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6288 if (!W_ERROR_IS_OK(result))
6291 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6294 return update_printer_sec(handle, level, info, p,
6297 return publish_or_unpublish_printer(p, handle, info);
6299 return WERR_UNKNOWN_LEVEL;
6303 /****************************************************************************
6304 ****************************************************************************/
6306 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6308 POLICY_HND *handle = &q_u->handle;
6309 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6312 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6316 if (Printer->notify.client_connected==True) {
6319 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6321 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6322 !get_printer_snum(p, handle, &snum) )
6325 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6328 Printer->notify.flags=0;
6329 Printer->notify.options=0;
6330 Printer->notify.localmachine[0]='\0';
6331 Printer->notify.printerlocal=0;
6332 if (Printer->notify.option)
6333 free_spool_notify_option(&Printer->notify.option);
6334 Printer->notify.client_connected=False;
6339 /****************************************************************************
6340 ****************************************************************************/
6342 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6344 /* that's an [in out] buffer (despite appearences to the contrary) */
6345 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6348 return WERR_INVALID_PARAM; /* this is what a NT server
6349 returns for AddJob. AddJob
6350 must fail on non-local
6354 /****************************************************************************
6355 ****************************************************************************/
6357 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6358 int position, int snum,
6359 NT_PRINTER_INFO_LEVEL *ntprinter)
6363 t=gmtime(&queue->time);
6365 job_info->jobid=queue->job;
6366 init_unistr(&job_info->printername, lp_servicename(snum));
6367 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6368 init_unistr(&job_info->username, queue->fs_user);
6369 init_unistr(&job_info->document, queue->fs_file);
6370 init_unistr(&job_info->datatype, "RAW");
6371 init_unistr(&job_info->text_status, "");
6372 job_info->status=nt_printj_status(queue->status);
6373 job_info->priority=queue->priority;
6374 job_info->position=position;
6375 job_info->totalpages=queue->page_count;
6376 job_info->pagesprinted=0;
6378 make_systemtime(&job_info->submitted, t);
6381 /****************************************************************************
6382 ****************************************************************************/
6384 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6385 int position, int snum,
6386 NT_PRINTER_INFO_LEVEL *ntprinter,
6387 DEVICEMODE *devmode)
6391 t=gmtime(&queue->time);
6393 job_info->jobid=queue->job;
6395 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6397 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6398 init_unistr(&job_info->username, queue->fs_user);
6399 init_unistr(&job_info->document, queue->fs_file);
6400 init_unistr(&job_info->notifyname, queue->fs_user);
6401 init_unistr(&job_info->datatype, "RAW");
6402 init_unistr(&job_info->printprocessor, "winprint");
6403 init_unistr(&job_info->parameters, "");
6404 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6405 init_unistr(&job_info->text_status, "");
6407 /* and here the security descriptor */
6409 job_info->status=nt_printj_status(queue->status);
6410 job_info->priority=queue->priority;
6411 job_info->position=position;
6412 job_info->starttime=0;
6413 job_info->untiltime=0;
6414 job_info->totalpages=queue->page_count;
6415 job_info->size=queue->size;
6416 make_systemtime(&(job_info->submitted), t);
6417 job_info->timeelapsed=0;
6418 job_info->pagesprinted=0;
6420 job_info->devmode = devmode;
6425 /****************************************************************************
6426 Enumjobs at level 1.
6427 ****************************************************************************/
6429 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6430 NT_PRINTER_INFO_LEVEL *ntprinter,
6431 NEW_BUFFER *buffer, uint32 offered,
6432 uint32 *needed, uint32 *returned)
6437 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6444 for (i=0; i<*returned; i++)
6445 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6449 /* check the required size. */
6450 for (i=0; i<*returned; i++)
6451 (*needed) += spoolss_size_job_info_1(&info[i]);
6453 if (!alloc_buffer_size(buffer, *needed)) {
6455 return WERR_INSUFFICIENT_BUFFER;
6458 /* fill the buffer with the structures */
6459 for (i=0; i<*returned; i++)
6460 smb_io_job_info_1("", buffer, &info[i], 0);
6465 if (*needed > offered) {
6467 return WERR_INSUFFICIENT_BUFFER;
6473 /****************************************************************************
6474 Enumjobs at level 2.
6475 ****************************************************************************/
6477 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6478 NT_PRINTER_INFO_LEVEL *ntprinter,
6479 NEW_BUFFER *buffer, uint32 offered,
6480 uint32 *needed, uint32 *returned)
6482 JOB_INFO_2 *info = NULL;
6485 DEVICEMODE *devmode = NULL;
6487 info=SMB_MALLOC_ARRAY(JOB_INFO_2,*returned);
6490 result = WERR_NOMEM;
6494 /* this should not be a failure condition if the devmode is NULL */
6496 devmode = construct_dev_mode(snum);
6498 for (i=0; i<*returned; i++)
6499 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6502 free_a_printer(&ntprinter, 2);
6505 /* check the required size. */
6506 for (i=0; i<*returned; i++)
6507 (*needed) += spoolss_size_job_info_2(&info[i]);
6509 if (*needed > offered) {
6511 result = WERR_INSUFFICIENT_BUFFER;
6515 if (!alloc_buffer_size(buffer, *needed)) {
6517 result = WERR_INSUFFICIENT_BUFFER;
6521 /* fill the buffer with the structures */
6522 for (i=0; i<*returned; i++)
6523 smb_io_job_info_2("", buffer, &info[i], 0);
6528 free_a_printer(&ntprinter, 2);
6529 free_devmode(devmode);
6537 /****************************************************************************
6539 ****************************************************************************/
6541 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6543 POLICY_HND *handle = &q_u->handle;
6544 uint32 level = q_u->level;
6545 NEW_BUFFER *buffer = NULL;
6546 uint32 offered = q_u->offered;
6547 uint32 *needed = &r_u->needed;
6548 uint32 *returned = &r_u->returned;
6550 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6552 print_status_struct prt_status;
6553 print_queue_struct *queue=NULL;
6555 /* that's an [in out] buffer */
6556 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6557 buffer = r_u->buffer;
6559 DEBUG(4,("_spoolss_enumjobs\n"));
6564 /* lookup the printer snum and tdb entry */
6566 if (!get_printer_snum(p, handle, &snum))
6569 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6570 if ( !W_ERROR_IS_OK(wret) )
6573 *returned = print_queue_status(snum, &queue, &prt_status);
6574 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6576 if (*returned == 0) {
6583 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6586 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6591 wret = WERR_UNKNOWN_LEVEL;
6594 free_a_printer( &ntprinter, 2 );
6598 /****************************************************************************
6599 ****************************************************************************/
6601 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6606 /****************************************************************************
6607 ****************************************************************************/
6609 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6611 POLICY_HND *handle = &q_u->handle;
6612 uint32 jobid = q_u->jobid;
6613 uint32 command = q_u->command;
6615 struct current_user user;
6617 WERROR errcode = WERR_BADFUNC;
6619 if (!get_printer_snum(p, handle, &snum)) {
6623 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6624 return WERR_INVALID_PRINTER_NAME;
6627 get_current_user(&user, p);
6630 case JOB_CONTROL_CANCEL:
6631 case JOB_CONTROL_DELETE:
6632 if (print_job_delete(&user, snum, jobid, &errcode)) {
6636 case JOB_CONTROL_PAUSE:
6637 if (print_job_pause(&user, snum, jobid, &errcode)) {
6641 case JOB_CONTROL_RESTART:
6642 case JOB_CONTROL_RESUME:
6643 if (print_job_resume(&user, snum, jobid, &errcode)) {
6648 return WERR_UNKNOWN_LEVEL;
6654 /****************************************************************************
6655 Enumerates all printer drivers at level 1.
6656 ****************************************************************************/
6658 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6663 fstring *list = NULL;
6665 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6666 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6670 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6672 ndrivers=get_ntdrivers(&list, architecture, version);
6673 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6679 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6680 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6681 SAFE_FREE(driver_info_1);
6685 else driver_info_1 = tdi1;
6688 for (i=0; i<ndrivers; i++) {
6690 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6691 ZERO_STRUCT(driver);
6692 status = get_a_printer_driver(&driver, 3, list[i],
6693 architecture, version);
6694 if (!W_ERROR_IS_OK(status)) {
6698 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6699 free_a_printer_driver(driver, 3);
6702 *returned+=ndrivers;
6706 /* check the required size. */
6707 for (i=0; i<*returned; i++) {
6708 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6709 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6712 if (!alloc_buffer_size(buffer, *needed)) {
6713 SAFE_FREE(driver_info_1);
6714 return WERR_INSUFFICIENT_BUFFER;
6717 /* fill the buffer with the driver structures */
6718 for (i=0; i<*returned; i++) {
6719 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6720 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6723 SAFE_FREE(driver_info_1);
6725 if (*needed > offered) {
6727 return WERR_INSUFFICIENT_BUFFER;
6733 /****************************************************************************
6734 Enumerates all printer drivers at level 2.
6735 ****************************************************************************/
6737 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6742 fstring *list = NULL;
6744 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6745 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6749 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6751 ndrivers=get_ntdrivers(&list, architecture, version);
6752 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6758 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6759 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6760 SAFE_FREE(driver_info_2);
6764 else driver_info_2 = tdi2;
6767 for (i=0; i<ndrivers; i++) {
6770 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6771 ZERO_STRUCT(driver);
6772 status = get_a_printer_driver(&driver, 3, list[i],
6773 architecture, version);
6774 if (!W_ERROR_IS_OK(status)) {
6778 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6779 free_a_printer_driver(driver, 3);
6782 *returned+=ndrivers;
6786 /* check the required size. */
6787 for (i=0; i<*returned; i++) {
6788 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6789 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6792 if (!alloc_buffer_size(buffer, *needed)) {
6793 SAFE_FREE(driver_info_2);
6794 return WERR_INSUFFICIENT_BUFFER;
6797 /* fill the buffer with the form structures */
6798 for (i=0; i<*returned; i++) {
6799 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6800 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6803 SAFE_FREE(driver_info_2);
6805 if (*needed > offered) {
6807 return WERR_INSUFFICIENT_BUFFER;
6813 /****************************************************************************
6814 Enumerates all printer drivers at level 3.
6815 ****************************************************************************/
6817 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6822 fstring *list = NULL;
6824 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6825 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6829 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6831 ndrivers=get_ntdrivers(&list, architecture, version);
6832 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6838 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6839 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6840 SAFE_FREE(driver_info_3);
6844 else driver_info_3 = tdi3;
6847 for (i=0; i<ndrivers; i++) {
6850 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6851 ZERO_STRUCT(driver);
6852 status = get_a_printer_driver(&driver, 3, list[i],
6853 architecture, version);
6854 if (!W_ERROR_IS_OK(status)) {
6858 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6859 free_a_printer_driver(driver, 3);
6862 *returned+=ndrivers;
6866 /* check the required size. */
6867 for (i=0; i<*returned; i++) {
6868 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6869 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6872 if (!alloc_buffer_size(buffer, *needed)) {
6873 SAFE_FREE(driver_info_3);
6874 return WERR_INSUFFICIENT_BUFFER;
6877 /* fill the buffer with the driver structures */
6878 for (i=0; i<*returned; i++) {
6879 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6880 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6883 for (i=0; i<*returned; i++)
6884 SAFE_FREE(driver_info_3[i].dependentfiles);
6886 SAFE_FREE(driver_info_3);
6888 if (*needed > offered) {
6890 return WERR_INSUFFICIENT_BUFFER;
6896 /****************************************************************************
6897 Enumerates all printer drivers.
6898 ****************************************************************************/
6900 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6902 uint32 level = q_u->level;
6903 NEW_BUFFER *buffer = NULL;
6904 uint32 offered = q_u->offered;
6905 uint32 *needed = &r_u->needed;
6906 uint32 *returned = &r_u->returned;
6908 fstring *list = NULL;
6910 fstring architecture;
6912 /* that's an [in out] buffer */
6913 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6914 buffer = r_u->buffer;
6916 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6920 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6921 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6923 if ( !is_myname_or_ipaddr( servername ) )
6924 return WERR_UNKNOWN_PRINTER_DRIVER;
6928 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6930 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6932 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6936 return WERR_UNKNOWN_LEVEL;
6940 /****************************************************************************
6941 ****************************************************************************/
6943 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6945 form->flag=list->flag;
6946 init_unistr(&form->name, list->name);
6947 form->width=list->width;
6948 form->length=list->length;
6949 form->left=list->left;
6950 form->top=list->top;
6951 form->right=list->right;
6952 form->bottom=list->bottom;
6955 /****************************************************************************
6956 ****************************************************************************/
6958 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6960 uint32 level = q_u->level;
6961 NEW_BUFFER *buffer = NULL;
6962 uint32 offered = q_u->offered;
6963 uint32 *needed = &r_u->needed;
6964 uint32 *numofforms = &r_u->numofforms;
6965 uint32 numbuiltinforms;
6967 nt_forms_struct *list=NULL;
6968 nt_forms_struct *builtinlist=NULL;
6973 /* that's an [in out] buffer */
6974 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6975 buffer = r_u->buffer;
6977 DEBUG(4,("_spoolss_enumforms\n"));
6978 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6979 DEBUGADD(5,("Info level [%d]\n", level));
6981 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6982 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6983 *numofforms = get_ntforms(&list);
6984 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6985 *numofforms += numbuiltinforms;
6987 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6991 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
6996 /* construct the list of form structures */
6997 for (i=0; i<numbuiltinforms; i++) {
6998 DEBUGADD(6,("Filling form number [%d]\n",i));
6999 fill_form_1(&forms_1[i], &builtinlist[i]);
7002 SAFE_FREE(builtinlist);
7004 for (; i<*numofforms; i++) {
7005 DEBUGADD(6,("Filling form number [%d]\n",i));
7006 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7011 /* check the required size. */
7012 for (i=0; i<numbuiltinforms; i++) {
7013 DEBUGADD(6,("adding form [%d]'s size\n",i));
7014 buffer_size += spoolss_size_form_1(&forms_1[i]);
7016 for (; i<*numofforms; i++) {
7017 DEBUGADD(6,("adding form [%d]'s size\n",i));
7018 buffer_size += spoolss_size_form_1(&forms_1[i]);
7021 *needed=buffer_size;
7023 if (!alloc_buffer_size(buffer, buffer_size)){
7025 return WERR_INSUFFICIENT_BUFFER;
7028 /* fill the buffer with the form structures */
7029 for (i=0; i<numbuiltinforms; i++) {
7030 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7031 smb_io_form_1("", buffer, &forms_1[i], 0);
7033 for (; i<*numofforms; i++) {
7034 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7035 smb_io_form_1("", buffer, &forms_1[i], 0);
7040 if (*needed > offered) {
7042 return WERR_INSUFFICIENT_BUFFER;
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 NEW_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 */
7075 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7076 buffer = r_u->buffer;
7078 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7080 DEBUG(4,("_spoolss_getform\n"));
7081 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7082 DEBUGADD(5,("Info level [%d]\n", level));
7084 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7085 if (!foundBuiltin) {
7086 numofforms = get_ntforms(&list);
7087 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7089 if (numofforms == 0)
7096 fill_form_1(&form_1, &builtin_form);
7099 /* Check if the requested name is in the list of form structures */
7100 for (i=0; i<numofforms; i++) {
7102 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7104 if (strequal(form_name, list[i].name)) {
7105 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7106 fill_form_1(&form_1, &list[i]);
7112 if (i == numofforms) {
7116 /* check the required size. */
7118 *needed=spoolss_size_form_1(&form_1);
7120 if (!alloc_buffer_size(buffer, buffer_size)){
7121 return WERR_INSUFFICIENT_BUFFER;
7124 if (*needed > offered) {
7125 return WERR_INSUFFICIENT_BUFFER;
7128 /* fill the buffer with the form structures */
7129 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7130 smb_io_form_1("", buffer, &form_1, 0);
7136 return WERR_UNKNOWN_LEVEL;
7140 /****************************************************************************
7141 ****************************************************************************/
7143 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7145 init_unistr(&port->port_name, name);
7148 /****************************************************************************
7149 ****************************************************************************/
7151 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7153 init_unistr(&port->port_name, name);
7154 init_unistr(&port->monitor_name, "Local Monitor");
7155 init_unistr(&port->description, "Local Port");
7156 port->port_type=PORT_TYPE_WRITE;
7160 /****************************************************************************
7162 ****************************************************************************/
7164 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7166 PORT_INFO_1 *ports=NULL;
7169 if (*lp_enumports_cmd()) {
7170 char *cmd = lp_enumports_cmd();
7177 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7179 DEBUG(10,("Running [%s]\n", command));
7180 ret = smbrun(command, &fd);
7181 DEBUG(10,("Returned [%d]\n", ret));
7185 /* Is this the best error to return here? */
7186 return WERR_ACCESS_DENIED;
7190 qlines = fd_lines_load(fd, &numlines);
7191 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7195 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7196 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7197 dos_errstr(WERR_NOMEM)));
7198 file_lines_free(qlines);
7202 for (i=0; i<numlines; i++) {
7203 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7204 fill_port_1(&ports[i], qlines[i]);
7207 file_lines_free(qlines);
7210 *returned = numlines;
7213 *returned = 1; /* Sole Samba port returned. */
7215 if((ports=SMB_MALLOC_P(PORT_INFO_1)) == NULL)
7218 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7220 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7223 /* check the required size. */
7224 for (i=0; i<*returned; i++) {
7225 DEBUGADD(6,("adding port [%d]'s size\n", i));
7226 *needed += spoolss_size_port_info_1(&ports[i]);
7229 if (!alloc_buffer_size(buffer, *needed)) {
7231 return WERR_INSUFFICIENT_BUFFER;
7234 /* fill the buffer with the ports structures */
7235 for (i=0; i<*returned; i++) {
7236 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7237 smb_io_port_1("", buffer, &ports[i], 0);
7242 if (*needed > offered) {
7244 return WERR_INSUFFICIENT_BUFFER;
7250 /****************************************************************************
7252 ****************************************************************************/
7254 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7256 PORT_INFO_2 *ports=NULL;
7259 if (*lp_enumports_cmd()) {
7260 char *cmd = lp_enumports_cmd();
7269 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7270 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7272 path = lp_lockdir();
7274 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7275 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7278 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7279 ret = smbrun(command, &fd);
7280 DEBUGADD(10,("returned [%d]\n", ret));
7284 /* Is this the best error to return here? */
7285 return WERR_ACCESS_DENIED;
7289 qlines = fd_lines_load(fd, &numlines);
7290 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7294 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7295 file_lines_free(qlines);
7299 for (i=0; i<numlines; i++) {
7300 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7301 fill_port_2(&(ports[i]), qlines[i]);
7304 file_lines_free(qlines);
7307 *returned = numlines;
7313 if((ports=SMB_MALLOC_P(PORT_INFO_2)) == NULL)
7316 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7318 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7321 /* check the required size. */
7322 for (i=0; i<*returned; i++) {
7323 DEBUGADD(6,("adding port [%d]'s size\n", i));
7324 *needed += spoolss_size_port_info_2(&ports[i]);
7327 if (!alloc_buffer_size(buffer, *needed)) {
7329 return WERR_INSUFFICIENT_BUFFER;
7332 /* fill the buffer with the ports structures */
7333 for (i=0; i<*returned; i++) {
7334 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7335 smb_io_port_2("", buffer, &ports[i], 0);
7340 if (*needed > offered) {
7342 return WERR_INSUFFICIENT_BUFFER;
7348 /****************************************************************************
7350 ****************************************************************************/
7352 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7354 uint32 level = q_u->level;
7355 NEW_BUFFER *buffer = NULL;
7356 uint32 offered = q_u->offered;
7357 uint32 *needed = &r_u->needed;
7358 uint32 *returned = &r_u->returned;
7360 /* that's an [in out] buffer */
7361 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7362 buffer = r_u->buffer;
7364 DEBUG(4,("_spoolss_enumports\n"));
7371 return enumports_level_1(buffer, offered, needed, returned);
7373 return enumports_level_2(buffer, offered, needed, returned);
7375 return WERR_UNKNOWN_LEVEL;
7379 /****************************************************************************
7380 ****************************************************************************/
7382 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7383 const SPOOL_PRINTER_INFO_LEVEL *info,
7384 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7385 uint32 user_switch, const SPOOL_USER_CTR *user,
7388 NT_PRINTER_INFO_LEVEL *printer = NULL;
7391 WERROR err = WERR_OK;
7393 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7394 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7398 ZERO_STRUCTP(printer);
7400 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7401 if (!convert_printer_info(info, printer, 2)) {
7402 free_a_printer(&printer, 2);
7406 /* check to see if the printer already exists */
7408 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7409 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7410 printer->info_2->sharename));
7411 free_a_printer(&printer, 2);
7412 return WERR_PRINTER_ALREADY_EXISTS;
7415 /* FIXME!!! smbd should check to see if the driver is installed before
7416 trying to add a printer like this --jerry */
7418 if (*lp_addprinter_cmd() ) {
7419 if ( !add_printer_hook(printer) ) {
7420 free_a_printer(&printer,2);
7421 return WERR_ACCESS_DENIED;
7425 /* use our primary netbios name since get_a_printer() will convert
7426 it to what the client expects on a case by case basis */
7428 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7429 printer->info_2->sharename);
7432 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7433 free_a_printer(&printer,2);
7434 return WERR_ACCESS_DENIED;
7437 /* you must be a printer admin to add a new printer */
7438 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7439 free_a_printer(&printer,2);
7440 return WERR_ACCESS_DENIED;
7444 * Do sanity check on the requested changes for Samba.
7447 if (!check_printer_ok(printer->info_2, snum)) {
7448 free_a_printer(&printer,2);
7449 return WERR_INVALID_PARAM;
7453 * When a printer is created, the drivername bound to the printer is used
7454 * to lookup previously saved driver initialization info, which is then
7455 * bound to the new printer, simulating what happens in the Windows arch.
7460 set_driver_init(printer, 2);
7464 /* A valid devmode was included, convert and link it
7466 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7468 if (!convert_devicemode(printer->info_2->printername, devmode,
7469 &printer->info_2->devmode))
7473 /* write the ASCII on disk */
7474 err = mod_a_printer(printer, 2);
7475 if (!W_ERROR_IS_OK(err)) {
7476 free_a_printer(&printer,2);
7480 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7481 /* Handle open failed - remove addition. */
7482 del_a_printer(printer->info_2->sharename);
7483 free_a_printer(&printer,2);
7484 return WERR_ACCESS_DENIED;
7487 update_c_setprinter(False);
7488 free_a_printer(&printer,2);
7493 /****************************************************************************
7494 ****************************************************************************/
7496 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7498 UNISTR2 *uni_srv_name = &q_u->server_name;
7499 uint32 level = q_u->level;
7500 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7501 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7502 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7503 uint32 user_switch = q_u->user_switch;
7504 SPOOL_USER_CTR *user = &q_u->user_ctr;
7505 POLICY_HND *handle = &r_u->handle;
7509 /* we don't handle yet */
7510 /* but I know what to do ... */
7511 return WERR_UNKNOWN_LEVEL;
7513 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7515 user_switch, user, handle);
7517 return WERR_UNKNOWN_LEVEL;
7521 /****************************************************************************
7522 ****************************************************************************/
7524 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7526 uint32 level = q_u->level;
7527 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7528 WERROR err = WERR_OK;
7529 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7530 struct current_user user;
7531 fstring driver_name;
7534 ZERO_STRUCT(driver);
7536 get_current_user(&user, p);
7538 if (!convert_printer_driver_info(info, &driver, level)) {
7543 DEBUG(5,("Cleaning driver's information\n"));
7544 err = clean_up_driver_struct(driver, level, &user);
7545 if (!W_ERROR_IS_OK(err))
7548 DEBUG(5,("Moving driver to final destination\n"));
7549 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7550 if (W_ERROR_IS_OK(err))
7551 err = WERR_ACCESS_DENIED;
7555 if (add_a_printer_driver(driver, level)!=0) {
7556 err = WERR_ACCESS_DENIED;
7560 /* BEGIN_ADMIN_LOG */
7563 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7564 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7565 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7568 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7569 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7570 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7576 * I think this is where he DrvUpgradePrinter() hook would be
7577 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7578 * server. Right now, we just need to send ourselves a message
7579 * to update each printer bound to this driver. --jerry
7582 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7583 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7588 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7589 * decide if the driver init data should be deleted. The rules are:
7590 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7591 * 2) delete init data only if there is no 2k/Xp driver
7592 * 3) always delete init data
7593 * The generalized rule is always use init data from the highest order driver.
7594 * It is necessary to follow the driver install by an initialization step to
7595 * finish off this process.
7598 version = driver.info_3->cversion;
7599 else if (level == 6)
7600 version = driver.info_6->version;
7605 * 9x printer driver - never delete init data
7608 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7613 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7614 * there is no 2k/Xp driver init data for this driver name.
7618 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7620 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7622 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7624 if (!del_driver_init(driver_name))
7625 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7628 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7630 free_a_printer_driver(driver1,3);
7631 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7638 * 2k or Xp printer driver - always delete init data
7641 if (!del_driver_init(driver_name))
7642 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7646 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7652 free_a_printer_driver(driver, level);
7656 /********************************************************************
7657 * spoolss_addprinterdriverex
7658 ********************************************************************/
7660 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7662 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7663 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7666 * we only support the semantics of AddPrinterDriver()
7667 * i.e. only copy files that are newer than existing ones
7670 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7671 return WERR_ACCESS_DENIED;
7673 ZERO_STRUCT(q_u_local);
7674 ZERO_STRUCT(r_u_local);
7676 /* just pass the information off to _spoolss_addprinterdriver() */
7677 q_u_local.server_name_ptr = q_u->server_name_ptr;
7678 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7679 q_u_local.level = q_u->level;
7680 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7682 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7685 /****************************************************************************
7686 ****************************************************************************/
7688 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7690 init_unistr(&info->name, name);
7693 /****************************************************************************
7694 ****************************************************************************/
7696 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7702 const char *short_archi;
7703 DRIVER_DIRECTORY_1 *info=NULL;
7705 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7706 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7708 /* check for beginning double '\'s and that the server
7711 pservername = servername;
7712 if ( *pservername == '\\' && strlen(servername)>2 ) {
7716 if ( !is_myname_or_ipaddr( pservername ) )
7717 return WERR_INVALID_PARAM;
7719 if (!(short_archi = get_short_archi(long_archi)))
7720 return WERR_INVALID_ENVIRONMENT;
7722 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7725 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7727 DEBUG(4,("printer driver directory: [%s]\n", path));
7729 fill_driverdir_1(info, path);
7731 *needed += spoolss_size_driverdir_info_1(info);
7733 if (!alloc_buffer_size(buffer, *needed)) {
7735 return WERR_INSUFFICIENT_BUFFER;
7738 smb_io_driverdir_1("", buffer, info, 0);
7742 if (*needed > offered)
7743 return WERR_INSUFFICIENT_BUFFER;
7748 /****************************************************************************
7749 ****************************************************************************/
7751 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7753 UNISTR2 *name = &q_u->name;
7754 UNISTR2 *uni_environment = &q_u->environment;
7755 uint32 level = q_u->level;
7756 NEW_BUFFER *buffer = NULL;
7757 uint32 offered = q_u->offered;
7758 uint32 *needed = &r_u->needed;
7760 /* that's an [in out] buffer */
7761 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7762 buffer = r_u->buffer;
7764 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7770 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7772 return WERR_UNKNOWN_LEVEL;
7776 /****************************************************************************
7777 ****************************************************************************/
7779 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7781 POLICY_HND *handle = &q_u->handle;
7782 uint32 idx = q_u->index;
7783 uint32 in_value_len = q_u->valuesize;
7784 uint32 in_data_len = q_u->datasize;
7785 uint32 *out_max_value_len = &r_u->valuesize;
7786 uint16 **out_value = &r_u->value;
7787 uint32 *out_value_len = &r_u->realvaluesize;
7788 uint32 *out_type = &r_u->type;
7789 uint32 *out_max_data_len = &r_u->datasize;
7790 uint8 **data_out = &r_u->data;
7791 uint32 *out_data_len = &r_u->realdatasize;
7793 NT_PRINTER_INFO_LEVEL *printer = NULL;
7795 uint32 biggest_valuesize;
7796 uint32 biggest_datasize;
7798 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7801 REGISTRY_VALUE *val = NULL;
7802 NT_PRINTER_DATA *p_data;
7803 int i, key_index, num_values;
7806 ZERO_STRUCT( printer );
7810 *out_max_data_len = 0;
7814 DEBUG(5,("spoolss_enumprinterdata\n"));
7817 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7821 if (!get_printer_snum(p,handle, &snum))
7824 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7825 if (!W_ERROR_IS_OK(result))
7828 p_data = &printer->info_2->data;
7829 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7834 * The NT machine wants to know the biggest size of value and data
7836 * cf: MSDN EnumPrinterData remark section
7839 if ( !in_value_len && !in_data_len && (key_index != -1) )
7841 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7843 biggest_valuesize = 0;
7844 biggest_datasize = 0;
7846 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7848 for ( i=0; i<num_values; i++ )
7850 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7852 name_length = strlen(val->valuename);
7853 if ( strlen(val->valuename) > biggest_valuesize )
7854 biggest_valuesize = name_length;
7856 if ( val->size > biggest_datasize )
7857 biggest_datasize = val->size;
7859 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7863 /* the value is an UNICODE string but real_value_size is the length
7864 in bytes including the trailing 0 */
7866 *out_value_len = 2 * (1+biggest_valuesize);
7867 *out_data_len = biggest_datasize;
7869 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7875 * the value len is wrong in NT sp3
7876 * that's the number of bytes not the number of unicode chars
7879 if ( key_index != -1 )
7880 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7885 /* out_value should default to "" or else NT4 has
7886 problems unmarshalling the response */
7888 *out_max_value_len=(in_value_len/sizeof(uint16));
7890 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7892 result = WERR_NOMEM;
7896 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7898 /* the data is counted in bytes */
7900 *out_max_data_len = in_data_len;
7901 *out_data_len = in_data_len;
7903 /* only allocate when given a non-zero data_len */
7905 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7907 result = WERR_NOMEM;
7911 result = WERR_NO_MORE_ITEMS;
7917 * - counted in bytes in the request
7918 * - counted in UNICODE chars in the max reply
7919 * - counted in bytes in the real size
7921 * take a pause *before* coding not *during* coding
7925 *out_max_value_len=(in_value_len/sizeof(uint16));
7926 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7928 result = WERR_NOMEM;
7932 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7936 *out_type = regval_type( val );
7938 /* data - counted in bytes */
7940 *out_max_data_len = in_data_len;
7941 if ( (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7943 result = WERR_NOMEM;
7946 data_len = (size_t)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 == PRINTER_HANDLE_IS_PRINTSERVER ) {
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 == PRINTER_HANDLE_IS_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 == PRINTER_HANDLE_IS_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 == PRINTER_HANDLE_IS_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 == PRINTER_HANDLE_IS_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 == PRINTER_HANDLE_IS_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 == PRINTER_HANDLE_IS_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(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8324 PRINTPROCESSOR_1 *info_1=NULL;
8326 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8331 init_unistr(&info_1->name, "winprint");
8333 *needed += spoolss_size_printprocessor_info_1(info_1);
8335 if (!alloc_buffer_size(buffer, *needed))
8336 return WERR_INSUFFICIENT_BUFFER;
8338 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8342 if (*needed > offered) {
8344 return WERR_INSUFFICIENT_BUFFER;
8350 /****************************************************************************
8351 ****************************************************************************/
8353 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8355 uint32 level = q_u->level;
8356 NEW_BUFFER *buffer = NULL;
8357 uint32 offered = q_u->offered;
8358 uint32 *needed = &r_u->needed;
8359 uint32 *returned = &r_u->returned;
8361 /* that's an [in out] buffer */
8362 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8363 buffer = r_u->buffer;
8365 DEBUG(5,("spoolss_enumprintprocessors\n"));
8368 * Enumerate the print processors ...
8370 * Just reply with "winprint", to keep NT happy
8371 * and I can use my nice printer checker.
8379 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8381 return WERR_UNKNOWN_LEVEL;
8385 /****************************************************************************
8386 enumprintprocdatatypes level 1.
8387 ****************************************************************************/
8389 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8391 PRINTPROCDATATYPE_1 *info_1=NULL;
8393 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8398 init_unistr(&info_1->name, "RAW");
8400 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8402 if (!alloc_buffer_size(buffer, *needed))
8403 return WERR_INSUFFICIENT_BUFFER;
8405 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8409 if (*needed > offered) {
8411 return WERR_INSUFFICIENT_BUFFER;
8417 /****************************************************************************
8418 ****************************************************************************/
8420 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8422 uint32 level = q_u->level;
8423 NEW_BUFFER *buffer = NULL;
8424 uint32 offered = q_u->offered;
8425 uint32 *needed = &r_u->needed;
8426 uint32 *returned = &r_u->returned;
8428 /* that's an [in out] buffer */
8429 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8430 buffer = r_u->buffer;
8432 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8439 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8441 return WERR_UNKNOWN_LEVEL;
8445 /****************************************************************************
8446 enumprintmonitors level 1.
8447 ****************************************************************************/
8449 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8451 PRINTMONITOR_1 *info_1=NULL;
8453 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8458 init_unistr(&info_1->name, "Local Port");
8460 *needed += spoolss_size_printmonitor_info_1(info_1);
8462 if (!alloc_buffer_size(buffer, *needed))
8463 return WERR_INSUFFICIENT_BUFFER;
8465 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8469 if (*needed > offered) {
8471 return WERR_INSUFFICIENT_BUFFER;
8477 /****************************************************************************
8478 enumprintmonitors level 2.
8479 ****************************************************************************/
8481 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8483 PRINTMONITOR_2 *info_2=NULL;
8485 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8490 init_unistr(&info_2->name, "Local Port");
8491 init_unistr(&info_2->environment, "Windows NT X86");
8492 init_unistr(&info_2->dll_name, "localmon.dll");
8494 *needed += spoolss_size_printmonitor_info_2(info_2);
8496 if (!alloc_buffer_size(buffer, *needed))
8497 return WERR_INSUFFICIENT_BUFFER;
8499 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8503 if (*needed > offered) {
8505 return WERR_INSUFFICIENT_BUFFER;
8511 /****************************************************************************
8512 ****************************************************************************/
8514 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8516 uint32 level = q_u->level;
8517 NEW_BUFFER *buffer = NULL;
8518 uint32 offered = q_u->offered;
8519 uint32 *needed = &r_u->needed;
8520 uint32 *returned = &r_u->returned;
8522 /* that's an [in out] buffer */
8523 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8524 buffer = r_u->buffer;
8526 DEBUG(5,("spoolss_enumprintmonitors\n"));
8529 * Enumerate the print monitors ...
8531 * Just reply with "Local Port", to keep NT happy
8532 * and I can use my nice printer checker.
8540 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8542 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8544 return WERR_UNKNOWN_LEVEL;
8548 /****************************************************************************
8549 ****************************************************************************/
8551 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8552 NT_PRINTER_INFO_LEVEL *ntprinter,
8553 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8558 JOB_INFO_1 *info_1=NULL;
8560 info_1=SMB_MALLOC_P(JOB_INFO_1);
8562 if (info_1 == NULL) {
8566 for (i=0; i<count && found==False; i++) {
8567 if ((*queue)[i].job==(int)jobid)
8573 /* NT treats not found as bad param... yet another bad choice */
8574 return WERR_INVALID_PARAM;
8577 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8579 *needed += spoolss_size_job_info_1(info_1);
8581 if (!alloc_buffer_size(buffer, *needed)) {
8583 return WERR_INSUFFICIENT_BUFFER;
8586 smb_io_job_info_1("", buffer, info_1, 0);
8590 if (*needed > offered)
8591 return WERR_INSUFFICIENT_BUFFER;
8596 /****************************************************************************
8597 ****************************************************************************/
8599 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8600 NT_PRINTER_INFO_LEVEL *ntprinter,
8601 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8608 DEVICEMODE *devmode = NULL;
8609 NT_DEVICEMODE *nt_devmode = NULL;
8611 info_2=SMB_MALLOC_P(JOB_INFO_2);
8613 ZERO_STRUCTP(info_2);
8615 if (info_2 == NULL) {
8620 for ( i=0; i<count && found==False; i++ )
8622 if ((*queue)[i].job == (int)jobid)
8628 /* NT treats not found as bad param... yet another bad
8630 ret = WERR_INVALID_PARAM;
8635 * if the print job does not have a DEVMODE associated with it,
8636 * just use the one for the printer. A NULL devicemode is not
8637 * a failure condition
8640 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8641 devmode = construct_dev_mode(snum);
8643 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8644 ZERO_STRUCTP( devmode );
8645 convert_nt_devicemode( devmode, nt_devmode );
8649 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8651 *needed += spoolss_size_job_info_2(info_2);
8653 if (!alloc_buffer_size(buffer, *needed)) {
8654 ret = WERR_INSUFFICIENT_BUFFER;
8658 smb_io_job_info_2("", buffer, info_2, 0);
8660 if (*needed > offered) {
8661 ret = WERR_INSUFFICIENT_BUFFER;
8668 /* Cleanup allocated memory */
8670 free_job_info_2(info_2); /* Also frees devmode */
8676 /****************************************************************************
8677 ****************************************************************************/
8679 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8681 POLICY_HND *handle = &q_u->handle;
8682 uint32 jobid = q_u->jobid;
8683 uint32 level = q_u->level;
8684 NEW_BUFFER *buffer = NULL;
8685 uint32 offered = q_u->offered;
8686 uint32 *needed = &r_u->needed;
8687 WERROR wstatus = WERR_OK;
8688 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8691 print_queue_struct *queue = NULL;
8692 print_status_struct prt_status;
8694 /* that's an [in out] buffer */
8695 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8696 buffer = r_u->buffer;
8698 DEBUG(5,("spoolss_getjob\n"));
8702 if (!get_printer_snum(p, handle, &snum))
8705 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8706 if ( !W_ERROR_IS_OK(wstatus) )
8709 count = print_queue_status(snum, &queue, &prt_status);
8711 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8712 count, prt_status.status, prt_status.message));
8716 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8717 buffer, offered, needed);
8720 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8721 buffer, offered, needed);
8724 wstatus = WERR_UNKNOWN_LEVEL;
8729 free_a_printer( &ntprinter, 2 );
8734 /********************************************************************
8735 spoolss_getprinterdataex
8737 From MSDN documentation of GetPrinterDataEx: pass request
8738 to GetPrinterData if key is "PrinterDriverData".
8739 ********************************************************************/
8741 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8743 POLICY_HND *handle = &q_u->handle;
8744 uint32 in_size = q_u->size;
8745 uint32 *type = &r_u->type;
8746 uint32 *out_size = &r_u->size;
8747 uint8 **data = &r_u->data;
8748 uint32 *needed = &r_u->needed;
8749 fstring keyname, valuename;
8751 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8753 NT_PRINTER_INFO_LEVEL *printer = NULL;
8755 WERROR status = WERR_OK;
8757 DEBUG(4,("_spoolss_getprinterdataex\n"));
8759 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8760 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8762 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8763 keyname, valuename));
8765 /* in case of problem, return some default values */
8769 *out_size = in_size;
8772 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8773 status = WERR_BADFID;
8777 /* Is the handle to a printer or to the server? */
8779 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8780 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8781 status = WERR_INVALID_PARAM;
8785 if ( !get_printer_snum(p,handle, &snum) )
8788 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8789 if ( !W_ERROR_IS_OK(status) )
8792 /* check to see if the keyname is valid */
8793 if ( !strlen(keyname) ) {
8794 status = WERR_INVALID_PARAM;
8798 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8799 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8800 free_a_printer( &printer, 2 );
8801 status = WERR_BADFILE;
8805 /* When given a new keyname, we should just create it */
8807 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8809 if (*needed > *out_size)
8810 status = WERR_MORE_DATA;
8813 if ( !W_ERROR_IS_OK(status) )
8815 DEBUG(5, ("error: allocating %d\n", *out_size));
8817 /* reply this param doesn't exist */
8821 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8822 status = WERR_NOMEM;
8832 free_a_printer( &printer, 2 );
8837 /********************************************************************
8838 * spoolss_setprinterdataex
8839 ********************************************************************/
8841 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8843 POLICY_HND *handle = &q_u->handle;
8844 uint32 type = q_u->type;
8845 uint8 *data = q_u->data;
8846 uint32 real_len = q_u->real_len;
8848 NT_PRINTER_INFO_LEVEL *printer = NULL;
8850 WERROR status = WERR_OK;
8851 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8856 DEBUG(4,("_spoolss_setprinterdataex\n"));
8858 /* From MSDN documentation of SetPrinterDataEx: pass request to
8859 SetPrinterData if key is "PrinterDriverData" */
8862 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8866 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8867 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8868 return WERR_INVALID_PARAM;
8871 if ( !get_printer_snum(p,handle, &snum) )
8875 * Access check : NT returns "access denied" if you make a
8876 * SetPrinterData call without the necessary privildge.
8877 * we were originally returning OK if nothing changed
8878 * which made Win2k issue **a lot** of SetPrinterData
8879 * when connecting to a printer --jerry
8882 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8884 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8885 return WERR_ACCESS_DENIED;
8888 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8889 if (!W_ERROR_IS_OK(status))
8892 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8893 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8895 /* check for OID in valuename */
8897 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8903 /* save the registry data */
8905 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8907 if ( W_ERROR_IS_OK(status) )
8909 /* save the OID if one was specified */
8911 fstrcat( keyname, "\\" );
8912 fstrcat( keyname, SPOOL_OID_KEY );
8915 * I'm not checking the status here on purpose. Don't know
8916 * if this is right, but I'm returning the status from the
8917 * previous set_printer_dataex() call. I have no idea if
8918 * this is right. --jerry
8921 set_printer_dataex( printer, keyname, valuename,
8922 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8925 status = mod_a_printer(printer, 2);
8928 free_a_printer(&printer, 2);
8934 /********************************************************************
8935 * spoolss_deleteprinterdataex
8936 ********************************************************************/
8938 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8940 POLICY_HND *handle = &q_u->handle;
8941 UNISTR2 *value = &q_u->valuename;
8942 UNISTR2 *key = &q_u->keyname;
8944 NT_PRINTER_INFO_LEVEL *printer = NULL;
8946 WERROR status = WERR_OK;
8947 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8948 pstring valuename, keyname;
8950 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8953 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8957 if (!get_printer_snum(p, handle, &snum))
8960 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8961 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8962 return WERR_ACCESS_DENIED;
8965 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8966 if (!W_ERROR_IS_OK(status))
8969 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8970 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8972 status = delete_printer_dataex( printer, keyname, valuename );
8974 if ( W_ERROR_IS_OK(status) )
8975 mod_a_printer( printer, 2 );
8977 free_a_printer(&printer, 2);
8982 /********************************************************************
8983 * spoolss_enumprinterkey
8984 ********************************************************************/
8987 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8990 fstring *keynames = NULL;
8991 uint16 *enumkeys = NULL;
8994 POLICY_HND *handle = &q_u->handle;
8995 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8996 NT_PRINTER_DATA *data;
8997 NT_PRINTER_INFO_LEVEL *printer = NULL;
8999 WERROR status = WERR_BADFILE;
9002 DEBUG(4,("_spoolss_enumprinterkey\n"));
9005 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9009 if ( !get_printer_snum(p,handle, &snum) )
9012 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9013 if (!W_ERROR_IS_OK(status))
9016 /* get the list of subkey names */
9018 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9019 data = &printer->info_2->data;
9021 num_keys = get_printer_subkeys( data, key, &keynames );
9023 if ( num_keys == -1 ) {
9024 status = WERR_BADFILE;
9028 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9030 r_u->needed = printerkey_len*2;
9032 if ( q_u->size < r_u->needed ) {
9033 status = WERR_MORE_DATA;
9037 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9038 status = WERR_NOMEM;
9044 if ( q_u->size < r_u->needed )
9045 status = WERR_MORE_DATA;
9048 free_a_printer( &printer, 2 );
9049 SAFE_FREE( keynames );
9054 /********************************************************************
9055 * spoolss_deleteprinterkey
9056 ********************************************************************/
9058 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9060 POLICY_HND *handle = &q_u->handle;
9061 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9063 NT_PRINTER_INFO_LEVEL *printer = NULL;
9067 DEBUG(5,("spoolss_deleteprinterkey\n"));
9070 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9074 /* if keyname == NULL, return error */
9076 if ( !q_u->keyname.buffer )
9077 return WERR_INVALID_PARAM;
9079 if (!get_printer_snum(p, handle, &snum))
9082 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9083 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9084 return WERR_ACCESS_DENIED;
9087 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9088 if (!W_ERROR_IS_OK(status))
9091 /* delete the key and all subneys */
9093 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9095 status = delete_all_printer_data( printer->info_2, key );
9097 if ( W_ERROR_IS_OK(status) )
9098 status = mod_a_printer(printer, 2);
9100 free_a_printer( &printer, 2 );
9106 /********************************************************************
9107 * spoolss_enumprinterdataex
9108 ********************************************************************/
9110 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9112 POLICY_HND *handle = &q_u->handle;
9113 uint32 in_size = q_u->size;
9116 NT_PRINTER_INFO_LEVEL *printer = NULL;
9117 PRINTER_ENUM_VALUES *enum_values = NULL;
9118 NT_PRINTER_DATA *p_data;
9120 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9125 REGISTRY_VALUE *val;
9130 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9133 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9138 * first check for a keyname of NULL or "". Win2k seems to send
9139 * this a lot and we should send back WERR_INVALID_PARAM
9140 * no need to spend time looking up the printer in this case.
9144 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9145 if ( !strlen(key) ) {
9146 result = WERR_INVALID_PARAM;
9150 /* get the printer off of disk */
9152 if (!get_printer_snum(p,handle, &snum))
9155 ZERO_STRUCT(printer);
9156 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9157 if (!W_ERROR_IS_OK(result))
9160 /* now look for a match on the key name */
9162 p_data = &printer->info_2->data;
9164 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9165 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9167 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9168 result = WERR_INVALID_PARAM;
9175 /* allocate the memory for the array of pointers -- if necessary */
9177 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9180 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9182 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9183 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9184 result = WERR_NOMEM;
9188 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9192 * loop through all params and build the array to pass
9193 * back to the client
9196 for ( i=0; i<num_entries; i++ )
9198 /* lookup the registry value */
9200 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9201 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9205 value_name = regval_name( val );
9206 init_unistr( &enum_values[i].valuename, value_name );
9207 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9208 enum_values[i].type = regval_type( val );
9210 data_len = regval_size( val );
9212 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9214 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9216 result = WERR_NOMEM;
9220 enum_values[i].data_len = data_len;
9222 /* keep track of the size of the array in bytes */
9224 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9227 /* housekeeping information in the reply */
9229 r_u->needed = needed;
9230 r_u->returned = num_entries;
9232 if (needed > in_size) {
9233 result = WERR_MORE_DATA;
9237 /* copy data into the reply */
9239 r_u->ctr.size = r_u->needed;
9240 r_u->ctr.size_of_array = r_u->returned;
9241 r_u->ctr.values = enum_values;
9247 free_a_printer(&printer, 2);
9252 /****************************************************************************
9253 ****************************************************************************/
9255 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9257 init_unistr(&info->name, name);
9260 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9261 UNISTR2 *environment,
9268 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9270 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9272 if (!get_short_archi(long_archi))
9273 return WERR_INVALID_ENVIRONMENT;
9275 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9278 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9280 fill_printprocessordirectory_1(info, path);
9282 *needed += spoolss_size_printprocessordirectory_info_1(info);
9284 if (!alloc_buffer_size(buffer, *needed)) {
9286 return WERR_INSUFFICIENT_BUFFER;
9289 smb_io_printprocessordirectory_1("", buffer, info, 0);
9293 if (*needed > offered)
9294 return WERR_INSUFFICIENT_BUFFER;
9299 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9301 uint32 level = q_u->level;
9302 NEW_BUFFER *buffer = NULL;
9303 uint32 offered = q_u->offered;
9304 uint32 *needed = &r_u->needed;
9307 /* that's an [in out] buffer */
9308 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9309 buffer = r_u->buffer;
9311 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9317 result = getprintprocessordirectory_level_1
9318 (&q_u->name, &q_u->environment, buffer, offered, needed);
9321 result = WERR_UNKNOWN_LEVEL;
9329 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9330 SPOOL_R_REPLYOPENPRINTER *r_u)
9332 DEBUG(5,("_spoolss_replyopenprinter\n"));
9334 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9339 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9340 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9342 DEBUG(5,("_spoolss_replycloseprinter\n"));