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 = (SPOOL_NOTIFY_OPTION *)malloc(sizeof(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 for (snum=0; !found && snum<n_services; snum++) {
518 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
521 /* ------ sharename ------ */
523 fstrcpy(sname, lp_servicename(snum));
525 DEBUGADD(10, ("share: %s\n",sname));
527 if ( strequal(sname, aprinter) ) {
533 /* do another loop to look for printernames */
535 for (snum=0; !found && snum<n_services; snum++) {
537 /* no point in checking if this is not a printer or
538 we aren't allowing printername != sharename */
540 if ( !(lp_snum_ok(snum)
542 && !lp_force_printername(snum)) )
547 fstrcpy(sname, lp_servicename(snum));
550 result = get_a_printer( NULL, &printer, 2, sname );
551 if ( !W_ERROR_IS_OK(result) ) {
552 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
553 sname, dos_errstr(result)));
557 /* printername is always returned as \\server\printername */
558 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
559 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
560 printer->info_2->printername));
561 free_a_printer( &printer, 2);
567 if ( strequal(printername, aprinter) ) {
571 DEBUGADD(10, ("printername: %s\n", printername));
573 free_a_printer( &printer, 2);
577 DEBUGADD(4,("Printer not found\n"));
581 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
583 fstrcpy(Printer->sharename, sname);
588 /****************************************************************************
589 Find first available printer slot. creates a printer handle for you.
590 ****************************************************************************/
592 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
594 Printer_entry *new_printer;
596 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
598 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
601 ZERO_STRUCTP(new_printer);
603 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
604 SAFE_FREE(new_printer);
608 /* Add to the internal list. */
609 DLIST_ADD(printers_list, new_printer);
611 new_printer->notify.option=NULL;
613 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
614 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
615 close_printer_handle(p, hnd);
619 if (!set_printer_hnd_printertype(new_printer, name)) {
620 close_printer_handle(p, hnd);
624 if (!set_printer_hnd_name(new_printer, name)) {
625 close_printer_handle(p, hnd);
629 new_printer->access_granted = access_granted;
631 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
636 /****************************************************************************
637 Allocate more memory for a BUFFER.
638 ****************************************************************************/
640 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
648 /* damn, I'm doing the reverse operation of prs_grow() :) */
649 if (buffer_size < prs_data_size(ps))
652 extra_space = buffer_size - prs_data_size(ps);
655 * save the offset and move to the end of the buffer
656 * prs_grow() checks the extra_space against the offset
658 old_offset=prs_offset(ps);
659 prs_set_offset(ps, prs_data_size(ps));
661 if (!prs_grow(ps, extra_space))
664 prs_set_offset(ps, old_offset);
666 buffer->string_at_end=prs_data_size(ps);
671 /***************************************************************************
672 check to see if the client motify handle is monitoring the notification
673 given by (notify_type, notify_field).
674 **************************************************************************/
676 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
682 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
685 SPOOL_NOTIFY_OPTION *option = p->notify.option;
689 * Flags should always be zero when the change notify
690 * is registered by the client's spooler. A user Win32 app
691 * might use the flags though instead of the NOTIFY_OPTION_INFO
700 return is_monitoring_event_flags(
701 p->notify.flags, notify_type, notify_field);
703 for (i = 0; i < option->count; i++) {
705 /* Check match for notify_type */
707 if (option->ctr.type[i].type != notify_type)
710 /* Check match for field */
712 for (j = 0; j < option->ctr.type[i].count; j++) {
713 if (option->ctr.type[i].fields[j] == notify_field) {
719 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
720 p->servername, p->sharename, notify_type, notify_field));
725 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
727 static void notify_one_value(struct spoolss_notify_msg *msg,
728 SPOOL_NOTIFY_INFO_DATA *data,
731 data->notify_data.value[0] = msg->notify.value[0];
732 data->notify_data.value[1] = 0;
735 static void notify_string(struct spoolss_notify_msg *msg,
736 SPOOL_NOTIFY_INFO_DATA *data,
741 /* The length of the message includes the trailing \0 */
743 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
745 data->notify_data.data.length = msg->len * 2;
746 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
748 if (!data->notify_data.data.string) {
749 data->notify_data.data.length = 0;
753 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
756 static void notify_system_time(struct spoolss_notify_msg *msg,
757 SPOOL_NOTIFY_INFO_DATA *data,
763 if (msg->len != sizeof(time_t)) {
764 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
769 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
770 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
774 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
775 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
779 if (!spoolss_io_system_time("", &ps, 0, &systime))
782 data->notify_data.data.length = prs_offset(&ps);
783 data->notify_data.data.string = talloc(mem_ctx, prs_offset(&ps));
785 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
790 struct notify2_message_table {
792 void (*fn)(struct spoolss_notify_msg *msg,
793 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
796 static struct notify2_message_table printer_notify_table[] = {
797 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
798 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
799 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
800 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
801 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
802 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
803 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
804 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
805 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
806 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
807 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
808 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
809 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
810 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
811 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
812 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
813 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
814 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
815 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
818 static struct notify2_message_table job_notify_table[] = {
819 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
820 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
821 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
822 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
823 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
824 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
825 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
826 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
827 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
828 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
829 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
830 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
831 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
832 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
833 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
834 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
835 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
836 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
837 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
838 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
839 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
840 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
841 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
842 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
846 /***********************************************************************
847 Allocate talloc context for container object
848 **********************************************************************/
850 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
855 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
860 /***********************************************************************
861 release all allocated memory and zero out structure
862 **********************************************************************/
864 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
870 talloc_destroy(ctr->ctx);
877 /***********************************************************************
878 **********************************************************************/
880 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
888 /***********************************************************************
889 **********************************************************************/
891 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
893 if ( !ctr || !ctr->msg_groups )
896 if ( idx >= ctr->num_groups )
899 return &ctr->msg_groups[idx];
903 /***********************************************************************
904 How many groups of change messages do we have ?
905 **********************************************************************/
907 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
912 return ctr->num_groups;
915 /***********************************************************************
916 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
917 **********************************************************************/
919 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
921 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
922 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
923 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
929 /* loop over all groups looking for a matching printer name */
931 for ( i=0; i<ctr->num_groups; i++ ) {
932 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
936 /* add a new group? */
938 if ( i == ctr->num_groups ) {
941 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
942 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
945 ctr->msg_groups = groups;
947 /* clear the new entry and set the printer name */
949 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
950 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
953 /* add the change messages; 'i' is the correct index now regardless */
955 msg_grp = &ctr->msg_groups[i];
959 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
960 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
963 msg_grp->msgs = msg_list;
965 new_slot = msg_grp->num_msgs-1;
966 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
968 /* need to allocate own copy of data */
971 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
973 return ctr->num_groups;
976 /***********************************************************************
977 Send a change notication message on all handles which have a call
979 **********************************************************************/
981 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
984 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
985 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
986 SPOOLSS_NOTIFY_MSG *messages;
987 int sending_msg_count;
990 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
994 messages = msg_group->msgs;
997 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
1001 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1003 /* loop over all printers */
1005 for (p = printers_list; p; p = p->next) {
1006 SPOOL_NOTIFY_INFO_DATA *data;
1007 uint32 data_len = 0;
1011 /* Is there notification on this handle? */
1013 if ( !p->notify.client_connected )
1016 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
1018 /* For this printer? Print servers always receive
1021 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
1022 ( !strequal(msg_group->printername, p->sharename) ) )
1025 DEBUG(10,("Our printer\n"));
1027 /* allocate the max entries possible */
1029 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
1032 /* build the array of change notifications */
1034 sending_msg_count = 0;
1036 for ( i=0; i<msg_group->num_msgs; i++ ) {
1037 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1039 /* Are we monitoring this event? */
1041 if (!is_monitoring_event(p, msg->type, msg->field))
1044 sending_msg_count++;
1047 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1048 msg->type, msg->field, p->sharename));
1051 * if the is a printer notification handle and not a job notification
1052 * type, then set the id to 0. Other wise just use what was specified
1055 * When registering change notification on a print server handle
1056 * we always need to send back the id (snum) matching the printer
1057 * for which the change took place. For change notify registered
1058 * on a printer handle, this does not matter and the id should be 0.
1063 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1069 /* Convert unix jobid to smb jobid */
1071 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1072 id = sysjob_to_jobid(msg->id);
1075 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1080 construct_info_data( &data[data_len], msg->type, msg->field, id );
1083 case PRINTER_NOTIFY_TYPE:
1084 if ( printer_notify_table[msg->field].fn )
1085 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1088 case JOB_NOTIFY_TYPE:
1089 if ( job_notify_table[msg->field].fn )
1090 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1094 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1101 if ( sending_msg_count ) {
1102 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
1103 data_len, data, p->notify.change, 0 );
1108 DEBUG(8,("send_notify2_changes: Exit...\n"));
1112 /***********************************************************************
1113 **********************************************************************/
1115 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1118 uint32 tv_sec, tv_usec;
1121 /* Unpack message */
1123 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1126 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1128 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1131 tdb_unpack((char *)buf + offset, len - offset, "dd",
1132 &msg->notify.value[0], &msg->notify.value[1]);
1134 tdb_unpack((char *)buf + offset, len - offset, "B",
1135 &msg->len, &msg->notify.data);
1137 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1138 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1140 tv->tv_sec = tv_sec;
1141 tv->tv_usec = tv_usec;
1144 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1145 msg->notify.value[1]));
1147 dump_data(3, msg->notify.data, msg->len);
1152 /********************************************************************
1153 Receive a notify2 message list
1154 ********************************************************************/
1156 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1158 size_t msg_count, i;
1159 char *buf = (char *)msg;
1162 SPOOLSS_NOTIFY_MSG notify;
1163 SPOOLSS_NOTIFY_MSG_CTR messages;
1167 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1171 msg_count = IVAL(buf, 0);
1174 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1176 if (msg_count == 0) {
1177 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1181 /* initialize the container */
1183 ZERO_STRUCT( messages );
1184 notify_msg_ctr_init( &messages );
1187 * build message groups for each printer identified
1188 * in a change_notify msg. Remember that a PCN message
1189 * includes the handle returned for the srv_spoolss_replyopenprinter()
1190 * call. Therefore messages are grouped according to printer handle.
1193 for ( i=0; i<msg_count; i++ ) {
1194 struct timeval msg_tv;
1196 if (msg_ptr + 4 - buf > len) {
1197 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1201 msg_len = IVAL(msg_ptr,0);
1204 if (msg_ptr + msg_len - buf > len) {
1205 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1209 /* unpack messages */
1211 ZERO_STRUCT( notify );
1212 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1215 /* add to correct list in container */
1217 notify_msg_ctr_addmsg( &messages, ¬ify );
1219 /* free memory that might have been allocated by notify2_unpack_msg() */
1221 if ( notify.len != 0 )
1222 SAFE_FREE( notify.notify.data );
1225 /* process each group of messages */
1227 num_groups = notify_msg_ctr_numgroups( &messages );
1228 for ( i=0; i<num_groups; i++ )
1229 send_notify2_changes( &messages, i );
1234 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1236 notify_msg_ctr_destroy( &messages );
1241 /********************************************************************
1242 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1243 one smbd, all of processes must clear their printer cache immediately.
1244 ********************************************************************/
1246 void receive_printer_mod_msg(int msg_type, pid_t src, void *buf, size_t len)
1248 fstring printername;
1250 fstrcpy( printername, buf );
1252 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername ));
1254 invalidate_printer_hnd_cache( printername );
1257 /********************************************************************
1258 Send a message to ourself about new driver being installed
1259 so we can upgrade the information for each printer bound to this
1261 ********************************************************************/
1263 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1265 int len = strlen(drivername);
1270 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1273 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1278 /**********************************************************************
1279 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1280 over all printers, upgrading ones as necessary
1281 **********************************************************************/
1283 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1287 int n_services = lp_numservices();
1289 len = MIN(len,sizeof(drivername)-1);
1290 strncpy(drivername, buf, len);
1292 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1294 /* Iterate the printer list */
1296 for (snum=0; snum<n_services; snum++)
1298 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1301 NT_PRINTER_INFO_LEVEL *printer = NULL;
1303 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1304 if (!W_ERROR_IS_OK(result))
1307 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1309 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1311 /* all we care about currently is the change_id */
1313 result = mod_a_printer(printer, 2);
1314 if (!W_ERROR_IS_OK(result)) {
1315 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1316 dos_errstr(result)));
1320 free_a_printer(&printer, 2);
1327 /********************************************************************
1328 Update the cache for all printq's with a registered client
1330 ********************************************************************/
1332 void update_monitored_printq_cache( void )
1334 Printer_entry *printer = printers_list;
1337 /* loop through all printers and update the cache where
1338 client_connected == True */
1341 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1342 && printer->notify.client_connected )
1344 snum = print_queue_snum(printer->sharename);
1345 print_queue_status( snum, NULL, NULL );
1348 printer = printer->next;
1353 /********************************************************************
1354 Send a message to ourself about new driver being installed
1355 so we can upgrade the information for each printer bound to this
1357 ********************************************************************/
1359 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1361 int len = strlen(drivername);
1366 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1369 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1374 /**********************************************************************
1375 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1376 over all printers, resetting printer data as neessary
1377 **********************************************************************/
1379 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1383 int n_services = lp_numservices();
1385 len = MIN( len, sizeof(drivername)-1 );
1386 strncpy( drivername, buf, len );
1388 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1390 /* Iterate the printer list */
1392 for ( snum=0; snum<n_services; snum++ )
1394 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1397 NT_PRINTER_INFO_LEVEL *printer = NULL;
1399 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1400 if ( !W_ERROR_IS_OK(result) )
1404 * if the printer is bound to the driver,
1405 * then reset to the new driver initdata
1408 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1410 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1412 if ( !set_driver_init(printer, 2) ) {
1413 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1414 printer->info_2->printername, printer->info_2->drivername));
1417 result = mod_a_printer( printer, 2 );
1418 if ( !W_ERROR_IS_OK(result) ) {
1419 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1420 get_dos_error_msg(result)));
1424 free_a_printer( &printer, 2 );
1433 /********************************************************************
1434 Copy routines used by convert_to_openprinterex()
1435 *******************************************************************/
1437 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1445 DEBUG (8,("dup_devmode\n"));
1447 /* bulk copy first */
1449 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1453 /* dup the pointer members separately */
1455 len = unistrlen(devmode->devicename.buffer);
1457 d->devicename.buffer = talloc(ctx, len*2);
1458 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1463 len = unistrlen(devmode->formname.buffer);
1465 d->devicename.buffer = talloc(ctx, len*2);
1466 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1470 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1475 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1477 if (!new_ctr || !ctr)
1480 DEBUG(8,("copy_devmode_ctr\n"));
1482 new_ctr->size = ctr->size;
1483 new_ctr->devmode_ptr = ctr->devmode_ptr;
1485 if(ctr->devmode_ptr)
1486 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1489 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1491 if (!new_def || !def)
1494 DEBUG(8,("copy_printer_defaults\n"));
1496 new_def->datatype_ptr = def->datatype_ptr;
1498 if (def->datatype_ptr)
1499 copy_unistr2(&new_def->datatype, &def->datatype);
1501 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1503 new_def->access_required = def->access_required;
1506 /********************************************************************
1507 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1508 * SPOOL_Q_OPEN_PRINTER_EX structure
1509 ********************************************************************/
1511 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1513 if (!q_u_ex || !q_u)
1516 DEBUG(8,("convert_to_openprinterex\n"));
1518 q_u_ex->printername_ptr = q_u->printername_ptr;
1520 if (q_u->printername_ptr)
1521 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1523 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1526 /********************************************************************
1527 * spoolss_open_printer
1529 * called from the spoolss dispatcher
1530 ********************************************************************/
1532 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1534 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1535 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1540 ZERO_STRUCT(q_u_ex);
1541 ZERO_STRUCT(r_u_ex);
1543 /* convert the OpenPrinter() call to OpenPrinterEx() */
1545 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1547 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1549 /* convert back to OpenPrinter() */
1551 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1556 /********************************************************************
1557 * spoolss_open_printer
1559 * If the openprinterex rpc call contains a devmode,
1560 * it's a per-user one. This per-user devmode is derivated
1561 * from the global devmode. Openprinterex() contains a per-user
1562 * devmode for when you do EMF printing and spooling.
1563 * In the EMF case, the NT workstation is only doing half the job
1564 * of rendering the page. The other half is done by running the printer
1565 * driver on the server.
1566 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1567 * The EMF file only contains what is to be printed on the page.
1568 * So in order for the server to know how to print, the NT client sends
1569 * a devicemode attached to the openprinterex call.
1570 * But this devicemode is short lived, it's only valid for the current print job.
1572 * If Samba would have supported EMF spooling, this devicemode would
1573 * have been attached to the handle, to sent it to the driver to correctly
1574 * rasterize the EMF file.
1576 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1577 * we just act as a pass-thru between windows and the printer.
1579 * In order to know that Samba supports only RAW spooling, NT has to call
1580 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1581 * and until NT sends a RAW job, we refuse it.
1583 * But to call getprinter() or startdoc(), you first need a valid handle,
1584 * and to get an handle you have to call openprintex(). Hence why you have
1585 * a devicemode in the openprinterex() call.
1588 * Differences between NT4 and NT 2000.
1591 * On NT4, you only have a global devicemode. This global devicemode can be changed
1592 * by the administrator (or by a user with enough privs). Everytime a user
1593 * wants to print, the devicemode is resetted to the default. In Word, everytime
1594 * you print, the printer's characteristics are always reset to the global devicemode.
1598 * In W2K, there is the notion of per-user devicemode. The first time you use
1599 * a printer, a per-user devicemode is build from the global devicemode.
1600 * If you change your per-user devicemode, it is saved in the registry, under the
1601 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1602 * printer preferences available.
1604 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1605 * on the General Tab of the printer properties windows.
1607 * To change the global devicemode: it's the "Printing Defaults..." button
1608 * on the Advanced Tab of the printer properties window.
1611 ********************************************************************/
1613 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1615 UNISTR2 *printername = NULL;
1616 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1617 POLICY_HND *handle = &r_u->handle;
1621 struct current_user user;
1622 Printer_entry *Printer=NULL;
1624 if (q_u->printername_ptr != 0)
1625 printername = &q_u->printername;
1627 if (printername == NULL)
1628 return WERR_INVALID_PRINTER_NAME;
1630 /* some sanity check because you can open a printer or a print server */
1631 /* aka: \\server\printer or \\server */
1632 unistr2_to_ascii(name, printername, sizeof(name)-1);
1634 DEBUGADD(3,("checking name: %s\n",name));
1636 if (!open_printer_hnd(p, handle, name, 0))
1637 return WERR_INVALID_PRINTER_NAME;
1639 Printer=find_printer_index_by_hnd(p, handle);
1641 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1642 "handle we created for printer %s\n", name ));
1643 close_printer_handle(p,handle);
1644 return WERR_INVALID_PRINTER_NAME;
1647 get_current_user(&user, p);
1650 * First case: the user is opening the print server:
1652 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1653 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1655 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1656 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1657 * or if the user is listed in the smb.conf printer admin parameter.
1659 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1660 * client view printer folder, but does not show the MSAPW.
1662 * Note: this test needs code to check access rights here too. Jeremy
1663 * could you look at this?
1665 * Second case: the user is opening a printer:
1666 * NT doesn't let us connect to a printer if the connecting user
1667 * doesn't have print permission.
1670 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1672 /* Printserver handles use global struct... */
1676 /* Map standard access rights to object specific access rights */
1678 se_map_standard(&printer_default->access_required,
1679 &printserver_std_mapping);
1681 /* Deny any object specific bits that don't apply to print
1682 servers (i.e printer and job specific bits) */
1684 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1686 if (printer_default->access_required &
1687 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1688 DEBUG(3, ("access DENIED for non-printserver bits"));
1689 close_printer_handle(p, handle);
1690 return WERR_ACCESS_DENIED;
1693 /* Allow admin access */
1695 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1697 if (!lp_ms_add_printer_wizard()) {
1698 close_printer_handle(p, handle);
1699 return WERR_ACCESS_DENIED;
1702 /* if the user is not root and not a printer admin, then fail */
1705 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1707 close_printer_handle(p, handle);
1708 return WERR_ACCESS_DENIED;
1711 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1715 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1718 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1719 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1721 /* We fall through to return WERR_OK */
1726 /* NT doesn't let us connect to a printer if the connecting user
1727 doesn't have print permission. */
1729 if (!get_printer_snum(p, handle, &snum)) {
1730 close_printer_handle(p, handle);
1734 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1736 /* map an empty access mask to the minimum access mask */
1737 if (printer_default->access_required == 0x0)
1738 printer_default->access_required = PRINTER_ACCESS_USE;
1741 * If we are not serving the printer driver for this printer,
1742 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1743 * will keep NT clients happy --jerry
1746 if (lp_use_client_driver(snum)
1747 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1749 printer_default->access_required = PRINTER_ACCESS_USE;
1752 /* check smb.conf parameters and the the sec_desc */
1754 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1755 DEBUG(3, ("access DENIED for printer open\n"));
1756 close_printer_handle(p, handle);
1757 return WERR_ACCESS_DENIED;
1760 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1761 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1762 close_printer_handle(p, handle);
1763 return WERR_ACCESS_DENIED;
1766 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1767 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1769 printer_default->access_required = PRINTER_ACCESS_USE;
1771 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1772 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1776 Printer->access_granted = printer_default->access_required;
1779 * If the client sent a devmode in the OpenPrinter() call, then
1780 * save it here in case we get a job submission on this handle
1783 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1784 && q_u->printer_default.devmode_cont.devmode_ptr )
1786 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1787 &Printer->nt_devmode );
1790 #if 0 /* JERRY -- I'm doubtful this is really effective */
1791 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1792 optimization in Windows 2000 clients --jerry */
1794 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1795 && (RA_WIN2K == get_remote_arch()) )
1797 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1798 sys_usleep( 500000 );
1805 /****************************************************************************
1806 ****************************************************************************/
1808 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1809 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1815 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1824 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1825 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1831 printer->info_3=NULL;
1832 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1836 printer->info_6=NULL;
1837 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1847 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1848 NT_DEVICEMODE **pp_nt_devmode)
1850 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1853 * Ensure nt_devmode is a valid pointer
1854 * as we will be overwriting it.
1857 if (nt_devmode == NULL) {
1858 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1859 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1863 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1864 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1866 nt_devmode->specversion=devmode->specversion;
1867 nt_devmode->driverversion=devmode->driverversion;
1868 nt_devmode->size=devmode->size;
1869 nt_devmode->fields=devmode->fields;
1870 nt_devmode->orientation=devmode->orientation;
1871 nt_devmode->papersize=devmode->papersize;
1872 nt_devmode->paperlength=devmode->paperlength;
1873 nt_devmode->paperwidth=devmode->paperwidth;
1874 nt_devmode->scale=devmode->scale;
1875 nt_devmode->copies=devmode->copies;
1876 nt_devmode->defaultsource=devmode->defaultsource;
1877 nt_devmode->printquality=devmode->printquality;
1878 nt_devmode->color=devmode->color;
1879 nt_devmode->duplex=devmode->duplex;
1880 nt_devmode->yresolution=devmode->yresolution;
1881 nt_devmode->ttoption=devmode->ttoption;
1882 nt_devmode->collate=devmode->collate;
1884 nt_devmode->logpixels=devmode->logpixels;
1885 nt_devmode->bitsperpel=devmode->bitsperpel;
1886 nt_devmode->pelswidth=devmode->pelswidth;
1887 nt_devmode->pelsheight=devmode->pelsheight;
1888 nt_devmode->displayflags=devmode->displayflags;
1889 nt_devmode->displayfrequency=devmode->displayfrequency;
1890 nt_devmode->icmmethod=devmode->icmmethod;
1891 nt_devmode->icmintent=devmode->icmintent;
1892 nt_devmode->mediatype=devmode->mediatype;
1893 nt_devmode->dithertype=devmode->dithertype;
1894 nt_devmode->reserved1=devmode->reserved1;
1895 nt_devmode->reserved2=devmode->reserved2;
1896 nt_devmode->panningwidth=devmode->panningwidth;
1897 nt_devmode->panningheight=devmode->panningheight;
1900 * Only change private and driverextra if the incoming devmode
1901 * has a new one. JRA.
1904 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1905 SAFE_FREE(nt_devmode->private);
1906 nt_devmode->driverextra=devmode->driverextra;
1907 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1909 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1912 *pp_nt_devmode = nt_devmode;
1917 /********************************************************************
1918 * _spoolss_enddocprinter_internal.
1919 ********************************************************************/
1921 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1923 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1927 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1931 if (!get_printer_snum(p, handle, &snum))
1934 Printer->document_started=False;
1935 print_job_end(snum, Printer->jobid,True);
1936 /* error codes unhandled so far ... */
1941 /********************************************************************
1942 * api_spoolss_closeprinter
1943 ********************************************************************/
1945 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1947 POLICY_HND *handle = &q_u->handle;
1949 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1951 if (Printer && Printer->document_started)
1952 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1954 if (!close_printer_handle(p, handle))
1957 /* clear the returned printer handle. Observed behavior
1958 from Win2k server. Don't think this really matters.
1959 Previous code just copied the value of the closed
1962 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1967 /********************************************************************
1968 * api_spoolss_deleteprinter
1970 ********************************************************************/
1972 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1974 POLICY_HND *handle = &q_u->handle;
1975 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1978 if (Printer && Printer->document_started)
1979 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1981 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1983 result = delete_printer_handle(p, handle);
1985 update_c_setprinter(False);
1990 /*******************************************************************
1991 * static function to lookup the version id corresponding to an
1992 * long architecture string
1993 ******************************************************************/
1995 static int get_version_id (char * arch)
1998 struct table_node archi_table[]= {
2000 {"Windows 4.0", "WIN40", 0 },
2001 {"Windows NT x86", "W32X86", 2 },
2002 {"Windows NT R4000", "W32MIPS", 2 },
2003 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2004 {"Windows NT PowerPC", "W32PPC", 2 },
2005 {"Windows IA64", "IA64", 3 },
2006 {"Windows x64", "x64", 3 },
2010 for (i=0; archi_table[i].long_archi != NULL; i++)
2012 if (strcmp(arch, archi_table[i].long_archi) == 0)
2013 return (archi_table[i].version);
2019 /********************************************************************
2020 * _spoolss_deleteprinterdriver
2021 ********************************************************************/
2023 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2027 NT_PRINTER_DRIVER_INFO_LEVEL info;
2028 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2030 struct current_user user;
2032 WERROR status_win2k = WERR_ACCESS_DENIED;
2034 get_current_user(&user, p);
2036 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2037 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2039 /* check that we have a valid driver name first */
2041 if ((version=get_version_id(arch)) == -1)
2042 return WERR_INVALID_ENVIRONMENT;
2045 ZERO_STRUCT(info_win2k);
2047 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2049 /* try for Win2k driver if "Windows NT x86" */
2051 if ( version == 2 ) {
2053 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2054 status = WERR_UNKNOWN_PRINTER_DRIVER;
2058 /* otherwise it was a failure */
2060 status = WERR_UNKNOWN_PRINTER_DRIVER;
2066 if (printer_driver_in_use(info.info_3)) {
2067 status = WERR_PRINTER_DRIVER_IN_USE;
2073 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2075 /* if we get to here, we now have 2 driver info structures to remove */
2076 /* remove the Win2k driver first*/
2078 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2079 free_a_printer_driver( info_win2k, 3 );
2081 /* this should not have failed---if it did, report to client */
2082 if ( !W_ERROR_IS_OK(status_win2k) )
2087 status = delete_printer_driver(info.info_3, &user, version, False);
2089 /* if at least one of the deletes succeeded return OK */
2091 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2095 free_a_printer_driver( info, 3 );
2100 /********************************************************************
2101 * spoolss_deleteprinterdriverex
2102 ********************************************************************/
2104 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2108 NT_PRINTER_DRIVER_INFO_LEVEL info;
2109 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2111 uint32 flags = q_u->delete_flags;
2113 struct current_user user;
2115 WERROR status_win2k = WERR_ACCESS_DENIED;
2117 get_current_user(&user, p);
2119 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2120 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2122 /* check that we have a valid driver name first */
2123 if ((version=get_version_id(arch)) == -1) {
2124 /* this is what NT returns */
2125 return WERR_INVALID_ENVIRONMENT;
2128 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2129 version = q_u->version;
2132 ZERO_STRUCT(info_win2k);
2134 status = get_a_printer_driver(&info, 3, driver, arch, version);
2136 if ( !W_ERROR_IS_OK(status) )
2139 * if the client asked for a specific version,
2140 * or this is something other than Windows NT x86,
2144 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2147 /* try for Win2k driver if "Windows NT x86" */
2150 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2151 status = WERR_UNKNOWN_PRINTER_DRIVER;
2156 if ( printer_driver_in_use(info.info_3) ) {
2157 status = WERR_PRINTER_DRIVER_IN_USE;
2162 * we have a couple of cases to consider.
2163 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2164 * then the delete should fail if **any** files overlap with
2166 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2167 * non-overlapping files
2168 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2169 * is set, the do not delete any files
2170 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2173 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2175 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2177 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2178 /* no idea of the correct error here */
2179 status = WERR_ACCESS_DENIED;
2184 /* also check for W32X86/3 if necessary; maybe we already have? */
2186 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2187 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2190 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2191 /* no idea of the correct error here */
2192 free_a_printer_driver( info_win2k, 3 );
2193 status = WERR_ACCESS_DENIED;
2197 /* if we get to here, we now have 2 driver info structures to remove */
2198 /* remove the Win2k driver first*/
2200 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2201 free_a_printer_driver( info_win2k, 3 );
2203 /* this should not have failed---if it did, report to client */
2205 if ( !W_ERROR_IS_OK(status_win2k) )
2210 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2212 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2215 free_a_printer_driver( info, 3 );
2221 /****************************************************************************
2222 Internal routine for retreiving printerdata
2223 ***************************************************************************/
2225 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2226 const char *key, const char *value, uint32 *type, uint8 **data,
2227 uint32 *needed, uint32 in_size )
2229 REGISTRY_VALUE *val;
2232 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2233 return WERR_BADFILE;
2235 *type = regval_type( val );
2237 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2239 size = regval_size( val );
2241 /* copy the min(in_size, len) */
2244 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2246 /* special case for 0 length values */
2248 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2252 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2261 DEBUG(5,("get_printer_dataex: copy done\n"));
2266 /****************************************************************************
2267 Internal routine for removing printerdata
2268 ***************************************************************************/
2270 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2272 return delete_printer_data( printer->info_2, key, value );
2275 /****************************************************************************
2276 Internal routine for storing printerdata
2277 ***************************************************************************/
2279 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2280 uint32 type, uint8 *data, int real_len )
2282 delete_printer_data( printer->info_2, key, value );
2284 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2287 /********************************************************************
2288 GetPrinterData on a printer server Handle.
2289 ********************************************************************/
2291 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2295 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2297 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2299 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2305 if (!StrCaseCmp(value, "BeepEnabled")) {
2307 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2309 SIVAL(*data, 0, 0x00);
2314 if (!StrCaseCmp(value, "EventLog")) {
2316 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2318 /* formally was 0x1b */
2319 SIVAL(*data, 0, 0x0);
2324 if (!StrCaseCmp(value, "NetPopup")) {
2326 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2328 SIVAL(*data, 0, 0x00);
2333 if (!StrCaseCmp(value, "MajorVersion")) {
2335 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2338 /* Windows NT 4.0 seems to not allow uploading of drivers
2339 to a server that reports 0x3 as the MajorVersion.
2340 need to investigate more how Win2k gets around this .
2343 if ( RA_WINNT == get_remote_arch() )
2352 if (!StrCaseCmp(value, "MinorVersion")) {
2354 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2362 * uint32 size = 0x114
2364 * uint32 minor = [0|1]
2365 * uint32 build = [2195|2600]
2366 * extra unicode string = e.g. "Service Pack 3"
2368 if (!StrCaseCmp(value, "OSVersion")) {
2372 if((*data = (uint8 *)talloc(ctx, (*needed)*sizeof(uint8) )) == NULL)
2374 ZERO_STRUCTP( *data );
2376 SIVAL(*data, 0, *needed); /* size */
2377 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2379 SIVAL(*data, 12, 2195); /* build */
2381 /* leave extra string empty */
2387 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2388 const char *string="C:\\PRINTERS";
2390 *needed = 2*(strlen(string)+1);
2391 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2393 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2395 /* it's done by hand ready to go on the wire */
2396 for (i=0; i<strlen(string); i++) {
2397 (*data)[2*i]=string[i];
2398 (*data)[2*i+1]='\0';
2403 if (!StrCaseCmp(value, "Architecture")) {
2404 const char *string="Windows NT x86";
2406 *needed = 2*(strlen(string)+1);
2407 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2409 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2410 for (i=0; i<strlen(string); i++) {
2411 (*data)[2*i]=string[i];
2412 (*data)[2*i+1]='\0';
2417 if (!StrCaseCmp(value, "DsPresent")) {
2419 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2421 SIVAL(*data, 0, 0x01);
2426 if (!StrCaseCmp(value, "DNSMachineName")) {
2429 if (!get_mydnsfullname(hostname))
2430 return WERR_BADFILE;
2432 *needed = 2*(strlen(hostname)+1);
2433 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2435 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2436 for (i=0; i<strlen(hostname); i++) {
2437 (*data)[2*i]=hostname[i];
2438 (*data)[2*i+1]='\0';
2444 return WERR_BADFILE;
2447 /********************************************************************
2448 * spoolss_getprinterdata
2449 ********************************************************************/
2451 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2453 POLICY_HND *handle = &q_u->handle;
2454 UNISTR2 *valuename = &q_u->valuename;
2455 uint32 in_size = q_u->size;
2456 uint32 *type = &r_u->type;
2457 uint32 *out_size = &r_u->size;
2458 uint8 **data = &r_u->data;
2459 uint32 *needed = &r_u->needed;
2462 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2463 NT_PRINTER_INFO_LEVEL *printer = NULL;
2467 * Reminder: when it's a string, the length is in BYTES
2468 * even if UNICODE is negociated.
2473 *out_size = in_size;
2475 /* in case of problem, return some default values */
2480 DEBUG(4,("_spoolss_getprinterdata\n"));
2483 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2484 status = WERR_BADFID;
2488 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2490 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2491 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2494 if ( !get_printer_snum(p,handle, &snum) ) {
2495 status = WERR_BADFID;
2499 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2500 if ( !W_ERROR_IS_OK(status) )
2503 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2505 if ( strequal(value, "ChangeId") ) {
2507 *needed = sizeof(uint32);
2508 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2509 status = WERR_NOMEM;
2512 SIVAL( *data, 0, printer->info_2->changeid );
2516 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2519 if (*needed > *out_size)
2520 status = WERR_MORE_DATA;
2523 if ( !W_ERROR_IS_OK(status) )
2525 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2527 /* reply this param doesn't exist */
2530 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2532 free_a_printer( &printer, 2 );
2541 /* cleanup & exit */
2544 free_a_printer( &printer, 2 );
2549 /*********************************************************
2550 Connect to the client machine.
2551 **********************************************************/
2553 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2554 struct in_addr *client_ip, const char *remote_machine)
2556 ZERO_STRUCTP(the_cli);
2558 if(cli_initialise(the_cli) == NULL) {
2559 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2563 if ( is_zero_ip(*client_ip) ) {
2564 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2565 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2566 cli_shutdown(the_cli);
2570 if (ismyip(the_cli->dest_ip)) {
2571 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2572 cli_shutdown(the_cli);
2577 the_cli->dest_ip.s_addr = client_ip->s_addr;
2578 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2579 inet_ntoa(*client_ip) ));
2582 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2583 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) ));
2584 cli_shutdown(the_cli);
2588 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2589 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2591 cli_shutdown(the_cli);
2595 the_cli->protocol = PROTOCOL_NT1;
2596 cli_setup_signing_state(the_cli, lp_client_signing());
2598 if (!cli_negprot(the_cli)) {
2599 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2600 cli_shutdown(the_cli);
2604 if (the_cli->protocol != PROTOCOL_NT1) {
2605 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2606 cli_shutdown(the_cli);
2611 * Do an anonymous session setup.
2614 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2615 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2616 cli_shutdown(the_cli);
2620 if (!(the_cli->sec_mode & 1)) {
2621 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2622 cli_shutdown(the_cli);
2626 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2627 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) ));
2628 cli_shutdown(the_cli);
2633 * Ok - we have an anonymous connection to the IPC$ share.
2634 * Now start the NT Domain stuff :-).
2637 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2638 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)));
2639 cli_nt_session_close(the_cli);
2640 cli_ulogoff(the_cli);
2641 cli_shutdown(the_cli);
2648 /***************************************************************************
2649 Connect to the client.
2650 ****************************************************************************/
2652 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2653 uint32 localprinter, uint32 type,
2654 POLICY_HND *handle, struct in_addr *client_ip)
2659 * If it's the first connection, contact the client
2660 * and connect to the IPC$ share anonymously
2662 if (smb_connections==0) {
2663 fstring unix_printer;
2665 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2667 ZERO_STRUCT(notify_cli);
2669 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2672 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2673 /* Tell the connections db we're now interested in printer
2674 * notify messages. */
2675 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2679 * Tell the specific printing tdb we want messages for this printer
2680 * by registering our PID.
2683 if (!print_notify_register_pid(snum))
2684 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2688 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2691 if (!W_ERROR_IS_OK(result))
2692 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2693 dos_errstr(result)));
2695 return (W_ERROR_IS_OK(result));
2698 /********************************************************************
2700 * ReplyFindFirstPrinterChangeNotifyEx
2702 * before replying OK: status=0 a rpc call is made to the workstation
2703 * asking ReplyOpenPrinter
2705 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2706 * called from api_spoolss_rffpcnex
2707 ********************************************************************/
2709 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2711 POLICY_HND *handle = &q_u->handle;
2712 uint32 flags = q_u->flags;
2713 uint32 options = q_u->options;
2714 UNISTR2 *localmachine = &q_u->localmachine;
2715 uint32 printerlocal = q_u->printerlocal;
2717 SPOOL_NOTIFY_OPTION *option = q_u->option;
2718 struct in_addr client_ip;
2720 /* store the notify value in the printer struct */
2722 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2725 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2729 Printer->notify.flags=flags;
2730 Printer->notify.options=options;
2731 Printer->notify.printerlocal=printerlocal;
2733 if (Printer->notify.option)
2734 free_spool_notify_option(&Printer->notify.option);
2736 Printer->notify.option=dup_spool_notify_option(option);
2738 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2739 sizeof(Printer->notify.localmachine)-1);
2741 /* Connect to the client machine and send a ReplyOpenPrinter */
2743 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2745 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2746 !get_printer_snum(p, handle, &snum) )
2749 client_ip.s_addr = inet_addr(p->conn->client_address);
2751 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2752 Printer->notify.printerlocal, 1,
2753 &Printer->notify.client_hnd, &client_ip))
2754 return WERR_SERVER_UNAVAILABLE;
2756 Printer->notify.client_connected=True;
2761 /*******************************************************************
2762 * fill a notify_info_data with the servername
2763 ********************************************************************/
2765 void spoolss_notify_server_name(int snum,
2766 SPOOL_NOTIFY_INFO_DATA *data,
2767 print_queue_struct *queue,
2768 NT_PRINTER_INFO_LEVEL *printer,
2769 TALLOC_CTX *mem_ctx)
2774 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2776 data->notify_data.data.length = len;
2777 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2779 if (!data->notify_data.data.string) {
2780 data->notify_data.data.length = 0;
2784 memcpy(data->notify_data.data.string, temp, len);
2787 /*******************************************************************
2788 * fill a notify_info_data with the printername (not including the servername).
2789 ********************************************************************/
2791 void spoolss_notify_printer_name(int snum,
2792 SPOOL_NOTIFY_INFO_DATA *data,
2793 print_queue_struct *queue,
2794 NT_PRINTER_INFO_LEVEL *printer,
2795 TALLOC_CTX *mem_ctx)
2800 /* the notify name should not contain the \\server\ part */
2801 char *p = strrchr(printer->info_2->printername, '\\');
2804 p = printer->info_2->printername;
2809 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2811 data->notify_data.data.length = len;
2812 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2814 if (!data->notify_data.data.string) {
2815 data->notify_data.data.length = 0;
2819 memcpy(data->notify_data.data.string, temp, len);
2822 /*******************************************************************
2823 * fill a notify_info_data with the servicename
2824 ********************************************************************/
2826 void spoolss_notify_share_name(int snum,
2827 SPOOL_NOTIFY_INFO_DATA *data,
2828 print_queue_struct *queue,
2829 NT_PRINTER_INFO_LEVEL *printer,
2830 TALLOC_CTX *mem_ctx)
2835 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2837 data->notify_data.data.length = len;
2838 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2840 if (!data->notify_data.data.string) {
2841 data->notify_data.data.length = 0;
2845 memcpy(data->notify_data.data.string, temp, len);
2848 /*******************************************************************
2849 * fill a notify_info_data with the port name
2850 ********************************************************************/
2852 void spoolss_notify_port_name(int snum,
2853 SPOOL_NOTIFY_INFO_DATA *data,
2854 print_queue_struct *queue,
2855 NT_PRINTER_INFO_LEVEL *printer,
2856 TALLOC_CTX *mem_ctx)
2861 /* even if it's strange, that's consistant in all the code */
2863 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2865 data->notify_data.data.length = len;
2866 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2868 if (!data->notify_data.data.string) {
2869 data->notify_data.data.length = 0;
2873 memcpy(data->notify_data.data.string, temp, len);
2876 /*******************************************************************
2877 * fill a notify_info_data with the printername
2878 * but it doesn't exist, have to see what to do
2879 ********************************************************************/
2881 void spoolss_notify_driver_name(int snum,
2882 SPOOL_NOTIFY_INFO_DATA *data,
2883 print_queue_struct *queue,
2884 NT_PRINTER_INFO_LEVEL *printer,
2885 TALLOC_CTX *mem_ctx)
2890 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2892 data->notify_data.data.length = len;
2893 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2895 if (!data->notify_data.data.string) {
2896 data->notify_data.data.length = 0;
2900 memcpy(data->notify_data.data.string, temp, len);
2903 /*******************************************************************
2904 * fill a notify_info_data with the comment
2905 ********************************************************************/
2907 void spoolss_notify_comment(int snum,
2908 SPOOL_NOTIFY_INFO_DATA *data,
2909 print_queue_struct *queue,
2910 NT_PRINTER_INFO_LEVEL *printer,
2911 TALLOC_CTX *mem_ctx)
2916 if (*printer->info_2->comment == '\0')
2917 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2919 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2921 data->notify_data.data.length = len;
2922 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2924 if (!data->notify_data.data.string) {
2925 data->notify_data.data.length = 0;
2929 memcpy(data->notify_data.data.string, temp, len);
2932 /*******************************************************************
2933 * fill a notify_info_data with the comment
2934 * location = "Room 1, floor 2, building 3"
2935 ********************************************************************/
2937 void spoolss_notify_location(int snum,
2938 SPOOL_NOTIFY_INFO_DATA *data,
2939 print_queue_struct *queue,
2940 NT_PRINTER_INFO_LEVEL *printer,
2941 TALLOC_CTX *mem_ctx)
2946 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2948 data->notify_data.data.length = len;
2949 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2951 if (!data->notify_data.data.string) {
2952 data->notify_data.data.length = 0;
2956 memcpy(data->notify_data.data.string, temp, len);
2959 /*******************************************************************
2960 * fill a notify_info_data with the device mode
2961 * jfm:xxxx don't to it for know but that's a real problem !!!
2962 ********************************************************************/
2964 static void spoolss_notify_devmode(int snum,
2965 SPOOL_NOTIFY_INFO_DATA *data,
2966 print_queue_struct *queue,
2967 NT_PRINTER_INFO_LEVEL *printer,
2968 TALLOC_CTX *mem_ctx)
2972 /*******************************************************************
2973 * fill a notify_info_data with the separator file name
2974 ********************************************************************/
2976 void spoolss_notify_sepfile(int snum,
2977 SPOOL_NOTIFY_INFO_DATA *data,
2978 print_queue_struct *queue,
2979 NT_PRINTER_INFO_LEVEL *printer,
2980 TALLOC_CTX *mem_ctx)
2985 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2987 data->notify_data.data.length = len;
2988 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2990 if (!data->notify_data.data.string) {
2991 data->notify_data.data.length = 0;
2995 memcpy(data->notify_data.data.string, temp, len);
2998 /*******************************************************************
2999 * fill a notify_info_data with the print processor
3000 * jfm:xxxx return always winprint to indicate we don't do anything to it
3001 ********************************************************************/
3003 void spoolss_notify_print_processor(int snum,
3004 SPOOL_NOTIFY_INFO_DATA *data,
3005 print_queue_struct *queue,
3006 NT_PRINTER_INFO_LEVEL *printer,
3007 TALLOC_CTX *mem_ctx)
3012 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3014 data->notify_data.data.length = len;
3015 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3017 if (!data->notify_data.data.string) {
3018 data->notify_data.data.length = 0;
3022 memcpy(data->notify_data.data.string, temp, len);
3025 /*******************************************************************
3026 * fill a notify_info_data with the print processor options
3027 * jfm:xxxx send an empty string
3028 ********************************************************************/
3030 void spoolss_notify_parameters(int snum,
3031 SPOOL_NOTIFY_INFO_DATA *data,
3032 print_queue_struct *queue,
3033 NT_PRINTER_INFO_LEVEL *printer,
3034 TALLOC_CTX *mem_ctx)
3039 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3041 data->notify_data.data.length = len;
3042 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3044 if (!data->notify_data.data.string) {
3045 data->notify_data.data.length = 0;
3049 memcpy(data->notify_data.data.string, temp, len);
3052 /*******************************************************************
3053 * fill a notify_info_data with the data type
3054 * jfm:xxxx always send RAW as data type
3055 ********************************************************************/
3057 void spoolss_notify_datatype(int snum,
3058 SPOOL_NOTIFY_INFO_DATA *data,
3059 print_queue_struct *queue,
3060 NT_PRINTER_INFO_LEVEL *printer,
3061 TALLOC_CTX *mem_ctx)
3066 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3068 data->notify_data.data.length = len;
3069 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3071 if (!data->notify_data.data.string) {
3072 data->notify_data.data.length = 0;
3076 memcpy(data->notify_data.data.string, temp, len);
3079 /*******************************************************************
3080 * fill a notify_info_data with the security descriptor
3081 * jfm:xxxx send an null pointer to say no security desc
3082 * have to implement security before !
3083 ********************************************************************/
3085 static void spoolss_notify_security_desc(int snum,
3086 SPOOL_NOTIFY_INFO_DATA *data,
3087 print_queue_struct *queue,
3088 NT_PRINTER_INFO_LEVEL *printer,
3089 TALLOC_CTX *mem_ctx)
3091 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3092 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3095 /*******************************************************************
3096 * fill a notify_info_data with the attributes
3097 * jfm:xxxx a samba printer is always shared
3098 ********************************************************************/
3100 void spoolss_notify_attributes(int snum,
3101 SPOOL_NOTIFY_INFO_DATA *data,
3102 print_queue_struct *queue,
3103 NT_PRINTER_INFO_LEVEL *printer,
3104 TALLOC_CTX *mem_ctx)
3106 data->notify_data.value[0] = printer->info_2->attributes;
3107 data->notify_data.value[1] = 0;
3110 /*******************************************************************
3111 * fill a notify_info_data with the priority
3112 ********************************************************************/
3114 static void spoolss_notify_priority(int snum,
3115 SPOOL_NOTIFY_INFO_DATA *data,
3116 print_queue_struct *queue,
3117 NT_PRINTER_INFO_LEVEL *printer,
3118 TALLOC_CTX *mem_ctx)
3120 data->notify_data.value[0] = printer->info_2->priority;
3121 data->notify_data.value[1] = 0;
3124 /*******************************************************************
3125 * fill a notify_info_data with the default priority
3126 ********************************************************************/
3128 static void spoolss_notify_default_priority(int snum,
3129 SPOOL_NOTIFY_INFO_DATA *data,
3130 print_queue_struct *queue,
3131 NT_PRINTER_INFO_LEVEL *printer,
3132 TALLOC_CTX *mem_ctx)
3134 data->notify_data.value[0] = printer->info_2->default_priority;
3135 data->notify_data.value[1] = 0;
3138 /*******************************************************************
3139 * fill a notify_info_data with the start time
3140 ********************************************************************/
3142 static void spoolss_notify_start_time(int snum,
3143 SPOOL_NOTIFY_INFO_DATA *data,
3144 print_queue_struct *queue,
3145 NT_PRINTER_INFO_LEVEL *printer,
3146 TALLOC_CTX *mem_ctx)
3148 data->notify_data.value[0] = printer->info_2->starttime;
3149 data->notify_data.value[1] = 0;
3152 /*******************************************************************
3153 * fill a notify_info_data with the until time
3154 ********************************************************************/
3156 static void spoolss_notify_until_time(int snum,
3157 SPOOL_NOTIFY_INFO_DATA *data,
3158 print_queue_struct *queue,
3159 NT_PRINTER_INFO_LEVEL *printer,
3160 TALLOC_CTX *mem_ctx)
3162 data->notify_data.value[0] = printer->info_2->untiltime;
3163 data->notify_data.value[1] = 0;
3166 /*******************************************************************
3167 * fill a notify_info_data with the status
3168 ********************************************************************/
3170 static void spoolss_notify_status(int snum,
3171 SPOOL_NOTIFY_INFO_DATA *data,
3172 print_queue_struct *queue,
3173 NT_PRINTER_INFO_LEVEL *printer,
3174 TALLOC_CTX *mem_ctx)
3176 print_status_struct status;
3178 print_queue_length(snum, &status);
3179 data->notify_data.value[0]=(uint32) status.status;
3180 data->notify_data.value[1] = 0;
3183 /*******************************************************************
3184 * fill a notify_info_data with the number of jobs queued
3185 ********************************************************************/
3187 void spoolss_notify_cjobs(int snum,
3188 SPOOL_NOTIFY_INFO_DATA *data,
3189 print_queue_struct *queue,
3190 NT_PRINTER_INFO_LEVEL *printer,
3191 TALLOC_CTX *mem_ctx)
3193 data->notify_data.value[0] = print_queue_length(snum, NULL);
3194 data->notify_data.value[1] = 0;
3197 /*******************************************************************
3198 * fill a notify_info_data with the average ppm
3199 ********************************************************************/
3201 static void spoolss_notify_average_ppm(int snum,
3202 SPOOL_NOTIFY_INFO_DATA *data,
3203 print_queue_struct *queue,
3204 NT_PRINTER_INFO_LEVEL *printer,
3205 TALLOC_CTX *mem_ctx)
3207 /* always respond 8 pages per minutes */
3208 /* a little hard ! */
3209 data->notify_data.value[0] = printer->info_2->averageppm;
3210 data->notify_data.value[1] = 0;
3213 /*******************************************************************
3214 * fill a notify_info_data with username
3215 ********************************************************************/
3217 static void spoolss_notify_username(int snum,
3218 SPOOL_NOTIFY_INFO_DATA *data,
3219 print_queue_struct *queue,
3220 NT_PRINTER_INFO_LEVEL *printer,
3221 TALLOC_CTX *mem_ctx)
3226 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3228 data->notify_data.data.length = len;
3229 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3231 if (!data->notify_data.data.string) {
3232 data->notify_data.data.length = 0;
3236 memcpy(data->notify_data.data.string, temp, len);
3239 /*******************************************************************
3240 * fill a notify_info_data with job status
3241 ********************************************************************/
3243 static void spoolss_notify_job_status(int snum,
3244 SPOOL_NOTIFY_INFO_DATA *data,
3245 print_queue_struct *queue,
3246 NT_PRINTER_INFO_LEVEL *printer,
3247 TALLOC_CTX *mem_ctx)
3249 data->notify_data.value[0]=nt_printj_status(queue->status);
3250 data->notify_data.value[1] = 0;
3253 /*******************************************************************
3254 * fill a notify_info_data with job name
3255 ********************************************************************/
3257 static void spoolss_notify_job_name(int snum,
3258 SPOOL_NOTIFY_INFO_DATA *data,
3259 print_queue_struct *queue,
3260 NT_PRINTER_INFO_LEVEL *printer,
3261 TALLOC_CTX *mem_ctx)
3266 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3268 data->notify_data.data.length = len;
3269 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3271 if (!data->notify_data.data.string) {
3272 data->notify_data.data.length = 0;
3276 memcpy(data->notify_data.data.string, temp, len);
3279 /*******************************************************************
3280 * fill a notify_info_data with job status
3281 ********************************************************************/
3283 static void spoolss_notify_job_status_string(int snum,
3284 SPOOL_NOTIFY_INFO_DATA *data,
3285 print_queue_struct *queue,
3286 NT_PRINTER_INFO_LEVEL *printer,
3287 TALLOC_CTX *mem_ctx)
3290 * Now we're returning job status codes we just return a "" here. JRA.
3297 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3300 switch (queue->status) {
3305 p = ""; /* NT provides the paused string */
3314 #endif /* NO LONGER NEEDED. */
3316 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3318 data->notify_data.data.length = len;
3319 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3321 if (!data->notify_data.data.string) {
3322 data->notify_data.data.length = 0;
3326 memcpy(data->notify_data.data.string, temp, len);
3329 /*******************************************************************
3330 * fill a notify_info_data with job time
3331 ********************************************************************/
3333 static void spoolss_notify_job_time(int snum,
3334 SPOOL_NOTIFY_INFO_DATA *data,
3335 print_queue_struct *queue,
3336 NT_PRINTER_INFO_LEVEL *printer,
3337 TALLOC_CTX *mem_ctx)
3339 data->notify_data.value[0]=0x0;
3340 data->notify_data.value[1]=0;
3343 /*******************************************************************
3344 * fill a notify_info_data with job size
3345 ********************************************************************/
3347 static void spoolss_notify_job_size(int snum,
3348 SPOOL_NOTIFY_INFO_DATA *data,
3349 print_queue_struct *queue,
3350 NT_PRINTER_INFO_LEVEL *printer,
3351 TALLOC_CTX *mem_ctx)
3353 data->notify_data.value[0]=queue->size;
3354 data->notify_data.value[1]=0;
3357 /*******************************************************************
3358 * fill a notify_info_data with page info
3359 ********************************************************************/
3360 static void spoolss_notify_total_pages(int snum,
3361 SPOOL_NOTIFY_INFO_DATA *data,
3362 print_queue_struct *queue,
3363 NT_PRINTER_INFO_LEVEL *printer,
3364 TALLOC_CTX *mem_ctx)
3366 data->notify_data.value[0]=queue->page_count;
3367 data->notify_data.value[1]=0;
3370 /*******************************************************************
3371 * fill a notify_info_data with pages printed info.
3372 ********************************************************************/
3373 static void spoolss_notify_pages_printed(int snum,
3374 SPOOL_NOTIFY_INFO_DATA *data,
3375 print_queue_struct *queue,
3376 NT_PRINTER_INFO_LEVEL *printer,
3377 TALLOC_CTX *mem_ctx)
3379 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3380 data->notify_data.value[1]=0;
3383 /*******************************************************************
3384 Fill a notify_info_data with job position.
3385 ********************************************************************/
3387 static void spoolss_notify_job_position(int snum,
3388 SPOOL_NOTIFY_INFO_DATA *data,
3389 print_queue_struct *queue,
3390 NT_PRINTER_INFO_LEVEL *printer,
3391 TALLOC_CTX *mem_ctx)
3393 data->notify_data.value[0]=queue->job;
3394 data->notify_data.value[1]=0;
3397 /*******************************************************************
3398 Fill a notify_info_data with submitted time.
3399 ********************************************************************/
3401 static void spoolss_notify_submitted_time(int snum,
3402 SPOOL_NOTIFY_INFO_DATA *data,
3403 print_queue_struct *queue,
3404 NT_PRINTER_INFO_LEVEL *printer,
3405 TALLOC_CTX *mem_ctx)
3412 t=gmtime(&queue->time);
3414 len = sizeof(SYSTEMTIME);
3416 data->notify_data.data.length = len;
3417 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3419 if (!data->notify_data.data.string) {
3420 data->notify_data.data.length = 0;
3424 make_systemtime(&st, t);
3427 * Systemtime must be linearized as a set of UINT16's.
3428 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3431 p = (char *)data->notify_data.data.string;
3432 SSVAL(p, 0, st.year);
3433 SSVAL(p, 2, st.month);
3434 SSVAL(p, 4, st.dayofweek);
3435 SSVAL(p, 6, st.day);
3436 SSVAL(p, 8, st.hour);
3437 SSVAL(p, 10, st.minute);
3438 SSVAL(p, 12, st.second);
3439 SSVAL(p, 14, st.milliseconds);
3442 struct s_notify_info_data_table
3448 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3449 print_queue_struct *queue,
3450 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3453 /* A table describing the various print notification constants and
3454 whether the notification data is a pointer to a variable sized
3455 buffer, a one value uint32 or a two value uint32. */
3457 static const struct s_notify_info_data_table notify_info_data_table[] =
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3477 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3478 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3479 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3480 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3481 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3482 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3483 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3484 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3500 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3501 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3502 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3503 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3504 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3505 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3506 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3507 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3508 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3511 /*******************************************************************
3512 Return the size of info_data structure.
3513 ********************************************************************/
3515 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3519 for (i = 0; i < sizeof(notify_info_data_table); i++)
3521 if ( (notify_info_data_table[i].type == type)
3522 && (notify_info_data_table[i].field == field) )
3524 switch(notify_info_data_table[i].size)
3526 case NOTIFY_ONE_VALUE:
3527 case NOTIFY_TWO_VALUE:
3532 /* The only pointer notify data I have seen on
3533 the wire is the submitted time and this has
3534 the notify size set to 4. -tpot */
3536 case NOTIFY_POINTER:
3539 case NOTIFY_SECDESC:
3545 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3550 /*******************************************************************
3551 Return the type of notify_info_data.
3552 ********************************************************************/
3554 static int type_of_notify_info_data(uint16 type, uint16 field)
3558 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3559 if (notify_info_data_table[i].type == type &&
3560 notify_info_data_table[i].field == field)
3561 return notify_info_data_table[i].size;
3567 /****************************************************************************
3568 ****************************************************************************/
3570 static int search_notify(uint16 type, uint16 field, int *value)
3574 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3575 if (notify_info_data_table[i].type == type &&
3576 notify_info_data_table[i].field == field &&
3577 notify_info_data_table[i].fn != NULL) {
3586 /****************************************************************************
3587 ****************************************************************************/
3589 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3591 info_data->type = type;
3592 info_data->field = field;
3593 info_data->reserved = 0;
3595 info_data->size = size_of_notify_info_data(type, field);
3596 info_data->enc_type = type_of_notify_info_data(type, field);
3603 /*******************************************************************
3605 * fill a notify_info struct with info asked
3607 ********************************************************************/
3609 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3610 snum, SPOOL_NOTIFY_OPTION_TYPE
3611 *option_type, uint32 id,
3612 TALLOC_CTX *mem_ctx)
3618 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3619 NT_PRINTER_INFO_LEVEL *printer = NULL;
3620 print_queue_struct *queue=NULL;
3622 type=option_type->type;
3624 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3625 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3626 option_type->count, lp_servicename(snum)));
3628 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3631 for(field_num=0; field_num<option_type->count; field_num++) {
3632 field = option_type->fields[field_num];
3634 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3636 if (!search_notify(type, field, &j) )
3639 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3640 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3645 current_data = &info->data[info->count];
3647 construct_info_data(current_data, type, field, id);
3649 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3650 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3652 notify_info_data_table[j].fn(snum, current_data, queue,
3658 free_a_printer(&printer, 2);
3662 /*******************************************************************
3664 * fill a notify_info struct with info asked
3666 ********************************************************************/
3668 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3669 SPOOL_NOTIFY_INFO *info,
3670 NT_PRINTER_INFO_LEVEL *printer,
3671 int snum, SPOOL_NOTIFY_OPTION_TYPE
3672 *option_type, uint32 id,
3673 TALLOC_CTX *mem_ctx)
3679 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3681 DEBUG(4,("construct_notify_jobs_info\n"));
3683 type = option_type->type;
3685 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3686 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3687 option_type->count));
3689 for(field_num=0; field_num<option_type->count; field_num++) {
3690 field = option_type->fields[field_num];
3692 if (!search_notify(type, field, &j) )
3695 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3696 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3699 else info->data = tid;
3701 current_data=&(info->data[info->count]);
3703 construct_info_data(current_data, type, field, id);
3704 notify_info_data_table[j].fn(snum, current_data, queue,
3713 * JFM: The enumeration is not that simple, it's even non obvious.
3715 * let's take an example: I want to monitor the PRINTER SERVER for
3716 * the printer's name and the number of jobs currently queued.
3717 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3718 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3720 * I have 3 printers on the back of my server.
3722 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3725 * 1 printer 1 name 1
3726 * 2 printer 1 cjob 1
3727 * 3 printer 2 name 2
3728 * 4 printer 2 cjob 2
3729 * 5 printer 3 name 3
3730 * 6 printer 3 name 3
3732 * that's the print server case, the printer case is even worse.
3735 /*******************************************************************
3737 * enumerate all printers on the printserver
3738 * fill a notify_info struct with info asked
3740 ********************************************************************/
3742 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3743 SPOOL_NOTIFY_INFO *info,
3744 TALLOC_CTX *mem_ctx)
3747 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3748 int n_services=lp_numservices();
3750 SPOOL_NOTIFY_OPTION *option;
3751 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3753 DEBUG(4,("printserver_notify_info\n"));
3758 option=Printer->notify.option;
3763 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3764 sending a ffpcn() request first */
3769 for (i=0; i<option->count; i++) {
3770 option_type=&(option->ctr.type[i]);
3772 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3775 for (snum=0; snum<n_services; snum++)
3777 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3778 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3784 * Debugging information, don't delete.
3787 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3788 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3789 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3791 for (i=0; i<info->count; i++) {
3792 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3793 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3794 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3801 /*******************************************************************
3803 * fill a notify_info struct with info asked
3805 ********************************************************************/
3807 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3808 TALLOC_CTX *mem_ctx)
3811 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3814 SPOOL_NOTIFY_OPTION *option;
3815 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3817 print_queue_struct *queue=NULL;
3818 print_status_struct status;
3820 DEBUG(4,("printer_notify_info\n"));
3825 option=Printer->notify.option;
3831 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3832 sending a ffpcn() request first */
3837 get_printer_snum(p, hnd, &snum);
3839 for (i=0; i<option->count; i++) {
3840 option_type=&option->ctr.type[i];
3842 switch ( option_type->type ) {
3843 case PRINTER_NOTIFY_TYPE:
3844 if(construct_notify_printer_info(Printer, info, snum,
3850 case JOB_NOTIFY_TYPE: {
3851 NT_PRINTER_INFO_LEVEL *printer = NULL;
3853 count = print_queue_status(snum, &queue, &status);
3855 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3858 for (j=0; j<count; j++) {
3859 construct_notify_jobs_info(&queue[j], info,
3866 free_a_printer(&printer, 2);
3876 * Debugging information, don't delete.
3879 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3880 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3881 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3883 for (i=0; i<info->count; i++) {
3884 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3885 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3886 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3892 /********************************************************************
3894 ********************************************************************/
3896 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3898 POLICY_HND *handle = &q_u->handle;
3899 SPOOL_NOTIFY_INFO *info = &r_u->info;
3901 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3902 WERROR result = WERR_BADFID;
3904 /* we always have a NOTIFY_INFO struct */
3908 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3909 OUR_HANDLE(handle)));
3913 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3916 * We are now using the change value, and
3917 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3918 * I don't have a global notification system, I'm sending back all the
3919 * informations even when _NOTHING_ has changed.
3922 /* We need to keep track of the change value to send back in
3923 RRPCN replies otherwise our updates are ignored. */
3925 Printer->notify.fnpcn = True;
3927 if (Printer->notify.client_connected) {
3928 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3929 Printer->notify.change = q_u->change;
3932 /* just ignore the SPOOL_NOTIFY_OPTION */
3934 switch (Printer->printer_type) {
3935 case PRINTER_HANDLE_IS_PRINTSERVER:
3936 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3939 case PRINTER_HANDLE_IS_PRINTER:
3940 result = printer_notify_info(p, handle, info, p->mem_ctx);
3944 Printer->notify.fnpcn = False;
3950 /********************************************************************
3951 * construct_printer_info_0
3952 * fill a printer_info_0 struct
3953 ********************************************************************/
3955 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3959 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3960 counter_printer_0 *session_counter;
3961 uint32 global_counter;
3964 print_status_struct status;
3966 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3969 count = print_queue_length(snum, &status);
3971 /* check if we already have a counter for this printer */
3972 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3973 if (session_counter->snum == snum)
3977 /* it's the first time, add it to the list */
3978 if (session_counter==NULL) {
3979 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3980 free_a_printer(&ntprinter, 2);
3983 ZERO_STRUCTP(session_counter);
3984 session_counter->snum=snum;
3985 session_counter->counter=0;
3986 DLIST_ADD(counter_list, session_counter);
3990 session_counter->counter++;
3993 * the global_counter should be stored in a TDB as it's common to all the clients
3994 * and should be zeroed on samba startup
3996 global_counter=session_counter->counter;
3998 pstrcpy(chaine,ntprinter->info_2->printername);
4000 init_unistr(&printer->printername, chaine);
4002 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
4003 init_unistr(&printer->servername, chaine);
4005 printer->cjobs = count;
4006 printer->total_jobs = 0;
4007 printer->total_bytes = 0;
4009 setuptime = (time_t)ntprinter->info_2->setuptime;
4010 t=gmtime(&setuptime);
4012 printer->year = t->tm_year+1900;
4013 printer->month = t->tm_mon+1;
4014 printer->dayofweek = t->tm_wday;
4015 printer->day = t->tm_mday;
4016 printer->hour = t->tm_hour;
4017 printer->minute = t->tm_min;
4018 printer->second = t->tm_sec;
4019 printer->milliseconds = 0;
4021 printer->global_counter = global_counter;
4022 printer->total_pages = 0;
4024 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4025 printer->major_version = 0x0005; /* NT 5 */
4026 printer->build_version = 0x0893; /* build 2195 */
4028 printer->unknown7 = 0x1;
4029 printer->unknown8 = 0x0;
4030 printer->unknown9 = 0x0;
4031 printer->session_counter = session_counter->counter;
4032 printer->unknown11 = 0x0;
4033 printer->printer_errors = 0x0; /* number of print failure */
4034 printer->unknown13 = 0x0;
4035 printer->unknown14 = 0x1;
4036 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4037 printer->unknown16 = 0x0;
4038 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4039 printer->unknown18 = 0x0;
4040 printer->status = nt_printq_status(status.status);
4041 printer->unknown20 = 0x0;
4042 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4043 printer->unknown22 = 0x0;
4044 printer->unknown23 = 0x6; /* 6 ???*/
4045 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4046 printer->unknown25 = 0;
4047 printer->unknown26 = 0;
4048 printer->unknown27 = 0;
4049 printer->unknown28 = 0;
4050 printer->unknown29 = 0;
4052 free_a_printer(&ntprinter,2);
4056 /********************************************************************
4057 * construct_printer_info_1
4058 * fill a printer_info_1 struct
4059 ********************************************************************/
4060 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4064 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4066 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4069 printer->flags=flags;
4071 if (*ntprinter->info_2->comment == '\0') {
4072 init_unistr(&printer->comment, lp_comment(snum));
4073 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4074 ntprinter->info_2->drivername, lp_comment(snum));
4077 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4078 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4079 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4082 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4084 init_unistr(&printer->description, chaine);
4085 init_unistr(&printer->name, chaine2);
4087 free_a_printer(&ntprinter,2);
4092 /****************************************************************************
4093 Free a DEVMODE struct.
4094 ****************************************************************************/
4096 static void free_dev_mode(DEVICEMODE *dev)
4101 SAFE_FREE(dev->private);
4106 /****************************************************************************
4107 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4108 should be valid upon entry
4109 ****************************************************************************/
4111 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4113 if ( !devmode || !ntdevmode )
4116 init_unistr(&devmode->devicename, ntdevmode->devicename);
4118 init_unistr(&devmode->formname, ntdevmode->formname);
4120 devmode->specversion = ntdevmode->specversion;
4121 devmode->driverversion = ntdevmode->driverversion;
4122 devmode->size = ntdevmode->size;
4123 devmode->driverextra = ntdevmode->driverextra;
4124 devmode->fields = ntdevmode->fields;
4126 devmode->orientation = ntdevmode->orientation;
4127 devmode->papersize = ntdevmode->papersize;
4128 devmode->paperlength = ntdevmode->paperlength;
4129 devmode->paperwidth = ntdevmode->paperwidth;
4130 devmode->scale = ntdevmode->scale;
4131 devmode->copies = ntdevmode->copies;
4132 devmode->defaultsource = ntdevmode->defaultsource;
4133 devmode->printquality = ntdevmode->printquality;
4134 devmode->color = ntdevmode->color;
4135 devmode->duplex = ntdevmode->duplex;
4136 devmode->yresolution = ntdevmode->yresolution;
4137 devmode->ttoption = ntdevmode->ttoption;
4138 devmode->collate = ntdevmode->collate;
4139 devmode->icmmethod = ntdevmode->icmmethod;
4140 devmode->icmintent = ntdevmode->icmintent;
4141 devmode->mediatype = ntdevmode->mediatype;
4142 devmode->dithertype = ntdevmode->dithertype;
4144 if (ntdevmode->private != NULL) {
4145 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4152 /****************************************************************************
4153 Create a DEVMODE struct. Returns malloced memory.
4154 ****************************************************************************/
4156 DEVICEMODE *construct_dev_mode(int snum)
4158 NT_PRINTER_INFO_LEVEL *printer = NULL;
4159 DEVICEMODE *devmode = NULL;
4161 DEBUG(7,("construct_dev_mode\n"));
4163 DEBUGADD(8,("getting printer characteristics\n"));
4165 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4168 if ( !printer->info_2->devmode ) {
4169 DEBUG(5, ("BONG! There was no device mode!\n"));
4173 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4174 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4178 ZERO_STRUCTP(devmode);
4180 DEBUGADD(8,("loading DEVICEMODE\n"));
4182 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4183 free_dev_mode( devmode );
4188 free_a_printer(&printer,2);
4193 /********************************************************************
4194 * construct_printer_info_2
4195 * fill a printer_info_2 struct
4196 ********************************************************************/
4198 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4201 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4203 print_status_struct status;
4205 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4208 count = print_queue_length(snum, &status);
4210 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4211 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4212 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4213 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4214 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4216 if (*ntprinter->info_2->comment == '\0')
4217 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4219 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4221 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4222 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4223 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4224 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4225 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4227 printer->attributes = ntprinter->info_2->attributes;
4229 printer->priority = ntprinter->info_2->priority; /* priority */
4230 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4231 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4232 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4233 printer->status = nt_printq_status(status.status); /* status */
4234 printer->cjobs = count; /* jobs */
4235 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4237 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4238 DEBUG(8, ("Returning NULL Devicemode!\n"));
4241 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4242 /* steal the printer info sec_desc structure. [badly done]. */
4243 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4244 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4245 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4246 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4249 printer->secdesc = NULL;
4252 free_a_printer(&ntprinter, 2);
4256 /********************************************************************
4257 * construct_printer_info_3
4258 * fill a printer_info_3 struct
4259 ********************************************************************/
4261 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4263 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4264 PRINTER_INFO_3 *printer = NULL;
4266 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4270 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4271 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4275 ZERO_STRUCTP(printer);
4277 printer->flags = 4; /* These are the components of the SD we are returning. */
4278 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4279 /* steal the printer info sec_desc structure. [badly done]. */
4280 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4284 * Set the flags for the components we are returning.
4287 if (printer->secdesc->owner_sid)
4288 printer->flags |= OWNER_SECURITY_INFORMATION;
4290 if (printer->secdesc->grp_sid)
4291 printer->flags |= GROUP_SECURITY_INFORMATION;
4293 if (printer->secdesc->dacl)
4294 printer->flags |= DACL_SECURITY_INFORMATION;
4296 if (printer->secdesc->sacl)
4297 printer->flags |= SACL_SECURITY_INFORMATION;
4300 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4301 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4302 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4305 free_a_printer(&ntprinter, 2);
4307 *pp_printer = printer;
4311 /********************************************************************
4312 * construct_printer_info_4
4313 * fill a printer_info_4 struct
4314 ********************************************************************/
4316 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4318 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4320 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4323 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4324 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4325 printer->attributes = ntprinter->info_2->attributes;
4327 free_a_printer(&ntprinter, 2);
4331 /********************************************************************
4332 * construct_printer_info_5
4333 * fill a printer_info_5 struct
4334 ********************************************************************/
4336 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4338 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4340 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4343 init_unistr(&printer->printername, ntprinter->info_2->printername);
4344 init_unistr(&printer->portname, ntprinter->info_2->portname);
4345 printer->attributes = ntprinter->info_2->attributes;
4347 /* these two are not used by NT+ according to MSDN */
4349 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4350 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4352 free_a_printer(&ntprinter, 2);
4357 /********************************************************************
4358 * construct_printer_info_7
4359 * fill a printer_info_7 struct
4360 ********************************************************************/
4362 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4364 char *guid_str = NULL;
4367 if (is_printer_published(print_hnd, snum, &guid)) {
4368 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4369 strupper_m(guid_str);
4370 init_unistr(&printer->guid, guid_str);
4371 printer->action = SPOOL_DS_PUBLISH;
4373 init_unistr(&printer->guid, "");
4374 printer->action = SPOOL_DS_UNPUBLISH;
4380 /********************************************************************
4381 Spoolss_enumprinters.
4382 ********************************************************************/
4384 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4388 int n_services=lp_numservices();
4389 PRINTER_INFO_1 *tp, *printers=NULL;
4390 PRINTER_INFO_1 current_prt;
4392 DEBUG(4,("enum_all_printers_info_1\n"));
4394 for (snum=0; snum<n_services; snum++) {
4395 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4396 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4398 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4399 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4400 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4401 SAFE_FREE(printers);
4406 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4408 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4414 /* check the required size. */
4415 for (i=0; i<*returned; i++)
4416 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4418 if (!alloc_buffer_size(buffer, *needed))
4419 return WERR_INSUFFICIENT_BUFFER;
4421 /* fill the buffer with the structures */
4422 for (i=0; i<*returned; i++)
4423 smb_io_printer_info_1("", buffer, &printers[i], 0);
4426 SAFE_FREE(printers);
4428 if (*needed > offered) {
4430 return WERR_INSUFFICIENT_BUFFER;
4436 /********************************************************************
4437 enum_all_printers_info_1_local.
4438 *********************************************************************/
4440 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4442 DEBUG(4,("enum_all_printers_info_1_local\n"));
4444 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4447 /********************************************************************
4448 enum_all_printers_info_1_name.
4449 *********************************************************************/
4451 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4455 DEBUG(4,("enum_all_printers_info_1_name\n"));
4457 if ((name[0] == '\\') && (name[1] == '\\'))
4460 if (is_myname_or_ipaddr(s)) {
4461 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4464 return WERR_INVALID_NAME;
4467 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4468 /********************************************************************
4469 enum_all_printers_info_1_remote.
4470 *********************************************************************/
4472 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4474 PRINTER_INFO_1 *printer;
4475 fstring printername;
4478 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4480 /* JFM: currently it's more a place holder than anything else.
4481 * In the spooler world there is a notion of server registration.
4482 * the print servers are registered on the PDC (in the same domain)
4484 * We should have a TDB here. The registration is done thru an
4485 * undocumented RPC call.
4488 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4493 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4494 slprintf(desc, sizeof(desc)-1,"%s", name);
4495 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4497 init_unistr(&printer->description, desc);
4498 init_unistr(&printer->name, printername);
4499 init_unistr(&printer->comment, comment);
4500 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4502 /* check the required size. */
4503 *needed += spoolss_size_printer_info_1(printer);
4505 if (!alloc_buffer_size(buffer, *needed)) {
4507 return WERR_INSUFFICIENT_BUFFER;
4510 /* fill the buffer with the structures */
4511 smb_io_printer_info_1("", buffer, printer, 0);
4516 if (*needed > offered) {
4518 return WERR_INSUFFICIENT_BUFFER;
4526 /********************************************************************
4527 enum_all_printers_info_1_network.
4528 *********************************************************************/
4530 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4534 DEBUG(4,("enum_all_printers_info_1_network\n"));
4536 /* If we respond to a enum_printers level 1 on our name with flags
4537 set to PRINTER_ENUM_REMOTE with a list of printers then these
4538 printers incorrectly appear in the APW browse list.
4539 Specifically the printers for the server appear at the workgroup
4540 level where all the other servers in the domain are
4541 listed. Windows responds to this call with a
4542 WERR_CAN_NOT_COMPLETE so we should do the same. */
4544 if (name[0] == '\\' && name[1] == '\\')
4547 if (is_myname_or_ipaddr(s))
4548 return WERR_CAN_NOT_COMPLETE;
4550 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4553 /********************************************************************
4554 * api_spoolss_enumprinters
4556 * called from api_spoolss_enumprinters (see this to understand)
4557 ********************************************************************/
4559 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4563 int n_services=lp_numservices();
4564 PRINTER_INFO_2 *tp, *printers=NULL;
4565 PRINTER_INFO_2 current_prt;
4567 for (snum=0; snum<n_services; snum++) {
4568 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4569 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4571 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4572 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4573 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4574 SAFE_FREE(printers);
4579 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4580 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4586 /* check the required size. */
4587 for (i=0; i<*returned; i++)
4588 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4590 if (!alloc_buffer_size(buffer, *needed)) {
4591 for (i=0; i<*returned; i++) {
4592 free_devmode(printers[i].devmode);
4594 SAFE_FREE(printers);
4595 return WERR_INSUFFICIENT_BUFFER;
4598 /* fill the buffer with the structures */
4599 for (i=0; i<*returned; i++)
4600 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4603 for (i=0; i<*returned; i++) {
4604 free_devmode(printers[i].devmode);
4606 SAFE_FREE(printers);
4608 if (*needed > offered) {
4610 return WERR_INSUFFICIENT_BUFFER;
4616 /********************************************************************
4617 * handle enumeration of printers at level 1
4618 ********************************************************************/
4620 static WERROR enumprinters_level1( uint32 flags, fstring name,
4621 NEW_BUFFER *buffer, uint32 offered,
4622 uint32 *needed, uint32 *returned)
4624 /* Not all the flags are equals */
4626 if (flags & PRINTER_ENUM_LOCAL)
4627 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4629 if (flags & PRINTER_ENUM_NAME)
4630 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4632 #if 0 /* JERRY - disabled for now */
4633 if (flags & PRINTER_ENUM_REMOTE)
4634 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4637 if (flags & PRINTER_ENUM_NETWORK)
4638 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4640 return WERR_OK; /* NT4sp5 does that */
4643 /********************************************************************
4644 * handle enumeration of printers at level 2
4645 ********************************************************************/
4647 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4648 NEW_BUFFER *buffer, uint32 offered,
4649 uint32 *needed, uint32 *returned)
4651 char *s = servername;
4653 if (flags & PRINTER_ENUM_LOCAL) {
4654 return enum_all_printers_info_2(buffer, offered, needed, returned);
4657 if (flags & PRINTER_ENUM_NAME) {
4658 if ((servername[0] == '\\') && (servername[1] == '\\'))
4660 if (is_myname_or_ipaddr(s))
4661 return enum_all_printers_info_2(buffer, offered, needed, returned);
4663 return WERR_INVALID_NAME;
4666 if (flags & PRINTER_ENUM_REMOTE)
4667 return WERR_UNKNOWN_LEVEL;
4672 /********************************************************************
4673 * handle enumeration of printers at level 5
4674 ********************************************************************/
4676 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4677 NEW_BUFFER *buffer, uint32 offered,
4678 uint32 *needed, uint32 *returned)
4680 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4684 /********************************************************************
4685 * api_spoolss_enumprinters
4687 * called from api_spoolss_enumprinters (see this to understand)
4688 ********************************************************************/
4690 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4692 uint32 flags = q_u->flags;
4693 UNISTR2 *servername = &q_u->servername;
4694 uint32 level = q_u->level;
4695 NEW_BUFFER *buffer = NULL;
4696 uint32 offered = q_u->offered;
4697 uint32 *needed = &r_u->needed;
4698 uint32 *returned = &r_u->returned;
4702 /* that's an [in out] buffer */
4703 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4704 buffer = r_u->buffer;
4706 DEBUG(4,("_spoolss_enumprinters\n"));
4713 * flags==PRINTER_ENUM_NAME
4714 * if name=="" then enumerates all printers
4715 * if name!="" then enumerate the printer
4716 * flags==PRINTER_ENUM_REMOTE
4717 * name is NULL, enumerate printers
4718 * Level 2: name!="" enumerates printers, name can't be NULL
4719 * Level 3: doesn't exist
4720 * Level 4: does a local registry lookup
4721 * Level 5: same as Level 2
4724 unistr2_to_ascii(name, servername, sizeof(name)-1);
4729 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4731 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4733 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4738 return WERR_UNKNOWN_LEVEL;
4741 /****************************************************************************
4742 ****************************************************************************/
4744 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4746 PRINTER_INFO_0 *printer=NULL;
4748 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4751 construct_printer_info_0(print_hnd, printer, snum);
4753 /* check the required size. */
4754 *needed += spoolss_size_printer_info_0(printer);
4756 if (!alloc_buffer_size(buffer, *needed)) {
4758 return WERR_INSUFFICIENT_BUFFER;
4761 /* fill the buffer with the structures */
4762 smb_io_printer_info_0("", buffer, printer, 0);
4767 if (*needed > offered) {
4768 return WERR_INSUFFICIENT_BUFFER;
4774 /****************************************************************************
4775 ****************************************************************************/
4777 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4779 PRINTER_INFO_1 *printer=NULL;
4781 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4784 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4786 /* check the required size. */
4787 *needed += spoolss_size_printer_info_1(printer);
4789 if (!alloc_buffer_size(buffer, *needed)) {
4791 return WERR_INSUFFICIENT_BUFFER;
4794 /* fill the buffer with the structures */
4795 smb_io_printer_info_1("", buffer, printer, 0);
4800 if (*needed > offered) {
4801 return WERR_INSUFFICIENT_BUFFER;
4807 /****************************************************************************
4808 ****************************************************************************/
4810 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4812 PRINTER_INFO_2 *printer=NULL;
4814 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4817 construct_printer_info_2(print_hnd, printer, snum);
4819 /* check the required size. */
4820 *needed += spoolss_size_printer_info_2(printer);
4822 if (!alloc_buffer_size(buffer, *needed)) {
4823 free_printer_info_2(printer);
4824 return WERR_INSUFFICIENT_BUFFER;
4827 /* fill the buffer with the structures */
4828 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4829 free_printer_info_2(printer);
4834 free_printer_info_2(printer);
4836 if (*needed > offered) {
4837 return WERR_INSUFFICIENT_BUFFER;
4843 /****************************************************************************
4844 ****************************************************************************/
4846 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4848 PRINTER_INFO_3 *printer=NULL;
4850 if (!construct_printer_info_3(print_hnd, &printer, snum))
4853 /* check the required size. */
4854 *needed += spoolss_size_printer_info_3(printer);
4856 if (!alloc_buffer_size(buffer, *needed)) {
4857 free_printer_info_3(printer);
4858 return WERR_INSUFFICIENT_BUFFER;
4861 /* fill the buffer with the structures */
4862 smb_io_printer_info_3("", buffer, printer, 0);
4865 free_printer_info_3(printer);
4867 if (*needed > offered) {
4868 return WERR_INSUFFICIENT_BUFFER;
4874 /****************************************************************************
4875 ****************************************************************************/
4877 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4879 PRINTER_INFO_4 *printer=NULL;
4881 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4884 if (!construct_printer_info_4(print_hnd, printer, snum))
4887 /* check the required size. */
4888 *needed += spoolss_size_printer_info_4(printer);
4890 if (!alloc_buffer_size(buffer, *needed)) {
4891 free_printer_info_4(printer);
4892 return WERR_INSUFFICIENT_BUFFER;
4895 /* fill the buffer with the structures */
4896 smb_io_printer_info_4("", buffer, printer, 0);
4899 free_printer_info_4(printer);
4901 if (*needed > offered) {
4902 return WERR_INSUFFICIENT_BUFFER;
4908 /****************************************************************************
4909 ****************************************************************************/
4911 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4913 PRINTER_INFO_5 *printer=NULL;
4915 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4918 if (!construct_printer_info_5(print_hnd, printer, snum))
4921 /* check the required size. */
4922 *needed += spoolss_size_printer_info_5(printer);
4924 if (!alloc_buffer_size(buffer, *needed)) {
4925 free_printer_info_5(printer);
4926 return WERR_INSUFFICIENT_BUFFER;
4929 /* fill the buffer with the structures */
4930 smb_io_printer_info_5("", buffer, printer, 0);
4933 free_printer_info_5(printer);
4935 if (*needed > offered) {
4936 return WERR_INSUFFICIENT_BUFFER;
4942 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4944 PRINTER_INFO_7 *printer=NULL;
4946 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4949 if (!construct_printer_info_7(print_hnd, printer, snum))
4952 /* check the required size. */
4953 *needed += spoolss_size_printer_info_7(printer);
4955 if (!alloc_buffer_size(buffer, *needed)) {
4956 free_printer_info_7(printer);
4957 return WERR_INSUFFICIENT_BUFFER;
4960 /* fill the buffer with the structures */
4961 smb_io_printer_info_7("", buffer, printer, 0);
4964 free_printer_info_7(printer);
4966 if (*needed > offered) {
4967 return WERR_INSUFFICIENT_BUFFER;
4973 /****************************************************************************
4974 ****************************************************************************/
4976 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4978 POLICY_HND *handle = &q_u->handle;
4979 uint32 level = q_u->level;
4980 NEW_BUFFER *buffer = NULL;
4981 uint32 offered = q_u->offered;
4982 uint32 *needed = &r_u->needed;
4983 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4987 /* that's an [in out] buffer */
4988 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4989 buffer = r_u->buffer;
4993 if (!get_printer_snum(p, handle, &snum))
4998 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5000 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5002 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5004 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5006 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5008 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5010 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5012 return WERR_UNKNOWN_LEVEL;
5015 /********************************************************************
5016 * fill a DRIVER_INFO_1 struct
5017 ********************************************************************/
5019 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5021 init_unistr( &info->name, driver.info_3->name);
5024 /********************************************************************
5025 * construct_printer_driver_info_1
5026 ********************************************************************/
5028 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5030 NT_PRINTER_INFO_LEVEL *printer = NULL;
5031 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5033 ZERO_STRUCT(driver);
5035 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5036 return WERR_INVALID_PRINTER_NAME;
5038 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5039 return WERR_UNKNOWN_PRINTER_DRIVER;
5041 fill_printer_driver_info_1(info, driver, servername, architecture);
5043 free_a_printer(&printer,2);
5048 /********************************************************************
5049 * construct_printer_driver_info_2
5050 * fill a printer_info_2 struct
5051 ********************************************************************/
5053 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5057 info->version=driver.info_3->cversion;
5059 init_unistr( &info->name, driver.info_3->name );
5060 init_unistr( &info->architecture, driver.info_3->environment );
5063 if (strlen(driver.info_3->driverpath)) {
5064 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5065 init_unistr( &info->driverpath, temp );
5067 init_unistr( &info->driverpath, "" );
5069 if (strlen(driver.info_3->datafile)) {
5070 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5071 init_unistr( &info->datafile, temp );
5073 init_unistr( &info->datafile, "" );
5075 if (strlen(driver.info_3->configfile)) {
5076 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5077 init_unistr( &info->configfile, temp );
5079 init_unistr( &info->configfile, "" );
5082 /********************************************************************
5083 * construct_printer_driver_info_2
5084 * fill a printer_info_2 struct
5085 ********************************************************************/
5087 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5089 NT_PRINTER_INFO_LEVEL *printer = NULL;
5090 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5092 ZERO_STRUCT(printer);
5093 ZERO_STRUCT(driver);
5095 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5096 return WERR_INVALID_PRINTER_NAME;
5098 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5099 return WERR_UNKNOWN_PRINTER_DRIVER;
5101 fill_printer_driver_info_2(info, driver, servername);
5103 free_a_printer(&printer,2);
5108 /********************************************************************
5109 * copy a strings array and convert to UNICODE
5111 * convert an array of ascii string to a UNICODE string
5112 ********************************************************************/
5114 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5122 DEBUG(6,("init_unistr_array\n"));
5133 v = ""; /* hack to handle null lists */
5136 /* hack to allow this to be used in places other than when generating
5137 the list of dependent files */
5140 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5144 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5146 /* add one extra unit16 for the second terminating NULL */
5148 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5149 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5157 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5162 /* special case for ""; we need to add both NULL's here */
5164 (*uni_array)[j++]=0x0000;
5165 (*uni_array)[j]=0x0000;
5168 DEBUGADD(6,("last one:done\n"));
5170 /* return size of array in uint16's */
5175 /********************************************************************
5176 * construct_printer_info_3
5177 * fill a printer_info_3 struct
5178 ********************************************************************/
5180 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5186 info->version=driver.info_3->cversion;
5188 init_unistr( &info->name, driver.info_3->name );
5189 init_unistr( &info->architecture, driver.info_3->environment );
5191 if (strlen(driver.info_3->driverpath)) {
5192 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5193 init_unistr( &info->driverpath, temp );
5195 init_unistr( &info->driverpath, "" );
5197 if (strlen(driver.info_3->datafile)) {
5198 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5199 init_unistr( &info->datafile, temp );
5201 init_unistr( &info->datafile, "" );
5203 if (strlen(driver.info_3->configfile)) {
5204 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5205 init_unistr( &info->configfile, temp );
5207 init_unistr( &info->configfile, "" );
5209 if (strlen(driver.info_3->helpfile)) {
5210 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5211 init_unistr( &info->helpfile, temp );
5213 init_unistr( &info->helpfile, "" );
5215 init_unistr( &info->monitorname, driver.info_3->monitorname );
5216 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5218 info->dependentfiles=NULL;
5219 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5222 /********************************************************************
5223 * construct_printer_info_3
5224 * fill a printer_info_3 struct
5225 ********************************************************************/
5227 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5229 NT_PRINTER_INFO_LEVEL *printer = NULL;
5230 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5232 ZERO_STRUCT(driver);
5234 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5235 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5236 if (!W_ERROR_IS_OK(status))
5237 return WERR_INVALID_PRINTER_NAME;
5239 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5240 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5245 * I put this code in during testing. Helpful when commenting out the
5246 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5247 * as win2k always queries the driver using an infor level of 6.
5248 * I've left it in (but ifdef'd out) because I'll probably
5249 * use it in experimentation again in the future. --jerry 22/01/2002
5252 if (!W_ERROR_IS_OK(status)) {
5254 * Is this a W2k client ?
5257 /* Yes - try again with a WinNT driver. */
5259 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5260 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5264 if (!W_ERROR_IS_OK(status)) {
5265 free_a_printer(&printer,2);
5266 return WERR_UNKNOWN_PRINTER_DRIVER;
5274 fill_printer_driver_info_3(info, driver, servername);
5276 free_a_printer(&printer,2);
5281 /********************************************************************
5282 * construct_printer_info_6
5283 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5284 ********************************************************************/
5286 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5292 memset(&nullstr, '\0', sizeof(fstring));
5294 info->version=driver.info_3->cversion;
5296 init_unistr( &info->name, driver.info_3->name );
5297 init_unistr( &info->architecture, driver.info_3->environment );
5299 if (strlen(driver.info_3->driverpath)) {
5300 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5301 init_unistr( &info->driverpath, temp );
5303 init_unistr( &info->driverpath, "" );
5305 if (strlen(driver.info_3->datafile)) {
5306 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5307 init_unistr( &info->datafile, temp );
5309 init_unistr( &info->datafile, "" );
5311 if (strlen(driver.info_3->configfile)) {
5312 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5313 init_unistr( &info->configfile, temp );
5315 init_unistr( &info->configfile, "" );
5317 if (strlen(driver.info_3->helpfile)) {
5318 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5319 init_unistr( &info->helpfile, temp );
5321 init_unistr( &info->helpfile, "" );
5323 init_unistr( &info->monitorname, driver.info_3->monitorname );
5324 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5326 info->dependentfiles = NULL;
5327 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5329 info->previousdrivernames=NULL;
5330 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5332 info->driver_date.low=0;
5333 info->driver_date.high=0;
5336 info->driver_version_low=0;
5337 info->driver_version_high=0;
5339 init_unistr( &info->mfgname, "");
5340 init_unistr( &info->oem_url, "");
5341 init_unistr( &info->hardware_id, "");
5342 init_unistr( &info->provider, "");
5345 /********************************************************************
5346 * construct_printer_info_6
5347 * fill a printer_info_6 struct
5348 ********************************************************************/
5350 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5351 fstring servername, fstring architecture, uint32 version)
5353 NT_PRINTER_INFO_LEVEL *printer = NULL;
5354 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5357 ZERO_STRUCT(driver);
5359 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5361 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5363 if (!W_ERROR_IS_OK(status))
5364 return WERR_INVALID_PRINTER_NAME;
5366 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5368 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5370 if (!W_ERROR_IS_OK(status))
5373 * Is this a W2k client ?
5377 free_a_printer(&printer,2);
5378 return WERR_UNKNOWN_PRINTER_DRIVER;
5381 /* Yes - try again with a WinNT driver. */
5383 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5384 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5385 if (!W_ERROR_IS_OK(status)) {
5386 free_a_printer(&printer,2);
5387 return WERR_UNKNOWN_PRINTER_DRIVER;
5391 fill_printer_driver_info_6(info, driver, servername);
5393 free_a_printer(&printer,2);
5394 free_a_printer_driver(driver, 3);
5399 /****************************************************************************
5400 ****************************************************************************/
5402 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5404 SAFE_FREE(info->dependentfiles);
5407 /****************************************************************************
5408 ****************************************************************************/
5410 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5412 SAFE_FREE(info->dependentfiles);
5416 /****************************************************************************
5417 ****************************************************************************/
5419 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5421 DRIVER_INFO_1 *info=NULL;
5424 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5427 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5428 if (!W_ERROR_IS_OK(status)) {
5433 /* check the required size. */
5434 *needed += spoolss_size_printer_driver_info_1(info);
5436 if (!alloc_buffer_size(buffer, *needed)) {
5438 return WERR_INSUFFICIENT_BUFFER;
5441 /* fill the buffer with the structures */
5442 smb_io_printer_driver_info_1("", buffer, info, 0);
5447 if (*needed > offered)
5448 return WERR_INSUFFICIENT_BUFFER;
5453 /****************************************************************************
5454 ****************************************************************************/
5456 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5458 DRIVER_INFO_2 *info=NULL;
5461 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5464 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5465 if (!W_ERROR_IS_OK(status)) {
5470 /* check the required size. */
5471 *needed += spoolss_size_printer_driver_info_2(info);
5473 if (!alloc_buffer_size(buffer, *needed)) {
5475 return WERR_INSUFFICIENT_BUFFER;
5478 /* fill the buffer with the structures */
5479 smb_io_printer_driver_info_2("", buffer, info, 0);
5484 if (*needed > offered)
5485 return WERR_INSUFFICIENT_BUFFER;
5490 /****************************************************************************
5491 ****************************************************************************/
5493 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5500 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5501 if (!W_ERROR_IS_OK(status)) {
5505 /* check the required size. */
5506 *needed += spoolss_size_printer_driver_info_3(&info);
5508 if (!alloc_buffer_size(buffer, *needed)) {
5509 free_printer_driver_info_3(&info);
5510 return WERR_INSUFFICIENT_BUFFER;
5513 /* fill the buffer with the structures */
5514 smb_io_printer_driver_info_3("", buffer, &info, 0);
5516 free_printer_driver_info_3(&info);
5518 if (*needed > offered)
5519 return WERR_INSUFFICIENT_BUFFER;
5524 /****************************************************************************
5525 ****************************************************************************/
5527 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5534 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5535 if (!W_ERROR_IS_OK(status)) {
5539 /* check the required size. */
5540 *needed += spoolss_size_printer_driver_info_6(&info);
5542 if (!alloc_buffer_size(buffer, *needed)) {
5543 free_printer_driver_info_6(&info);
5544 return WERR_INSUFFICIENT_BUFFER;
5547 /* fill the buffer with the structures */
5548 smb_io_printer_driver_info_6("", buffer, &info, 0);
5550 free_printer_driver_info_6(&info);
5552 if (*needed > offered)
5553 return WERR_INSUFFICIENT_BUFFER;
5558 /****************************************************************************
5559 ****************************************************************************/
5561 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5563 POLICY_HND *handle = &q_u->handle;
5564 UNISTR2 *uni_arch = &q_u->architecture;
5565 uint32 level = q_u->level;
5566 uint32 clientmajorversion = q_u->clientmajorversion;
5567 NEW_BUFFER *buffer = NULL;
5568 uint32 offered = q_u->offered;
5569 uint32 *needed = &r_u->needed;
5570 uint32 *servermajorversion = &r_u->servermajorversion;
5571 uint32 *serverminorversion = &r_u->serverminorversion;
5572 Printer_entry *printer;
5575 fstring architecture;
5578 /* that's an [in out] buffer */
5579 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5580 buffer = r_u->buffer;
5582 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5584 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5585 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5586 return WERR_INVALID_PRINTER_NAME;
5590 *servermajorversion = 0;
5591 *serverminorversion = 0;
5593 fstrcpy(servername, get_server_name( printer ));
5594 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5596 if (!get_printer_snum(p, handle, &snum))
5601 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5603 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5605 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5607 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5610 /* apparently this call is the equivalent of
5611 EnumPrinterDataEx() for the DsDriver key */
5616 return WERR_UNKNOWN_LEVEL;
5619 /****************************************************************************
5620 ****************************************************************************/
5622 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5624 POLICY_HND *handle = &q_u->handle;
5626 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5629 DEBUG(3,("Error in startpageprinter printer handle\n"));
5633 Printer->page_started=True;
5637 /****************************************************************************
5638 ****************************************************************************/
5640 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5642 POLICY_HND *handle = &q_u->handle;
5645 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5648 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5652 if (!get_printer_snum(p, handle, &snum))
5655 Printer->page_started=False;
5656 print_job_endpage(snum, Printer->jobid);
5661 /********************************************************************
5662 * api_spoolss_getprinter
5663 * called from the spoolss dispatcher
5665 ********************************************************************/
5667 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5669 POLICY_HND *handle = &q_u->handle;
5670 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5671 uint32 *jobid = &r_u->jobid;
5673 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5677 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5678 struct current_user user;
5681 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5685 get_current_user(&user, p);
5688 * a nice thing with NT is it doesn't listen to what you tell it.
5689 * when asked to send _only_ RAW datas, it tries to send datas
5692 * So I add checks like in NT Server ...
5695 if (info_1->p_datatype != 0) {
5696 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5697 if (strcmp(datatype, "RAW") != 0) {
5699 return WERR_INVALID_DATATYPE;
5703 /* get the share number of the printer */
5704 if (!get_printer_snum(p, handle, &snum)) {
5708 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5710 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5712 /* An error occured in print_job_start() so return an appropriate
5715 if (Printer->jobid == -1) {
5716 return map_werror_from_unix(errno);
5719 Printer->document_started=True;
5720 (*jobid) = Printer->jobid;
5725 /********************************************************************
5726 * api_spoolss_getprinter
5727 * called from the spoolss dispatcher
5729 ********************************************************************/
5731 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5733 POLICY_HND *handle = &q_u->handle;
5735 return _spoolss_enddocprinter_internal(p, handle);
5738 /****************************************************************************
5739 ****************************************************************************/
5741 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5743 POLICY_HND *handle = &q_u->handle;
5744 uint32 buffer_size = q_u->buffer_size;
5745 uint8 *buffer = q_u->buffer;
5746 uint32 *buffer_written = &q_u->buffer_size2;
5748 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5751 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5752 r_u->buffer_written = q_u->buffer_size2;
5756 if (!get_printer_snum(p, handle, &snum))
5759 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5760 if (*buffer_written == -1) {
5761 r_u->buffer_written = 0;
5762 if (errno == ENOSPC)
5763 return WERR_NO_SPOOL_SPACE;
5765 return WERR_ACCESS_DENIED;
5768 r_u->buffer_written = q_u->buffer_size2;
5773 /********************************************************************
5774 * api_spoolss_getprinter
5775 * called from the spoolss dispatcher
5777 ********************************************************************/
5779 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5782 struct current_user user;
5784 WERROR errcode = WERR_BADFUNC;
5785 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5787 get_current_user(&user, p);
5790 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5794 if (!get_printer_snum(p, handle, &snum))
5798 case PRINTER_CONTROL_PAUSE:
5799 if (print_queue_pause(&user, snum, &errcode)) {
5803 case PRINTER_CONTROL_RESUME:
5804 case PRINTER_CONTROL_UNPAUSE:
5805 if (print_queue_resume(&user, snum, &errcode)) {
5809 case PRINTER_CONTROL_PURGE:
5810 if (print_queue_purge(&user, snum, &errcode)) {
5815 return WERR_UNKNOWN_LEVEL;
5821 /********************************************************************
5822 * api_spoolss_abortprinter
5823 * From MSDN: "Deletes printer's spool file if printer is configured
5825 ********************************************************************/
5827 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5829 POLICY_HND *handle = &q_u->handle;
5830 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5832 struct current_user user;
5833 WERROR errcode = WERR_OK;
5836 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5840 if (!get_printer_snum(p, handle, &snum))
5843 get_current_user( &user, p );
5845 print_job_delete( &user, snum, Printer->jobid, &errcode );
5850 /********************************************************************
5851 * called by spoolss_api_setprinter
5852 * when updating a printer description
5853 ********************************************************************/
5855 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5856 const SPOOL_PRINTER_INFO_LEVEL *info,
5857 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5859 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5860 struct current_user user;
5864 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5866 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5867 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5868 OUR_HANDLE(handle)));
5870 result = WERR_BADFID;
5874 /* NT seems to like setting the security descriptor even though
5875 nothing may have actually changed. */
5877 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5879 if (DEBUGLEVEL >= 10) {
5883 the_acl = old_secdesc_ctr->sec->dacl;
5884 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5885 PRINTERNAME(snum), the_acl->num_aces));
5887 for (i = 0; i < the_acl->num_aces; i++) {
5890 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5892 DEBUG(10, ("%s 0x%08x\n", sid_str,
5893 the_acl->ace[i].info.mask));
5896 the_acl = secdesc_ctr->sec->dacl;
5899 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5900 PRINTERNAME(snum), the_acl->num_aces));
5902 for (i = 0; i < the_acl->num_aces; i++) {
5905 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5907 DEBUG(10, ("%s 0x%08x\n", sid_str,
5908 the_acl->ace[i].info.mask));
5911 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5915 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5917 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5922 /* Work out which user is performing the operation */
5924 get_current_user(&user, p);
5926 /* Check the user has permissions to change the security
5927 descriptor. By experimentation with two NT machines, the user
5928 requires Full Access to the printer to change security
5931 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5932 result = WERR_ACCESS_DENIED;
5936 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5943 /********************************************************************
5944 Canonicalize printer info from a client
5946 ATTN: It does not matter what we set the servername to hear
5947 since we do the necessary work in get_a_printer() to set it to
5948 the correct value based on what the client sent in the
5949 _spoolss_open_printer_ex().
5950 ********************************************************************/
5952 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5954 fstring printername;
5957 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5958 "portname=%s drivername=%s comment=%s location=%s\n",
5959 info->servername, info->printername, info->sharename,
5960 info->portname, info->drivername, info->comment, info->location));
5962 /* we force some elements to "correct" values */
5963 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5964 fstrcpy(info->sharename, lp_servicename(snum));
5966 /* check to see if we allow printername != sharename */
5968 if ( lp_force_printername(snum) ) {
5969 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5970 global_myname(), info->sharename );
5973 /* make sure printername is in \\server\printername format */
5975 fstrcpy( printername, info->printername );
5977 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5978 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5982 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5983 global_myname(), p );
5986 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5987 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5994 /****************************************************************************
5995 ****************************************************************************/
5997 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5999 extern userdom_struct current_user_info;
6000 char *cmd = lp_addprinter_cmd();
6006 fstring remote_machine = "%m";
6008 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6010 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6011 cmd, printer->info_2->printername, printer->info_2->sharename,
6012 printer->info_2->portname, printer->info_2->drivername,
6013 printer->info_2->location, printer->info_2->comment, remote_machine);
6015 DEBUG(10,("Running [%s]\n", command));
6016 ret = smbrun(command, &fd);
6017 DEBUGADD(10,("returned [%d]\n", ret));
6026 /* Get lines and convert them back to dos-codepage */
6027 qlines = fd_lines_load(fd, &numlines);
6028 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6032 /* Set the portname to what the script says the portname should be. */
6033 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6034 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6036 /* Send SIGHUP to process group... is there a better way? */
6039 /* reload our services immediately */
6040 reload_services( False );
6043 file_lines_free(qlines);
6047 /********************************************************************
6048 * Called by spoolss_api_setprinter
6049 * when updating a printer description.
6050 ********************************************************************/
6052 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6053 const SPOOL_PRINTER_INFO_LEVEL *info,
6054 DEVICEMODE *devmode)
6057 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6058 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6063 DEBUG(8,("update_printer\n"));
6068 result = WERR_BADFID;
6072 if (!get_printer_snum(p, handle, &snum)) {
6073 result = WERR_BADFID;
6077 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6078 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6079 result = WERR_BADFID;
6083 DEBUGADD(8,("Converting info_2 struct\n"));
6086 * convert_printer_info converts the incoming
6087 * info from the client and overwrites the info
6088 * just read from the tdb in the pointer 'printer'.
6091 if (!convert_printer_info(info, printer, level)) {
6092 result = WERR_NOMEM;
6097 /* we have a valid devmode
6098 convert it and link it*/
6100 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6101 if (!convert_devicemode(printer->info_2->printername, devmode,
6102 &printer->info_2->devmode)) {
6103 result = WERR_NOMEM;
6108 /* Do sanity check on the requested changes for Samba */
6110 if (!check_printer_ok(printer->info_2, snum)) {
6111 result = WERR_INVALID_PARAM;
6115 /* FIXME!!! If the driver has changed we really should verify that
6116 it is installed before doing much else --jerry */
6118 /* Check calling user has permission to update printer description */
6120 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6121 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6122 result = WERR_ACCESS_DENIED;
6126 /* Call addprinter hook */
6127 /* Check changes to see if this is really needed */
6129 if ( *lp_addprinter_cmd()
6130 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6131 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6132 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6133 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6135 if ( !add_printer_hook(printer) ) {
6136 result = WERR_ACCESS_DENIED;
6141 * make sure we actually reload the services after
6142 * this as smb.conf could have a new section in it
6143 * .... shouldn't .... but could
6145 reload_services(False);
6149 * When a *new* driver is bound to a printer, the drivername is used to
6150 * lookup previously saved driver initialization info, which is then
6151 * bound to the printer, simulating what happens in the Windows arch.
6153 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6155 if (!set_driver_init(printer, 2))
6157 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6158 printer->info_2->drivername));
6161 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6162 printer->info_2->drivername));
6164 notify_printer_driver(snum, printer->info_2->drivername);
6168 * flag which changes actually occured. This is a small subset of
6169 * all the possible changes. We also have to update things in the
6173 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6174 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6175 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6176 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6178 notify_printer_comment(snum, printer->info_2->comment);
6181 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6182 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6183 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6184 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6186 notify_printer_sharename(snum, printer->info_2->sharename);
6189 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6192 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6195 pname = printer->info_2->printername;
6198 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6199 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6200 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6202 notify_printer_printername( snum, pname );
6205 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6206 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6207 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6208 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6210 notify_printer_port(snum, printer->info_2->portname);
6213 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6214 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6215 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6216 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6218 notify_printer_location(snum, printer->info_2->location);
6221 /* here we need to update some more DsSpooler keys */
6222 /* uNCName, serverName, shortServerName */
6224 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6225 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6226 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6227 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6228 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6230 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6231 global_myname(), printer->info_2->sharename );
6232 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6233 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6234 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6236 /* Update printer info */
6237 result = mod_a_printer(printer, 2);
6240 free_a_printer(&printer, 2);
6241 free_a_printer(&old_printer, 2);
6247 /****************************************************************************
6248 ****************************************************************************/
6249 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6250 const SPOOL_PRINTER_INFO_LEVEL *info)
6253 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6255 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6257 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6262 if (!get_printer_snum(p, handle, &snum))
6265 nt_printer_publish(Printer, snum, info7->action);
6269 return WERR_UNKNOWN_LEVEL;
6272 /****************************************************************************
6273 ****************************************************************************/
6275 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6277 POLICY_HND *handle = &q_u->handle;
6278 uint32 level = q_u->level;
6279 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6280 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6281 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6282 uint32 command = q_u->command;
6285 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6288 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6292 /* check the level */
6295 return control_printer(handle, command, p);
6297 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6298 if (!W_ERROR_IS_OK(result))
6301 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6304 return update_printer_sec(handle, level, info, p,
6307 return publish_or_unpublish_printer(p, handle, info);
6309 return WERR_UNKNOWN_LEVEL;
6313 /****************************************************************************
6314 ****************************************************************************/
6316 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6318 POLICY_HND *handle = &q_u->handle;
6319 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6322 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6326 if (Printer->notify.client_connected==True) {
6329 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6331 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6332 !get_printer_snum(p, handle, &snum) )
6335 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6338 Printer->notify.flags=0;
6339 Printer->notify.options=0;
6340 Printer->notify.localmachine[0]='\0';
6341 Printer->notify.printerlocal=0;
6342 if (Printer->notify.option)
6343 free_spool_notify_option(&Printer->notify.option);
6344 Printer->notify.client_connected=False;
6349 /****************************************************************************
6350 ****************************************************************************/
6352 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6354 /* that's an [in out] buffer (despite appearences to the contrary) */
6355 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6358 return WERR_INVALID_PARAM; /* this is what a NT server
6359 returns for AddJob. AddJob
6360 must fail on non-local
6364 /****************************************************************************
6365 ****************************************************************************/
6367 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6368 int position, int snum,
6369 NT_PRINTER_INFO_LEVEL *ntprinter)
6373 t=gmtime(&queue->time);
6375 job_info->jobid=queue->job;
6376 init_unistr(&job_info->printername, lp_servicename(snum));
6377 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6378 init_unistr(&job_info->username, queue->fs_user);
6379 init_unistr(&job_info->document, queue->fs_file);
6380 init_unistr(&job_info->datatype, "RAW");
6381 init_unistr(&job_info->text_status, "");
6382 job_info->status=nt_printj_status(queue->status);
6383 job_info->priority=queue->priority;
6384 job_info->position=position;
6385 job_info->totalpages=queue->page_count;
6386 job_info->pagesprinted=0;
6388 make_systemtime(&job_info->submitted, t);
6391 /****************************************************************************
6392 ****************************************************************************/
6394 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6395 int position, int snum,
6396 NT_PRINTER_INFO_LEVEL *ntprinter,
6397 DEVICEMODE *devmode)
6401 t=gmtime(&queue->time);
6403 job_info->jobid=queue->job;
6405 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6407 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6408 init_unistr(&job_info->username, queue->fs_user);
6409 init_unistr(&job_info->document, queue->fs_file);
6410 init_unistr(&job_info->notifyname, queue->fs_user);
6411 init_unistr(&job_info->datatype, "RAW");
6412 init_unistr(&job_info->printprocessor, "winprint");
6413 init_unistr(&job_info->parameters, "");
6414 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6415 init_unistr(&job_info->text_status, "");
6417 /* and here the security descriptor */
6419 job_info->status=nt_printj_status(queue->status);
6420 job_info->priority=queue->priority;
6421 job_info->position=position;
6422 job_info->starttime=0;
6423 job_info->untiltime=0;
6424 job_info->totalpages=queue->page_count;
6425 job_info->size=queue->size;
6426 make_systemtime(&(job_info->submitted), t);
6427 job_info->timeelapsed=0;
6428 job_info->pagesprinted=0;
6430 job_info->devmode = devmode;
6435 /****************************************************************************
6436 Enumjobs at level 1.
6437 ****************************************************************************/
6439 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6440 NT_PRINTER_INFO_LEVEL *ntprinter,
6441 NEW_BUFFER *buffer, uint32 offered,
6442 uint32 *needed, uint32 *returned)
6447 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6454 for (i=0; i<*returned; i++)
6455 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6459 /* check the required size. */
6460 for (i=0; i<*returned; i++)
6461 (*needed) += spoolss_size_job_info_1(&info[i]);
6463 if (!alloc_buffer_size(buffer, *needed)) {
6465 return WERR_INSUFFICIENT_BUFFER;
6468 /* fill the buffer with the structures */
6469 for (i=0; i<*returned; i++)
6470 smb_io_job_info_1("", buffer, &info[i], 0);
6475 if (*needed > offered) {
6477 return WERR_INSUFFICIENT_BUFFER;
6483 /****************************************************************************
6484 Enumjobs at level 2.
6485 ****************************************************************************/
6487 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6488 NT_PRINTER_INFO_LEVEL *ntprinter,
6489 NEW_BUFFER *buffer, uint32 offered,
6490 uint32 *needed, uint32 *returned)
6492 JOB_INFO_2 *info = NULL;
6495 DEVICEMODE *devmode = NULL;
6497 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6500 result = WERR_NOMEM;
6504 /* this should not be a failure condition if the devmode is NULL */
6506 devmode = construct_dev_mode(snum);
6508 for (i=0; i<*returned; i++)
6509 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6512 free_a_printer(&ntprinter, 2);
6515 /* check the required size. */
6516 for (i=0; i<*returned; i++)
6517 (*needed) += spoolss_size_job_info_2(&info[i]);
6519 if (*needed > offered) {
6521 result = WERR_INSUFFICIENT_BUFFER;
6525 if (!alloc_buffer_size(buffer, *needed)) {
6527 result = WERR_INSUFFICIENT_BUFFER;
6531 /* fill the buffer with the structures */
6532 for (i=0; i<*returned; i++)
6533 smb_io_job_info_2("", buffer, &info[i], 0);
6538 free_a_printer(&ntprinter, 2);
6539 free_devmode(devmode);
6547 /****************************************************************************
6549 ****************************************************************************/
6551 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6553 POLICY_HND *handle = &q_u->handle;
6554 uint32 level = q_u->level;
6555 NEW_BUFFER *buffer = NULL;
6556 uint32 offered = q_u->offered;
6557 uint32 *needed = &r_u->needed;
6558 uint32 *returned = &r_u->returned;
6560 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6562 print_status_struct prt_status;
6563 print_queue_struct *queue=NULL;
6565 /* that's an [in out] buffer */
6566 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6567 buffer = r_u->buffer;
6569 DEBUG(4,("_spoolss_enumjobs\n"));
6574 /* lookup the printer snum and tdb entry */
6576 if (!get_printer_snum(p, handle, &snum))
6579 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6580 if ( !W_ERROR_IS_OK(wret) )
6583 *returned = print_queue_status(snum, &queue, &prt_status);
6584 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6586 if (*returned == 0) {
6593 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6596 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6601 wret = WERR_UNKNOWN_LEVEL;
6604 free_a_printer( &ntprinter, 2 );
6608 /****************************************************************************
6609 ****************************************************************************/
6611 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6616 /****************************************************************************
6617 ****************************************************************************/
6619 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6621 POLICY_HND *handle = &q_u->handle;
6622 uint32 jobid = q_u->jobid;
6623 uint32 command = q_u->command;
6625 struct current_user user;
6627 WERROR errcode = WERR_BADFUNC;
6629 if (!get_printer_snum(p, handle, &snum)) {
6633 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6634 return WERR_INVALID_PRINTER_NAME;
6637 get_current_user(&user, p);
6640 case JOB_CONTROL_CANCEL:
6641 case JOB_CONTROL_DELETE:
6642 if (print_job_delete(&user, snum, jobid, &errcode)) {
6646 case JOB_CONTROL_PAUSE:
6647 if (print_job_pause(&user, snum, jobid, &errcode)) {
6651 case JOB_CONTROL_RESTART:
6652 case JOB_CONTROL_RESUME:
6653 if (print_job_resume(&user, snum, jobid, &errcode)) {
6658 return WERR_UNKNOWN_LEVEL;
6664 /****************************************************************************
6665 Enumerates all printer drivers at level 1.
6666 ****************************************************************************/
6668 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6673 fstring *list = NULL;
6675 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6676 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6680 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6682 ndrivers=get_ntdrivers(&list, architecture, version);
6683 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6689 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6690 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6691 SAFE_FREE(driver_info_1);
6695 else driver_info_1 = tdi1;
6698 for (i=0; i<ndrivers; i++) {
6700 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6701 ZERO_STRUCT(driver);
6702 status = get_a_printer_driver(&driver, 3, list[i],
6703 architecture, version);
6704 if (!W_ERROR_IS_OK(status)) {
6708 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6709 free_a_printer_driver(driver, 3);
6712 *returned+=ndrivers;
6716 /* check the required size. */
6717 for (i=0; i<*returned; i++) {
6718 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6719 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6722 if (!alloc_buffer_size(buffer, *needed)) {
6723 SAFE_FREE(driver_info_1);
6724 return WERR_INSUFFICIENT_BUFFER;
6727 /* fill the buffer with the driver structures */
6728 for (i=0; i<*returned; i++) {
6729 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6730 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6733 SAFE_FREE(driver_info_1);
6735 if (*needed > offered) {
6737 return WERR_INSUFFICIENT_BUFFER;
6743 /****************************************************************************
6744 Enumerates all printer drivers at level 2.
6745 ****************************************************************************/
6747 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6752 fstring *list = NULL;
6754 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6755 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6759 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6761 ndrivers=get_ntdrivers(&list, architecture, version);
6762 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6768 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6769 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6770 SAFE_FREE(driver_info_2);
6774 else driver_info_2 = tdi2;
6777 for (i=0; i<ndrivers; i++) {
6780 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6781 ZERO_STRUCT(driver);
6782 status = get_a_printer_driver(&driver, 3, list[i],
6783 architecture, version);
6784 if (!W_ERROR_IS_OK(status)) {
6788 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6789 free_a_printer_driver(driver, 3);
6792 *returned+=ndrivers;
6796 /* check the required size. */
6797 for (i=0; i<*returned; i++) {
6798 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6799 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6802 if (!alloc_buffer_size(buffer, *needed)) {
6803 SAFE_FREE(driver_info_2);
6804 return WERR_INSUFFICIENT_BUFFER;
6807 /* fill the buffer with the form structures */
6808 for (i=0; i<*returned; i++) {
6809 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6810 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6813 SAFE_FREE(driver_info_2);
6815 if (*needed > offered) {
6817 return WERR_INSUFFICIENT_BUFFER;
6823 /****************************************************************************
6824 Enumerates all printer drivers at level 3.
6825 ****************************************************************************/
6827 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6832 fstring *list = NULL;
6834 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6835 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6839 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6841 ndrivers=get_ntdrivers(&list, architecture, version);
6842 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6848 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6849 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6850 SAFE_FREE(driver_info_3);
6854 else driver_info_3 = tdi3;
6857 for (i=0; i<ndrivers; i++) {
6860 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6861 ZERO_STRUCT(driver);
6862 status = get_a_printer_driver(&driver, 3, list[i],
6863 architecture, version);
6864 if (!W_ERROR_IS_OK(status)) {
6868 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6869 free_a_printer_driver(driver, 3);
6872 *returned+=ndrivers;
6876 /* check the required size. */
6877 for (i=0; i<*returned; i++) {
6878 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6879 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6882 if (!alloc_buffer_size(buffer, *needed)) {
6883 SAFE_FREE(driver_info_3);
6884 return WERR_INSUFFICIENT_BUFFER;
6887 /* fill the buffer with the driver structures */
6888 for (i=0; i<*returned; i++) {
6889 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6890 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6893 for (i=0; i<*returned; i++)
6894 SAFE_FREE(driver_info_3[i].dependentfiles);
6896 SAFE_FREE(driver_info_3);
6898 if (*needed > offered) {
6900 return WERR_INSUFFICIENT_BUFFER;
6906 /****************************************************************************
6907 Enumerates all printer drivers.
6908 ****************************************************************************/
6910 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6912 uint32 level = q_u->level;
6913 NEW_BUFFER *buffer = NULL;
6914 uint32 offered = q_u->offered;
6915 uint32 *needed = &r_u->needed;
6916 uint32 *returned = &r_u->returned;
6918 fstring *list = NULL;
6920 fstring architecture;
6922 /* that's an [in out] buffer */
6923 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6924 buffer = r_u->buffer;
6926 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6930 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6931 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6933 if ( !is_myname_or_ipaddr( servername ) )
6934 return WERR_UNKNOWN_PRINTER_DRIVER;
6938 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6940 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6942 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6946 return WERR_UNKNOWN_LEVEL;
6950 /****************************************************************************
6951 ****************************************************************************/
6953 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6955 form->flag=list->flag;
6956 init_unistr(&form->name, list->name);
6957 form->width=list->width;
6958 form->length=list->length;
6959 form->left=list->left;
6960 form->top=list->top;
6961 form->right=list->right;
6962 form->bottom=list->bottom;
6965 /****************************************************************************
6966 ****************************************************************************/
6968 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6970 uint32 level = q_u->level;
6971 NEW_BUFFER *buffer = NULL;
6972 uint32 offered = q_u->offered;
6973 uint32 *needed = &r_u->needed;
6974 uint32 *numofforms = &r_u->numofforms;
6975 uint32 numbuiltinforms;
6977 nt_forms_struct *list=NULL;
6978 nt_forms_struct *builtinlist=NULL;
6983 /* that's an [in out] buffer */
6984 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6985 buffer = r_u->buffer;
6987 DEBUG(4,("_spoolss_enumforms\n"));
6988 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6989 DEBUGADD(5,("Info level [%d]\n", level));
6991 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6992 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6993 *numofforms = get_ntforms(&list);
6994 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6995 *numofforms += numbuiltinforms;
6997 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
7001 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
7006 /* construct the list of form structures */
7007 for (i=0; i<numbuiltinforms; i++) {
7008 DEBUGADD(6,("Filling form number [%d]\n",i));
7009 fill_form_1(&forms_1[i], &builtinlist[i]);
7012 SAFE_FREE(builtinlist);
7014 for (; i<*numofforms; i++) {
7015 DEBUGADD(6,("Filling form number [%d]\n",i));
7016 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7021 /* check the required size. */
7022 for (i=0; i<numbuiltinforms; i++) {
7023 DEBUGADD(6,("adding form [%d]'s size\n",i));
7024 buffer_size += spoolss_size_form_1(&forms_1[i]);
7026 for (; i<*numofforms; i++) {
7027 DEBUGADD(6,("adding form [%d]'s size\n",i));
7028 buffer_size += spoolss_size_form_1(&forms_1[i]);
7031 *needed=buffer_size;
7033 if (!alloc_buffer_size(buffer, buffer_size)){
7035 return WERR_INSUFFICIENT_BUFFER;
7038 /* fill the buffer with the form structures */
7039 for (i=0; i<numbuiltinforms; i++) {
7040 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7041 smb_io_form_1("", buffer, &forms_1[i], 0);
7043 for (; i<*numofforms; i++) {
7044 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7045 smb_io_form_1("", buffer, &forms_1[i], 0);
7050 if (*needed > offered) {
7052 return WERR_INSUFFICIENT_BUFFER;
7059 SAFE_FREE(builtinlist);
7060 return WERR_UNKNOWN_LEVEL;
7065 /****************************************************************************
7066 ****************************************************************************/
7068 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7070 uint32 level = q_u->level;
7071 UNISTR2 *uni_formname = &q_u->formname;
7072 NEW_BUFFER *buffer = NULL;
7073 uint32 offered = q_u->offered;
7074 uint32 *needed = &r_u->needed;
7076 nt_forms_struct *list=NULL;
7077 nt_forms_struct builtin_form;
7082 int numofforms=0, i=0;
7084 /* that's an [in out] buffer */
7085 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7086 buffer = r_u->buffer;
7088 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7090 DEBUG(4,("_spoolss_getform\n"));
7091 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7092 DEBUGADD(5,("Info level [%d]\n", level));
7094 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7095 if (!foundBuiltin) {
7096 numofforms = get_ntforms(&list);
7097 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7099 if (numofforms == 0)
7106 fill_form_1(&form_1, &builtin_form);
7109 /* Check if the requested name is in the list of form structures */
7110 for (i=0; i<numofforms; i++) {
7112 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7114 if (strequal(form_name, list[i].name)) {
7115 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7116 fill_form_1(&form_1, &list[i]);
7122 if (i == numofforms) {
7126 /* check the required size. */
7128 *needed=spoolss_size_form_1(&form_1);
7130 if (!alloc_buffer_size(buffer, buffer_size)){
7131 return WERR_INSUFFICIENT_BUFFER;
7134 if (*needed > offered) {
7135 return WERR_INSUFFICIENT_BUFFER;
7138 /* fill the buffer with the form structures */
7139 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7140 smb_io_form_1("", buffer, &form_1, 0);
7146 return WERR_UNKNOWN_LEVEL;
7150 /****************************************************************************
7151 ****************************************************************************/
7153 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7155 init_unistr(&port->port_name, name);
7158 /****************************************************************************
7159 ****************************************************************************/
7161 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7163 init_unistr(&port->port_name, name);
7164 init_unistr(&port->monitor_name, "Local Monitor");
7165 init_unistr(&port->description, "Local Port");
7166 port->port_type=PORT_TYPE_WRITE;
7170 /****************************************************************************
7172 ****************************************************************************/
7174 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7176 PORT_INFO_1 *ports=NULL;
7179 if (*lp_enumports_cmd()) {
7180 char *cmd = lp_enumports_cmd();
7187 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7189 DEBUG(10,("Running [%s]\n", command));
7190 ret = smbrun(command, &fd);
7191 DEBUG(10,("Returned [%d]\n", ret));
7195 /* Is this the best error to return here? */
7196 return WERR_ACCESS_DENIED;
7200 qlines = fd_lines_load(fd, &numlines);
7201 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7205 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7206 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7207 dos_errstr(WERR_NOMEM)));
7208 file_lines_free(qlines);
7212 for (i=0; i<numlines; i++) {
7213 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7214 fill_port_1(&ports[i], qlines[i]);
7217 file_lines_free(qlines);
7220 *returned = numlines;
7223 *returned = 1; /* Sole Samba port returned. */
7225 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7228 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7230 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7233 /* check the required size. */
7234 for (i=0; i<*returned; i++) {
7235 DEBUGADD(6,("adding port [%d]'s size\n", i));
7236 *needed += spoolss_size_port_info_1(&ports[i]);
7239 if (!alloc_buffer_size(buffer, *needed)) {
7241 return WERR_INSUFFICIENT_BUFFER;
7244 /* fill the buffer with the ports structures */
7245 for (i=0; i<*returned; i++) {
7246 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7247 smb_io_port_1("", buffer, &ports[i], 0);
7252 if (*needed > offered) {
7254 return WERR_INSUFFICIENT_BUFFER;
7260 /****************************************************************************
7262 ****************************************************************************/
7264 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7266 PORT_INFO_2 *ports=NULL;
7269 if (*lp_enumports_cmd()) {
7270 char *cmd = lp_enumports_cmd();
7279 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7280 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7282 path = lp_lockdir();
7284 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7285 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7288 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7289 ret = smbrun(command, &fd);
7290 DEBUGADD(10,("returned [%d]\n", ret));
7294 /* Is this the best error to return here? */
7295 return WERR_ACCESS_DENIED;
7299 qlines = fd_lines_load(fd, &numlines);
7300 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7304 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7305 file_lines_free(qlines);
7309 for (i=0; i<numlines; i++) {
7310 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7311 fill_port_2(&(ports[i]), qlines[i]);
7314 file_lines_free(qlines);
7317 *returned = numlines;
7323 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7326 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7328 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7331 /* check the required size. */
7332 for (i=0; i<*returned; i++) {
7333 DEBUGADD(6,("adding port [%d]'s size\n", i));
7334 *needed += spoolss_size_port_info_2(&ports[i]);
7337 if (!alloc_buffer_size(buffer, *needed)) {
7339 return WERR_INSUFFICIENT_BUFFER;
7342 /* fill the buffer with the ports structures */
7343 for (i=0; i<*returned; i++) {
7344 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7345 smb_io_port_2("", buffer, &ports[i], 0);
7350 if (*needed > offered) {
7352 return WERR_INSUFFICIENT_BUFFER;
7358 /****************************************************************************
7360 ****************************************************************************/
7362 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7364 uint32 level = q_u->level;
7365 NEW_BUFFER *buffer = NULL;
7366 uint32 offered = q_u->offered;
7367 uint32 *needed = &r_u->needed;
7368 uint32 *returned = &r_u->returned;
7370 /* that's an [in out] buffer */
7371 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7372 buffer = r_u->buffer;
7374 DEBUG(4,("_spoolss_enumports\n"));
7381 return enumports_level_1(buffer, offered, needed, returned);
7383 return enumports_level_2(buffer, offered, needed, returned);
7385 return WERR_UNKNOWN_LEVEL;
7389 /****************************************************************************
7390 ****************************************************************************/
7392 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7393 const SPOOL_PRINTER_INFO_LEVEL *info,
7394 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7395 uint32 user_switch, const SPOOL_USER_CTR *user,
7398 NT_PRINTER_INFO_LEVEL *printer = NULL;
7401 WERROR err = WERR_OK;
7403 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7404 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7408 ZERO_STRUCTP(printer);
7410 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7411 if (!convert_printer_info(info, printer, 2)) {
7412 free_a_printer(&printer, 2);
7416 /* check to see if the printer already exists */
7418 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7419 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7420 printer->info_2->sharename));
7421 free_a_printer(&printer, 2);
7422 return WERR_PRINTER_ALREADY_EXISTS;
7425 /* FIXME!!! smbd should check to see if the driver is installed before
7426 trying to add a printer like this --jerry */
7428 if (*lp_addprinter_cmd() ) {
7429 if ( !add_printer_hook(printer) ) {
7430 free_a_printer(&printer,2);
7431 return WERR_ACCESS_DENIED;
7435 /* use our primary netbios name since get_a_printer() will convert
7436 it to what the client expects on a case by case basis */
7438 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7439 printer->info_2->sharename);
7442 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7443 free_a_printer(&printer,2);
7444 return WERR_ACCESS_DENIED;
7447 /* you must be a printer admin to add a new printer */
7448 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7449 free_a_printer(&printer,2);
7450 return WERR_ACCESS_DENIED;
7454 * Do sanity check on the requested changes for Samba.
7457 if (!check_printer_ok(printer->info_2, snum)) {
7458 free_a_printer(&printer,2);
7459 return WERR_INVALID_PARAM;
7463 * When a printer is created, the drivername bound to the printer is used
7464 * to lookup previously saved driver initialization info, which is then
7465 * bound to the new printer, simulating what happens in the Windows arch.
7470 set_driver_init(printer, 2);
7474 /* A valid devmode was included, convert and link it
7476 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7478 if (!convert_devicemode(printer->info_2->printername, devmode,
7479 &printer->info_2->devmode))
7483 /* write the ASCII on disk */
7484 err = mod_a_printer(printer, 2);
7485 if (!W_ERROR_IS_OK(err)) {
7486 free_a_printer(&printer,2);
7490 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7491 /* Handle open failed - remove addition. */
7492 del_a_printer(printer->info_2->sharename);
7493 free_a_printer(&printer,2);
7494 return WERR_ACCESS_DENIED;
7497 update_c_setprinter(False);
7498 free_a_printer(&printer,2);
7503 /****************************************************************************
7504 ****************************************************************************/
7506 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7508 UNISTR2 *uni_srv_name = &q_u->server_name;
7509 uint32 level = q_u->level;
7510 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7511 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7512 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7513 uint32 user_switch = q_u->user_switch;
7514 SPOOL_USER_CTR *user = &q_u->user_ctr;
7515 POLICY_HND *handle = &r_u->handle;
7519 /* we don't handle yet */
7520 /* but I know what to do ... */
7521 return WERR_UNKNOWN_LEVEL;
7523 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7525 user_switch, user, handle);
7527 return WERR_UNKNOWN_LEVEL;
7531 /****************************************************************************
7532 ****************************************************************************/
7534 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7536 uint32 level = q_u->level;
7537 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7538 WERROR err = WERR_OK;
7539 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7540 struct current_user user;
7541 fstring driver_name;
7544 ZERO_STRUCT(driver);
7546 get_current_user(&user, p);
7548 if (!convert_printer_driver_info(info, &driver, level)) {
7553 DEBUG(5,("Cleaning driver's information\n"));
7554 err = clean_up_driver_struct(driver, level, &user);
7555 if (!W_ERROR_IS_OK(err))
7558 DEBUG(5,("Moving driver to final destination\n"));
7559 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7560 if (W_ERROR_IS_OK(err))
7561 err = WERR_ACCESS_DENIED;
7565 if (add_a_printer_driver(driver, level)!=0) {
7566 err = WERR_ACCESS_DENIED;
7570 /* BEGIN_ADMIN_LOG */
7573 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7574 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7575 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7578 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7579 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7580 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7586 * I think this is where he DrvUpgradePrinter() hook would be
7587 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7588 * server. Right now, we just need to send ourselves a message
7589 * to update each printer bound to this driver. --jerry
7592 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7593 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7598 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7599 * decide if the driver init data should be deleted. The rules are:
7600 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7601 * 2) delete init data only if there is no 2k/Xp driver
7602 * 3) always delete init data
7603 * The generalized rule is always use init data from the highest order driver.
7604 * It is necessary to follow the driver install by an initialization step to
7605 * finish off this process.
7608 version = driver.info_3->cversion;
7609 else if (level == 6)
7610 version = driver.info_6->version;
7615 * 9x printer driver - never delete init data
7618 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7623 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7624 * there is no 2k/Xp driver init data for this driver name.
7628 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7630 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7632 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7634 if (!del_driver_init(driver_name))
7635 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7638 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7640 free_a_printer_driver(driver1,3);
7641 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7648 * 2k or Xp printer driver - always delete init data
7651 if (!del_driver_init(driver_name))
7652 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7656 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7662 free_a_printer_driver(driver, level);
7666 /********************************************************************
7667 * spoolss_addprinterdriverex
7668 ********************************************************************/
7670 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7672 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7673 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7676 * we only support the semantics of AddPrinterDriver()
7677 * i.e. only copy files that are newer than existing ones
7680 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7681 return WERR_ACCESS_DENIED;
7683 ZERO_STRUCT(q_u_local);
7684 ZERO_STRUCT(r_u_local);
7686 /* just pass the information off to _spoolss_addprinterdriver() */
7687 q_u_local.server_name_ptr = q_u->server_name_ptr;
7688 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7689 q_u_local.level = q_u->level;
7690 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7692 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7695 /****************************************************************************
7696 ****************************************************************************/
7698 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7700 init_unistr(&info->name, name);
7703 /****************************************************************************
7704 ****************************************************************************/
7706 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7712 const char *short_archi;
7713 DRIVER_DIRECTORY_1 *info=NULL;
7715 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7716 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7718 /* check for beginning double '\'s and that the server
7721 pservername = servername;
7722 if ( *pservername == '\\' && strlen(servername)>2 ) {
7726 if ( !is_myname_or_ipaddr( pservername ) )
7727 return WERR_INVALID_PARAM;
7729 if (!(short_archi = get_short_archi(long_archi)))
7730 return WERR_INVALID_ENVIRONMENT;
7732 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7735 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7737 DEBUG(4,("printer driver directory: [%s]\n", path));
7739 fill_driverdir_1(info, path);
7741 *needed += spoolss_size_driverdir_info_1(info);
7743 if (!alloc_buffer_size(buffer, *needed)) {
7745 return WERR_INSUFFICIENT_BUFFER;
7748 smb_io_driverdir_1("", buffer, info, 0);
7752 if (*needed > offered)
7753 return WERR_INSUFFICIENT_BUFFER;
7758 /****************************************************************************
7759 ****************************************************************************/
7761 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7763 UNISTR2 *name = &q_u->name;
7764 UNISTR2 *uni_environment = &q_u->environment;
7765 uint32 level = q_u->level;
7766 NEW_BUFFER *buffer = NULL;
7767 uint32 offered = q_u->offered;
7768 uint32 *needed = &r_u->needed;
7770 /* that's an [in out] buffer */
7771 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7772 buffer = r_u->buffer;
7774 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7780 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7782 return WERR_UNKNOWN_LEVEL;
7786 /****************************************************************************
7787 ****************************************************************************/
7789 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7791 POLICY_HND *handle = &q_u->handle;
7792 uint32 idx = q_u->index;
7793 uint32 in_value_len = q_u->valuesize;
7794 uint32 in_data_len = q_u->datasize;
7795 uint32 *out_max_value_len = &r_u->valuesize;
7796 uint16 **out_value = &r_u->value;
7797 uint32 *out_value_len = &r_u->realvaluesize;
7798 uint32 *out_type = &r_u->type;
7799 uint32 *out_max_data_len = &r_u->datasize;
7800 uint8 **data_out = &r_u->data;
7801 uint32 *out_data_len = &r_u->realdatasize;
7803 NT_PRINTER_INFO_LEVEL *printer = NULL;
7805 uint32 biggest_valuesize;
7806 uint32 biggest_datasize;
7808 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7811 REGISTRY_VALUE *val = NULL;
7812 NT_PRINTER_DATA *p_data;
7813 int i, key_index, num_values;
7816 ZERO_STRUCT( printer );
7820 *out_max_data_len = 0;
7824 DEBUG(5,("spoolss_enumprinterdata\n"));
7827 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7831 if (!get_printer_snum(p,handle, &snum))
7834 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7835 if (!W_ERROR_IS_OK(result))
7838 p_data = &printer->info_2->data;
7839 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7844 * The NT machine wants to know the biggest size of value and data
7846 * cf: MSDN EnumPrinterData remark section
7849 if ( !in_value_len && !in_data_len && (key_index != -1) )
7851 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7853 biggest_valuesize = 0;
7854 biggest_datasize = 0;
7856 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7858 for ( i=0; i<num_values; i++ )
7860 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7862 name_length = strlen(val->valuename);
7863 if ( strlen(val->valuename) > biggest_valuesize )
7864 biggest_valuesize = name_length;
7866 if ( val->size > biggest_datasize )
7867 biggest_datasize = val->size;
7869 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7873 /* the value is an UNICODE string but real_value_size is the length
7874 in bytes including the trailing 0 */
7876 *out_value_len = 2 * (1+biggest_valuesize);
7877 *out_data_len = biggest_datasize;
7879 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7885 * the value len is wrong in NT sp3
7886 * that's the number of bytes not the number of unicode chars
7889 if ( key_index != -1 )
7890 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7895 /* out_value should default to "" or else NT4 has
7896 problems unmarshalling the response */
7898 *out_max_value_len=(in_value_len/sizeof(uint16));
7900 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7902 result = WERR_NOMEM;
7906 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7908 /* the data is counted in bytes */
7910 *out_max_data_len = in_data_len;
7911 *out_data_len = in_data_len;
7913 /* only allocate when given a non-zero data_len */
7915 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7917 result = WERR_NOMEM;
7921 result = WERR_NO_MORE_ITEMS;
7927 * - counted in bytes in the request
7928 * - counted in UNICODE chars in the max reply
7929 * - counted in bytes in the real size
7931 * take a pause *before* coding not *during* coding
7935 *out_max_value_len=(in_value_len/sizeof(uint16));
7936 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7938 result = WERR_NOMEM;
7942 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7946 *out_type = regval_type( val );
7948 /* data - counted in bytes */
7950 *out_max_data_len = in_data_len;
7951 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7953 result = WERR_NOMEM;
7956 data_len = (size_t)regval_size(val);
7957 memcpy( *data_out, regval_data_p(val), data_len );
7958 *out_data_len = data_len;
7962 free_a_printer(&printer, 2);
7966 /****************************************************************************
7967 ****************************************************************************/
7969 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7971 POLICY_HND *handle = &q_u->handle;
7972 UNISTR2 *value = &q_u->value;
7973 uint32 type = q_u->type;
7974 uint8 *data = q_u->data;
7975 uint32 real_len = q_u->real_len;
7977 NT_PRINTER_INFO_LEVEL *printer = NULL;
7979 WERROR status = WERR_OK;
7980 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7983 DEBUG(5,("spoolss_setprinterdata\n"));
7986 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7990 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7991 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7992 return WERR_INVALID_PARAM;
7995 if (!get_printer_snum(p,handle, &snum))
7999 * Access check : NT returns "access denied" if you make a
8000 * SetPrinterData call without the necessary privildge.
8001 * we were originally returning OK if nothing changed
8002 * which made Win2k issue **a lot** of SetPrinterData
8003 * when connecting to a printer --jerry
8006 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8008 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8009 status = WERR_ACCESS_DENIED;
8013 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8014 if (!W_ERROR_IS_OK(status))
8017 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8020 * When client side code sets a magic printer data key, detect it and save
8021 * the current printer data and the magic key's data (its the DEVMODE) for
8022 * future printer/driver initializations.
8024 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8026 /* Set devmode and printer initialization info */
8027 status = save_driver_init( printer, 2, data, real_len );
8029 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8033 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8034 type, data, real_len );
8035 if ( W_ERROR_IS_OK(status) )
8036 status = mod_a_printer(printer, 2);
8040 free_a_printer(&printer, 2);
8045 /****************************************************************************
8046 ****************************************************************************/
8048 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8050 POLICY_HND *handle = &q_u->handle;
8051 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8054 DEBUG(5,("_spoolss_resetprinter\n"));
8057 * All we do is to check to see if the handle and queue is valid.
8058 * This call really doesn't mean anything to us because we only
8059 * support RAW printing. --jerry
8063 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8067 if (!get_printer_snum(p,handle, &snum))
8071 /* blindly return success */
8076 /****************************************************************************
8077 ****************************************************************************/
8079 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8081 POLICY_HND *handle = &q_u->handle;
8082 UNISTR2 *value = &q_u->valuename;
8084 NT_PRINTER_INFO_LEVEL *printer = NULL;
8086 WERROR status = WERR_OK;
8087 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8090 DEBUG(5,("spoolss_deleteprinterdata\n"));
8093 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8097 if (!get_printer_snum(p, handle, &snum))
8100 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8101 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8102 return WERR_ACCESS_DENIED;
8105 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8106 if (!W_ERROR_IS_OK(status))
8109 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8111 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8113 if ( W_ERROR_IS_OK(status) )
8114 mod_a_printer( printer, 2 );
8116 free_a_printer(&printer, 2);
8121 /****************************************************************************
8122 ****************************************************************************/
8124 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8126 POLICY_HND *handle = &q_u->handle;
8127 FORM *form = &q_u->form;
8128 nt_forms_struct tmpForm;
8130 WERROR status = WERR_OK;
8131 NT_PRINTER_INFO_LEVEL *printer = NULL;
8134 nt_forms_struct *list=NULL;
8135 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8137 DEBUG(5,("spoolss_addform\n"));
8140 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8145 /* forms can be added on printer of on the print server handle */
8147 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8149 if (!get_printer_snum(p,handle, &snum))
8152 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8153 if (!W_ERROR_IS_OK(status))
8157 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8158 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8159 status = WERR_ACCESS_DENIED;
8163 /* can't add if builtin */
8165 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8166 status = WERR_ALREADY_EXISTS;
8170 count = get_ntforms(&list);
8172 if(!add_a_form(&list, form, &count)) {
8173 status = WERR_NOMEM;
8177 write_ntforms(&list, count);
8180 * ChangeID must always be set if this is a printer
8183 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8184 status = mod_a_printer(printer, 2);
8188 free_a_printer(&printer, 2);
8194 /****************************************************************************
8195 ****************************************************************************/
8197 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8199 POLICY_HND *handle = &q_u->handle;
8200 UNISTR2 *form_name = &q_u->name;
8201 nt_forms_struct tmpForm;
8203 nt_forms_struct *list=NULL;
8204 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8206 WERROR status = WERR_OK;
8207 NT_PRINTER_INFO_LEVEL *printer = NULL;
8209 DEBUG(5,("spoolss_deleteform\n"));
8212 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8216 /* forms can be deleted on printer of on the print server handle */
8218 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8220 if (!get_printer_snum(p,handle, &snum))
8223 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8224 if (!W_ERROR_IS_OK(status))
8228 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8229 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8230 status = WERR_ACCESS_DENIED;
8234 /* can't delete if builtin */
8236 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8237 status = WERR_INVALID_PARAM;
8241 count = get_ntforms(&list);
8243 if ( !delete_a_form(&list, form_name, &count, &status ))
8247 * ChangeID must always be set if this is a printer
8250 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8251 status = mod_a_printer(printer, 2);
8255 free_a_printer(&printer, 2);
8261 /****************************************************************************
8262 ****************************************************************************/
8264 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8266 POLICY_HND *handle = &q_u->handle;
8267 FORM *form = &q_u->form;
8268 nt_forms_struct tmpForm;
8270 WERROR status = WERR_OK;
8271 NT_PRINTER_INFO_LEVEL *printer = NULL;
8274 nt_forms_struct *list=NULL;
8275 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8277 DEBUG(5,("spoolss_setform\n"));
8280 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8284 /* forms can be modified on printer of on the print server handle */
8286 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8288 if (!get_printer_snum(p,handle, &snum))
8291 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8292 if (!W_ERROR_IS_OK(status))
8296 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8297 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8298 status = WERR_ACCESS_DENIED;
8302 /* can't set if builtin */
8303 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8304 status = WERR_INVALID_PARAM;
8308 count = get_ntforms(&list);
8309 update_a_form(&list, form, count);
8310 write_ntforms(&list, count);
8313 * ChangeID must always be set if this is a printer
8316 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8317 status = mod_a_printer(printer, 2);
8322 free_a_printer(&printer, 2);
8328 /****************************************************************************
8329 enumprintprocessors level 1.
8330 ****************************************************************************/
8332 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8334 PRINTPROCESSOR_1 *info_1=NULL;
8336 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8341 init_unistr(&info_1->name, "winprint");
8343 *needed += spoolss_size_printprocessor_info_1(info_1);
8345 if (!alloc_buffer_size(buffer, *needed))
8346 return WERR_INSUFFICIENT_BUFFER;
8348 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8352 if (*needed > offered) {
8354 return WERR_INSUFFICIENT_BUFFER;
8360 /****************************************************************************
8361 ****************************************************************************/
8363 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8365 uint32 level = q_u->level;
8366 NEW_BUFFER *buffer = NULL;
8367 uint32 offered = q_u->offered;
8368 uint32 *needed = &r_u->needed;
8369 uint32 *returned = &r_u->returned;
8371 /* that's an [in out] buffer */
8372 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8373 buffer = r_u->buffer;
8375 DEBUG(5,("spoolss_enumprintprocessors\n"));
8378 * Enumerate the print processors ...
8380 * Just reply with "winprint", to keep NT happy
8381 * and I can use my nice printer checker.
8389 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8391 return WERR_UNKNOWN_LEVEL;
8395 /****************************************************************************
8396 enumprintprocdatatypes level 1.
8397 ****************************************************************************/
8399 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8401 PRINTPROCDATATYPE_1 *info_1=NULL;
8403 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8408 init_unistr(&info_1->name, "RAW");
8410 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8412 if (!alloc_buffer_size(buffer, *needed))
8413 return WERR_INSUFFICIENT_BUFFER;
8415 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8419 if (*needed > offered) {
8421 return WERR_INSUFFICIENT_BUFFER;
8427 /****************************************************************************
8428 ****************************************************************************/
8430 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8432 uint32 level = q_u->level;
8433 NEW_BUFFER *buffer = NULL;
8434 uint32 offered = q_u->offered;
8435 uint32 *needed = &r_u->needed;
8436 uint32 *returned = &r_u->returned;
8438 /* that's an [in out] buffer */
8439 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8440 buffer = r_u->buffer;
8442 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8449 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8451 return WERR_UNKNOWN_LEVEL;
8455 /****************************************************************************
8456 enumprintmonitors level 1.
8457 ****************************************************************************/
8459 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8461 PRINTMONITOR_1 *info_1=NULL;
8463 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8468 init_unistr(&info_1->name, "Local Port");
8470 *needed += spoolss_size_printmonitor_info_1(info_1);
8472 if (!alloc_buffer_size(buffer, *needed))
8473 return WERR_INSUFFICIENT_BUFFER;
8475 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8479 if (*needed > offered) {
8481 return WERR_INSUFFICIENT_BUFFER;
8487 /****************************************************************************
8488 enumprintmonitors level 2.
8489 ****************************************************************************/
8491 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8493 PRINTMONITOR_2 *info_2=NULL;
8495 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8500 init_unistr(&info_2->name, "Local Port");
8501 init_unistr(&info_2->environment, "Windows NT X86");
8502 init_unistr(&info_2->dll_name, "localmon.dll");
8504 *needed += spoolss_size_printmonitor_info_2(info_2);
8506 if (!alloc_buffer_size(buffer, *needed))
8507 return WERR_INSUFFICIENT_BUFFER;
8509 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8513 if (*needed > offered) {
8515 return WERR_INSUFFICIENT_BUFFER;
8521 /****************************************************************************
8522 ****************************************************************************/
8524 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8526 uint32 level = q_u->level;
8527 NEW_BUFFER *buffer = NULL;
8528 uint32 offered = q_u->offered;
8529 uint32 *needed = &r_u->needed;
8530 uint32 *returned = &r_u->returned;
8532 /* that's an [in out] buffer */
8533 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8534 buffer = r_u->buffer;
8536 DEBUG(5,("spoolss_enumprintmonitors\n"));
8539 * Enumerate the print monitors ...
8541 * Just reply with "Local Port", to keep NT happy
8542 * and I can use my nice printer checker.
8550 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8552 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8554 return WERR_UNKNOWN_LEVEL;
8558 /****************************************************************************
8559 ****************************************************************************/
8561 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8562 NT_PRINTER_INFO_LEVEL *ntprinter,
8563 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8568 JOB_INFO_1 *info_1=NULL;
8570 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8572 if (info_1 == NULL) {
8576 for (i=0; i<count && found==False; i++) {
8577 if ((*queue)[i].job==(int)jobid)
8583 /* NT treats not found as bad param... yet another bad choice */
8584 return WERR_INVALID_PARAM;
8587 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8589 *needed += spoolss_size_job_info_1(info_1);
8591 if (!alloc_buffer_size(buffer, *needed)) {
8593 return WERR_INSUFFICIENT_BUFFER;
8596 smb_io_job_info_1("", buffer, info_1, 0);
8600 if (*needed > offered)
8601 return WERR_INSUFFICIENT_BUFFER;
8606 /****************************************************************************
8607 ****************************************************************************/
8609 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8610 NT_PRINTER_INFO_LEVEL *ntprinter,
8611 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8618 DEVICEMODE *devmode = NULL;
8619 NT_DEVICEMODE *nt_devmode = NULL;
8621 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8623 ZERO_STRUCTP(info_2);
8625 if (info_2 == NULL) {
8630 for ( i=0; i<count && found==False; i++ )
8632 if ((*queue)[i].job == (int)jobid)
8638 /* NT treats not found as bad param... yet another bad
8640 ret = WERR_INVALID_PARAM;
8645 * if the print job does not have a DEVMODE associated with it,
8646 * just use the one for the printer. A NULL devicemode is not
8647 * a failure condition
8650 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8651 devmode = construct_dev_mode(snum);
8653 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8654 ZERO_STRUCTP( devmode );
8655 convert_nt_devicemode( devmode, nt_devmode );
8659 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8661 *needed += spoolss_size_job_info_2(info_2);
8663 if (!alloc_buffer_size(buffer, *needed)) {
8664 ret = WERR_INSUFFICIENT_BUFFER;
8668 smb_io_job_info_2("", buffer, info_2, 0);
8670 if (*needed > offered) {
8671 ret = WERR_INSUFFICIENT_BUFFER;
8678 /* Cleanup allocated memory */
8680 free_job_info_2(info_2); /* Also frees devmode */
8686 /****************************************************************************
8687 ****************************************************************************/
8689 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8691 POLICY_HND *handle = &q_u->handle;
8692 uint32 jobid = q_u->jobid;
8693 uint32 level = q_u->level;
8694 NEW_BUFFER *buffer = NULL;
8695 uint32 offered = q_u->offered;
8696 uint32 *needed = &r_u->needed;
8697 WERROR wstatus = WERR_OK;
8698 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8701 print_queue_struct *queue = NULL;
8702 print_status_struct prt_status;
8704 /* that's an [in out] buffer */
8705 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8706 buffer = r_u->buffer;
8708 DEBUG(5,("spoolss_getjob\n"));
8712 if (!get_printer_snum(p, handle, &snum))
8715 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8716 if ( !W_ERROR_IS_OK(wstatus) )
8719 count = print_queue_status(snum, &queue, &prt_status);
8721 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8722 count, prt_status.status, prt_status.message));
8726 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8727 buffer, offered, needed);
8730 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8731 buffer, offered, needed);
8734 wstatus = WERR_UNKNOWN_LEVEL;
8739 free_a_printer( &ntprinter, 2 );
8744 /********************************************************************
8745 spoolss_getprinterdataex
8747 From MSDN documentation of GetPrinterDataEx: pass request
8748 to GetPrinterData if key is "PrinterDriverData".
8749 ********************************************************************/
8751 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8753 POLICY_HND *handle = &q_u->handle;
8754 uint32 in_size = q_u->size;
8755 uint32 *type = &r_u->type;
8756 uint32 *out_size = &r_u->size;
8757 uint8 **data = &r_u->data;
8758 uint32 *needed = &r_u->needed;
8759 fstring keyname, valuename;
8761 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8763 NT_PRINTER_INFO_LEVEL *printer = NULL;
8765 WERROR status = WERR_OK;
8767 DEBUG(4,("_spoolss_getprinterdataex\n"));
8769 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8770 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8772 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8773 keyname, valuename));
8775 /* in case of problem, return some default values */
8779 *out_size = in_size;
8782 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8783 status = WERR_BADFID;
8787 /* Is the handle to a printer or to the server? */
8789 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8790 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8791 status = WERR_INVALID_PARAM;
8795 if ( !get_printer_snum(p,handle, &snum) )
8798 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8799 if ( !W_ERROR_IS_OK(status) )
8802 /* check to see if the keyname is valid */
8803 if ( !strlen(keyname) ) {
8804 status = WERR_INVALID_PARAM;
8808 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8809 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8810 free_a_printer( &printer, 2 );
8811 status = WERR_BADFILE;
8815 /* When given a new keyname, we should just create it */
8817 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8819 if (*needed > *out_size)
8820 status = WERR_MORE_DATA;
8823 if ( !W_ERROR_IS_OK(status) )
8825 DEBUG(5, ("error: allocating %d\n", *out_size));
8827 /* reply this param doesn't exist */
8831 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8832 status = WERR_NOMEM;
8842 free_a_printer( &printer, 2 );
8847 /********************************************************************
8848 * spoolss_setprinterdataex
8849 ********************************************************************/
8851 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8853 POLICY_HND *handle = &q_u->handle;
8854 uint32 type = q_u->type;
8855 uint8 *data = q_u->data;
8856 uint32 real_len = q_u->real_len;
8858 NT_PRINTER_INFO_LEVEL *printer = NULL;
8860 WERROR status = WERR_OK;
8861 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8866 DEBUG(4,("_spoolss_setprinterdataex\n"));
8868 /* From MSDN documentation of SetPrinterDataEx: pass request to
8869 SetPrinterData if key is "PrinterDriverData" */
8872 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8876 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8877 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8878 return WERR_INVALID_PARAM;
8881 if ( !get_printer_snum(p,handle, &snum) )
8885 * Access check : NT returns "access denied" if you make a
8886 * SetPrinterData call without the necessary privildge.
8887 * we were originally returning OK if nothing changed
8888 * which made Win2k issue **a lot** of SetPrinterData
8889 * when connecting to a printer --jerry
8892 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8894 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8895 return WERR_ACCESS_DENIED;
8898 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8899 if (!W_ERROR_IS_OK(status))
8902 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8903 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8905 /* check for OID in valuename */
8907 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8913 /* save the registry data */
8915 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8917 if ( W_ERROR_IS_OK(status) )
8919 /* save the OID if one was specified */
8921 fstrcat( keyname, "\\" );
8922 fstrcat( keyname, SPOOL_OID_KEY );
8925 * I'm not checking the status here on purpose. Don't know
8926 * if this is right, but I'm returning the status from the
8927 * previous set_printer_dataex() call. I have no idea if
8928 * this is right. --jerry
8931 set_printer_dataex( printer, keyname, valuename,
8932 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8935 status = mod_a_printer(printer, 2);
8938 free_a_printer(&printer, 2);
8944 /********************************************************************
8945 * spoolss_deleteprinterdataex
8946 ********************************************************************/
8948 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8950 POLICY_HND *handle = &q_u->handle;
8951 UNISTR2 *value = &q_u->valuename;
8952 UNISTR2 *key = &q_u->keyname;
8954 NT_PRINTER_INFO_LEVEL *printer = NULL;
8956 WERROR status = WERR_OK;
8957 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8958 pstring valuename, keyname;
8960 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8963 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8967 if (!get_printer_snum(p, handle, &snum))
8970 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8971 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8972 return WERR_ACCESS_DENIED;
8975 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8976 if (!W_ERROR_IS_OK(status))
8979 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8980 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8982 status = delete_printer_dataex( printer, keyname, valuename );
8984 if ( W_ERROR_IS_OK(status) )
8985 mod_a_printer( printer, 2 );
8987 free_a_printer(&printer, 2);
8992 /********************************************************************
8993 * spoolss_enumprinterkey
8994 ********************************************************************/
8997 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9000 fstring *keynames = NULL;
9001 uint16 *enumkeys = NULL;
9004 POLICY_HND *handle = &q_u->handle;
9005 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9006 NT_PRINTER_DATA *data;
9007 NT_PRINTER_INFO_LEVEL *printer = NULL;
9009 WERROR status = WERR_BADFILE;
9012 DEBUG(4,("_spoolss_enumprinterkey\n"));
9015 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9019 if ( !get_printer_snum(p,handle, &snum) )
9022 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9023 if (!W_ERROR_IS_OK(status))
9026 /* get the list of subkey names */
9028 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9029 data = &printer->info_2->data;
9031 num_keys = get_printer_subkeys( data, key, &keynames );
9033 if ( num_keys == -1 ) {
9034 status = WERR_BADFILE;
9038 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9040 r_u->needed = printerkey_len*2;
9042 if ( q_u->size < r_u->needed ) {
9043 status = WERR_MORE_DATA;
9047 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9048 status = WERR_NOMEM;
9054 if ( q_u->size < r_u->needed )
9055 status = WERR_MORE_DATA;
9058 free_a_printer( &printer, 2 );
9059 SAFE_FREE( keynames );
9064 /********************************************************************
9065 * spoolss_deleteprinterkey
9066 ********************************************************************/
9068 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9070 POLICY_HND *handle = &q_u->handle;
9071 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9073 NT_PRINTER_INFO_LEVEL *printer = NULL;
9077 DEBUG(5,("spoolss_deleteprinterkey\n"));
9080 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9084 /* if keyname == NULL, return error */
9086 if ( !q_u->keyname.buffer )
9087 return WERR_INVALID_PARAM;
9089 if (!get_printer_snum(p, handle, &snum))
9092 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9093 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9094 return WERR_ACCESS_DENIED;
9097 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9098 if (!W_ERROR_IS_OK(status))
9101 /* delete the key and all subneys */
9103 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9105 status = delete_all_printer_data( printer->info_2, key );
9107 if ( W_ERROR_IS_OK(status) )
9108 status = mod_a_printer(printer, 2);
9110 free_a_printer( &printer, 2 );
9116 /********************************************************************
9117 * spoolss_enumprinterdataex
9118 ********************************************************************/
9120 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9122 POLICY_HND *handle = &q_u->handle;
9123 uint32 in_size = q_u->size;
9126 NT_PRINTER_INFO_LEVEL *printer = NULL;
9127 PRINTER_ENUM_VALUES *enum_values = NULL;
9128 NT_PRINTER_DATA *p_data;
9130 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9135 REGISTRY_VALUE *val;
9140 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9143 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9148 * first check for a keyname of NULL or "". Win2k seems to send
9149 * this a lot and we should send back WERR_INVALID_PARAM
9150 * no need to spend time looking up the printer in this case.
9154 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9155 if ( !strlen(key) ) {
9156 result = WERR_INVALID_PARAM;
9160 /* get the printer off of disk */
9162 if (!get_printer_snum(p,handle, &snum))
9165 ZERO_STRUCT(printer);
9166 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9167 if (!W_ERROR_IS_OK(result))
9170 /* now look for a match on the key name */
9172 p_data = &printer->info_2->data;
9174 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9175 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9177 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9178 result = WERR_INVALID_PARAM;
9185 /* allocate the memory for the array of pointers -- if necessary */
9187 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9190 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9192 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9193 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9194 result = WERR_NOMEM;
9198 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9202 * loop through all params and build the array to pass
9203 * back to the client
9206 for ( i=0; i<num_entries; i++ )
9208 /* lookup the registry value */
9210 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9211 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9215 value_name = regval_name( val );
9216 init_unistr( &enum_values[i].valuename, value_name );
9217 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9218 enum_values[i].type = regval_type( val );
9220 data_len = regval_size( val );
9222 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9224 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9226 result = WERR_NOMEM;
9230 enum_values[i].data_len = data_len;
9232 /* keep track of the size of the array in bytes */
9234 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9237 /* housekeeping information in the reply */
9239 r_u->needed = needed;
9240 r_u->returned = num_entries;
9242 if (needed > in_size) {
9243 result = WERR_MORE_DATA;
9247 /* copy data into the reply */
9249 r_u->ctr.size = r_u->needed;
9250 r_u->ctr.size_of_array = r_u->returned;
9251 r_u->ctr.values = enum_values;
9257 free_a_printer(&printer, 2);
9262 /****************************************************************************
9263 ****************************************************************************/
9265 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9267 init_unistr(&info->name, name);
9270 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9271 UNISTR2 *environment,
9278 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9280 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9282 if (!get_short_archi(long_archi))
9283 return WERR_INVALID_ENVIRONMENT;
9285 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9288 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9290 fill_printprocessordirectory_1(info, path);
9292 *needed += spoolss_size_printprocessordirectory_info_1(info);
9294 if (!alloc_buffer_size(buffer, *needed)) {
9296 return WERR_INSUFFICIENT_BUFFER;
9299 smb_io_printprocessordirectory_1("", buffer, info, 0);
9303 if (*needed > offered)
9304 return WERR_INSUFFICIENT_BUFFER;
9309 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9311 uint32 level = q_u->level;
9312 NEW_BUFFER *buffer = NULL;
9313 uint32 offered = q_u->offered;
9314 uint32 *needed = &r_u->needed;
9317 /* that's an [in out] buffer */
9318 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9319 buffer = r_u->buffer;
9321 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9327 result = getprintprocessordirectory_level_1
9328 (&q_u->name, &q_u->environment, buffer, offered, needed);
9331 result = WERR_UNKNOWN_LEVEL;
9339 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9340 SPOOL_R_REPLYOPENPRINTER *r_u)
9342 DEBUG(5,("_spoolss_replyopenprinter\n"));
9344 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9349 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9350 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9352 DEBUG(5,("_spoolss_replycloseprinter\n"));