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 if (!lp_ms_add_printer_wizard()) {
1688 close_printer_handle(p, handle);
1689 return WERR_ACCESS_DENIED;
1692 /* if the user is not root and not a printer admin, then fail */
1695 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1697 close_printer_handle(p, handle);
1698 return WERR_ACCESS_DENIED;
1701 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1705 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1708 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1709 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1711 /* We fall through to return WERR_OK */
1716 /* NT doesn't let us connect to a printer if the connecting user
1717 doesn't have print permission. */
1719 if (!get_printer_snum(p, handle, &snum)) {
1720 close_printer_handle(p, handle);
1724 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1726 /* map an empty access mask to the minimum access mask */
1727 if (printer_default->access_required == 0x0)
1728 printer_default->access_required = PRINTER_ACCESS_USE;
1731 * If we are not serving the printer driver for this printer,
1732 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1733 * will keep NT clients happy --jerry
1736 if (lp_use_client_driver(snum)
1737 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1739 printer_default->access_required = PRINTER_ACCESS_USE;
1742 /* check smb.conf parameters and the the sec_desc */
1744 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1745 DEBUG(3, ("access DENIED for printer open\n"));
1746 close_printer_handle(p, handle);
1747 return WERR_ACCESS_DENIED;
1750 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1751 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1752 close_printer_handle(p, handle);
1753 return WERR_ACCESS_DENIED;
1756 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1757 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1759 printer_default->access_required = PRINTER_ACCESS_USE;
1761 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1762 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1766 Printer->access_granted = printer_default->access_required;
1769 * If the client sent a devmode in the OpenPrinter() call, then
1770 * save it here in case we get a job submission on this handle
1773 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1774 && q_u->printer_default.devmode_cont.devmode_ptr )
1776 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1777 &Printer->nt_devmode );
1780 #if 0 /* JERRY -- I'm doubtful this is really effective */
1781 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1782 optimization in Windows 2000 clients --jerry */
1784 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1785 && (RA_WIN2K == get_remote_arch()) )
1787 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1788 sys_usleep( 500000 );
1795 /****************************************************************************
1796 ****************************************************************************/
1798 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1799 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1805 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1814 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1815 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1821 printer->info_3=NULL;
1822 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1826 printer->info_6=NULL;
1827 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1837 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1838 NT_DEVICEMODE **pp_nt_devmode)
1840 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1843 * Ensure nt_devmode is a valid pointer
1844 * as we will be overwriting it.
1847 if (nt_devmode == NULL) {
1848 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1849 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1853 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1854 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1856 nt_devmode->specversion=devmode->specversion;
1857 nt_devmode->driverversion=devmode->driverversion;
1858 nt_devmode->size=devmode->size;
1859 nt_devmode->fields=devmode->fields;
1860 nt_devmode->orientation=devmode->orientation;
1861 nt_devmode->papersize=devmode->papersize;
1862 nt_devmode->paperlength=devmode->paperlength;
1863 nt_devmode->paperwidth=devmode->paperwidth;
1864 nt_devmode->scale=devmode->scale;
1865 nt_devmode->copies=devmode->copies;
1866 nt_devmode->defaultsource=devmode->defaultsource;
1867 nt_devmode->printquality=devmode->printquality;
1868 nt_devmode->color=devmode->color;
1869 nt_devmode->duplex=devmode->duplex;
1870 nt_devmode->yresolution=devmode->yresolution;
1871 nt_devmode->ttoption=devmode->ttoption;
1872 nt_devmode->collate=devmode->collate;
1874 nt_devmode->logpixels=devmode->logpixels;
1875 nt_devmode->bitsperpel=devmode->bitsperpel;
1876 nt_devmode->pelswidth=devmode->pelswidth;
1877 nt_devmode->pelsheight=devmode->pelsheight;
1878 nt_devmode->displayflags=devmode->displayflags;
1879 nt_devmode->displayfrequency=devmode->displayfrequency;
1880 nt_devmode->icmmethod=devmode->icmmethod;
1881 nt_devmode->icmintent=devmode->icmintent;
1882 nt_devmode->mediatype=devmode->mediatype;
1883 nt_devmode->dithertype=devmode->dithertype;
1884 nt_devmode->reserved1=devmode->reserved1;
1885 nt_devmode->reserved2=devmode->reserved2;
1886 nt_devmode->panningwidth=devmode->panningwidth;
1887 nt_devmode->panningheight=devmode->panningheight;
1890 * Only change private and driverextra if the incoming devmode
1891 * has a new one. JRA.
1894 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1895 SAFE_FREE(nt_devmode->private);
1896 nt_devmode->driverextra=devmode->driverextra;
1897 if((nt_devmode->private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1899 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1902 *pp_nt_devmode = nt_devmode;
1907 /********************************************************************
1908 * _spoolss_enddocprinter_internal.
1909 ********************************************************************/
1911 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1913 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1917 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1921 if (!get_printer_snum(p, handle, &snum))
1924 Printer->document_started=False;
1925 print_job_end(snum, Printer->jobid,True);
1926 /* error codes unhandled so far ... */
1931 /********************************************************************
1932 * api_spoolss_closeprinter
1933 ********************************************************************/
1935 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1937 POLICY_HND *handle = &q_u->handle;
1939 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1941 if (Printer && Printer->document_started)
1942 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1944 if (!close_printer_handle(p, handle))
1947 /* clear the returned printer handle. Observed behavior
1948 from Win2k server. Don't think this really matters.
1949 Previous code just copied the value of the closed
1952 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1957 /********************************************************************
1958 * api_spoolss_deleteprinter
1960 ********************************************************************/
1962 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1964 POLICY_HND *handle = &q_u->handle;
1965 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1968 if (Printer && Printer->document_started)
1969 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1971 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1973 result = delete_printer_handle(p, handle);
1975 update_c_setprinter(False);
1980 /*******************************************************************
1981 * static function to lookup the version id corresponding to an
1982 * long architecture string
1983 ******************************************************************/
1985 static int get_version_id (char * arch)
1988 struct table_node archi_table[]= {
1990 {"Windows 4.0", "WIN40", 0 },
1991 {"Windows NT x86", "W32X86", 2 },
1992 {"Windows NT R4000", "W32MIPS", 2 },
1993 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1994 {"Windows NT PowerPC", "W32PPC", 2 },
1995 {"Windows IA64", "IA64", 3 },
1996 {"Windows x64", "x64", 3 },
2000 for (i=0; archi_table[i].long_archi != NULL; i++)
2002 if (strcmp(arch, archi_table[i].long_archi) == 0)
2003 return (archi_table[i].version);
2009 /********************************************************************
2010 * _spoolss_deleteprinterdriver
2011 ********************************************************************/
2013 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2017 NT_PRINTER_DRIVER_INFO_LEVEL info;
2018 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2020 struct current_user user;
2022 WERROR status_win2k = WERR_ACCESS_DENIED;
2024 get_current_user(&user, p);
2026 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2027 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2029 /* check that we have a valid driver name first */
2031 if ((version=get_version_id(arch)) == -1)
2032 return WERR_INVALID_ENVIRONMENT;
2035 ZERO_STRUCT(info_win2k);
2037 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2039 /* try for Win2k driver if "Windows NT x86" */
2041 if ( version == 2 ) {
2043 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2044 status = WERR_UNKNOWN_PRINTER_DRIVER;
2048 /* otherwise it was a failure */
2050 status = WERR_UNKNOWN_PRINTER_DRIVER;
2056 if (printer_driver_in_use(info.info_3)) {
2057 status = WERR_PRINTER_DRIVER_IN_USE;
2063 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2065 /* if we get to here, we now have 2 driver info structures to remove */
2066 /* remove the Win2k driver first*/
2068 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2069 free_a_printer_driver( info_win2k, 3 );
2071 /* this should not have failed---if it did, report to client */
2072 if ( !W_ERROR_IS_OK(status_win2k) )
2077 status = delete_printer_driver(info.info_3, &user, version, False);
2079 /* if at least one of the deletes succeeded return OK */
2081 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2085 free_a_printer_driver( info, 3 );
2090 /********************************************************************
2091 * spoolss_deleteprinterdriverex
2092 ********************************************************************/
2094 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2098 NT_PRINTER_DRIVER_INFO_LEVEL info;
2099 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2101 uint32 flags = q_u->delete_flags;
2103 struct current_user user;
2105 WERROR status_win2k = WERR_ACCESS_DENIED;
2107 get_current_user(&user, p);
2109 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2110 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2112 /* check that we have a valid driver name first */
2113 if ((version=get_version_id(arch)) == -1) {
2114 /* this is what NT returns */
2115 return WERR_INVALID_ENVIRONMENT;
2118 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2119 version = q_u->version;
2122 ZERO_STRUCT(info_win2k);
2124 status = get_a_printer_driver(&info, 3, driver, arch, version);
2126 if ( !W_ERROR_IS_OK(status) )
2129 * if the client asked for a specific version,
2130 * or this is something other than Windows NT x86,
2134 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2137 /* try for Win2k driver if "Windows NT x86" */
2140 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2141 status = WERR_UNKNOWN_PRINTER_DRIVER;
2146 if ( printer_driver_in_use(info.info_3) ) {
2147 status = WERR_PRINTER_DRIVER_IN_USE;
2152 * we have a couple of cases to consider.
2153 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2154 * then the delete should fail if **any** files overlap with
2156 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2157 * non-overlapping files
2158 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2159 * is set, the do not delete any files
2160 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2163 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2165 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2167 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2168 /* no idea of the correct error here */
2169 status = WERR_ACCESS_DENIED;
2174 /* also check for W32X86/3 if necessary; maybe we already have? */
2176 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2177 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2180 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2181 /* no idea of the correct error here */
2182 free_a_printer_driver( info_win2k, 3 );
2183 status = WERR_ACCESS_DENIED;
2187 /* if we get to here, we now have 2 driver info structures to remove */
2188 /* remove the Win2k driver first*/
2190 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2191 free_a_printer_driver( info_win2k, 3 );
2193 /* this should not have failed---if it did, report to client */
2195 if ( !W_ERROR_IS_OK(status_win2k) )
2200 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2202 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2205 free_a_printer_driver( info, 3 );
2211 /****************************************************************************
2212 Internal routine for retreiving printerdata
2213 ***************************************************************************/
2215 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2216 const char *key, const char *value, uint32 *type, uint8 **data,
2217 uint32 *needed, uint32 in_size )
2219 REGISTRY_VALUE *val;
2222 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2223 return WERR_BADFILE;
2225 *type = regval_type( val );
2227 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2229 size = regval_size( val );
2231 /* copy the min(in_size, len) */
2234 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2236 /* special case for 0 length values */
2238 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2242 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2251 DEBUG(5,("get_printer_dataex: copy done\n"));
2256 /****************************************************************************
2257 Internal routine for removing printerdata
2258 ***************************************************************************/
2260 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2262 return delete_printer_data( printer->info_2, key, value );
2265 /****************************************************************************
2266 Internal routine for storing printerdata
2267 ***************************************************************************/
2269 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2270 uint32 type, uint8 *data, int real_len )
2272 delete_printer_data( printer->info_2, key, value );
2274 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2277 /********************************************************************
2278 GetPrinterData on a printer server Handle.
2279 ********************************************************************/
2281 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2285 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2287 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2289 if((*data = (uint8 *)TALLOC_ZERO(ctx, 4*sizeof(uint8) )) == NULL)
2295 if (!StrCaseCmp(value, "BeepEnabled")) {
2297 if((*data = (uint8 *)TALLOC(ctx, 4*sizeof(uint8) )) == NULL)
2299 SIVAL(*data, 0, 0x00);
2304 if (!StrCaseCmp(value, "EventLog")) {
2306 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2308 /* formally was 0x1b */
2309 SIVAL(*data, 0, 0x0);
2314 if (!StrCaseCmp(value, "NetPopup")) {
2316 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2318 SIVAL(*data, 0, 0x00);
2323 if (!StrCaseCmp(value, "MajorVersion")) {
2325 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2328 /* Windows NT 4.0 seems to not allow uploading of drivers
2329 to a server that reports 0x3 as the MajorVersion.
2330 need to investigate more how Win2k gets around this .
2333 if ( RA_WINNT == get_remote_arch() )
2342 if (!StrCaseCmp(value, "MinorVersion")) {
2344 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2352 * uint32 size = 0x114
2354 * uint32 minor = [0|1]
2355 * uint32 build = [2195|2600]
2356 * extra unicode string = e.g. "Service Pack 3"
2358 if (!StrCaseCmp(value, "OSVersion")) {
2362 if((*data = (uint8 *)TALLOC(ctx, *needed)) == NULL)
2364 ZERO_STRUCTP( *data );
2366 SIVAL(*data, 0, *needed); /* size */
2367 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2369 SIVAL(*data, 12, 2195); /* build */
2371 /* leave extra string empty */
2377 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2378 const char *string="C:\\PRINTERS";
2380 *needed = 2*(strlen(string)+1);
2381 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2383 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2385 /* it's done by hand ready to go on the wire */
2386 for (i=0; i<strlen(string); i++) {
2387 (*data)[2*i]=string[i];
2388 (*data)[2*i+1]='\0';
2393 if (!StrCaseCmp(value, "Architecture")) {
2394 const char *string="Windows NT x86";
2396 *needed = 2*(strlen(string)+1);
2397 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2399 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2400 for (i=0; i<strlen(string); i++) {
2401 (*data)[2*i]=string[i];
2402 (*data)[2*i+1]='\0';
2407 if (!StrCaseCmp(value, "DsPresent")) {
2409 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2411 SIVAL(*data, 0, 0x01);
2416 if (!StrCaseCmp(value, "DNSMachineName")) {
2419 if (!get_mydnsfullname(hostname))
2420 return WERR_BADFILE;
2422 *needed = 2*(strlen(hostname)+1);
2423 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2425 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2426 for (i=0; i<strlen(hostname); i++) {
2427 (*data)[2*i]=hostname[i];
2428 (*data)[2*i+1]='\0';
2434 return WERR_BADFILE;
2437 /********************************************************************
2438 * spoolss_getprinterdata
2439 ********************************************************************/
2441 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2443 POLICY_HND *handle = &q_u->handle;
2444 UNISTR2 *valuename = &q_u->valuename;
2445 uint32 in_size = q_u->size;
2446 uint32 *type = &r_u->type;
2447 uint32 *out_size = &r_u->size;
2448 uint8 **data = &r_u->data;
2449 uint32 *needed = &r_u->needed;
2452 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2453 NT_PRINTER_INFO_LEVEL *printer = NULL;
2457 * Reminder: when it's a string, the length is in BYTES
2458 * even if UNICODE is negociated.
2463 *out_size = in_size;
2465 /* in case of problem, return some default values */
2470 DEBUG(4,("_spoolss_getprinterdata\n"));
2473 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2474 status = WERR_BADFID;
2478 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2480 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2481 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2484 if ( !get_printer_snum(p,handle, &snum) ) {
2485 status = WERR_BADFID;
2489 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2490 if ( !W_ERROR_IS_OK(status) )
2493 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2495 if ( strequal(value, "ChangeId") ) {
2497 *needed = sizeof(uint32);
2498 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2499 status = WERR_NOMEM;
2502 SIVAL( *data, 0, printer->info_2->changeid );
2506 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2509 if (*needed > *out_size)
2510 status = WERR_MORE_DATA;
2513 if ( !W_ERROR_IS_OK(status) )
2515 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2517 /* reply this param doesn't exist */
2520 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2522 free_a_printer( &printer, 2 );
2531 /* cleanup & exit */
2534 free_a_printer( &printer, 2 );
2539 /*********************************************************
2540 Connect to the client machine.
2541 **********************************************************/
2543 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2544 struct in_addr *client_ip, const char *remote_machine)
2546 ZERO_STRUCTP(the_cli);
2548 if(cli_initialise(the_cli) == NULL) {
2549 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2553 if ( is_zero_ip(*client_ip) ) {
2554 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2555 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2556 cli_shutdown(the_cli);
2560 if (ismyip(the_cli->dest_ip)) {
2561 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2562 cli_shutdown(the_cli);
2567 the_cli->dest_ip.s_addr = client_ip->s_addr;
2568 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2569 inet_ntoa(*client_ip) ));
2572 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2573 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) ));
2574 cli_shutdown(the_cli);
2578 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2579 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2581 cli_shutdown(the_cli);
2585 the_cli->protocol = PROTOCOL_NT1;
2586 cli_setup_signing_state(the_cli, lp_client_signing());
2588 if (!cli_negprot(the_cli)) {
2589 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2590 cli_shutdown(the_cli);
2594 if (the_cli->protocol != PROTOCOL_NT1) {
2595 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2596 cli_shutdown(the_cli);
2601 * Do an anonymous session setup.
2604 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2605 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2606 cli_shutdown(the_cli);
2610 if (!(the_cli->sec_mode & 1)) {
2611 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2612 cli_shutdown(the_cli);
2616 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2617 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) ));
2618 cli_shutdown(the_cli);
2623 * Ok - we have an anonymous connection to the IPC$ share.
2624 * Now start the NT Domain stuff :-).
2627 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2628 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)));
2629 cli_nt_session_close(the_cli);
2630 cli_ulogoff(the_cli);
2631 cli_shutdown(the_cli);
2638 /***************************************************************************
2639 Connect to the client.
2640 ****************************************************************************/
2642 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2643 uint32 localprinter, uint32 type,
2644 POLICY_HND *handle, struct in_addr *client_ip)
2649 * If it's the first connection, contact the client
2650 * and connect to the IPC$ share anonymously
2652 if (smb_connections==0) {
2653 fstring unix_printer;
2655 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2657 ZERO_STRUCT(notify_cli);
2659 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2662 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2663 /* Tell the connections db we're now interested in printer
2664 * notify messages. */
2665 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2669 * Tell the specific printing tdb we want messages for this printer
2670 * by registering our PID.
2673 if (!print_notify_register_pid(snum))
2674 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2678 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2681 if (!W_ERROR_IS_OK(result))
2682 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2683 dos_errstr(result)));
2685 return (W_ERROR_IS_OK(result));
2688 /********************************************************************
2690 * ReplyFindFirstPrinterChangeNotifyEx
2692 * before replying OK: status=0 a rpc call is made to the workstation
2693 * asking ReplyOpenPrinter
2695 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2696 * called from api_spoolss_rffpcnex
2697 ********************************************************************/
2699 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2701 POLICY_HND *handle = &q_u->handle;
2702 uint32 flags = q_u->flags;
2703 uint32 options = q_u->options;
2704 UNISTR2 *localmachine = &q_u->localmachine;
2705 uint32 printerlocal = q_u->printerlocal;
2707 SPOOL_NOTIFY_OPTION *option = q_u->option;
2708 struct in_addr client_ip;
2710 /* store the notify value in the printer struct */
2712 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2715 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2719 Printer->notify.flags=flags;
2720 Printer->notify.options=options;
2721 Printer->notify.printerlocal=printerlocal;
2723 if (Printer->notify.option)
2724 free_spool_notify_option(&Printer->notify.option);
2726 Printer->notify.option=dup_spool_notify_option(option);
2728 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2729 sizeof(Printer->notify.localmachine)-1);
2731 /* Connect to the client machine and send a ReplyOpenPrinter */
2733 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2735 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2736 !get_printer_snum(p, handle, &snum) )
2739 client_ip.s_addr = inet_addr(p->conn->client_address);
2741 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2742 Printer->notify.printerlocal, 1,
2743 &Printer->notify.client_hnd, &client_ip))
2744 return WERR_SERVER_UNAVAILABLE;
2746 Printer->notify.client_connected=True;
2751 /*******************************************************************
2752 * fill a notify_info_data with the servername
2753 ********************************************************************/
2755 void spoolss_notify_server_name(int snum,
2756 SPOOL_NOTIFY_INFO_DATA *data,
2757 print_queue_struct *queue,
2758 NT_PRINTER_INFO_LEVEL *printer,
2759 TALLOC_CTX *mem_ctx)
2764 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2766 data->notify_data.data.length = len;
2767 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2769 if (!data->notify_data.data.string) {
2770 data->notify_data.data.length = 0;
2774 memcpy(data->notify_data.data.string, temp, len);
2777 /*******************************************************************
2778 * fill a notify_info_data with the printername (not including the servername).
2779 ********************************************************************/
2781 void spoolss_notify_printer_name(int snum,
2782 SPOOL_NOTIFY_INFO_DATA *data,
2783 print_queue_struct *queue,
2784 NT_PRINTER_INFO_LEVEL *printer,
2785 TALLOC_CTX *mem_ctx)
2790 /* the notify name should not contain the \\server\ part */
2791 char *p = strrchr(printer->info_2->printername, '\\');
2794 p = printer->info_2->printername;
2799 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2801 data->notify_data.data.length = len;
2802 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2804 if (!data->notify_data.data.string) {
2805 data->notify_data.data.length = 0;
2809 memcpy(data->notify_data.data.string, temp, len);
2812 /*******************************************************************
2813 * fill a notify_info_data with the servicename
2814 ********************************************************************/
2816 void spoolss_notify_share_name(int snum,
2817 SPOOL_NOTIFY_INFO_DATA *data,
2818 print_queue_struct *queue,
2819 NT_PRINTER_INFO_LEVEL *printer,
2820 TALLOC_CTX *mem_ctx)
2825 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2827 data->notify_data.data.length = len;
2828 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2830 if (!data->notify_data.data.string) {
2831 data->notify_data.data.length = 0;
2835 memcpy(data->notify_data.data.string, temp, len);
2838 /*******************************************************************
2839 * fill a notify_info_data with the port name
2840 ********************************************************************/
2842 void spoolss_notify_port_name(int snum,
2843 SPOOL_NOTIFY_INFO_DATA *data,
2844 print_queue_struct *queue,
2845 NT_PRINTER_INFO_LEVEL *printer,
2846 TALLOC_CTX *mem_ctx)
2851 /* even if it's strange, that's consistant in all the code */
2853 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2855 data->notify_data.data.length = len;
2856 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2858 if (!data->notify_data.data.string) {
2859 data->notify_data.data.length = 0;
2863 memcpy(data->notify_data.data.string, temp, len);
2866 /*******************************************************************
2867 * fill a notify_info_data with the printername
2868 * but it doesn't exist, have to see what to do
2869 ********************************************************************/
2871 void spoolss_notify_driver_name(int snum,
2872 SPOOL_NOTIFY_INFO_DATA *data,
2873 print_queue_struct *queue,
2874 NT_PRINTER_INFO_LEVEL *printer,
2875 TALLOC_CTX *mem_ctx)
2880 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2882 data->notify_data.data.length = len;
2883 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2885 if (!data->notify_data.data.string) {
2886 data->notify_data.data.length = 0;
2890 memcpy(data->notify_data.data.string, temp, len);
2893 /*******************************************************************
2894 * fill a notify_info_data with the comment
2895 ********************************************************************/
2897 void spoolss_notify_comment(int snum,
2898 SPOOL_NOTIFY_INFO_DATA *data,
2899 print_queue_struct *queue,
2900 NT_PRINTER_INFO_LEVEL *printer,
2901 TALLOC_CTX *mem_ctx)
2906 if (*printer->info_2->comment == '\0')
2907 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2909 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2911 data->notify_data.data.length = len;
2912 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2914 if (!data->notify_data.data.string) {
2915 data->notify_data.data.length = 0;
2919 memcpy(data->notify_data.data.string, temp, len);
2922 /*******************************************************************
2923 * fill a notify_info_data with the comment
2924 * location = "Room 1, floor 2, building 3"
2925 ********************************************************************/
2927 void spoolss_notify_location(int snum,
2928 SPOOL_NOTIFY_INFO_DATA *data,
2929 print_queue_struct *queue,
2930 NT_PRINTER_INFO_LEVEL *printer,
2931 TALLOC_CTX *mem_ctx)
2936 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2938 data->notify_data.data.length = len;
2939 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2941 if (!data->notify_data.data.string) {
2942 data->notify_data.data.length = 0;
2946 memcpy(data->notify_data.data.string, temp, len);
2949 /*******************************************************************
2950 * fill a notify_info_data with the device mode
2951 * jfm:xxxx don't to it for know but that's a real problem !!!
2952 ********************************************************************/
2954 static void spoolss_notify_devmode(int snum,
2955 SPOOL_NOTIFY_INFO_DATA *data,
2956 print_queue_struct *queue,
2957 NT_PRINTER_INFO_LEVEL *printer,
2958 TALLOC_CTX *mem_ctx)
2962 /*******************************************************************
2963 * fill a notify_info_data with the separator file name
2964 ********************************************************************/
2966 void spoolss_notify_sepfile(int snum,
2967 SPOOL_NOTIFY_INFO_DATA *data,
2968 print_queue_struct *queue,
2969 NT_PRINTER_INFO_LEVEL *printer,
2970 TALLOC_CTX *mem_ctx)
2975 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2977 data->notify_data.data.length = len;
2978 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2980 if (!data->notify_data.data.string) {
2981 data->notify_data.data.length = 0;
2985 memcpy(data->notify_data.data.string, temp, len);
2988 /*******************************************************************
2989 * fill a notify_info_data with the print processor
2990 * jfm:xxxx return always winprint to indicate we don't do anything to it
2991 ********************************************************************/
2993 void spoolss_notify_print_processor(int snum,
2994 SPOOL_NOTIFY_INFO_DATA *data,
2995 print_queue_struct *queue,
2996 NT_PRINTER_INFO_LEVEL *printer,
2997 TALLOC_CTX *mem_ctx)
3002 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3004 data->notify_data.data.length = len;
3005 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3007 if (!data->notify_data.data.string) {
3008 data->notify_data.data.length = 0;
3012 memcpy(data->notify_data.data.string, temp, len);
3015 /*******************************************************************
3016 * fill a notify_info_data with the print processor options
3017 * jfm:xxxx send an empty string
3018 ********************************************************************/
3020 void spoolss_notify_parameters(int snum,
3021 SPOOL_NOTIFY_INFO_DATA *data,
3022 print_queue_struct *queue,
3023 NT_PRINTER_INFO_LEVEL *printer,
3024 TALLOC_CTX *mem_ctx)
3029 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3031 data->notify_data.data.length = len;
3032 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3034 if (!data->notify_data.data.string) {
3035 data->notify_data.data.length = 0;
3039 memcpy(data->notify_data.data.string, temp, len);
3042 /*******************************************************************
3043 * fill a notify_info_data with the data type
3044 * jfm:xxxx always send RAW as data type
3045 ********************************************************************/
3047 void spoolss_notify_datatype(int snum,
3048 SPOOL_NOTIFY_INFO_DATA *data,
3049 print_queue_struct *queue,
3050 NT_PRINTER_INFO_LEVEL *printer,
3051 TALLOC_CTX *mem_ctx)
3056 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3058 data->notify_data.data.length = len;
3059 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3061 if (!data->notify_data.data.string) {
3062 data->notify_data.data.length = 0;
3066 memcpy(data->notify_data.data.string, temp, len);
3069 /*******************************************************************
3070 * fill a notify_info_data with the security descriptor
3071 * jfm:xxxx send an null pointer to say no security desc
3072 * have to implement security before !
3073 ********************************************************************/
3075 static void spoolss_notify_security_desc(int snum,
3076 SPOOL_NOTIFY_INFO_DATA *data,
3077 print_queue_struct *queue,
3078 NT_PRINTER_INFO_LEVEL *printer,
3079 TALLOC_CTX *mem_ctx)
3081 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3082 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3085 /*******************************************************************
3086 * fill a notify_info_data with the attributes
3087 * jfm:xxxx a samba printer is always shared
3088 ********************************************************************/
3090 void spoolss_notify_attributes(int snum,
3091 SPOOL_NOTIFY_INFO_DATA *data,
3092 print_queue_struct *queue,
3093 NT_PRINTER_INFO_LEVEL *printer,
3094 TALLOC_CTX *mem_ctx)
3096 data->notify_data.value[0] = printer->info_2->attributes;
3097 data->notify_data.value[1] = 0;
3100 /*******************************************************************
3101 * fill a notify_info_data with the priority
3102 ********************************************************************/
3104 static void spoolss_notify_priority(int snum,
3105 SPOOL_NOTIFY_INFO_DATA *data,
3106 print_queue_struct *queue,
3107 NT_PRINTER_INFO_LEVEL *printer,
3108 TALLOC_CTX *mem_ctx)
3110 data->notify_data.value[0] = printer->info_2->priority;
3111 data->notify_data.value[1] = 0;
3114 /*******************************************************************
3115 * fill a notify_info_data with the default priority
3116 ********************************************************************/
3118 static void spoolss_notify_default_priority(int snum,
3119 SPOOL_NOTIFY_INFO_DATA *data,
3120 print_queue_struct *queue,
3121 NT_PRINTER_INFO_LEVEL *printer,
3122 TALLOC_CTX *mem_ctx)
3124 data->notify_data.value[0] = printer->info_2->default_priority;
3125 data->notify_data.value[1] = 0;
3128 /*******************************************************************
3129 * fill a notify_info_data with the start time
3130 ********************************************************************/
3132 static void spoolss_notify_start_time(int snum,
3133 SPOOL_NOTIFY_INFO_DATA *data,
3134 print_queue_struct *queue,
3135 NT_PRINTER_INFO_LEVEL *printer,
3136 TALLOC_CTX *mem_ctx)
3138 data->notify_data.value[0] = printer->info_2->starttime;
3139 data->notify_data.value[1] = 0;
3142 /*******************************************************************
3143 * fill a notify_info_data with the until time
3144 ********************************************************************/
3146 static void spoolss_notify_until_time(int snum,
3147 SPOOL_NOTIFY_INFO_DATA *data,
3148 print_queue_struct *queue,
3149 NT_PRINTER_INFO_LEVEL *printer,
3150 TALLOC_CTX *mem_ctx)
3152 data->notify_data.value[0] = printer->info_2->untiltime;
3153 data->notify_data.value[1] = 0;
3156 /*******************************************************************
3157 * fill a notify_info_data with the status
3158 ********************************************************************/
3160 static void spoolss_notify_status(int snum,
3161 SPOOL_NOTIFY_INFO_DATA *data,
3162 print_queue_struct *queue,
3163 NT_PRINTER_INFO_LEVEL *printer,
3164 TALLOC_CTX *mem_ctx)
3166 print_status_struct status;
3168 print_queue_length(snum, &status);
3169 data->notify_data.value[0]=(uint32) status.status;
3170 data->notify_data.value[1] = 0;
3173 /*******************************************************************
3174 * fill a notify_info_data with the number of jobs queued
3175 ********************************************************************/
3177 void spoolss_notify_cjobs(int snum,
3178 SPOOL_NOTIFY_INFO_DATA *data,
3179 print_queue_struct *queue,
3180 NT_PRINTER_INFO_LEVEL *printer,
3181 TALLOC_CTX *mem_ctx)
3183 data->notify_data.value[0] = print_queue_length(snum, NULL);
3184 data->notify_data.value[1] = 0;
3187 /*******************************************************************
3188 * fill a notify_info_data with the average ppm
3189 ********************************************************************/
3191 static void spoolss_notify_average_ppm(int snum,
3192 SPOOL_NOTIFY_INFO_DATA *data,
3193 print_queue_struct *queue,
3194 NT_PRINTER_INFO_LEVEL *printer,
3195 TALLOC_CTX *mem_ctx)
3197 /* always respond 8 pages per minutes */
3198 /* a little hard ! */
3199 data->notify_data.value[0] = printer->info_2->averageppm;
3200 data->notify_data.value[1] = 0;
3203 /*******************************************************************
3204 * fill a notify_info_data with username
3205 ********************************************************************/
3207 static void spoolss_notify_username(int snum,
3208 SPOOL_NOTIFY_INFO_DATA *data,
3209 print_queue_struct *queue,
3210 NT_PRINTER_INFO_LEVEL *printer,
3211 TALLOC_CTX *mem_ctx)
3216 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3218 data->notify_data.data.length = len;
3219 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3221 if (!data->notify_data.data.string) {
3222 data->notify_data.data.length = 0;
3226 memcpy(data->notify_data.data.string, temp, len);
3229 /*******************************************************************
3230 * fill a notify_info_data with job status
3231 ********************************************************************/
3233 static void spoolss_notify_job_status(int snum,
3234 SPOOL_NOTIFY_INFO_DATA *data,
3235 print_queue_struct *queue,
3236 NT_PRINTER_INFO_LEVEL *printer,
3237 TALLOC_CTX *mem_ctx)
3239 data->notify_data.value[0]=nt_printj_status(queue->status);
3240 data->notify_data.value[1] = 0;
3243 /*******************************************************************
3244 * fill a notify_info_data with job name
3245 ********************************************************************/
3247 static void spoolss_notify_job_name(int snum,
3248 SPOOL_NOTIFY_INFO_DATA *data,
3249 print_queue_struct *queue,
3250 NT_PRINTER_INFO_LEVEL *printer,
3251 TALLOC_CTX *mem_ctx)
3256 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3258 data->notify_data.data.length = len;
3259 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3261 if (!data->notify_data.data.string) {
3262 data->notify_data.data.length = 0;
3266 memcpy(data->notify_data.data.string, temp, len);
3269 /*******************************************************************
3270 * fill a notify_info_data with job status
3271 ********************************************************************/
3273 static void spoolss_notify_job_status_string(int snum,
3274 SPOOL_NOTIFY_INFO_DATA *data,
3275 print_queue_struct *queue,
3276 NT_PRINTER_INFO_LEVEL *printer,
3277 TALLOC_CTX *mem_ctx)
3280 * Now we're returning job status codes we just return a "" here. JRA.
3287 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3290 switch (queue->status) {
3295 p = ""; /* NT provides the paused string */
3304 #endif /* NO LONGER NEEDED. */
3306 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3308 data->notify_data.data.length = len;
3309 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3311 if (!data->notify_data.data.string) {
3312 data->notify_data.data.length = 0;
3316 memcpy(data->notify_data.data.string, temp, len);
3319 /*******************************************************************
3320 * fill a notify_info_data with job time
3321 ********************************************************************/
3323 static void spoolss_notify_job_time(int snum,
3324 SPOOL_NOTIFY_INFO_DATA *data,
3325 print_queue_struct *queue,
3326 NT_PRINTER_INFO_LEVEL *printer,
3327 TALLOC_CTX *mem_ctx)
3329 data->notify_data.value[0]=0x0;
3330 data->notify_data.value[1]=0;
3333 /*******************************************************************
3334 * fill a notify_info_data with job size
3335 ********************************************************************/
3337 static void spoolss_notify_job_size(int snum,
3338 SPOOL_NOTIFY_INFO_DATA *data,
3339 print_queue_struct *queue,
3340 NT_PRINTER_INFO_LEVEL *printer,
3341 TALLOC_CTX *mem_ctx)
3343 data->notify_data.value[0]=queue->size;
3344 data->notify_data.value[1]=0;
3347 /*******************************************************************
3348 * fill a notify_info_data with page info
3349 ********************************************************************/
3350 static void spoolss_notify_total_pages(int snum,
3351 SPOOL_NOTIFY_INFO_DATA *data,
3352 print_queue_struct *queue,
3353 NT_PRINTER_INFO_LEVEL *printer,
3354 TALLOC_CTX *mem_ctx)
3356 data->notify_data.value[0]=queue->page_count;
3357 data->notify_data.value[1]=0;
3360 /*******************************************************************
3361 * fill a notify_info_data with pages printed info.
3362 ********************************************************************/
3363 static void spoolss_notify_pages_printed(int snum,
3364 SPOOL_NOTIFY_INFO_DATA *data,
3365 print_queue_struct *queue,
3366 NT_PRINTER_INFO_LEVEL *printer,
3367 TALLOC_CTX *mem_ctx)
3369 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3370 data->notify_data.value[1]=0;
3373 /*******************************************************************
3374 Fill a notify_info_data with job position.
3375 ********************************************************************/
3377 static void spoolss_notify_job_position(int snum,
3378 SPOOL_NOTIFY_INFO_DATA *data,
3379 print_queue_struct *queue,
3380 NT_PRINTER_INFO_LEVEL *printer,
3381 TALLOC_CTX *mem_ctx)
3383 data->notify_data.value[0]=queue->job;
3384 data->notify_data.value[1]=0;
3387 /*******************************************************************
3388 Fill a notify_info_data with submitted time.
3389 ********************************************************************/
3391 static void spoolss_notify_submitted_time(int snum,
3392 SPOOL_NOTIFY_INFO_DATA *data,
3393 print_queue_struct *queue,
3394 NT_PRINTER_INFO_LEVEL *printer,
3395 TALLOC_CTX *mem_ctx)
3402 t=gmtime(&queue->time);
3404 len = sizeof(SYSTEMTIME);
3406 data->notify_data.data.length = len;
3407 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3409 if (!data->notify_data.data.string) {
3410 data->notify_data.data.length = 0;
3414 make_systemtime(&st, t);
3417 * Systemtime must be linearized as a set of UINT16's.
3418 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3421 p = (char *)data->notify_data.data.string;
3422 SSVAL(p, 0, st.year);
3423 SSVAL(p, 2, st.month);
3424 SSVAL(p, 4, st.dayofweek);
3425 SSVAL(p, 6, st.day);
3426 SSVAL(p, 8, st.hour);
3427 SSVAL(p, 10, st.minute);
3428 SSVAL(p, 12, st.second);
3429 SSVAL(p, 14, st.milliseconds);
3432 struct s_notify_info_data_table
3438 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3439 print_queue_struct *queue,
3440 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3443 /* A table describing the various print notification constants and
3444 whether the notification data is a pointer to a variable sized
3445 buffer, a one value uint32 or a two value uint32. */
3447 static const struct s_notify_info_data_table notify_info_data_table[] =
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3498 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3501 /*******************************************************************
3502 Return the size of info_data structure.
3503 ********************************************************************/
3505 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3509 for (i = 0; i < sizeof(notify_info_data_table); i++)
3511 if ( (notify_info_data_table[i].type == type)
3512 && (notify_info_data_table[i].field == field) )
3514 switch(notify_info_data_table[i].size)
3516 case NOTIFY_ONE_VALUE:
3517 case NOTIFY_TWO_VALUE:
3522 /* The only pointer notify data I have seen on
3523 the wire is the submitted time and this has
3524 the notify size set to 4. -tpot */
3526 case NOTIFY_POINTER:
3529 case NOTIFY_SECDESC:
3535 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3540 /*******************************************************************
3541 Return the type of notify_info_data.
3542 ********************************************************************/
3544 static int type_of_notify_info_data(uint16 type, uint16 field)
3548 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3549 if (notify_info_data_table[i].type == type &&
3550 notify_info_data_table[i].field == field)
3551 return notify_info_data_table[i].size;
3557 /****************************************************************************
3558 ****************************************************************************/
3560 static int search_notify(uint16 type, uint16 field, int *value)
3564 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3565 if (notify_info_data_table[i].type == type &&
3566 notify_info_data_table[i].field == field &&
3567 notify_info_data_table[i].fn != NULL) {
3576 /****************************************************************************
3577 ****************************************************************************/
3579 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3581 info_data->type = type;
3582 info_data->field = field;
3583 info_data->reserved = 0;
3585 info_data->size = size_of_notify_info_data(type, field);
3586 info_data->enc_type = type_of_notify_info_data(type, field);
3593 /*******************************************************************
3595 * fill a notify_info struct with info asked
3597 ********************************************************************/
3599 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3600 snum, SPOOL_NOTIFY_OPTION_TYPE
3601 *option_type, uint32 id,
3602 TALLOC_CTX *mem_ctx)
3608 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3609 NT_PRINTER_INFO_LEVEL *printer = NULL;
3610 print_queue_struct *queue=NULL;
3612 type=option_type->type;
3614 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3615 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3616 option_type->count, lp_servicename(snum)));
3618 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3621 for(field_num=0; field_num<option_type->count; field_num++) {
3622 field = option_type->fields[field_num];
3624 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3626 if (!search_notify(type, field, &j) )
3629 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3630 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3635 current_data = &info->data[info->count];
3637 construct_info_data(current_data, type, field, id);
3639 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3640 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3642 notify_info_data_table[j].fn(snum, current_data, queue,
3648 free_a_printer(&printer, 2);
3652 /*******************************************************************
3654 * fill a notify_info struct with info asked
3656 ********************************************************************/
3658 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3659 SPOOL_NOTIFY_INFO *info,
3660 NT_PRINTER_INFO_LEVEL *printer,
3661 int snum, SPOOL_NOTIFY_OPTION_TYPE
3662 *option_type, uint32 id,
3663 TALLOC_CTX *mem_ctx)
3669 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3671 DEBUG(4,("construct_notify_jobs_info\n"));
3673 type = option_type->type;
3675 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3676 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3677 option_type->count));
3679 for(field_num=0; field_num<option_type->count; field_num++) {
3680 field = option_type->fields[field_num];
3682 if (!search_notify(type, field, &j) )
3685 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3686 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3689 else info->data = tid;
3691 current_data=&(info->data[info->count]);
3693 construct_info_data(current_data, type, field, id);
3694 notify_info_data_table[j].fn(snum, current_data, queue,
3703 * JFM: The enumeration is not that simple, it's even non obvious.
3705 * let's take an example: I want to monitor the PRINTER SERVER for
3706 * the printer's name and the number of jobs currently queued.
3707 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3708 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3710 * I have 3 printers on the back of my server.
3712 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3715 * 1 printer 1 name 1
3716 * 2 printer 1 cjob 1
3717 * 3 printer 2 name 2
3718 * 4 printer 2 cjob 2
3719 * 5 printer 3 name 3
3720 * 6 printer 3 name 3
3722 * that's the print server case, the printer case is even worse.
3725 /*******************************************************************
3727 * enumerate all printers on the printserver
3728 * fill a notify_info struct with info asked
3730 ********************************************************************/
3732 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3733 SPOOL_NOTIFY_INFO *info,
3734 TALLOC_CTX *mem_ctx)
3737 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3738 int n_services=lp_numservices();
3740 SPOOL_NOTIFY_OPTION *option;
3741 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3743 DEBUG(4,("printserver_notify_info\n"));
3748 option=Printer->notify.option;
3753 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3754 sending a ffpcn() request first */
3759 for (i=0; i<option->count; i++) {
3760 option_type=&(option->ctr.type[i]);
3762 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3765 for (snum=0; snum<n_services; snum++)
3767 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3768 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3774 * Debugging information, don't delete.
3777 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3778 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3779 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3781 for (i=0; i<info->count; i++) {
3782 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3783 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3784 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3791 /*******************************************************************
3793 * fill a notify_info struct with info asked
3795 ********************************************************************/
3797 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3798 TALLOC_CTX *mem_ctx)
3801 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3804 SPOOL_NOTIFY_OPTION *option;
3805 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3807 print_queue_struct *queue=NULL;
3808 print_status_struct status;
3810 DEBUG(4,("printer_notify_info\n"));
3815 option=Printer->notify.option;
3821 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3822 sending a ffpcn() request first */
3827 get_printer_snum(p, hnd, &snum);
3829 for (i=0; i<option->count; i++) {
3830 option_type=&option->ctr.type[i];
3832 switch ( option_type->type ) {
3833 case PRINTER_NOTIFY_TYPE:
3834 if(construct_notify_printer_info(Printer, info, snum,
3840 case JOB_NOTIFY_TYPE: {
3841 NT_PRINTER_INFO_LEVEL *printer = NULL;
3843 count = print_queue_status(snum, &queue, &status);
3845 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3848 for (j=0; j<count; j++) {
3849 construct_notify_jobs_info(&queue[j], info,
3856 free_a_printer(&printer, 2);
3866 * Debugging information, don't delete.
3869 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3870 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3871 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3873 for (i=0; i<info->count; i++) {
3874 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3875 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3876 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3882 /********************************************************************
3884 ********************************************************************/
3886 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3888 POLICY_HND *handle = &q_u->handle;
3889 SPOOL_NOTIFY_INFO *info = &r_u->info;
3891 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3892 WERROR result = WERR_BADFID;
3894 /* we always have a NOTIFY_INFO struct */
3898 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3899 OUR_HANDLE(handle)));
3903 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3906 * We are now using the change value, and
3907 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3908 * I don't have a global notification system, I'm sending back all the
3909 * informations even when _NOTHING_ has changed.
3912 /* We need to keep track of the change value to send back in
3913 RRPCN replies otherwise our updates are ignored. */
3915 Printer->notify.fnpcn = True;
3917 if (Printer->notify.client_connected) {
3918 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3919 Printer->notify.change = q_u->change;
3922 /* just ignore the SPOOL_NOTIFY_OPTION */
3924 switch (Printer->printer_type) {
3925 case PRINTER_HANDLE_IS_PRINTSERVER:
3926 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3929 case PRINTER_HANDLE_IS_PRINTER:
3930 result = printer_notify_info(p, handle, info, p->mem_ctx);
3934 Printer->notify.fnpcn = False;
3940 /********************************************************************
3941 * construct_printer_info_0
3942 * fill a printer_info_0 struct
3943 ********************************************************************/
3945 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3949 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3950 counter_printer_0 *session_counter;
3951 uint32 global_counter;
3954 print_status_struct status;
3956 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3959 count = print_queue_length(snum, &status);
3961 /* check if we already have a counter for this printer */
3962 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3963 if (session_counter->snum == snum)
3967 /* it's the first time, add it to the list */
3968 if (session_counter==NULL) {
3969 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3970 free_a_printer(&ntprinter, 2);
3973 ZERO_STRUCTP(session_counter);
3974 session_counter->snum=snum;
3975 session_counter->counter=0;
3976 DLIST_ADD(counter_list, session_counter);
3980 session_counter->counter++;
3983 * the global_counter should be stored in a TDB as it's common to all the clients
3984 * and should be zeroed on samba startup
3986 global_counter=session_counter->counter;
3988 pstrcpy(chaine,ntprinter->info_2->printername);
3990 init_unistr(&printer->printername, chaine);
3992 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3993 init_unistr(&printer->servername, chaine);
3995 printer->cjobs = count;
3996 printer->total_jobs = 0;
3997 printer->total_bytes = 0;
3999 setuptime = (time_t)ntprinter->info_2->setuptime;
4000 t=gmtime(&setuptime);
4002 printer->year = t->tm_year+1900;
4003 printer->month = t->tm_mon+1;
4004 printer->dayofweek = t->tm_wday;
4005 printer->day = t->tm_mday;
4006 printer->hour = t->tm_hour;
4007 printer->minute = t->tm_min;
4008 printer->second = t->tm_sec;
4009 printer->milliseconds = 0;
4011 printer->global_counter = global_counter;
4012 printer->total_pages = 0;
4014 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4015 printer->major_version = 0x0005; /* NT 5 */
4016 printer->build_version = 0x0893; /* build 2195 */
4018 printer->unknown7 = 0x1;
4019 printer->unknown8 = 0x0;
4020 printer->unknown9 = 0x0;
4021 printer->session_counter = session_counter->counter;
4022 printer->unknown11 = 0x0;
4023 printer->printer_errors = 0x0; /* number of print failure */
4024 printer->unknown13 = 0x0;
4025 printer->unknown14 = 0x1;
4026 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4027 printer->unknown16 = 0x0;
4028 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4029 printer->unknown18 = 0x0;
4030 printer->status = nt_printq_status(status.status);
4031 printer->unknown20 = 0x0;
4032 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4033 printer->unknown22 = 0x0;
4034 printer->unknown23 = 0x6; /* 6 ???*/
4035 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4036 printer->unknown25 = 0;
4037 printer->unknown26 = 0;
4038 printer->unknown27 = 0;
4039 printer->unknown28 = 0;
4040 printer->unknown29 = 0;
4042 free_a_printer(&ntprinter,2);
4046 /********************************************************************
4047 * construct_printer_info_1
4048 * fill a printer_info_1 struct
4049 ********************************************************************/
4050 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4054 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4056 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4059 printer->flags=flags;
4061 if (*ntprinter->info_2->comment == '\0') {
4062 init_unistr(&printer->comment, lp_comment(snum));
4063 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4064 ntprinter->info_2->drivername, lp_comment(snum));
4067 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4068 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4069 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4072 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4074 init_unistr(&printer->description, chaine);
4075 init_unistr(&printer->name, chaine2);
4077 free_a_printer(&ntprinter,2);
4082 /****************************************************************************
4083 Free a DEVMODE struct.
4084 ****************************************************************************/
4086 static void free_dev_mode(DEVICEMODE *dev)
4091 SAFE_FREE(dev->private);
4096 /****************************************************************************
4097 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4098 should be valid upon entry
4099 ****************************************************************************/
4101 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4103 if ( !devmode || !ntdevmode )
4106 init_unistr(&devmode->devicename, ntdevmode->devicename);
4108 init_unistr(&devmode->formname, ntdevmode->formname);
4110 devmode->specversion = ntdevmode->specversion;
4111 devmode->driverversion = ntdevmode->driverversion;
4112 devmode->size = ntdevmode->size;
4113 devmode->driverextra = ntdevmode->driverextra;
4114 devmode->fields = ntdevmode->fields;
4116 devmode->orientation = ntdevmode->orientation;
4117 devmode->papersize = ntdevmode->papersize;
4118 devmode->paperlength = ntdevmode->paperlength;
4119 devmode->paperwidth = ntdevmode->paperwidth;
4120 devmode->scale = ntdevmode->scale;
4121 devmode->copies = ntdevmode->copies;
4122 devmode->defaultsource = ntdevmode->defaultsource;
4123 devmode->printquality = ntdevmode->printquality;
4124 devmode->color = ntdevmode->color;
4125 devmode->duplex = ntdevmode->duplex;
4126 devmode->yresolution = ntdevmode->yresolution;
4127 devmode->ttoption = ntdevmode->ttoption;
4128 devmode->collate = ntdevmode->collate;
4129 devmode->icmmethod = ntdevmode->icmmethod;
4130 devmode->icmintent = ntdevmode->icmintent;
4131 devmode->mediatype = ntdevmode->mediatype;
4132 devmode->dithertype = ntdevmode->dithertype;
4134 if (ntdevmode->private != NULL) {
4135 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4142 /****************************************************************************
4143 Create a DEVMODE struct. Returns malloced memory.
4144 ****************************************************************************/
4146 DEVICEMODE *construct_dev_mode(int snum)
4148 NT_PRINTER_INFO_LEVEL *printer = NULL;
4149 DEVICEMODE *devmode = NULL;
4151 DEBUG(7,("construct_dev_mode\n"));
4153 DEBUGADD(8,("getting printer characteristics\n"));
4155 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4158 if ( !printer->info_2->devmode ) {
4159 DEBUG(5, ("BONG! There was no device mode!\n"));
4163 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4164 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4168 ZERO_STRUCTP(devmode);
4170 DEBUGADD(8,("loading DEVICEMODE\n"));
4172 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4173 free_dev_mode( devmode );
4178 free_a_printer(&printer,2);
4183 /********************************************************************
4184 * construct_printer_info_2
4185 * fill a printer_info_2 struct
4186 ********************************************************************/
4188 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4191 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4193 print_status_struct status;
4195 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4198 count = print_queue_length(snum, &status);
4200 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4201 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4202 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4203 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4204 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4206 if (*ntprinter->info_2->comment == '\0')
4207 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4209 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4211 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4212 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4213 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4214 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4215 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4217 printer->attributes = ntprinter->info_2->attributes;
4219 printer->priority = ntprinter->info_2->priority; /* priority */
4220 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4221 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4222 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4223 printer->status = nt_printq_status(status.status); /* status */
4224 printer->cjobs = count; /* jobs */
4225 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4227 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4228 DEBUG(8, ("Returning NULL Devicemode!\n"));
4231 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4232 /* steal the printer info sec_desc structure. [badly done]. */
4233 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4234 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4235 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4236 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4239 printer->secdesc = NULL;
4242 free_a_printer(&ntprinter, 2);
4246 /********************************************************************
4247 * construct_printer_info_3
4248 * fill a printer_info_3 struct
4249 ********************************************************************/
4251 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4253 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4254 PRINTER_INFO_3 *printer = NULL;
4256 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4260 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4261 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4265 ZERO_STRUCTP(printer);
4267 printer->flags = 4; /* These are the components of the SD we are returning. */
4268 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4269 /* steal the printer info sec_desc structure. [badly done]. */
4270 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4274 * Set the flags for the components we are returning.
4277 if (printer->secdesc->owner_sid)
4278 printer->flags |= OWNER_SECURITY_INFORMATION;
4280 if (printer->secdesc->grp_sid)
4281 printer->flags |= GROUP_SECURITY_INFORMATION;
4283 if (printer->secdesc->dacl)
4284 printer->flags |= DACL_SECURITY_INFORMATION;
4286 if (printer->secdesc->sacl)
4287 printer->flags |= SACL_SECURITY_INFORMATION;
4290 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4291 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4292 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4295 free_a_printer(&ntprinter, 2);
4297 *pp_printer = printer;
4301 /********************************************************************
4302 * construct_printer_info_4
4303 * fill a printer_info_4 struct
4304 ********************************************************************/
4306 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4308 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4310 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4313 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4314 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4315 printer->attributes = ntprinter->info_2->attributes;
4317 free_a_printer(&ntprinter, 2);
4321 /********************************************************************
4322 * construct_printer_info_5
4323 * fill a printer_info_5 struct
4324 ********************************************************************/
4326 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4328 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4330 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4333 init_unistr(&printer->printername, ntprinter->info_2->printername);
4334 init_unistr(&printer->portname, ntprinter->info_2->portname);
4335 printer->attributes = ntprinter->info_2->attributes;
4337 /* these two are not used by NT+ according to MSDN */
4339 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4340 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4342 free_a_printer(&ntprinter, 2);
4347 /********************************************************************
4348 * construct_printer_info_7
4349 * fill a printer_info_7 struct
4350 ********************************************************************/
4352 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4354 char *guid_str = NULL;
4357 if (is_printer_published(print_hnd, snum, &guid)) {
4358 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4359 strupper_m(guid_str);
4360 init_unistr(&printer->guid, guid_str);
4361 printer->action = SPOOL_DS_PUBLISH;
4363 init_unistr(&printer->guid, "");
4364 printer->action = SPOOL_DS_UNPUBLISH;
4370 /********************************************************************
4371 Spoolss_enumprinters.
4372 ********************************************************************/
4374 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4378 int n_services=lp_numservices();
4379 PRINTER_INFO_1 *tp, *printers=NULL;
4380 PRINTER_INFO_1 current_prt;
4382 DEBUG(4,("enum_all_printers_info_1\n"));
4384 for (snum=0; snum<n_services; snum++) {
4385 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4386 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4388 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4389 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4390 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4391 SAFE_FREE(printers);
4396 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4398 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4404 /* check the required size. */
4405 for (i=0; i<*returned; i++)
4406 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4408 if (!alloc_buffer_size(buffer, *needed))
4409 return WERR_INSUFFICIENT_BUFFER;
4411 /* fill the buffer with the structures */
4412 for (i=0; i<*returned; i++)
4413 smb_io_printer_info_1("", buffer, &printers[i], 0);
4416 SAFE_FREE(printers);
4418 if (*needed > offered) {
4420 return WERR_INSUFFICIENT_BUFFER;
4426 /********************************************************************
4427 enum_all_printers_info_1_local.
4428 *********************************************************************/
4430 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4432 DEBUG(4,("enum_all_printers_info_1_local\n"));
4434 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4437 /********************************************************************
4438 enum_all_printers_info_1_name.
4439 *********************************************************************/
4441 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4445 DEBUG(4,("enum_all_printers_info_1_name\n"));
4447 if ((name[0] == '\\') && (name[1] == '\\'))
4450 if (is_myname_or_ipaddr(s)) {
4451 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4454 return WERR_INVALID_NAME;
4457 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4458 /********************************************************************
4459 enum_all_printers_info_1_remote.
4460 *********************************************************************/
4462 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4464 PRINTER_INFO_1 *printer;
4465 fstring printername;
4468 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4470 /* JFM: currently it's more a place holder than anything else.
4471 * In the spooler world there is a notion of server registration.
4472 * the print servers are registered on the PDC (in the same domain)
4474 * We should have a TDB here. The registration is done thru an
4475 * undocumented RPC call.
4478 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4483 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4484 slprintf(desc, sizeof(desc)-1,"%s", name);
4485 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4487 init_unistr(&printer->description, desc);
4488 init_unistr(&printer->name, printername);
4489 init_unistr(&printer->comment, comment);
4490 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4492 /* check the required size. */
4493 *needed += spoolss_size_printer_info_1(printer);
4495 if (!alloc_buffer_size(buffer, *needed)) {
4497 return WERR_INSUFFICIENT_BUFFER;
4500 /* fill the buffer with the structures */
4501 smb_io_printer_info_1("", buffer, printer, 0);
4506 if (*needed > offered) {
4508 return WERR_INSUFFICIENT_BUFFER;
4516 /********************************************************************
4517 enum_all_printers_info_1_network.
4518 *********************************************************************/
4520 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4524 DEBUG(4,("enum_all_printers_info_1_network\n"));
4526 /* If we respond to a enum_printers level 1 on our name with flags
4527 set to PRINTER_ENUM_REMOTE with a list of printers then these
4528 printers incorrectly appear in the APW browse list.
4529 Specifically the printers for the server appear at the workgroup
4530 level where all the other servers in the domain are
4531 listed. Windows responds to this call with a
4532 WERR_CAN_NOT_COMPLETE so we should do the same. */
4534 if (name[0] == '\\' && name[1] == '\\')
4537 if (is_myname_or_ipaddr(s))
4538 return WERR_CAN_NOT_COMPLETE;
4540 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4543 /********************************************************************
4544 * api_spoolss_enumprinters
4546 * called from api_spoolss_enumprinters (see this to understand)
4547 ********************************************************************/
4549 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4553 int n_services=lp_numservices();
4554 PRINTER_INFO_2 *tp, *printers=NULL;
4555 PRINTER_INFO_2 current_prt;
4557 for (snum=0; snum<n_services; snum++) {
4558 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4559 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4561 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4562 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) == NULL) {
4563 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4564 SAFE_FREE(printers);
4569 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4570 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4576 /* check the required size. */
4577 for (i=0; i<*returned; i++)
4578 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4580 if (!alloc_buffer_size(buffer, *needed)) {
4581 for (i=0; i<*returned; i++) {
4582 free_devmode(printers[i].devmode);
4584 SAFE_FREE(printers);
4585 return WERR_INSUFFICIENT_BUFFER;
4588 /* fill the buffer with the structures */
4589 for (i=0; i<*returned; i++)
4590 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4593 for (i=0; i<*returned; i++) {
4594 free_devmode(printers[i].devmode);
4596 SAFE_FREE(printers);
4598 if (*needed > offered) {
4600 return WERR_INSUFFICIENT_BUFFER;
4606 /********************************************************************
4607 * handle enumeration of printers at level 1
4608 ********************************************************************/
4610 static WERROR enumprinters_level1( uint32 flags, fstring name,
4611 NEW_BUFFER *buffer, uint32 offered,
4612 uint32 *needed, uint32 *returned)
4614 /* Not all the flags are equals */
4616 if (flags & PRINTER_ENUM_LOCAL)
4617 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4619 if (flags & PRINTER_ENUM_NAME)
4620 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4622 #if 0 /* JERRY - disabled for now */
4623 if (flags & PRINTER_ENUM_REMOTE)
4624 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4627 if (flags & PRINTER_ENUM_NETWORK)
4628 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4630 return WERR_OK; /* NT4sp5 does that */
4633 /********************************************************************
4634 * handle enumeration of printers at level 2
4635 ********************************************************************/
4637 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4638 NEW_BUFFER *buffer, uint32 offered,
4639 uint32 *needed, uint32 *returned)
4641 char *s = servername;
4643 if (flags & PRINTER_ENUM_LOCAL) {
4644 return enum_all_printers_info_2(buffer, offered, needed, returned);
4647 if (flags & PRINTER_ENUM_NAME) {
4648 if ((servername[0] == '\\') && (servername[1] == '\\'))
4650 if (is_myname_or_ipaddr(s))
4651 return enum_all_printers_info_2(buffer, offered, needed, returned);
4653 return WERR_INVALID_NAME;
4656 if (flags & PRINTER_ENUM_REMOTE)
4657 return WERR_UNKNOWN_LEVEL;
4662 /********************************************************************
4663 * handle enumeration of printers at level 5
4664 ********************************************************************/
4666 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4667 NEW_BUFFER *buffer, uint32 offered,
4668 uint32 *needed, uint32 *returned)
4670 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4674 /********************************************************************
4675 * api_spoolss_enumprinters
4677 * called from api_spoolss_enumprinters (see this to understand)
4678 ********************************************************************/
4680 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4682 uint32 flags = q_u->flags;
4683 UNISTR2 *servername = &q_u->servername;
4684 uint32 level = q_u->level;
4685 NEW_BUFFER *buffer = NULL;
4686 uint32 offered = q_u->offered;
4687 uint32 *needed = &r_u->needed;
4688 uint32 *returned = &r_u->returned;
4692 /* that's an [in out] buffer */
4693 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4694 buffer = r_u->buffer;
4696 DEBUG(4,("_spoolss_enumprinters\n"));
4703 * flags==PRINTER_ENUM_NAME
4704 * if name=="" then enumerates all printers
4705 * if name!="" then enumerate the printer
4706 * flags==PRINTER_ENUM_REMOTE
4707 * name is NULL, enumerate printers
4708 * Level 2: name!="" enumerates printers, name can't be NULL
4709 * Level 3: doesn't exist
4710 * Level 4: does a local registry lookup
4711 * Level 5: same as Level 2
4714 unistr2_to_ascii(name, servername, sizeof(name)-1);
4719 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4721 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4723 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4728 return WERR_UNKNOWN_LEVEL;
4731 /****************************************************************************
4732 ****************************************************************************/
4734 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4736 PRINTER_INFO_0 *printer=NULL;
4738 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4741 construct_printer_info_0(print_hnd, printer, snum);
4743 /* check the required size. */
4744 *needed += spoolss_size_printer_info_0(printer);
4746 if (!alloc_buffer_size(buffer, *needed)) {
4748 return WERR_INSUFFICIENT_BUFFER;
4751 /* fill the buffer with the structures */
4752 smb_io_printer_info_0("", buffer, printer, 0);
4757 if (*needed > offered) {
4758 return WERR_INSUFFICIENT_BUFFER;
4764 /****************************************************************************
4765 ****************************************************************************/
4767 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4769 PRINTER_INFO_1 *printer=NULL;
4771 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4774 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4776 /* check the required size. */
4777 *needed += spoolss_size_printer_info_1(printer);
4779 if (!alloc_buffer_size(buffer, *needed)) {
4781 return WERR_INSUFFICIENT_BUFFER;
4784 /* fill the buffer with the structures */
4785 smb_io_printer_info_1("", buffer, printer, 0);
4790 if (*needed > offered) {
4791 return WERR_INSUFFICIENT_BUFFER;
4797 /****************************************************************************
4798 ****************************************************************************/
4800 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4802 PRINTER_INFO_2 *printer=NULL;
4804 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4807 construct_printer_info_2(print_hnd, printer, snum);
4809 /* check the required size. */
4810 *needed += spoolss_size_printer_info_2(printer);
4812 if (!alloc_buffer_size(buffer, *needed)) {
4813 free_printer_info_2(printer);
4814 return WERR_INSUFFICIENT_BUFFER;
4817 /* fill the buffer with the structures */
4818 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4819 free_printer_info_2(printer);
4824 free_printer_info_2(printer);
4826 if (*needed > offered) {
4827 return WERR_INSUFFICIENT_BUFFER;
4833 /****************************************************************************
4834 ****************************************************************************/
4836 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4838 PRINTER_INFO_3 *printer=NULL;
4840 if (!construct_printer_info_3(print_hnd, &printer, snum))
4843 /* check the required size. */
4844 *needed += spoolss_size_printer_info_3(printer);
4846 if (!alloc_buffer_size(buffer, *needed)) {
4847 free_printer_info_3(printer);
4848 return WERR_INSUFFICIENT_BUFFER;
4851 /* fill the buffer with the structures */
4852 smb_io_printer_info_3("", buffer, printer, 0);
4855 free_printer_info_3(printer);
4857 if (*needed > offered) {
4858 return WERR_INSUFFICIENT_BUFFER;
4864 /****************************************************************************
4865 ****************************************************************************/
4867 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4869 PRINTER_INFO_4 *printer=NULL;
4871 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4874 if (!construct_printer_info_4(print_hnd, printer, snum))
4877 /* check the required size. */
4878 *needed += spoolss_size_printer_info_4(printer);
4880 if (!alloc_buffer_size(buffer, *needed)) {
4881 free_printer_info_4(printer);
4882 return WERR_INSUFFICIENT_BUFFER;
4885 /* fill the buffer with the structures */
4886 smb_io_printer_info_4("", buffer, printer, 0);
4889 free_printer_info_4(printer);
4891 if (*needed > offered) {
4892 return WERR_INSUFFICIENT_BUFFER;
4898 /****************************************************************************
4899 ****************************************************************************/
4901 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4903 PRINTER_INFO_5 *printer=NULL;
4905 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4908 if (!construct_printer_info_5(print_hnd, printer, snum))
4911 /* check the required size. */
4912 *needed += spoolss_size_printer_info_5(printer);
4914 if (!alloc_buffer_size(buffer, *needed)) {
4915 free_printer_info_5(printer);
4916 return WERR_INSUFFICIENT_BUFFER;
4919 /* fill the buffer with the structures */
4920 smb_io_printer_info_5("", buffer, printer, 0);
4923 free_printer_info_5(printer);
4925 if (*needed > offered) {
4926 return WERR_INSUFFICIENT_BUFFER;
4932 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4934 PRINTER_INFO_7 *printer=NULL;
4936 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4939 if (!construct_printer_info_7(print_hnd, printer, snum))
4942 /* check the required size. */
4943 *needed += spoolss_size_printer_info_7(printer);
4945 if (!alloc_buffer_size(buffer, *needed)) {
4946 free_printer_info_7(printer);
4947 return WERR_INSUFFICIENT_BUFFER;
4950 /* fill the buffer with the structures */
4951 smb_io_printer_info_7("", buffer, printer, 0);
4954 free_printer_info_7(printer);
4956 if (*needed > offered) {
4957 return WERR_INSUFFICIENT_BUFFER;
4963 /****************************************************************************
4964 ****************************************************************************/
4966 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4968 POLICY_HND *handle = &q_u->handle;
4969 uint32 level = q_u->level;
4970 NEW_BUFFER *buffer = NULL;
4971 uint32 offered = q_u->offered;
4972 uint32 *needed = &r_u->needed;
4973 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4977 /* that's an [in out] buffer */
4978 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4979 buffer = r_u->buffer;
4983 if (!get_printer_snum(p, handle, &snum))
4988 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4990 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4992 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4994 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4996 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4998 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5000 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5002 return WERR_UNKNOWN_LEVEL;
5005 /********************************************************************
5006 * fill a DRIVER_INFO_1 struct
5007 ********************************************************************/
5009 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5011 init_unistr( &info->name, driver.info_3->name);
5014 /********************************************************************
5015 * construct_printer_driver_info_1
5016 ********************************************************************/
5018 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5020 NT_PRINTER_INFO_LEVEL *printer = NULL;
5021 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5023 ZERO_STRUCT(driver);
5025 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5026 return WERR_INVALID_PRINTER_NAME;
5028 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5029 return WERR_UNKNOWN_PRINTER_DRIVER;
5031 fill_printer_driver_info_1(info, driver, servername, architecture);
5033 free_a_printer(&printer,2);
5038 /********************************************************************
5039 * construct_printer_driver_info_2
5040 * fill a printer_info_2 struct
5041 ********************************************************************/
5043 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5047 info->version=driver.info_3->cversion;
5049 init_unistr( &info->name, driver.info_3->name );
5050 init_unistr( &info->architecture, driver.info_3->environment );
5053 if (strlen(driver.info_3->driverpath)) {
5054 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5055 init_unistr( &info->driverpath, temp );
5057 init_unistr( &info->driverpath, "" );
5059 if (strlen(driver.info_3->datafile)) {
5060 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5061 init_unistr( &info->datafile, temp );
5063 init_unistr( &info->datafile, "" );
5065 if (strlen(driver.info_3->configfile)) {
5066 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5067 init_unistr( &info->configfile, temp );
5069 init_unistr( &info->configfile, "" );
5072 /********************************************************************
5073 * construct_printer_driver_info_2
5074 * fill a printer_info_2 struct
5075 ********************************************************************/
5077 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5079 NT_PRINTER_INFO_LEVEL *printer = NULL;
5080 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5082 ZERO_STRUCT(printer);
5083 ZERO_STRUCT(driver);
5085 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5086 return WERR_INVALID_PRINTER_NAME;
5088 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5089 return WERR_UNKNOWN_PRINTER_DRIVER;
5091 fill_printer_driver_info_2(info, driver, servername);
5093 free_a_printer(&printer,2);
5098 /********************************************************************
5099 * copy a strings array and convert to UNICODE
5101 * convert an array of ascii string to a UNICODE string
5102 ********************************************************************/
5104 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5112 DEBUG(6,("init_unistr_array\n"));
5123 v = ""; /* hack to handle null lists */
5126 /* hack to allow this to be used in places other than when generating
5127 the list of dependent files */
5130 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5134 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5136 /* add one extra unit16 for the second terminating NULL */
5138 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5139 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5147 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5152 /* special case for ""; we need to add both NULL's here */
5154 (*uni_array)[j++]=0x0000;
5155 (*uni_array)[j]=0x0000;
5158 DEBUGADD(6,("last one:done\n"));
5160 /* return size of array in uint16's */
5165 /********************************************************************
5166 * construct_printer_info_3
5167 * fill a printer_info_3 struct
5168 ********************************************************************/
5170 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5176 info->version=driver.info_3->cversion;
5178 init_unistr( &info->name, driver.info_3->name );
5179 init_unistr( &info->architecture, driver.info_3->environment );
5181 if (strlen(driver.info_3->driverpath)) {
5182 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5183 init_unistr( &info->driverpath, temp );
5185 init_unistr( &info->driverpath, "" );
5187 if (strlen(driver.info_3->datafile)) {
5188 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5189 init_unistr( &info->datafile, temp );
5191 init_unistr( &info->datafile, "" );
5193 if (strlen(driver.info_3->configfile)) {
5194 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5195 init_unistr( &info->configfile, temp );
5197 init_unistr( &info->configfile, "" );
5199 if (strlen(driver.info_3->helpfile)) {
5200 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5201 init_unistr( &info->helpfile, temp );
5203 init_unistr( &info->helpfile, "" );
5205 init_unistr( &info->monitorname, driver.info_3->monitorname );
5206 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5208 info->dependentfiles=NULL;
5209 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5212 /********************************************************************
5213 * construct_printer_info_3
5214 * fill a printer_info_3 struct
5215 ********************************************************************/
5217 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5219 NT_PRINTER_INFO_LEVEL *printer = NULL;
5220 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5222 ZERO_STRUCT(driver);
5224 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5225 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5226 if (!W_ERROR_IS_OK(status))
5227 return WERR_INVALID_PRINTER_NAME;
5229 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5230 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5235 * I put this code in during testing. Helpful when commenting out the
5236 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5237 * as win2k always queries the driver using an infor level of 6.
5238 * I've left it in (but ifdef'd out) because I'll probably
5239 * use it in experimentation again in the future. --jerry 22/01/2002
5242 if (!W_ERROR_IS_OK(status)) {
5244 * Is this a W2k client ?
5247 /* Yes - try again with a WinNT driver. */
5249 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5250 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5254 if (!W_ERROR_IS_OK(status)) {
5255 free_a_printer(&printer,2);
5256 return WERR_UNKNOWN_PRINTER_DRIVER;
5264 fill_printer_driver_info_3(info, driver, servername);
5266 free_a_printer(&printer,2);
5271 /********************************************************************
5272 * construct_printer_info_6
5273 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5274 ********************************************************************/
5276 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5282 memset(&nullstr, '\0', sizeof(fstring));
5284 info->version=driver.info_3->cversion;
5286 init_unistr( &info->name, driver.info_3->name );
5287 init_unistr( &info->architecture, driver.info_3->environment );
5289 if (strlen(driver.info_3->driverpath)) {
5290 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5291 init_unistr( &info->driverpath, temp );
5293 init_unistr( &info->driverpath, "" );
5295 if (strlen(driver.info_3->datafile)) {
5296 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5297 init_unistr( &info->datafile, temp );
5299 init_unistr( &info->datafile, "" );
5301 if (strlen(driver.info_3->configfile)) {
5302 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5303 init_unistr( &info->configfile, temp );
5305 init_unistr( &info->configfile, "" );
5307 if (strlen(driver.info_3->helpfile)) {
5308 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5309 init_unistr( &info->helpfile, temp );
5311 init_unistr( &info->helpfile, "" );
5313 init_unistr( &info->monitorname, driver.info_3->monitorname );
5314 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5316 info->dependentfiles = NULL;
5317 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5319 info->previousdrivernames=NULL;
5320 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5322 info->driver_date.low=0;
5323 info->driver_date.high=0;
5326 info->driver_version_low=0;
5327 info->driver_version_high=0;
5329 init_unistr( &info->mfgname, "");
5330 init_unistr( &info->oem_url, "");
5331 init_unistr( &info->hardware_id, "");
5332 init_unistr( &info->provider, "");
5335 /********************************************************************
5336 * construct_printer_info_6
5337 * fill a printer_info_6 struct
5338 ********************************************************************/
5340 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5341 fstring servername, fstring architecture, uint32 version)
5343 NT_PRINTER_INFO_LEVEL *printer = NULL;
5344 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5347 ZERO_STRUCT(driver);
5349 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5351 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5353 if (!W_ERROR_IS_OK(status))
5354 return WERR_INVALID_PRINTER_NAME;
5356 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5358 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5360 if (!W_ERROR_IS_OK(status))
5363 * Is this a W2k client ?
5367 free_a_printer(&printer,2);
5368 return WERR_UNKNOWN_PRINTER_DRIVER;
5371 /* Yes - try again with a WinNT driver. */
5373 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5374 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5375 if (!W_ERROR_IS_OK(status)) {
5376 free_a_printer(&printer,2);
5377 return WERR_UNKNOWN_PRINTER_DRIVER;
5381 fill_printer_driver_info_6(info, driver, servername);
5383 free_a_printer(&printer,2);
5384 free_a_printer_driver(driver, 3);
5389 /****************************************************************************
5390 ****************************************************************************/
5392 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5394 SAFE_FREE(info->dependentfiles);
5397 /****************************************************************************
5398 ****************************************************************************/
5400 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5402 SAFE_FREE(info->dependentfiles);
5406 /****************************************************************************
5407 ****************************************************************************/
5409 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5411 DRIVER_INFO_1 *info=NULL;
5414 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5417 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5418 if (!W_ERROR_IS_OK(status)) {
5423 /* check the required size. */
5424 *needed += spoolss_size_printer_driver_info_1(info);
5426 if (!alloc_buffer_size(buffer, *needed)) {
5428 return WERR_INSUFFICIENT_BUFFER;
5431 /* fill the buffer with the structures */
5432 smb_io_printer_driver_info_1("", buffer, info, 0);
5437 if (*needed > offered)
5438 return WERR_INSUFFICIENT_BUFFER;
5443 /****************************************************************************
5444 ****************************************************************************/
5446 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5448 DRIVER_INFO_2 *info=NULL;
5451 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5454 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5455 if (!W_ERROR_IS_OK(status)) {
5460 /* check the required size. */
5461 *needed += spoolss_size_printer_driver_info_2(info);
5463 if (!alloc_buffer_size(buffer, *needed)) {
5465 return WERR_INSUFFICIENT_BUFFER;
5468 /* fill the buffer with the structures */
5469 smb_io_printer_driver_info_2("", buffer, info, 0);
5474 if (*needed > offered)
5475 return WERR_INSUFFICIENT_BUFFER;
5480 /****************************************************************************
5481 ****************************************************************************/
5483 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5490 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5491 if (!W_ERROR_IS_OK(status)) {
5495 /* check the required size. */
5496 *needed += spoolss_size_printer_driver_info_3(&info);
5498 if (!alloc_buffer_size(buffer, *needed)) {
5499 free_printer_driver_info_3(&info);
5500 return WERR_INSUFFICIENT_BUFFER;
5503 /* fill the buffer with the structures */
5504 smb_io_printer_driver_info_3("", buffer, &info, 0);
5506 free_printer_driver_info_3(&info);
5508 if (*needed > offered)
5509 return WERR_INSUFFICIENT_BUFFER;
5514 /****************************************************************************
5515 ****************************************************************************/
5517 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5524 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5525 if (!W_ERROR_IS_OK(status)) {
5529 /* check the required size. */
5530 *needed += spoolss_size_printer_driver_info_6(&info);
5532 if (!alloc_buffer_size(buffer, *needed)) {
5533 free_printer_driver_info_6(&info);
5534 return WERR_INSUFFICIENT_BUFFER;
5537 /* fill the buffer with the structures */
5538 smb_io_printer_driver_info_6("", buffer, &info, 0);
5540 free_printer_driver_info_6(&info);
5542 if (*needed > offered)
5543 return WERR_INSUFFICIENT_BUFFER;
5548 /****************************************************************************
5549 ****************************************************************************/
5551 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5553 POLICY_HND *handle = &q_u->handle;
5554 UNISTR2 *uni_arch = &q_u->architecture;
5555 uint32 level = q_u->level;
5556 uint32 clientmajorversion = q_u->clientmajorversion;
5557 NEW_BUFFER *buffer = NULL;
5558 uint32 offered = q_u->offered;
5559 uint32 *needed = &r_u->needed;
5560 uint32 *servermajorversion = &r_u->servermajorversion;
5561 uint32 *serverminorversion = &r_u->serverminorversion;
5562 Printer_entry *printer;
5565 fstring architecture;
5568 /* that's an [in out] buffer */
5569 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5570 buffer = r_u->buffer;
5572 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5574 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5575 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5576 return WERR_INVALID_PRINTER_NAME;
5580 *servermajorversion = 0;
5581 *serverminorversion = 0;
5583 fstrcpy(servername, get_server_name( printer ));
5584 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5586 if (!get_printer_snum(p, handle, &snum))
5591 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5593 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5595 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5597 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5600 /* apparently this call is the equivalent of
5601 EnumPrinterDataEx() for the DsDriver key */
5606 return WERR_UNKNOWN_LEVEL;
5609 /****************************************************************************
5610 ****************************************************************************/
5612 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5614 POLICY_HND *handle = &q_u->handle;
5616 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5619 DEBUG(3,("Error in startpageprinter printer handle\n"));
5623 Printer->page_started=True;
5627 /****************************************************************************
5628 ****************************************************************************/
5630 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5632 POLICY_HND *handle = &q_u->handle;
5635 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5638 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5642 if (!get_printer_snum(p, handle, &snum))
5645 Printer->page_started=False;
5646 print_job_endpage(snum, Printer->jobid);
5651 /********************************************************************
5652 * api_spoolss_getprinter
5653 * called from the spoolss dispatcher
5655 ********************************************************************/
5657 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5659 POLICY_HND *handle = &q_u->handle;
5660 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5661 uint32 *jobid = &r_u->jobid;
5663 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5667 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5668 struct current_user user;
5671 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5675 get_current_user(&user, p);
5678 * a nice thing with NT is it doesn't listen to what you tell it.
5679 * when asked to send _only_ RAW datas, it tries to send datas
5682 * So I add checks like in NT Server ...
5685 if (info_1->p_datatype != 0) {
5686 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5687 if (strcmp(datatype, "RAW") != 0) {
5689 return WERR_INVALID_DATATYPE;
5693 /* get the share number of the printer */
5694 if (!get_printer_snum(p, handle, &snum)) {
5698 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5700 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5702 /* An error occured in print_job_start() so return an appropriate
5705 if (Printer->jobid == -1) {
5706 return map_werror_from_unix(errno);
5709 Printer->document_started=True;
5710 (*jobid) = Printer->jobid;
5715 /********************************************************************
5716 * api_spoolss_getprinter
5717 * called from the spoolss dispatcher
5719 ********************************************************************/
5721 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5723 POLICY_HND *handle = &q_u->handle;
5725 return _spoolss_enddocprinter_internal(p, handle);
5728 /****************************************************************************
5729 ****************************************************************************/
5731 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5733 POLICY_HND *handle = &q_u->handle;
5734 uint32 buffer_size = q_u->buffer_size;
5735 uint8 *buffer = q_u->buffer;
5736 uint32 *buffer_written = &q_u->buffer_size2;
5738 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5741 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5742 r_u->buffer_written = q_u->buffer_size2;
5746 if (!get_printer_snum(p, handle, &snum))
5749 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5750 if (*buffer_written == -1) {
5751 r_u->buffer_written = 0;
5752 if (errno == ENOSPC)
5753 return WERR_NO_SPOOL_SPACE;
5755 return WERR_ACCESS_DENIED;
5758 r_u->buffer_written = q_u->buffer_size2;
5763 /********************************************************************
5764 * api_spoolss_getprinter
5765 * called from the spoolss dispatcher
5767 ********************************************************************/
5769 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5772 struct current_user user;
5774 WERROR errcode = WERR_BADFUNC;
5775 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5777 get_current_user(&user, p);
5780 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5784 if (!get_printer_snum(p, handle, &snum))
5788 case PRINTER_CONTROL_PAUSE:
5789 if (print_queue_pause(&user, snum, &errcode)) {
5793 case PRINTER_CONTROL_RESUME:
5794 case PRINTER_CONTROL_UNPAUSE:
5795 if (print_queue_resume(&user, snum, &errcode)) {
5799 case PRINTER_CONTROL_PURGE:
5800 if (print_queue_purge(&user, snum, &errcode)) {
5805 return WERR_UNKNOWN_LEVEL;
5811 /********************************************************************
5812 * api_spoolss_abortprinter
5813 * From MSDN: "Deletes printer's spool file if printer is configured
5815 ********************************************************************/
5817 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5819 POLICY_HND *handle = &q_u->handle;
5820 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5822 struct current_user user;
5823 WERROR errcode = WERR_OK;
5826 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5830 if (!get_printer_snum(p, handle, &snum))
5833 get_current_user( &user, p );
5835 print_job_delete( &user, snum, Printer->jobid, &errcode );
5840 /********************************************************************
5841 * called by spoolss_api_setprinter
5842 * when updating a printer description
5843 ********************************************************************/
5845 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5846 const SPOOL_PRINTER_INFO_LEVEL *info,
5847 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5849 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5850 struct current_user user;
5854 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5856 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5857 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5858 OUR_HANDLE(handle)));
5860 result = WERR_BADFID;
5864 /* Check the user has permissions to change the security
5865 descriptor. By experimentation with two NT machines, the user
5866 requires Full Access to the printer to change security
5869 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5870 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5871 result = WERR_ACCESS_DENIED;
5875 /* NT seems to like setting the security descriptor even though
5876 nothing may have actually changed. */
5878 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5880 if (DEBUGLEVEL >= 10) {
5884 the_acl = old_secdesc_ctr->sec->dacl;
5885 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5886 PRINTERNAME(snum), the_acl->num_aces));
5888 for (i = 0; i < the_acl->num_aces; i++) {
5891 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5893 DEBUG(10, ("%s 0x%08x\n", sid_str,
5894 the_acl->ace[i].info.mask));
5897 the_acl = secdesc_ctr->sec->dacl;
5900 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5901 PRINTERNAME(snum), the_acl->num_aces));
5903 for (i = 0; i < the_acl->num_aces; i++) {
5906 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5908 DEBUG(10, ("%s 0x%08x\n", sid_str,
5909 the_acl->ace[i].info.mask));
5912 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5916 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5918 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5923 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5930 /********************************************************************
5931 Canonicalize printer info from a client
5933 ATTN: It does not matter what we set the servername to hear
5934 since we do the necessary work in get_a_printer() to set it to
5935 the correct value based on what the client sent in the
5936 _spoolss_open_printer_ex().
5937 ********************************************************************/
5939 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5941 fstring printername;
5944 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5945 "portname=%s drivername=%s comment=%s location=%s\n",
5946 info->servername, info->printername, info->sharename,
5947 info->portname, info->drivername, info->comment, info->location));
5949 /* we force some elements to "correct" values */
5950 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5951 fstrcpy(info->sharename, lp_servicename(snum));
5953 /* check to see if we allow printername != sharename */
5955 if ( lp_force_printername(snum) ) {
5956 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5957 global_myname(), info->sharename );
5960 /* make sure printername is in \\server\printername format */
5962 fstrcpy( printername, info->printername );
5964 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5965 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5969 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5970 global_myname(), p );
5973 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5974 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5981 /****************************************************************************
5982 ****************************************************************************/
5984 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5986 extern userdom_struct current_user_info;
5987 char *cmd = lp_addprinter_cmd();
5993 fstring remote_machine = "%m";
5995 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5997 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5998 cmd, printer->info_2->printername, printer->info_2->sharename,
5999 printer->info_2->portname, printer->info_2->drivername,
6000 printer->info_2->location, printer->info_2->comment, remote_machine);
6002 DEBUG(10,("Running [%s]\n", command));
6003 ret = smbrun(command, &fd);
6004 DEBUGADD(10,("returned [%d]\n", ret));
6013 /* Get lines and convert them back to dos-codepage */
6014 qlines = fd_lines_load(fd, &numlines);
6015 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6019 /* Set the portname to what the script says the portname should be. */
6020 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6021 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6023 /* Send SIGHUP to process group... is there a better way? */
6026 /* reload our services immediately */
6027 reload_services( False );
6030 file_lines_free(qlines);
6034 /********************************************************************
6035 * Called by spoolss_api_setprinter
6036 * when updating a printer description.
6037 ********************************************************************/
6039 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6040 const SPOOL_PRINTER_INFO_LEVEL *info,
6041 DEVICEMODE *devmode)
6044 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6045 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6050 DEBUG(8,("update_printer\n"));
6055 result = WERR_BADFID;
6059 if (!get_printer_snum(p, handle, &snum)) {
6060 result = WERR_BADFID;
6064 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6065 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6066 result = WERR_BADFID;
6070 DEBUGADD(8,("Converting info_2 struct\n"));
6073 * convert_printer_info converts the incoming
6074 * info from the client and overwrites the info
6075 * just read from the tdb in the pointer 'printer'.
6078 if (!convert_printer_info(info, printer, level)) {
6079 result = WERR_NOMEM;
6084 /* we have a valid devmode
6085 convert it and link it*/
6087 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6088 if (!convert_devicemode(printer->info_2->printername, devmode,
6089 &printer->info_2->devmode)) {
6090 result = WERR_NOMEM;
6095 /* Do sanity check on the requested changes for Samba */
6097 if (!check_printer_ok(printer->info_2, snum)) {
6098 result = WERR_INVALID_PARAM;
6102 /* FIXME!!! If the driver has changed we really should verify that
6103 it is installed before doing much else --jerry */
6105 /* Check calling user has permission to update printer description */
6107 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6108 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6109 result = WERR_ACCESS_DENIED;
6113 /* Call addprinter hook */
6114 /* Check changes to see if this is really needed */
6116 if ( *lp_addprinter_cmd()
6117 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6118 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6119 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6120 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6122 if ( !add_printer_hook(printer) ) {
6123 result = WERR_ACCESS_DENIED;
6128 * make sure we actually reload the services after
6129 * this as smb.conf could have a new section in it
6130 * .... shouldn't .... but could
6132 reload_services(False);
6136 * When a *new* driver is bound to a printer, the drivername is used to
6137 * lookup previously saved driver initialization info, which is then
6138 * bound to the printer, simulating what happens in the Windows arch.
6140 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6142 if (!set_driver_init(printer, 2))
6144 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6145 printer->info_2->drivername));
6148 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6149 printer->info_2->drivername));
6151 notify_printer_driver(snum, printer->info_2->drivername);
6155 * flag which changes actually occured. This is a small subset of
6156 * all the possible changes. We also have to update things in the
6160 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6161 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6162 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6163 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6165 notify_printer_comment(snum, printer->info_2->comment);
6168 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6169 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6170 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6171 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6173 notify_printer_sharename(snum, printer->info_2->sharename);
6176 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6179 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6182 pname = printer->info_2->printername;
6185 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6186 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6187 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6189 notify_printer_printername( snum, pname );
6192 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6193 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6194 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6195 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6197 notify_printer_port(snum, printer->info_2->portname);
6200 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6201 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6202 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6203 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6205 notify_printer_location(snum, printer->info_2->location);
6208 /* here we need to update some more DsSpooler keys */
6209 /* uNCName, serverName, shortServerName */
6211 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6212 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6213 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6214 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6215 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6217 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6218 global_myname(), printer->info_2->sharename );
6219 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6220 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6221 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6223 /* Update printer info */
6224 result = mod_a_printer(printer, 2);
6227 free_a_printer(&printer, 2);
6228 free_a_printer(&old_printer, 2);
6234 /****************************************************************************
6235 ****************************************************************************/
6236 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6237 const SPOOL_PRINTER_INFO_LEVEL *info)
6240 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6242 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6244 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6249 if (!get_printer_snum(p, handle, &snum))
6252 nt_printer_publish(Printer, snum, info7->action);
6256 return WERR_UNKNOWN_LEVEL;
6259 /****************************************************************************
6260 ****************************************************************************/
6262 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6264 POLICY_HND *handle = &q_u->handle;
6265 uint32 level = q_u->level;
6266 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6267 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6268 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6269 uint32 command = q_u->command;
6272 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6275 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6279 /* check the level */
6282 return control_printer(handle, command, p);
6284 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6285 if (!W_ERROR_IS_OK(result))
6288 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6291 return update_printer_sec(handle, level, info, p,
6294 return publish_or_unpublish_printer(p, handle, info);
6296 return WERR_UNKNOWN_LEVEL;
6300 /****************************************************************************
6301 ****************************************************************************/
6303 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6305 POLICY_HND *handle = &q_u->handle;
6306 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6309 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6313 if (Printer->notify.client_connected==True) {
6316 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6318 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6319 !get_printer_snum(p, handle, &snum) )
6322 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6325 Printer->notify.flags=0;
6326 Printer->notify.options=0;
6327 Printer->notify.localmachine[0]='\0';
6328 Printer->notify.printerlocal=0;
6329 if (Printer->notify.option)
6330 free_spool_notify_option(&Printer->notify.option);
6331 Printer->notify.client_connected=False;
6336 /****************************************************************************
6337 ****************************************************************************/
6339 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6341 /* that's an [in out] buffer (despite appearences to the contrary) */
6342 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6345 return WERR_INVALID_PARAM; /* this is what a NT server
6346 returns for AddJob. AddJob
6347 must fail on non-local
6351 /****************************************************************************
6352 ****************************************************************************/
6354 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6355 int position, int snum,
6356 NT_PRINTER_INFO_LEVEL *ntprinter)
6360 t=gmtime(&queue->time);
6362 job_info->jobid=queue->job;
6363 init_unistr(&job_info->printername, lp_servicename(snum));
6364 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6365 init_unistr(&job_info->username, queue->fs_user);
6366 init_unistr(&job_info->document, queue->fs_file);
6367 init_unistr(&job_info->datatype, "RAW");
6368 init_unistr(&job_info->text_status, "");
6369 job_info->status=nt_printj_status(queue->status);
6370 job_info->priority=queue->priority;
6371 job_info->position=position;
6372 job_info->totalpages=queue->page_count;
6373 job_info->pagesprinted=0;
6375 make_systemtime(&job_info->submitted, t);
6378 /****************************************************************************
6379 ****************************************************************************/
6381 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6382 int position, int snum,
6383 NT_PRINTER_INFO_LEVEL *ntprinter,
6384 DEVICEMODE *devmode)
6388 t=gmtime(&queue->time);
6390 job_info->jobid=queue->job;
6392 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6394 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6395 init_unistr(&job_info->username, queue->fs_user);
6396 init_unistr(&job_info->document, queue->fs_file);
6397 init_unistr(&job_info->notifyname, queue->fs_user);
6398 init_unistr(&job_info->datatype, "RAW");
6399 init_unistr(&job_info->printprocessor, "winprint");
6400 init_unistr(&job_info->parameters, "");
6401 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6402 init_unistr(&job_info->text_status, "");
6404 /* and here the security descriptor */
6406 job_info->status=nt_printj_status(queue->status);
6407 job_info->priority=queue->priority;
6408 job_info->position=position;
6409 job_info->starttime=0;
6410 job_info->untiltime=0;
6411 job_info->totalpages=queue->page_count;
6412 job_info->size=queue->size;
6413 make_systemtime(&(job_info->submitted), t);
6414 job_info->timeelapsed=0;
6415 job_info->pagesprinted=0;
6417 job_info->devmode = devmode;
6422 /****************************************************************************
6423 Enumjobs at level 1.
6424 ****************************************************************************/
6426 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6427 NT_PRINTER_INFO_LEVEL *ntprinter,
6428 NEW_BUFFER *buffer, uint32 offered,
6429 uint32 *needed, uint32 *returned)
6434 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6441 for (i=0; i<*returned; i++)
6442 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6446 /* check the required size. */
6447 for (i=0; i<*returned; i++)
6448 (*needed) += spoolss_size_job_info_1(&info[i]);
6450 if (!alloc_buffer_size(buffer, *needed)) {
6452 return WERR_INSUFFICIENT_BUFFER;
6455 /* fill the buffer with the structures */
6456 for (i=0; i<*returned; i++)
6457 smb_io_job_info_1("", buffer, &info[i], 0);
6462 if (*needed > offered) {
6464 return WERR_INSUFFICIENT_BUFFER;
6470 /****************************************************************************
6471 Enumjobs at level 2.
6472 ****************************************************************************/
6474 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6475 NT_PRINTER_INFO_LEVEL *ntprinter,
6476 NEW_BUFFER *buffer, uint32 offered,
6477 uint32 *needed, uint32 *returned)
6479 JOB_INFO_2 *info = NULL;
6482 DEVICEMODE *devmode = NULL;
6484 info=SMB_MALLOC_ARRAY(JOB_INFO_2,*returned);
6487 result = WERR_NOMEM;
6491 /* this should not be a failure condition if the devmode is NULL */
6493 devmode = construct_dev_mode(snum);
6495 for (i=0; i<*returned; i++)
6496 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6499 free_a_printer(&ntprinter, 2);
6502 /* check the required size. */
6503 for (i=0; i<*returned; i++)
6504 (*needed) += spoolss_size_job_info_2(&info[i]);
6506 if (*needed > offered) {
6508 result = WERR_INSUFFICIENT_BUFFER;
6512 if (!alloc_buffer_size(buffer, *needed)) {
6514 result = WERR_INSUFFICIENT_BUFFER;
6518 /* fill the buffer with the structures */
6519 for (i=0; i<*returned; i++)
6520 smb_io_job_info_2("", buffer, &info[i], 0);
6525 free_a_printer(&ntprinter, 2);
6526 free_devmode(devmode);
6534 /****************************************************************************
6536 ****************************************************************************/
6538 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6540 POLICY_HND *handle = &q_u->handle;
6541 uint32 level = q_u->level;
6542 NEW_BUFFER *buffer = NULL;
6543 uint32 offered = q_u->offered;
6544 uint32 *needed = &r_u->needed;
6545 uint32 *returned = &r_u->returned;
6547 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6549 print_status_struct prt_status;
6550 print_queue_struct *queue=NULL;
6552 /* that's an [in out] buffer */
6553 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6554 buffer = r_u->buffer;
6556 DEBUG(4,("_spoolss_enumjobs\n"));
6561 /* lookup the printer snum and tdb entry */
6563 if (!get_printer_snum(p, handle, &snum))
6566 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6567 if ( !W_ERROR_IS_OK(wret) )
6570 *returned = print_queue_status(snum, &queue, &prt_status);
6571 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6573 if (*returned == 0) {
6580 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6583 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6588 wret = WERR_UNKNOWN_LEVEL;
6591 free_a_printer( &ntprinter, 2 );
6595 /****************************************************************************
6596 ****************************************************************************/
6598 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6603 /****************************************************************************
6604 ****************************************************************************/
6606 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6608 POLICY_HND *handle = &q_u->handle;
6609 uint32 jobid = q_u->jobid;
6610 uint32 command = q_u->command;
6612 struct current_user user;
6614 WERROR errcode = WERR_BADFUNC;
6616 if (!get_printer_snum(p, handle, &snum)) {
6620 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6621 return WERR_INVALID_PRINTER_NAME;
6624 get_current_user(&user, p);
6627 case JOB_CONTROL_CANCEL:
6628 case JOB_CONTROL_DELETE:
6629 if (print_job_delete(&user, snum, jobid, &errcode)) {
6633 case JOB_CONTROL_PAUSE:
6634 if (print_job_pause(&user, snum, jobid, &errcode)) {
6638 case JOB_CONTROL_RESTART:
6639 case JOB_CONTROL_RESUME:
6640 if (print_job_resume(&user, snum, jobid, &errcode)) {
6645 return WERR_UNKNOWN_LEVEL;
6651 /****************************************************************************
6652 Enumerates all printer drivers at level 1.
6653 ****************************************************************************/
6655 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6660 fstring *list = NULL;
6662 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6663 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6667 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6669 ndrivers=get_ntdrivers(&list, architecture, version);
6670 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6676 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6677 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6678 SAFE_FREE(driver_info_1);
6682 else driver_info_1 = tdi1;
6685 for (i=0; i<ndrivers; i++) {
6687 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6688 ZERO_STRUCT(driver);
6689 status = get_a_printer_driver(&driver, 3, list[i],
6690 architecture, version);
6691 if (!W_ERROR_IS_OK(status)) {
6695 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6696 free_a_printer_driver(driver, 3);
6699 *returned+=ndrivers;
6703 /* check the required size. */
6704 for (i=0; i<*returned; i++) {
6705 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6706 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6709 if (!alloc_buffer_size(buffer, *needed)) {
6710 SAFE_FREE(driver_info_1);
6711 return WERR_INSUFFICIENT_BUFFER;
6714 /* fill the buffer with the driver structures */
6715 for (i=0; i<*returned; i++) {
6716 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6717 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6720 SAFE_FREE(driver_info_1);
6722 if (*needed > offered) {
6724 return WERR_INSUFFICIENT_BUFFER;
6730 /****************************************************************************
6731 Enumerates all printer drivers at level 2.
6732 ****************************************************************************/
6734 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6739 fstring *list = NULL;
6741 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6742 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6746 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6748 ndrivers=get_ntdrivers(&list, architecture, version);
6749 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6755 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6756 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6757 SAFE_FREE(driver_info_2);
6761 else driver_info_2 = tdi2;
6764 for (i=0; i<ndrivers; i++) {
6767 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6768 ZERO_STRUCT(driver);
6769 status = get_a_printer_driver(&driver, 3, list[i],
6770 architecture, version);
6771 if (!W_ERROR_IS_OK(status)) {
6775 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6776 free_a_printer_driver(driver, 3);
6779 *returned+=ndrivers;
6783 /* check the required size. */
6784 for (i=0; i<*returned; i++) {
6785 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6786 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6789 if (!alloc_buffer_size(buffer, *needed)) {
6790 SAFE_FREE(driver_info_2);
6791 return WERR_INSUFFICIENT_BUFFER;
6794 /* fill the buffer with the form structures */
6795 for (i=0; i<*returned; i++) {
6796 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6797 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6800 SAFE_FREE(driver_info_2);
6802 if (*needed > offered) {
6804 return WERR_INSUFFICIENT_BUFFER;
6810 /****************************************************************************
6811 Enumerates all printer drivers at level 3.
6812 ****************************************************************************/
6814 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6819 fstring *list = NULL;
6821 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6822 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6826 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6828 ndrivers=get_ntdrivers(&list, architecture, version);
6829 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6835 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6836 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6837 SAFE_FREE(driver_info_3);
6841 else driver_info_3 = tdi3;
6844 for (i=0; i<ndrivers; i++) {
6847 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6848 ZERO_STRUCT(driver);
6849 status = get_a_printer_driver(&driver, 3, list[i],
6850 architecture, version);
6851 if (!W_ERROR_IS_OK(status)) {
6855 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6856 free_a_printer_driver(driver, 3);
6859 *returned+=ndrivers;
6863 /* check the required size. */
6864 for (i=0; i<*returned; i++) {
6865 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6866 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6869 if (!alloc_buffer_size(buffer, *needed)) {
6870 SAFE_FREE(driver_info_3);
6871 return WERR_INSUFFICIENT_BUFFER;
6874 /* fill the buffer with the driver structures */
6875 for (i=0; i<*returned; i++) {
6876 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6877 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6880 for (i=0; i<*returned; i++)
6881 SAFE_FREE(driver_info_3[i].dependentfiles);
6883 SAFE_FREE(driver_info_3);
6885 if (*needed > offered) {
6887 return WERR_INSUFFICIENT_BUFFER;
6893 /****************************************************************************
6894 Enumerates all printer drivers.
6895 ****************************************************************************/
6897 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6899 uint32 level = q_u->level;
6900 NEW_BUFFER *buffer = NULL;
6901 uint32 offered = q_u->offered;
6902 uint32 *needed = &r_u->needed;
6903 uint32 *returned = &r_u->returned;
6905 fstring *list = NULL;
6907 fstring architecture;
6909 /* that's an [in out] buffer */
6910 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6911 buffer = r_u->buffer;
6913 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6917 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6918 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6920 if ( !is_myname_or_ipaddr( servername ) )
6921 return WERR_UNKNOWN_PRINTER_DRIVER;
6925 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6927 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6929 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6933 return WERR_UNKNOWN_LEVEL;
6937 /****************************************************************************
6938 ****************************************************************************/
6940 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6942 form->flag=list->flag;
6943 init_unistr(&form->name, list->name);
6944 form->width=list->width;
6945 form->length=list->length;
6946 form->left=list->left;
6947 form->top=list->top;
6948 form->right=list->right;
6949 form->bottom=list->bottom;
6952 /****************************************************************************
6953 ****************************************************************************/
6955 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6957 uint32 level = q_u->level;
6958 NEW_BUFFER *buffer = NULL;
6959 uint32 offered = q_u->offered;
6960 uint32 *needed = &r_u->needed;
6961 uint32 *numofforms = &r_u->numofforms;
6962 uint32 numbuiltinforms;
6964 nt_forms_struct *list=NULL;
6965 nt_forms_struct *builtinlist=NULL;
6970 /* that's an [in out] buffer */
6971 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6972 buffer = r_u->buffer;
6974 DEBUG(4,("_spoolss_enumforms\n"));
6975 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6976 DEBUGADD(5,("Info level [%d]\n", level));
6978 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6979 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6980 *numofforms = get_ntforms(&list);
6981 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6982 *numofforms += numbuiltinforms;
6984 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6988 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
6993 /* construct the list of form structures */
6994 for (i=0; i<numbuiltinforms; i++) {
6995 DEBUGADD(6,("Filling form number [%d]\n",i));
6996 fill_form_1(&forms_1[i], &builtinlist[i]);
6999 SAFE_FREE(builtinlist);
7001 for (; i<*numofforms; i++) {
7002 DEBUGADD(6,("Filling form number [%d]\n",i));
7003 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7008 /* check the required size. */
7009 for (i=0; i<numbuiltinforms; i++) {
7010 DEBUGADD(6,("adding form [%d]'s size\n",i));
7011 buffer_size += spoolss_size_form_1(&forms_1[i]);
7013 for (; i<*numofforms; i++) {
7014 DEBUGADD(6,("adding form [%d]'s size\n",i));
7015 buffer_size += spoolss_size_form_1(&forms_1[i]);
7018 *needed=buffer_size;
7020 if (!alloc_buffer_size(buffer, buffer_size)){
7022 return WERR_INSUFFICIENT_BUFFER;
7025 /* fill the buffer with the form structures */
7026 for (i=0; i<numbuiltinforms; i++) {
7027 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7028 smb_io_form_1("", buffer, &forms_1[i], 0);
7030 for (; i<*numofforms; i++) {
7031 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7032 smb_io_form_1("", buffer, &forms_1[i], 0);
7037 if (*needed > offered) {
7039 return WERR_INSUFFICIENT_BUFFER;
7046 SAFE_FREE(builtinlist);
7047 return WERR_UNKNOWN_LEVEL;
7052 /****************************************************************************
7053 ****************************************************************************/
7055 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7057 uint32 level = q_u->level;
7058 UNISTR2 *uni_formname = &q_u->formname;
7059 NEW_BUFFER *buffer = NULL;
7060 uint32 offered = q_u->offered;
7061 uint32 *needed = &r_u->needed;
7063 nt_forms_struct *list=NULL;
7064 nt_forms_struct builtin_form;
7069 int numofforms=0, i=0;
7071 /* that's an [in out] buffer */
7072 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7073 buffer = r_u->buffer;
7075 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7077 DEBUG(4,("_spoolss_getform\n"));
7078 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7079 DEBUGADD(5,("Info level [%d]\n", level));
7081 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7082 if (!foundBuiltin) {
7083 numofforms = get_ntforms(&list);
7084 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7086 if (numofforms == 0)
7093 fill_form_1(&form_1, &builtin_form);
7096 /* Check if the requested name is in the list of form structures */
7097 for (i=0; i<numofforms; i++) {
7099 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7101 if (strequal(form_name, list[i].name)) {
7102 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7103 fill_form_1(&form_1, &list[i]);
7109 if (i == numofforms) {
7113 /* check the required size. */
7115 *needed=spoolss_size_form_1(&form_1);
7117 if (!alloc_buffer_size(buffer, buffer_size)){
7118 return WERR_INSUFFICIENT_BUFFER;
7121 if (*needed > offered) {
7122 return WERR_INSUFFICIENT_BUFFER;
7125 /* fill the buffer with the form structures */
7126 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7127 smb_io_form_1("", buffer, &form_1, 0);
7133 return WERR_UNKNOWN_LEVEL;
7137 /****************************************************************************
7138 ****************************************************************************/
7140 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7142 init_unistr(&port->port_name, name);
7145 /****************************************************************************
7146 ****************************************************************************/
7148 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7150 init_unistr(&port->port_name, name);
7151 init_unistr(&port->monitor_name, "Local Monitor");
7152 init_unistr(&port->description, "Local Port");
7153 port->port_type=PORT_TYPE_WRITE;
7157 /****************************************************************************
7159 ****************************************************************************/
7161 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7163 PORT_INFO_1 *ports=NULL;
7166 if (*lp_enumports_cmd()) {
7167 char *cmd = lp_enumports_cmd();
7174 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7176 DEBUG(10,("Running [%s]\n", command));
7177 ret = smbrun(command, &fd);
7178 DEBUG(10,("Returned [%d]\n", ret));
7182 /* Is this the best error to return here? */
7183 return WERR_ACCESS_DENIED;
7187 qlines = fd_lines_load(fd, &numlines);
7188 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7192 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7193 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7194 dos_errstr(WERR_NOMEM)));
7195 file_lines_free(qlines);
7199 for (i=0; i<numlines; i++) {
7200 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7201 fill_port_1(&ports[i], qlines[i]);
7204 file_lines_free(qlines);
7207 *returned = numlines;
7210 *returned = 1; /* Sole Samba port returned. */
7212 if((ports=SMB_MALLOC_P(PORT_INFO_1)) == NULL)
7215 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7217 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7220 /* check the required size. */
7221 for (i=0; i<*returned; i++) {
7222 DEBUGADD(6,("adding port [%d]'s size\n", i));
7223 *needed += spoolss_size_port_info_1(&ports[i]);
7226 if (!alloc_buffer_size(buffer, *needed)) {
7228 return WERR_INSUFFICIENT_BUFFER;
7231 /* fill the buffer with the ports structures */
7232 for (i=0; i<*returned; i++) {
7233 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7234 smb_io_port_1("", buffer, &ports[i], 0);
7239 if (*needed > offered) {
7241 return WERR_INSUFFICIENT_BUFFER;
7247 /****************************************************************************
7249 ****************************************************************************/
7251 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7253 PORT_INFO_2 *ports=NULL;
7256 if (*lp_enumports_cmd()) {
7257 char *cmd = lp_enumports_cmd();
7266 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7267 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7269 path = lp_lockdir();
7271 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7272 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7275 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7276 ret = smbrun(command, &fd);
7277 DEBUGADD(10,("returned [%d]\n", ret));
7281 /* Is this the best error to return here? */
7282 return WERR_ACCESS_DENIED;
7286 qlines = fd_lines_load(fd, &numlines);
7287 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7291 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7292 file_lines_free(qlines);
7296 for (i=0; i<numlines; i++) {
7297 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7298 fill_port_2(&(ports[i]), qlines[i]);
7301 file_lines_free(qlines);
7304 *returned = numlines;
7310 if((ports=SMB_MALLOC_P(PORT_INFO_2)) == NULL)
7313 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7315 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7318 /* check the required size. */
7319 for (i=0; i<*returned; i++) {
7320 DEBUGADD(6,("adding port [%d]'s size\n", i));
7321 *needed += spoolss_size_port_info_2(&ports[i]);
7324 if (!alloc_buffer_size(buffer, *needed)) {
7326 return WERR_INSUFFICIENT_BUFFER;
7329 /* fill the buffer with the ports structures */
7330 for (i=0; i<*returned; i++) {
7331 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7332 smb_io_port_2("", buffer, &ports[i], 0);
7337 if (*needed > offered) {
7339 return WERR_INSUFFICIENT_BUFFER;
7345 /****************************************************************************
7347 ****************************************************************************/
7349 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7351 uint32 level = q_u->level;
7352 NEW_BUFFER *buffer = NULL;
7353 uint32 offered = q_u->offered;
7354 uint32 *needed = &r_u->needed;
7355 uint32 *returned = &r_u->returned;
7357 /* that's an [in out] buffer */
7358 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7359 buffer = r_u->buffer;
7361 DEBUG(4,("_spoolss_enumports\n"));
7368 return enumports_level_1(buffer, offered, needed, returned);
7370 return enumports_level_2(buffer, offered, needed, returned);
7372 return WERR_UNKNOWN_LEVEL;
7376 /****************************************************************************
7377 ****************************************************************************/
7379 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7380 const SPOOL_PRINTER_INFO_LEVEL *info,
7381 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7382 uint32 user_switch, const SPOOL_USER_CTR *user,
7385 NT_PRINTER_INFO_LEVEL *printer = NULL;
7388 WERROR err = WERR_OK;
7390 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7391 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7395 ZERO_STRUCTP(printer);
7397 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7398 if (!convert_printer_info(info, printer, 2)) {
7399 free_a_printer(&printer, 2);
7403 /* check to see if the printer already exists */
7405 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7406 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7407 printer->info_2->sharename));
7408 free_a_printer(&printer, 2);
7409 return WERR_PRINTER_ALREADY_EXISTS;
7412 /* FIXME!!! smbd should check to see if the driver is installed before
7413 trying to add a printer like this --jerry */
7415 if (*lp_addprinter_cmd() ) {
7416 if ( !add_printer_hook(printer) ) {
7417 free_a_printer(&printer,2);
7418 return WERR_ACCESS_DENIED;
7422 /* use our primary netbios name since get_a_printer() will convert
7423 it to what the client expects on a case by case basis */
7425 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7426 printer->info_2->sharename);
7429 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7430 free_a_printer(&printer,2);
7431 return WERR_ACCESS_DENIED;
7434 /* you must be a printer admin to add a new printer */
7435 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7436 free_a_printer(&printer,2);
7437 return WERR_ACCESS_DENIED;
7441 * Do sanity check on the requested changes for Samba.
7444 if (!check_printer_ok(printer->info_2, snum)) {
7445 free_a_printer(&printer,2);
7446 return WERR_INVALID_PARAM;
7450 * When a printer is created, the drivername bound to the printer is used
7451 * to lookup previously saved driver initialization info, which is then
7452 * bound to the new printer, simulating what happens in the Windows arch.
7457 set_driver_init(printer, 2);
7461 /* A valid devmode was included, convert and link it
7463 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7465 if (!convert_devicemode(printer->info_2->printername, devmode,
7466 &printer->info_2->devmode))
7470 /* write the ASCII on disk */
7471 err = mod_a_printer(printer, 2);
7472 if (!W_ERROR_IS_OK(err)) {
7473 free_a_printer(&printer,2);
7477 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7478 /* Handle open failed - remove addition. */
7479 del_a_printer(printer->info_2->sharename);
7480 free_a_printer(&printer,2);
7481 return WERR_ACCESS_DENIED;
7484 update_c_setprinter(False);
7485 free_a_printer(&printer,2);
7490 /****************************************************************************
7491 ****************************************************************************/
7493 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7495 UNISTR2 *uni_srv_name = &q_u->server_name;
7496 uint32 level = q_u->level;
7497 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7498 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7499 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7500 uint32 user_switch = q_u->user_switch;
7501 SPOOL_USER_CTR *user = &q_u->user_ctr;
7502 POLICY_HND *handle = &r_u->handle;
7506 /* we don't handle yet */
7507 /* but I know what to do ... */
7508 return WERR_UNKNOWN_LEVEL;
7510 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7512 user_switch, user, handle);
7514 return WERR_UNKNOWN_LEVEL;
7518 /****************************************************************************
7519 ****************************************************************************/
7521 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7523 uint32 level = q_u->level;
7524 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7525 WERROR err = WERR_OK;
7526 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7527 struct current_user user;
7528 fstring driver_name;
7531 ZERO_STRUCT(driver);
7533 get_current_user(&user, p);
7535 if (!convert_printer_driver_info(info, &driver, level)) {
7540 DEBUG(5,("Cleaning driver's information\n"));
7541 err = clean_up_driver_struct(driver, level, &user);
7542 if (!W_ERROR_IS_OK(err))
7545 DEBUG(5,("Moving driver to final destination\n"));
7546 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7547 if (W_ERROR_IS_OK(err))
7548 err = WERR_ACCESS_DENIED;
7552 if (add_a_printer_driver(driver, level)!=0) {
7553 err = WERR_ACCESS_DENIED;
7557 /* BEGIN_ADMIN_LOG */
7560 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7561 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7562 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7565 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7566 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7567 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7573 * I think this is where he DrvUpgradePrinter() hook would be
7574 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7575 * server. Right now, we just need to send ourselves a message
7576 * to update each printer bound to this driver. --jerry
7579 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7580 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7585 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7586 * decide if the driver init data should be deleted. The rules are:
7587 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7588 * 2) delete init data only if there is no 2k/Xp driver
7589 * 3) always delete init data
7590 * The generalized rule is always use init data from the highest order driver.
7591 * It is necessary to follow the driver install by an initialization step to
7592 * finish off this process.
7595 version = driver.info_3->cversion;
7596 else if (level == 6)
7597 version = driver.info_6->version;
7602 * 9x printer driver - never delete init data
7605 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7610 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7611 * there is no 2k/Xp driver init data for this driver name.
7615 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7617 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7619 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7621 if (!del_driver_init(driver_name))
7622 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7625 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7627 free_a_printer_driver(driver1,3);
7628 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7635 * 2k or Xp printer driver - always delete init data
7638 if (!del_driver_init(driver_name))
7639 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7643 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7649 free_a_printer_driver(driver, level);
7653 /********************************************************************
7654 * spoolss_addprinterdriverex
7655 ********************************************************************/
7657 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7659 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7660 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7663 * we only support the semantics of AddPrinterDriver()
7664 * i.e. only copy files that are newer than existing ones
7667 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7668 return WERR_ACCESS_DENIED;
7670 ZERO_STRUCT(q_u_local);
7671 ZERO_STRUCT(r_u_local);
7673 /* just pass the information off to _spoolss_addprinterdriver() */
7674 q_u_local.server_name_ptr = q_u->server_name_ptr;
7675 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7676 q_u_local.level = q_u->level;
7677 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7679 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7682 /****************************************************************************
7683 ****************************************************************************/
7685 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7687 init_unistr(&info->name, name);
7690 /****************************************************************************
7691 ****************************************************************************/
7693 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7699 const char *short_archi;
7700 DRIVER_DIRECTORY_1 *info=NULL;
7702 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7703 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7705 /* check for beginning double '\'s and that the server
7708 pservername = servername;
7709 if ( *pservername == '\\' && strlen(servername)>2 ) {
7713 if ( !is_myname_or_ipaddr( pservername ) )
7714 return WERR_INVALID_PARAM;
7716 if (!(short_archi = get_short_archi(long_archi)))
7717 return WERR_INVALID_ENVIRONMENT;
7719 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7722 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7724 DEBUG(4,("printer driver directory: [%s]\n", path));
7726 fill_driverdir_1(info, path);
7728 *needed += spoolss_size_driverdir_info_1(info);
7730 if (!alloc_buffer_size(buffer, *needed)) {
7732 return WERR_INSUFFICIENT_BUFFER;
7735 smb_io_driverdir_1("", buffer, info, 0);
7739 if (*needed > offered)
7740 return WERR_INSUFFICIENT_BUFFER;
7745 /****************************************************************************
7746 ****************************************************************************/
7748 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7750 UNISTR2 *name = &q_u->name;
7751 UNISTR2 *uni_environment = &q_u->environment;
7752 uint32 level = q_u->level;
7753 NEW_BUFFER *buffer = NULL;
7754 uint32 offered = q_u->offered;
7755 uint32 *needed = &r_u->needed;
7757 /* that's an [in out] buffer */
7758 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7759 buffer = r_u->buffer;
7761 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7767 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7769 return WERR_UNKNOWN_LEVEL;
7773 /****************************************************************************
7774 ****************************************************************************/
7776 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7778 POLICY_HND *handle = &q_u->handle;
7779 uint32 idx = q_u->index;
7780 uint32 in_value_len = q_u->valuesize;
7781 uint32 in_data_len = q_u->datasize;
7782 uint32 *out_max_value_len = &r_u->valuesize;
7783 uint16 **out_value = &r_u->value;
7784 uint32 *out_value_len = &r_u->realvaluesize;
7785 uint32 *out_type = &r_u->type;
7786 uint32 *out_max_data_len = &r_u->datasize;
7787 uint8 **data_out = &r_u->data;
7788 uint32 *out_data_len = &r_u->realdatasize;
7790 NT_PRINTER_INFO_LEVEL *printer = NULL;
7792 uint32 biggest_valuesize;
7793 uint32 biggest_datasize;
7795 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7798 REGISTRY_VALUE *val = NULL;
7799 NT_PRINTER_DATA *p_data;
7800 int i, key_index, num_values;
7803 ZERO_STRUCT( printer );
7807 *out_max_data_len = 0;
7811 DEBUG(5,("spoolss_enumprinterdata\n"));
7814 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7818 if (!get_printer_snum(p,handle, &snum))
7821 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7822 if (!W_ERROR_IS_OK(result))
7825 p_data = &printer->info_2->data;
7826 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7831 * The NT machine wants to know the biggest size of value and data
7833 * cf: MSDN EnumPrinterData remark section
7836 if ( !in_value_len && !in_data_len && (key_index != -1) )
7838 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7840 biggest_valuesize = 0;
7841 biggest_datasize = 0;
7843 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7845 for ( i=0; i<num_values; i++ )
7847 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7849 name_length = strlen(val->valuename);
7850 if ( strlen(val->valuename) > biggest_valuesize )
7851 biggest_valuesize = name_length;
7853 if ( val->size > biggest_datasize )
7854 biggest_datasize = val->size;
7856 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7860 /* the value is an UNICODE string but real_value_size is the length
7861 in bytes including the trailing 0 */
7863 *out_value_len = 2 * (1+biggest_valuesize);
7864 *out_data_len = biggest_datasize;
7866 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7872 * the value len is wrong in NT sp3
7873 * that's the number of bytes not the number of unicode chars
7876 if ( key_index != -1 )
7877 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7882 /* out_value should default to "" or else NT4 has
7883 problems unmarshalling the response */
7885 *out_max_value_len=(in_value_len/sizeof(uint16));
7887 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7889 result = WERR_NOMEM;
7893 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7895 /* the data is counted in bytes */
7897 *out_max_data_len = in_data_len;
7898 *out_data_len = in_data_len;
7900 /* only allocate when given a non-zero data_len */
7902 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7904 result = WERR_NOMEM;
7908 result = WERR_NO_MORE_ITEMS;
7914 * - counted in bytes in the request
7915 * - counted in UNICODE chars in the max reply
7916 * - counted in bytes in the real size
7918 * take a pause *before* coding not *during* coding
7922 *out_max_value_len=(in_value_len/sizeof(uint16));
7923 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7925 result = WERR_NOMEM;
7929 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7933 *out_type = regval_type( val );
7935 /* data - counted in bytes */
7937 *out_max_data_len = in_data_len;
7938 if ( (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7940 result = WERR_NOMEM;
7943 data_len = (size_t)regval_size(val);
7944 memcpy( *data_out, regval_data_p(val), data_len );
7945 *out_data_len = data_len;
7949 free_a_printer(&printer, 2);
7953 /****************************************************************************
7954 ****************************************************************************/
7956 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7958 POLICY_HND *handle = &q_u->handle;
7959 UNISTR2 *value = &q_u->value;
7960 uint32 type = q_u->type;
7961 uint8 *data = q_u->data;
7962 uint32 real_len = q_u->real_len;
7964 NT_PRINTER_INFO_LEVEL *printer = NULL;
7966 WERROR status = WERR_OK;
7967 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7970 DEBUG(5,("spoolss_setprinterdata\n"));
7973 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7977 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7978 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7979 return WERR_INVALID_PARAM;
7982 if (!get_printer_snum(p,handle, &snum))
7986 * Access check : NT returns "access denied" if you make a
7987 * SetPrinterData call without the necessary privildge.
7988 * we were originally returning OK if nothing changed
7989 * which made Win2k issue **a lot** of SetPrinterData
7990 * when connecting to a printer --jerry
7993 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7995 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7996 status = WERR_ACCESS_DENIED;
8000 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8001 if (!W_ERROR_IS_OK(status))
8004 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8007 * When client side code sets a magic printer data key, detect it and save
8008 * the current printer data and the magic key's data (its the DEVMODE) for
8009 * future printer/driver initializations.
8011 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8013 /* Set devmode and printer initialization info */
8014 status = save_driver_init( printer, 2, data, real_len );
8016 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8020 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8021 type, data, real_len );
8022 if ( W_ERROR_IS_OK(status) )
8023 status = mod_a_printer(printer, 2);
8027 free_a_printer(&printer, 2);
8032 /****************************************************************************
8033 ****************************************************************************/
8035 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8037 POLICY_HND *handle = &q_u->handle;
8038 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8041 DEBUG(5,("_spoolss_resetprinter\n"));
8044 * All we do is to check to see if the handle and queue is valid.
8045 * This call really doesn't mean anything to us because we only
8046 * support RAW printing. --jerry
8050 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8054 if (!get_printer_snum(p,handle, &snum))
8058 /* blindly return success */
8063 /****************************************************************************
8064 ****************************************************************************/
8066 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8068 POLICY_HND *handle = &q_u->handle;
8069 UNISTR2 *value = &q_u->valuename;
8071 NT_PRINTER_INFO_LEVEL *printer = NULL;
8073 WERROR status = WERR_OK;
8074 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8077 DEBUG(5,("spoolss_deleteprinterdata\n"));
8080 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8084 if (!get_printer_snum(p, handle, &snum))
8087 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8088 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8089 return WERR_ACCESS_DENIED;
8092 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8093 if (!W_ERROR_IS_OK(status))
8096 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8098 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8100 if ( W_ERROR_IS_OK(status) )
8101 mod_a_printer( printer, 2 );
8103 free_a_printer(&printer, 2);
8108 /****************************************************************************
8109 ****************************************************************************/
8111 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8113 POLICY_HND *handle = &q_u->handle;
8114 FORM *form = &q_u->form;
8115 nt_forms_struct tmpForm;
8117 WERROR status = WERR_OK;
8118 NT_PRINTER_INFO_LEVEL *printer = NULL;
8121 nt_forms_struct *list=NULL;
8122 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8124 DEBUG(5,("spoolss_addform\n"));
8127 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8132 /* forms can be added on printer of on the print server handle */
8134 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8136 if (!get_printer_snum(p,handle, &snum))
8139 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8140 if (!W_ERROR_IS_OK(status))
8144 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8145 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8146 status = WERR_ACCESS_DENIED;
8150 /* can't add if builtin */
8152 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8153 status = WERR_ALREADY_EXISTS;
8157 count = get_ntforms(&list);
8159 if(!add_a_form(&list, form, &count)) {
8160 status = WERR_NOMEM;
8164 write_ntforms(&list, count);
8167 * ChangeID must always be set if this is a printer
8170 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8171 status = mod_a_printer(printer, 2);
8175 free_a_printer(&printer, 2);
8181 /****************************************************************************
8182 ****************************************************************************/
8184 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8186 POLICY_HND *handle = &q_u->handle;
8187 UNISTR2 *form_name = &q_u->name;
8188 nt_forms_struct tmpForm;
8190 nt_forms_struct *list=NULL;
8191 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8193 WERROR status = WERR_OK;
8194 NT_PRINTER_INFO_LEVEL *printer = NULL;
8196 DEBUG(5,("spoolss_deleteform\n"));
8199 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8203 /* forms can be deleted on printer of on the print server handle */
8205 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8207 if (!get_printer_snum(p,handle, &snum))
8210 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8211 if (!W_ERROR_IS_OK(status))
8215 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8216 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8217 status = WERR_ACCESS_DENIED;
8221 /* can't delete if builtin */
8223 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8224 status = WERR_INVALID_PARAM;
8228 count = get_ntforms(&list);
8230 if ( !delete_a_form(&list, form_name, &count, &status ))
8234 * ChangeID must always be set if this is a printer
8237 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8238 status = mod_a_printer(printer, 2);
8242 free_a_printer(&printer, 2);
8248 /****************************************************************************
8249 ****************************************************************************/
8251 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8253 POLICY_HND *handle = &q_u->handle;
8254 FORM *form = &q_u->form;
8255 nt_forms_struct tmpForm;
8257 WERROR status = WERR_OK;
8258 NT_PRINTER_INFO_LEVEL *printer = NULL;
8261 nt_forms_struct *list=NULL;
8262 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8264 DEBUG(5,("spoolss_setform\n"));
8267 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8271 /* forms can be modified on printer of on the print server handle */
8273 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8275 if (!get_printer_snum(p,handle, &snum))
8278 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8279 if (!W_ERROR_IS_OK(status))
8283 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8284 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8285 status = WERR_ACCESS_DENIED;
8289 /* can't set if builtin */
8290 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8291 status = WERR_INVALID_PARAM;
8295 count = get_ntforms(&list);
8296 update_a_form(&list, form, count);
8297 write_ntforms(&list, count);
8300 * ChangeID must always be set if this is a printer
8303 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8304 status = mod_a_printer(printer, 2);
8309 free_a_printer(&printer, 2);
8315 /****************************************************************************
8316 enumprintprocessors level 1.
8317 ****************************************************************************/
8319 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8321 PRINTPROCESSOR_1 *info_1=NULL;
8323 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8328 init_unistr(&info_1->name, "winprint");
8330 *needed += spoolss_size_printprocessor_info_1(info_1);
8332 if (!alloc_buffer_size(buffer, *needed))
8333 return WERR_INSUFFICIENT_BUFFER;
8335 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8339 if (*needed > offered) {
8341 return WERR_INSUFFICIENT_BUFFER;
8347 /****************************************************************************
8348 ****************************************************************************/
8350 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8352 uint32 level = q_u->level;
8353 NEW_BUFFER *buffer = NULL;
8354 uint32 offered = q_u->offered;
8355 uint32 *needed = &r_u->needed;
8356 uint32 *returned = &r_u->returned;
8358 /* that's an [in out] buffer */
8359 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8360 buffer = r_u->buffer;
8362 DEBUG(5,("spoolss_enumprintprocessors\n"));
8365 * Enumerate the print processors ...
8367 * Just reply with "winprint", to keep NT happy
8368 * and I can use my nice printer checker.
8376 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8378 return WERR_UNKNOWN_LEVEL;
8382 /****************************************************************************
8383 enumprintprocdatatypes level 1.
8384 ****************************************************************************/
8386 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8388 PRINTPROCDATATYPE_1 *info_1=NULL;
8390 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8395 init_unistr(&info_1->name, "RAW");
8397 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8399 if (!alloc_buffer_size(buffer, *needed))
8400 return WERR_INSUFFICIENT_BUFFER;
8402 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8406 if (*needed > offered) {
8408 return WERR_INSUFFICIENT_BUFFER;
8414 /****************************************************************************
8415 ****************************************************************************/
8417 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8419 uint32 level = q_u->level;
8420 NEW_BUFFER *buffer = NULL;
8421 uint32 offered = q_u->offered;
8422 uint32 *needed = &r_u->needed;
8423 uint32 *returned = &r_u->returned;
8425 /* that's an [in out] buffer */
8426 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8427 buffer = r_u->buffer;
8429 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8436 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8438 return WERR_UNKNOWN_LEVEL;
8442 /****************************************************************************
8443 enumprintmonitors level 1.
8444 ****************************************************************************/
8446 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8448 PRINTMONITOR_1 *info_1=NULL;
8450 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8455 init_unistr(&info_1->name, "Local Port");
8457 *needed += spoolss_size_printmonitor_info_1(info_1);
8459 if (!alloc_buffer_size(buffer, *needed))
8460 return WERR_INSUFFICIENT_BUFFER;
8462 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8466 if (*needed > offered) {
8468 return WERR_INSUFFICIENT_BUFFER;
8474 /****************************************************************************
8475 enumprintmonitors level 2.
8476 ****************************************************************************/
8478 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8480 PRINTMONITOR_2 *info_2=NULL;
8482 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8487 init_unistr(&info_2->name, "Local Port");
8488 init_unistr(&info_2->environment, "Windows NT X86");
8489 init_unistr(&info_2->dll_name, "localmon.dll");
8491 *needed += spoolss_size_printmonitor_info_2(info_2);
8493 if (!alloc_buffer_size(buffer, *needed))
8494 return WERR_INSUFFICIENT_BUFFER;
8496 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8500 if (*needed > offered) {
8502 return WERR_INSUFFICIENT_BUFFER;
8508 /****************************************************************************
8509 ****************************************************************************/
8511 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8513 uint32 level = q_u->level;
8514 NEW_BUFFER *buffer = NULL;
8515 uint32 offered = q_u->offered;
8516 uint32 *needed = &r_u->needed;
8517 uint32 *returned = &r_u->returned;
8519 /* that's an [in out] buffer */
8520 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8521 buffer = r_u->buffer;
8523 DEBUG(5,("spoolss_enumprintmonitors\n"));
8526 * Enumerate the print monitors ...
8528 * Just reply with "Local Port", to keep NT happy
8529 * and I can use my nice printer checker.
8537 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8539 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8541 return WERR_UNKNOWN_LEVEL;
8545 /****************************************************************************
8546 ****************************************************************************/
8548 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8549 NT_PRINTER_INFO_LEVEL *ntprinter,
8550 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8555 JOB_INFO_1 *info_1=NULL;
8557 info_1=SMB_MALLOC_P(JOB_INFO_1);
8559 if (info_1 == NULL) {
8563 for (i=0; i<count && found==False; i++) {
8564 if ((*queue)[i].job==(int)jobid)
8570 /* NT treats not found as bad param... yet another bad choice */
8571 return WERR_INVALID_PARAM;
8574 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8576 *needed += spoolss_size_job_info_1(info_1);
8578 if (!alloc_buffer_size(buffer, *needed)) {
8580 return WERR_INSUFFICIENT_BUFFER;
8583 smb_io_job_info_1("", buffer, info_1, 0);
8587 if (*needed > offered)
8588 return WERR_INSUFFICIENT_BUFFER;
8593 /****************************************************************************
8594 ****************************************************************************/
8596 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8597 NT_PRINTER_INFO_LEVEL *ntprinter,
8598 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8605 DEVICEMODE *devmode = NULL;
8606 NT_DEVICEMODE *nt_devmode = NULL;
8608 info_2=SMB_MALLOC_P(JOB_INFO_2);
8610 ZERO_STRUCTP(info_2);
8612 if (info_2 == NULL) {
8617 for ( i=0; i<count && found==False; i++ )
8619 if ((*queue)[i].job == (int)jobid)
8625 /* NT treats not found as bad param... yet another bad
8627 ret = WERR_INVALID_PARAM;
8632 * if the print job does not have a DEVMODE associated with it,
8633 * just use the one for the printer. A NULL devicemode is not
8634 * a failure condition
8637 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8638 devmode = construct_dev_mode(snum);
8640 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8641 ZERO_STRUCTP( devmode );
8642 convert_nt_devicemode( devmode, nt_devmode );
8646 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8648 *needed += spoolss_size_job_info_2(info_2);
8650 if (!alloc_buffer_size(buffer, *needed)) {
8651 ret = WERR_INSUFFICIENT_BUFFER;
8655 smb_io_job_info_2("", buffer, info_2, 0);
8657 if (*needed > offered) {
8658 ret = WERR_INSUFFICIENT_BUFFER;
8665 /* Cleanup allocated memory */
8667 free_job_info_2(info_2); /* Also frees devmode */
8673 /****************************************************************************
8674 ****************************************************************************/
8676 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8678 POLICY_HND *handle = &q_u->handle;
8679 uint32 jobid = q_u->jobid;
8680 uint32 level = q_u->level;
8681 NEW_BUFFER *buffer = NULL;
8682 uint32 offered = q_u->offered;
8683 uint32 *needed = &r_u->needed;
8684 WERROR wstatus = WERR_OK;
8685 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8688 print_queue_struct *queue = NULL;
8689 print_status_struct prt_status;
8691 /* that's an [in out] buffer */
8692 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8693 buffer = r_u->buffer;
8695 DEBUG(5,("spoolss_getjob\n"));
8699 if (!get_printer_snum(p, handle, &snum))
8702 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8703 if ( !W_ERROR_IS_OK(wstatus) )
8706 count = print_queue_status(snum, &queue, &prt_status);
8708 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8709 count, prt_status.status, prt_status.message));
8713 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8714 buffer, offered, needed);
8717 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8718 buffer, offered, needed);
8721 wstatus = WERR_UNKNOWN_LEVEL;
8726 free_a_printer( &ntprinter, 2 );
8731 /********************************************************************
8732 spoolss_getprinterdataex
8734 From MSDN documentation of GetPrinterDataEx: pass request
8735 to GetPrinterData if key is "PrinterDriverData".
8736 ********************************************************************/
8738 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8740 POLICY_HND *handle = &q_u->handle;
8741 uint32 in_size = q_u->size;
8742 uint32 *type = &r_u->type;
8743 uint32 *out_size = &r_u->size;
8744 uint8 **data = &r_u->data;
8745 uint32 *needed = &r_u->needed;
8746 fstring keyname, valuename;
8748 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8750 NT_PRINTER_INFO_LEVEL *printer = NULL;
8752 WERROR status = WERR_OK;
8754 DEBUG(4,("_spoolss_getprinterdataex\n"));
8756 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8757 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8759 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8760 keyname, valuename));
8762 /* in case of problem, return some default values */
8766 *out_size = in_size;
8769 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8770 status = WERR_BADFID;
8774 /* Is the handle to a printer or to the server? */
8776 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8777 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8778 status = WERR_INVALID_PARAM;
8782 if ( !get_printer_snum(p,handle, &snum) )
8785 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8786 if ( !W_ERROR_IS_OK(status) )
8789 /* check to see if the keyname is valid */
8790 if ( !strlen(keyname) ) {
8791 status = WERR_INVALID_PARAM;
8795 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8796 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8797 free_a_printer( &printer, 2 );
8798 status = WERR_BADFILE;
8802 /* When given a new keyname, we should just create it */
8804 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8806 if (*needed > *out_size)
8807 status = WERR_MORE_DATA;
8810 if ( !W_ERROR_IS_OK(status) )
8812 DEBUG(5, ("error: allocating %d\n", *out_size));
8814 /* reply this param doesn't exist */
8818 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8819 status = WERR_NOMEM;
8829 free_a_printer( &printer, 2 );
8834 /********************************************************************
8835 * spoolss_setprinterdataex
8836 ********************************************************************/
8838 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8840 POLICY_HND *handle = &q_u->handle;
8841 uint32 type = q_u->type;
8842 uint8 *data = q_u->data;
8843 uint32 real_len = q_u->real_len;
8845 NT_PRINTER_INFO_LEVEL *printer = NULL;
8847 WERROR status = WERR_OK;
8848 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8853 DEBUG(4,("_spoolss_setprinterdataex\n"));
8855 /* From MSDN documentation of SetPrinterDataEx: pass request to
8856 SetPrinterData if key is "PrinterDriverData" */
8859 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8863 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8864 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8865 return WERR_INVALID_PARAM;
8868 if ( !get_printer_snum(p,handle, &snum) )
8872 * Access check : NT returns "access denied" if you make a
8873 * SetPrinterData call without the necessary privildge.
8874 * we were originally returning OK if nothing changed
8875 * which made Win2k issue **a lot** of SetPrinterData
8876 * when connecting to a printer --jerry
8879 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8881 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8882 return WERR_ACCESS_DENIED;
8885 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8886 if (!W_ERROR_IS_OK(status))
8889 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8890 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8892 /* check for OID in valuename */
8894 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8900 /* save the registry data */
8902 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8904 if ( W_ERROR_IS_OK(status) )
8906 /* save the OID if one was specified */
8908 fstrcat( keyname, "\\" );
8909 fstrcat( keyname, SPOOL_OID_KEY );
8912 * I'm not checking the status here on purpose. Don't know
8913 * if this is right, but I'm returning the status from the
8914 * previous set_printer_dataex() call. I have no idea if
8915 * this is right. --jerry
8918 set_printer_dataex( printer, keyname, valuename,
8919 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8922 status = mod_a_printer(printer, 2);
8925 free_a_printer(&printer, 2);
8931 /********************************************************************
8932 * spoolss_deleteprinterdataex
8933 ********************************************************************/
8935 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8937 POLICY_HND *handle = &q_u->handle;
8938 UNISTR2 *value = &q_u->valuename;
8939 UNISTR2 *key = &q_u->keyname;
8941 NT_PRINTER_INFO_LEVEL *printer = NULL;
8943 WERROR status = WERR_OK;
8944 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8945 pstring valuename, keyname;
8947 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8950 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8954 if (!get_printer_snum(p, handle, &snum))
8957 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8958 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8959 return WERR_ACCESS_DENIED;
8962 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8963 if (!W_ERROR_IS_OK(status))
8966 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8967 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8969 status = delete_printer_dataex( printer, keyname, valuename );
8971 if ( W_ERROR_IS_OK(status) )
8972 mod_a_printer( printer, 2 );
8974 free_a_printer(&printer, 2);
8979 /********************************************************************
8980 * spoolss_enumprinterkey
8981 ********************************************************************/
8984 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8987 fstring *keynames = NULL;
8988 uint16 *enumkeys = NULL;
8991 POLICY_HND *handle = &q_u->handle;
8992 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8993 NT_PRINTER_DATA *data;
8994 NT_PRINTER_INFO_LEVEL *printer = NULL;
8996 WERROR status = WERR_BADFILE;
8999 DEBUG(4,("_spoolss_enumprinterkey\n"));
9002 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9006 if ( !get_printer_snum(p,handle, &snum) )
9009 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9010 if (!W_ERROR_IS_OK(status))
9013 /* get the list of subkey names */
9015 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9016 data = &printer->info_2->data;
9018 num_keys = get_printer_subkeys( data, key, &keynames );
9020 if ( num_keys == -1 ) {
9021 status = WERR_BADFILE;
9025 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9027 r_u->needed = printerkey_len*2;
9029 if ( q_u->size < r_u->needed ) {
9030 status = WERR_MORE_DATA;
9034 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9035 status = WERR_NOMEM;
9041 if ( q_u->size < r_u->needed )
9042 status = WERR_MORE_DATA;
9045 free_a_printer( &printer, 2 );
9046 SAFE_FREE( keynames );
9051 /********************************************************************
9052 * spoolss_deleteprinterkey
9053 ********************************************************************/
9055 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9057 POLICY_HND *handle = &q_u->handle;
9058 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9060 NT_PRINTER_INFO_LEVEL *printer = NULL;
9064 DEBUG(5,("spoolss_deleteprinterkey\n"));
9067 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9071 /* if keyname == NULL, return error */
9073 if ( !q_u->keyname.buffer )
9074 return WERR_INVALID_PARAM;
9076 if (!get_printer_snum(p, handle, &snum))
9079 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9080 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9081 return WERR_ACCESS_DENIED;
9084 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9085 if (!W_ERROR_IS_OK(status))
9088 /* delete the key and all subneys */
9090 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9092 status = delete_all_printer_data( printer->info_2, key );
9094 if ( W_ERROR_IS_OK(status) )
9095 status = mod_a_printer(printer, 2);
9097 free_a_printer( &printer, 2 );
9103 /********************************************************************
9104 * spoolss_enumprinterdataex
9105 ********************************************************************/
9107 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9109 POLICY_HND *handle = &q_u->handle;
9110 uint32 in_size = q_u->size;
9113 NT_PRINTER_INFO_LEVEL *printer = NULL;
9114 PRINTER_ENUM_VALUES *enum_values = NULL;
9115 NT_PRINTER_DATA *p_data;
9117 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9122 REGISTRY_VALUE *val;
9127 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9130 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9135 * first check for a keyname of NULL or "". Win2k seems to send
9136 * this a lot and we should send back WERR_INVALID_PARAM
9137 * no need to spend time looking up the printer in this case.
9141 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9142 if ( !strlen(key) ) {
9143 result = WERR_INVALID_PARAM;
9147 /* get the printer off of disk */
9149 if (!get_printer_snum(p,handle, &snum))
9152 ZERO_STRUCT(printer);
9153 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9154 if (!W_ERROR_IS_OK(result))
9157 /* now look for a match on the key name */
9159 p_data = &printer->info_2->data;
9161 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9162 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9164 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9165 result = WERR_INVALID_PARAM;
9172 /* allocate the memory for the array of pointers -- if necessary */
9174 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9177 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9179 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9180 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9181 result = WERR_NOMEM;
9185 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9189 * loop through all params and build the array to pass
9190 * back to the client
9193 for ( i=0; i<num_entries; i++ )
9195 /* lookup the registry value */
9197 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9198 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9202 value_name = regval_name( val );
9203 init_unistr( &enum_values[i].valuename, value_name );
9204 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9205 enum_values[i].type = regval_type( val );
9207 data_len = regval_size( val );
9209 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9211 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9213 result = WERR_NOMEM;
9217 enum_values[i].data_len = data_len;
9219 /* keep track of the size of the array in bytes */
9221 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9224 /* housekeeping information in the reply */
9226 r_u->needed = needed;
9227 r_u->returned = num_entries;
9229 if (needed > in_size) {
9230 result = WERR_MORE_DATA;
9234 /* copy data into the reply */
9236 r_u->ctr.size = r_u->needed;
9237 r_u->ctr.size_of_array = r_u->returned;
9238 r_u->ctr.values = enum_values;
9244 free_a_printer(&printer, 2);
9249 /****************************************************************************
9250 ****************************************************************************/
9252 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9254 init_unistr(&info->name, name);
9257 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9258 UNISTR2 *environment,
9265 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9267 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9269 if (!get_short_archi(long_archi))
9270 return WERR_INVALID_ENVIRONMENT;
9272 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9275 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9277 fill_printprocessordirectory_1(info, path);
9279 *needed += spoolss_size_printprocessordirectory_info_1(info);
9281 if (!alloc_buffer_size(buffer, *needed)) {
9283 return WERR_INSUFFICIENT_BUFFER;
9286 smb_io_printprocessordirectory_1("", buffer, info, 0);
9290 if (*needed > offered)
9291 return WERR_INSUFFICIENT_BUFFER;
9296 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9298 uint32 level = q_u->level;
9299 NEW_BUFFER *buffer = NULL;
9300 uint32 offered = q_u->offered;
9301 uint32 *needed = &r_u->needed;
9304 /* that's an [in out] buffer */
9305 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9306 buffer = r_u->buffer;
9308 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9314 result = getprintprocessordirectory_level_1
9315 (&q_u->name, &q_u->environment, buffer, offered, needed);
9318 result = WERR_UNKNOWN_LEVEL;
9326 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9327 SPOOL_R_REPLYOPENPRINTER *r_u)
9329 DEBUG(5,("_spoolss_replyopenprinter\n"));
9331 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9336 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9337 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9339 DEBUG(5,("_spoolss_replycloseprinter\n"));