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) ) {
532 /* do another loop to look for printernames */
534 for (snum=0; !found && snum<n_services; snum++) {
536 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
539 fstrcpy(sname, lp_servicename(snum));
542 result = get_a_printer( NULL, &printer, 2, sname );
543 if ( !W_ERROR_IS_OK(result) ) {
544 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
545 sname, dos_errstr(result)));
549 /* printername is always returned as \\server\printername */
550 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
551 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
552 printer->info_2->printername));
553 free_a_printer( &printer, 2);
559 if ( strequal(printername, aprinter) ) {
563 DEBUGADD(10, ("printername: %s\n", printername));
565 free_a_printer( &printer, 2);
569 DEBUGADD(4,("Printer not found\n"));
573 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
575 fstrcpy(Printer->sharename, sname);
580 /****************************************************************************
581 Find first available printer slot. creates a printer handle for you.
582 ****************************************************************************/
584 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
586 Printer_entry *new_printer;
588 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
590 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
593 ZERO_STRUCTP(new_printer);
595 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
596 SAFE_FREE(new_printer);
600 /* Add to the internal list. */
601 DLIST_ADD(printers_list, new_printer);
603 new_printer->notify.option=NULL;
605 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
606 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
607 close_printer_handle(p, hnd);
611 if (!set_printer_hnd_printertype(new_printer, name)) {
612 close_printer_handle(p, hnd);
616 if (!set_printer_hnd_name(new_printer, name)) {
617 close_printer_handle(p, hnd);
621 new_printer->access_granted = access_granted;
623 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
628 /****************************************************************************
629 Allocate more memory for a BUFFER.
630 ****************************************************************************/
632 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
640 /* damn, I'm doing the reverse operation of prs_grow() :) */
641 if (buffer_size < prs_data_size(ps))
644 extra_space = buffer_size - prs_data_size(ps);
647 * save the offset and move to the end of the buffer
648 * prs_grow() checks the extra_space against the offset
650 old_offset=prs_offset(ps);
651 prs_set_offset(ps, prs_data_size(ps));
653 if (!prs_grow(ps, extra_space))
656 prs_set_offset(ps, old_offset);
658 buffer->string_at_end=prs_data_size(ps);
663 /***************************************************************************
664 check to see if the client motify handle is monitoring the notification
665 given by (notify_type, notify_field).
666 **************************************************************************/
668 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
674 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
677 SPOOL_NOTIFY_OPTION *option = p->notify.option;
681 * Flags should always be zero when the change notify
682 * is registered by the client's spooler. A user Win32 app
683 * might use the flags though instead of the NOTIFY_OPTION_INFO
692 return is_monitoring_event_flags(
693 p->notify.flags, notify_type, notify_field);
695 for (i = 0; i < option->count; i++) {
697 /* Check match for notify_type */
699 if (option->ctr.type[i].type != notify_type)
702 /* Check match for field */
704 for (j = 0; j < option->ctr.type[i].count; j++) {
705 if (option->ctr.type[i].fields[j] == notify_field) {
711 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
712 p->servername, p->sharename, notify_type, notify_field));
717 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
719 static void notify_one_value(struct spoolss_notify_msg *msg,
720 SPOOL_NOTIFY_INFO_DATA *data,
723 data->notify_data.value[0] = msg->notify.value[0];
724 data->notify_data.value[1] = 0;
727 static void notify_string(struct spoolss_notify_msg *msg,
728 SPOOL_NOTIFY_INFO_DATA *data,
733 /* The length of the message includes the trailing \0 */
735 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
737 data->notify_data.data.length = msg->len * 2;
738 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
740 if (!data->notify_data.data.string) {
741 data->notify_data.data.length = 0;
745 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
748 static void notify_system_time(struct spoolss_notify_msg *msg,
749 SPOOL_NOTIFY_INFO_DATA *data,
755 if (msg->len != sizeof(time_t)) {
756 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
761 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
762 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
766 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
767 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
771 if (!spoolss_io_system_time("", &ps, 0, &systime))
774 data->notify_data.data.length = prs_offset(&ps);
775 data->notify_data.data.string = talloc(mem_ctx, prs_offset(&ps));
777 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
782 struct notify2_message_table {
784 void (*fn)(struct spoolss_notify_msg *msg,
785 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
788 static struct notify2_message_table printer_notify_table[] = {
789 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
790 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
791 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
792 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
793 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
794 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
795 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
796 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
797 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
798 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
799 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
800 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
801 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
802 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
803 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
804 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
805 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
806 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
807 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
810 static struct notify2_message_table job_notify_table[] = {
811 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
812 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
813 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
814 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
815 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
816 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
817 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
818 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
819 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
820 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
821 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
822 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
823 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
824 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
825 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
826 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
827 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
828 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
829 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
830 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
831 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
832 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
833 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
834 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
838 /***********************************************************************
839 Allocate talloc context for container object
840 **********************************************************************/
842 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
847 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
852 /***********************************************************************
853 release all allocated memory and zero out structure
854 **********************************************************************/
856 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
862 talloc_destroy(ctr->ctx);
869 /***********************************************************************
870 **********************************************************************/
872 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
880 /***********************************************************************
881 **********************************************************************/
883 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
885 if ( !ctr || !ctr->msg_groups )
888 if ( idx >= ctr->num_groups )
891 return &ctr->msg_groups[idx];
895 /***********************************************************************
896 How many groups of change messages do we have ?
897 **********************************************************************/
899 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
904 return ctr->num_groups;
907 /***********************************************************************
908 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
909 **********************************************************************/
911 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
913 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
914 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
915 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
921 /* loop over all groups looking for a matching printer name */
923 for ( i=0; i<ctr->num_groups; i++ ) {
924 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
928 /* add a new group? */
930 if ( i == ctr->num_groups ) {
933 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
934 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
937 ctr->msg_groups = groups;
939 /* clear the new entry and set the printer name */
941 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
942 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
945 /* add the change messages; 'i' is the correct index now regardless */
947 msg_grp = &ctr->msg_groups[i];
951 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
952 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
955 msg_grp->msgs = msg_list;
957 new_slot = msg_grp->num_msgs-1;
958 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
960 /* need to allocate own copy of data */
963 msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
965 return ctr->num_groups;
968 /***********************************************************************
969 Send a change notication message on all handles which have a call
971 **********************************************************************/
973 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
976 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
977 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
978 SPOOLSS_NOTIFY_MSG *messages;
979 int sending_msg_count;
982 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
986 messages = msg_group->msgs;
989 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
993 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
995 /* loop over all printers */
997 for (p = printers_list; p; p = p->next) {
998 SPOOL_NOTIFY_INFO_DATA *data;
1003 /* Is there notification on this handle? */
1005 if ( !p->notify.client_connected )
1008 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
1010 /* For this printer? Print servers always receive
1013 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
1014 ( !strequal(msg_group->printername, p->sharename) ) )
1017 DEBUG(10,("Our printer\n"));
1019 /* allocate the max entries possible */
1021 data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
1024 /* build the array of change notifications */
1026 sending_msg_count = 0;
1028 for ( i=0; i<msg_group->num_msgs; i++ ) {
1029 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1031 /* Are we monitoring this event? */
1033 if (!is_monitoring_event(p, msg->type, msg->field))
1036 sending_msg_count++;
1039 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1040 msg->type, msg->field, p->sharename));
1043 * if the is a printer notification handle and not a job notification
1044 * type, then set the id to 0. Other wise just use what was specified
1047 * When registering change notification on a print server handle
1048 * we always need to send back the id (snum) matching the printer
1049 * for which the change took place. For change notify registered
1050 * on a printer handle, this does not matter and the id should be 0.
1055 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1061 /* Convert unix jobid to smb jobid */
1063 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1064 id = sysjob_to_jobid(msg->id);
1067 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1072 construct_info_data( &data[data_len], msg->type, msg->field, id );
1075 case PRINTER_NOTIFY_TYPE:
1076 if ( printer_notify_table[msg->field].fn )
1077 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1080 case JOB_NOTIFY_TYPE:
1081 if ( job_notify_table[msg->field].fn )
1082 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1086 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1093 if ( sending_msg_count ) {
1094 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
1095 data_len, data, p->notify.change, 0 );
1100 DEBUG(8,("send_notify2_changes: Exit...\n"));
1104 /***********************************************************************
1105 **********************************************************************/
1107 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1110 uint32 tv_sec, tv_usec;
1113 /* Unpack message */
1115 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1118 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1120 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1123 tdb_unpack((char *)buf + offset, len - offset, "dd",
1124 &msg->notify.value[0], &msg->notify.value[1]);
1126 tdb_unpack((char *)buf + offset, len - offset, "B",
1127 &msg->len, &msg->notify.data);
1129 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1130 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1132 tv->tv_sec = tv_sec;
1133 tv->tv_usec = tv_usec;
1136 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1137 msg->notify.value[1]));
1139 dump_data(3, msg->notify.data, msg->len);
1144 /********************************************************************
1145 Receive a notify2 message list
1146 ********************************************************************/
1148 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1150 size_t msg_count, i;
1151 char *buf = (char *)msg;
1154 SPOOLSS_NOTIFY_MSG notify;
1155 SPOOLSS_NOTIFY_MSG_CTR messages;
1159 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1163 msg_count = IVAL(buf, 0);
1166 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1168 if (msg_count == 0) {
1169 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1173 /* initialize the container */
1175 ZERO_STRUCT( messages );
1176 notify_msg_ctr_init( &messages );
1179 * build message groups for each printer identified
1180 * in a change_notify msg. Remember that a PCN message
1181 * includes the handle returned for the srv_spoolss_replyopenprinter()
1182 * call. Therefore messages are grouped according to printer handle.
1185 for ( i=0; i<msg_count; i++ ) {
1186 struct timeval msg_tv;
1188 if (msg_ptr + 4 - buf > len) {
1189 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1193 msg_len = IVAL(msg_ptr,0);
1196 if (msg_ptr + msg_len - buf > len) {
1197 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1201 /* unpack messages */
1203 ZERO_STRUCT( notify );
1204 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1207 /* add to correct list in container */
1209 notify_msg_ctr_addmsg( &messages, ¬ify );
1211 /* free memory that might have been allocated by notify2_unpack_msg() */
1213 if ( notify.len != 0 )
1214 SAFE_FREE( notify.notify.data );
1217 /* process each group of messages */
1219 num_groups = notify_msg_ctr_numgroups( &messages );
1220 for ( i=0; i<num_groups; i++ )
1221 send_notify2_changes( &messages, i );
1226 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1228 notify_msg_ctr_destroy( &messages );
1233 /********************************************************************
1234 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1235 one smbd, all of processes must clear their printer cache immediately.
1236 ********************************************************************/
1238 void receive_printer_mod_msg(int msg_type, pid_t src, void *buf, size_t len)
1240 fstring printername;
1242 fstrcpy( printername, buf );
1244 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername ));
1246 invalidate_printer_hnd_cache( printername );
1249 /********************************************************************
1250 Send a message to ourself about new driver being installed
1251 so we can upgrade the information for each printer bound to this
1253 ********************************************************************/
1255 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1257 int len = strlen(drivername);
1262 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1265 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1270 /**********************************************************************
1271 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1272 over all printers, upgrading ones as necessary
1273 **********************************************************************/
1275 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1279 int n_services = lp_numservices();
1281 len = MIN(len,sizeof(drivername)-1);
1282 strncpy(drivername, buf, len);
1284 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1286 /* Iterate the printer list */
1288 for (snum=0; snum<n_services; snum++)
1290 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1293 NT_PRINTER_INFO_LEVEL *printer = NULL;
1295 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1296 if (!W_ERROR_IS_OK(result))
1299 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1301 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1303 /* all we care about currently is the change_id */
1305 result = mod_a_printer(printer, 2);
1306 if (!W_ERROR_IS_OK(result)) {
1307 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1308 dos_errstr(result)));
1312 free_a_printer(&printer, 2);
1319 /********************************************************************
1320 Update the cache for all printq's with a registered client
1322 ********************************************************************/
1324 void update_monitored_printq_cache( void )
1326 Printer_entry *printer = printers_list;
1329 /* loop through all printers and update the cache where
1330 client_connected == True */
1333 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1334 && printer->notify.client_connected )
1336 snum = print_queue_snum(printer->sharename);
1337 print_queue_status( snum, NULL, NULL );
1340 printer = printer->next;
1345 /********************************************************************
1346 Send a message to ourself about new driver being installed
1347 so we can upgrade the information for each printer bound to this
1349 ********************************************************************/
1351 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1353 int len = strlen(drivername);
1358 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1361 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1366 /**********************************************************************
1367 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1368 over all printers, resetting printer data as neessary
1369 **********************************************************************/
1371 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1375 int n_services = lp_numservices();
1377 len = MIN( len, sizeof(drivername)-1 );
1378 strncpy( drivername, buf, len );
1380 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1382 /* Iterate the printer list */
1384 for ( snum=0; snum<n_services; snum++ )
1386 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1389 NT_PRINTER_INFO_LEVEL *printer = NULL;
1391 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1392 if ( !W_ERROR_IS_OK(result) )
1396 * if the printer is bound to the driver,
1397 * then reset to the new driver initdata
1400 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1402 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1404 if ( !set_driver_init(printer, 2) ) {
1405 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1406 printer->info_2->printername, printer->info_2->drivername));
1409 result = mod_a_printer( printer, 2 );
1410 if ( !W_ERROR_IS_OK(result) ) {
1411 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1412 get_dos_error_msg(result)));
1416 free_a_printer( &printer, 2 );
1425 /********************************************************************
1426 Copy routines used by convert_to_openprinterex()
1427 *******************************************************************/
1429 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1437 DEBUG (8,("dup_devmode\n"));
1439 /* bulk copy first */
1441 d = talloc_memdup(ctx, devmode, sizeof(DEVICEMODE));
1445 /* dup the pointer members separately */
1447 len = unistrlen(devmode->devicename.buffer);
1449 d->devicename.buffer = talloc(ctx, len*2);
1450 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1455 len = unistrlen(devmode->formname.buffer);
1457 d->devicename.buffer = talloc(ctx, len*2);
1458 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1462 d->private = talloc_memdup(ctx, devmode->private, devmode->driverextra);
1467 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1469 if (!new_ctr || !ctr)
1472 DEBUG(8,("copy_devmode_ctr\n"));
1474 new_ctr->size = ctr->size;
1475 new_ctr->devmode_ptr = ctr->devmode_ptr;
1477 if(ctr->devmode_ptr)
1478 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1481 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1483 if (!new_def || !def)
1486 DEBUG(8,("copy_printer_defaults\n"));
1488 new_def->datatype_ptr = def->datatype_ptr;
1490 if (def->datatype_ptr)
1491 copy_unistr2(&new_def->datatype, &def->datatype);
1493 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1495 new_def->access_required = def->access_required;
1498 /********************************************************************
1499 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1500 * SPOOL_Q_OPEN_PRINTER_EX structure
1501 ********************************************************************/
1503 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1505 if (!q_u_ex || !q_u)
1508 DEBUG(8,("convert_to_openprinterex\n"));
1510 q_u_ex->printername_ptr = q_u->printername_ptr;
1512 if (q_u->printername_ptr)
1513 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1515 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1518 /********************************************************************
1519 * spoolss_open_printer
1521 * called from the spoolss dispatcher
1522 ********************************************************************/
1524 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1526 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1527 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1532 ZERO_STRUCT(q_u_ex);
1533 ZERO_STRUCT(r_u_ex);
1535 /* convert the OpenPrinter() call to OpenPrinterEx() */
1537 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1539 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1541 /* convert back to OpenPrinter() */
1543 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1548 /********************************************************************
1549 * spoolss_open_printer
1551 * If the openprinterex rpc call contains a devmode,
1552 * it's a per-user one. This per-user devmode is derivated
1553 * from the global devmode. Openprinterex() contains a per-user
1554 * devmode for when you do EMF printing and spooling.
1555 * In the EMF case, the NT workstation is only doing half the job
1556 * of rendering the page. The other half is done by running the printer
1557 * driver on the server.
1558 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1559 * The EMF file only contains what is to be printed on the page.
1560 * So in order for the server to know how to print, the NT client sends
1561 * a devicemode attached to the openprinterex call.
1562 * But this devicemode is short lived, it's only valid for the current print job.
1564 * If Samba would have supported EMF spooling, this devicemode would
1565 * have been attached to the handle, to sent it to the driver to correctly
1566 * rasterize the EMF file.
1568 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1569 * we just act as a pass-thru between windows and the printer.
1571 * In order to know that Samba supports only RAW spooling, NT has to call
1572 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1573 * and until NT sends a RAW job, we refuse it.
1575 * But to call getprinter() or startdoc(), you first need a valid handle,
1576 * and to get an handle you have to call openprintex(). Hence why you have
1577 * a devicemode in the openprinterex() call.
1580 * Differences between NT4 and NT 2000.
1583 * On NT4, you only have a global devicemode. This global devicemode can be changed
1584 * by the administrator (or by a user with enough privs). Everytime a user
1585 * wants to print, the devicemode is resetted to the default. In Word, everytime
1586 * you print, the printer's characteristics are always reset to the global devicemode.
1590 * In W2K, there is the notion of per-user devicemode. The first time you use
1591 * a printer, a per-user devicemode is build from the global devicemode.
1592 * If you change your per-user devicemode, it is saved in the registry, under the
1593 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1594 * printer preferences available.
1596 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1597 * on the General Tab of the printer properties windows.
1599 * To change the global devicemode: it's the "Printing Defaults..." button
1600 * on the Advanced Tab of the printer properties window.
1603 ********************************************************************/
1605 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1607 UNISTR2 *printername = NULL;
1608 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1609 POLICY_HND *handle = &r_u->handle;
1613 struct current_user user;
1614 Printer_entry *Printer=NULL;
1616 if (q_u->printername_ptr != 0)
1617 printername = &q_u->printername;
1619 if (printername == NULL)
1620 return WERR_INVALID_PRINTER_NAME;
1622 /* some sanity check because you can open a printer or a print server */
1623 /* aka: \\server\printer or \\server */
1624 unistr2_to_ascii(name, printername, sizeof(name)-1);
1626 DEBUGADD(3,("checking name: %s\n",name));
1628 if (!open_printer_hnd(p, handle, name, 0))
1629 return WERR_INVALID_PRINTER_NAME;
1631 Printer=find_printer_index_by_hnd(p, handle);
1633 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1634 "handle we created for printer %s\n", name ));
1635 close_printer_handle(p,handle);
1636 return WERR_INVALID_PRINTER_NAME;
1639 get_current_user(&user, p);
1642 * First case: the user is opening the print server:
1644 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1645 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1647 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1648 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1649 * or if the user is listed in the smb.conf printer admin parameter.
1651 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1652 * client view printer folder, but does not show the MSAPW.
1654 * Note: this test needs code to check access rights here too. Jeremy
1655 * could you look at this?
1657 * Second case: the user is opening a printer:
1658 * NT doesn't let us connect to a printer if the connecting user
1659 * doesn't have print permission.
1662 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1664 /* Printserver handles use global struct... */
1668 /* Map standard access rights to object specific access rights */
1670 se_map_standard(&printer_default->access_required,
1671 &printserver_std_mapping);
1673 /* Deny any object specific bits that don't apply to print
1674 servers (i.e printer and job specific bits) */
1676 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1678 if (printer_default->access_required &
1679 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1680 DEBUG(3, ("access DENIED for non-printserver bits"));
1681 close_printer_handle(p, handle);
1682 return WERR_ACCESS_DENIED;
1685 /* Allow admin access */
1687 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1689 if (!lp_ms_add_printer_wizard()) {
1690 close_printer_handle(p, handle);
1691 return WERR_ACCESS_DENIED;
1694 /* if the user is not root and not a printer admin, then fail */
1697 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1699 close_printer_handle(p, handle);
1700 return WERR_ACCESS_DENIED;
1703 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1707 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1710 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1711 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1713 /* We fall through to return WERR_OK */
1718 /* NT doesn't let us connect to a printer if the connecting user
1719 doesn't have print permission. */
1721 if (!get_printer_snum(p, handle, &snum)) {
1722 close_printer_handle(p, handle);
1726 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1728 /* map an empty access mask to the minimum access mask */
1729 if (printer_default->access_required == 0x0)
1730 printer_default->access_required = PRINTER_ACCESS_USE;
1733 * If we are not serving the printer driver for this printer,
1734 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1735 * will keep NT clients happy --jerry
1738 if (lp_use_client_driver(snum)
1739 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1741 printer_default->access_required = PRINTER_ACCESS_USE;
1744 /* check smb.conf parameters and the the sec_desc */
1746 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1747 DEBUG(3, ("access DENIED for printer open\n"));
1748 close_printer_handle(p, handle);
1749 return WERR_ACCESS_DENIED;
1752 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1753 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1754 close_printer_handle(p, handle);
1755 return WERR_ACCESS_DENIED;
1758 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1759 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1761 printer_default->access_required = PRINTER_ACCESS_USE;
1763 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1764 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1768 Printer->access_granted = printer_default->access_required;
1771 * If the client sent a devmode in the OpenPrinter() call, then
1772 * save it here in case we get a job submission on this handle
1775 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1776 && q_u->printer_default.devmode_cont.devmode_ptr )
1778 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1779 &Printer->nt_devmode );
1782 #if 0 /* JERRY -- I'm doubtful this is really effective */
1783 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1784 optimization in Windows 2000 clients --jerry */
1786 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1787 && (RA_WIN2K == get_remote_arch()) )
1789 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1790 sys_usleep( 500000 );
1797 /****************************************************************************
1798 ****************************************************************************/
1800 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1801 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1807 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1816 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1817 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1823 printer->info_3=NULL;
1824 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1828 printer->info_6=NULL;
1829 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1839 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1840 NT_DEVICEMODE **pp_nt_devmode)
1842 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1845 * Ensure nt_devmode is a valid pointer
1846 * as we will be overwriting it.
1849 if (nt_devmode == NULL) {
1850 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1851 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1855 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1856 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1858 nt_devmode->specversion=devmode->specversion;
1859 nt_devmode->driverversion=devmode->driverversion;
1860 nt_devmode->size=devmode->size;
1861 nt_devmode->fields=devmode->fields;
1862 nt_devmode->orientation=devmode->orientation;
1863 nt_devmode->papersize=devmode->papersize;
1864 nt_devmode->paperlength=devmode->paperlength;
1865 nt_devmode->paperwidth=devmode->paperwidth;
1866 nt_devmode->scale=devmode->scale;
1867 nt_devmode->copies=devmode->copies;
1868 nt_devmode->defaultsource=devmode->defaultsource;
1869 nt_devmode->printquality=devmode->printquality;
1870 nt_devmode->color=devmode->color;
1871 nt_devmode->duplex=devmode->duplex;
1872 nt_devmode->yresolution=devmode->yresolution;
1873 nt_devmode->ttoption=devmode->ttoption;
1874 nt_devmode->collate=devmode->collate;
1876 nt_devmode->logpixels=devmode->logpixels;
1877 nt_devmode->bitsperpel=devmode->bitsperpel;
1878 nt_devmode->pelswidth=devmode->pelswidth;
1879 nt_devmode->pelsheight=devmode->pelsheight;
1880 nt_devmode->displayflags=devmode->displayflags;
1881 nt_devmode->displayfrequency=devmode->displayfrequency;
1882 nt_devmode->icmmethod=devmode->icmmethod;
1883 nt_devmode->icmintent=devmode->icmintent;
1884 nt_devmode->mediatype=devmode->mediatype;
1885 nt_devmode->dithertype=devmode->dithertype;
1886 nt_devmode->reserved1=devmode->reserved1;
1887 nt_devmode->reserved2=devmode->reserved2;
1888 nt_devmode->panningwidth=devmode->panningwidth;
1889 nt_devmode->panningheight=devmode->panningheight;
1892 * Only change private and driverextra if the incoming devmode
1893 * has a new one. JRA.
1896 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1897 SAFE_FREE(nt_devmode->private);
1898 nt_devmode->driverextra=devmode->driverextra;
1899 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
1901 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1904 *pp_nt_devmode = nt_devmode;
1909 /********************************************************************
1910 * _spoolss_enddocprinter_internal.
1911 ********************************************************************/
1913 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1915 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1919 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1923 if (!get_printer_snum(p, handle, &snum))
1926 Printer->document_started=False;
1927 print_job_end(snum, Printer->jobid,True);
1928 /* error codes unhandled so far ... */
1933 /********************************************************************
1934 * api_spoolss_closeprinter
1935 ********************************************************************/
1937 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1939 POLICY_HND *handle = &q_u->handle;
1941 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1943 if (Printer && Printer->document_started)
1944 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1946 if (!close_printer_handle(p, handle))
1949 /* clear the returned printer handle. Observed behavior
1950 from Win2k server. Don't think this really matters.
1951 Previous code just copied the value of the closed
1954 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1959 /********************************************************************
1960 * api_spoolss_deleteprinter
1962 ********************************************************************/
1964 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1966 POLICY_HND *handle = &q_u->handle;
1967 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1970 if (Printer && Printer->document_started)
1971 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1973 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1975 result = delete_printer_handle(p, handle);
1977 update_c_setprinter(False);
1982 /*******************************************************************
1983 * static function to lookup the version id corresponding to an
1984 * long architecture string
1985 ******************************************************************/
1987 static int get_version_id (char * arch)
1990 struct table_node archi_table[]= {
1992 {"Windows 4.0", "WIN40", 0 },
1993 {"Windows NT x86", "W32X86", 2 },
1994 {"Windows NT R4000", "W32MIPS", 2 },
1995 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1996 {"Windows NT PowerPC", "W32PPC", 2 },
1997 {"Windows IA64", "IA64", 3 },
1998 {"Windows x64", "x64", 3 },
2002 for (i=0; archi_table[i].long_archi != NULL; i++)
2004 if (strcmp(arch, archi_table[i].long_archi) == 0)
2005 return (archi_table[i].version);
2011 /********************************************************************
2012 * _spoolss_deleteprinterdriver
2013 ********************************************************************/
2015 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2019 NT_PRINTER_DRIVER_INFO_LEVEL info;
2020 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2022 struct current_user user;
2024 WERROR status_win2k = WERR_ACCESS_DENIED;
2026 get_current_user(&user, p);
2028 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2029 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2031 /* check that we have a valid driver name first */
2033 if ((version=get_version_id(arch)) == -1)
2034 return WERR_INVALID_ENVIRONMENT;
2037 ZERO_STRUCT(info_win2k);
2039 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2041 /* try for Win2k driver if "Windows NT x86" */
2043 if ( version == 2 ) {
2045 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2046 status = WERR_UNKNOWN_PRINTER_DRIVER;
2050 /* otherwise it was a failure */
2052 status = WERR_UNKNOWN_PRINTER_DRIVER;
2058 if (printer_driver_in_use(info.info_3)) {
2059 status = WERR_PRINTER_DRIVER_IN_USE;
2065 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2067 /* if we get to here, we now have 2 driver info structures to remove */
2068 /* remove the Win2k driver first*/
2070 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2071 free_a_printer_driver( info_win2k, 3 );
2073 /* this should not have failed---if it did, report to client */
2074 if ( !W_ERROR_IS_OK(status_win2k) )
2079 status = delete_printer_driver(info.info_3, &user, version, False);
2081 /* if at least one of the deletes succeeded return OK */
2083 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2087 free_a_printer_driver( info, 3 );
2092 /********************************************************************
2093 * spoolss_deleteprinterdriverex
2094 ********************************************************************/
2096 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2100 NT_PRINTER_DRIVER_INFO_LEVEL info;
2101 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2103 uint32 flags = q_u->delete_flags;
2105 struct current_user user;
2107 WERROR status_win2k = WERR_ACCESS_DENIED;
2109 get_current_user(&user, p);
2111 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2112 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2114 /* check that we have a valid driver name first */
2115 if ((version=get_version_id(arch)) == -1) {
2116 /* this is what NT returns */
2117 return WERR_INVALID_ENVIRONMENT;
2120 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2121 version = q_u->version;
2124 ZERO_STRUCT(info_win2k);
2126 status = get_a_printer_driver(&info, 3, driver, arch, version);
2128 if ( !W_ERROR_IS_OK(status) )
2131 * if the client asked for a specific version,
2132 * or this is something other than Windows NT x86,
2136 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2139 /* try for Win2k driver if "Windows NT x86" */
2142 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2143 status = WERR_UNKNOWN_PRINTER_DRIVER;
2148 if ( printer_driver_in_use(info.info_3) ) {
2149 status = WERR_PRINTER_DRIVER_IN_USE;
2154 * we have a couple of cases to consider.
2155 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2156 * then the delete should fail if **any** files overlap with
2158 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2159 * non-overlapping files
2160 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2161 * is set, the do not delete any files
2162 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2165 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2167 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2169 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2170 /* no idea of the correct error here */
2171 status = WERR_ACCESS_DENIED;
2176 /* also check for W32X86/3 if necessary; maybe we already have? */
2178 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2179 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2182 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2183 /* no idea of the correct error here */
2184 free_a_printer_driver( info_win2k, 3 );
2185 status = WERR_ACCESS_DENIED;
2189 /* if we get to here, we now have 2 driver info structures to remove */
2190 /* remove the Win2k driver first*/
2192 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2193 free_a_printer_driver( info_win2k, 3 );
2195 /* this should not have failed---if it did, report to client */
2197 if ( !W_ERROR_IS_OK(status_win2k) )
2202 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2204 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2207 free_a_printer_driver( info, 3 );
2213 /****************************************************************************
2214 Internal routine for retreiving printerdata
2215 ***************************************************************************/
2217 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2218 const char *key, const char *value, uint32 *type, uint8 **data,
2219 uint32 *needed, uint32 in_size )
2221 REGISTRY_VALUE *val;
2224 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2225 return WERR_BADFILE;
2227 *type = regval_type( val );
2229 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2231 size = regval_size( val );
2233 /* copy the min(in_size, len) */
2236 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2238 /* special case for 0 length values */
2240 if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
2244 if ( (*data = (uint8 *)talloc_zero(ctx, in_size)) == NULL )
2253 DEBUG(5,("get_printer_dataex: copy done\n"));
2258 /****************************************************************************
2259 Internal routine for removing printerdata
2260 ***************************************************************************/
2262 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2264 return delete_printer_data( printer->info_2, key, value );
2267 /****************************************************************************
2268 Internal routine for storing printerdata
2269 ***************************************************************************/
2271 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2272 uint32 type, uint8 *data, int real_len )
2274 delete_printer_data( printer->info_2, key, value );
2276 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2279 /********************************************************************
2280 GetPrinterData on a printer server Handle.
2281 ********************************************************************/
2283 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2287 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2289 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2291 if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
2297 if (!StrCaseCmp(value, "BeepEnabled")) {
2299 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2301 SIVAL(*data, 0, 0x00);
2306 if (!StrCaseCmp(value, "EventLog")) {
2308 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2310 /* formally was 0x1b */
2311 SIVAL(*data, 0, 0x0);
2316 if (!StrCaseCmp(value, "NetPopup")) {
2318 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2320 SIVAL(*data, 0, 0x00);
2325 if (!StrCaseCmp(value, "MajorVersion")) {
2327 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2330 /* Windows NT 4.0 seems to not allow uploading of drivers
2331 to a server that reports 0x3 as the MajorVersion.
2332 need to investigate more how Win2k gets around this .
2335 if ( RA_WINNT == get_remote_arch() )
2344 if (!StrCaseCmp(value, "MinorVersion")) {
2346 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2354 * uint32 size = 0x114
2356 * uint32 minor = [0|1]
2357 * uint32 build = [2195|2600]
2358 * extra unicode string = e.g. "Service Pack 3"
2360 if (!StrCaseCmp(value, "OSVersion")) {
2364 if((*data = (uint8 *)talloc(ctx, (*needed)*sizeof(uint8) )) == NULL)
2366 ZERO_STRUCTP( *data );
2368 SIVAL(*data, 0, *needed); /* size */
2369 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2371 SIVAL(*data, 12, 2195); /* build */
2373 /* leave extra string empty */
2379 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2380 const char *string="C:\\PRINTERS";
2382 *needed = 2*(strlen(string)+1);
2383 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2385 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2387 /* it's done by hand ready to go on the wire */
2388 for (i=0; i<strlen(string); i++) {
2389 (*data)[2*i]=string[i];
2390 (*data)[2*i+1]='\0';
2395 if (!StrCaseCmp(value, "Architecture")) {
2396 const char *string="Windows NT x86";
2398 *needed = 2*(strlen(string)+1);
2399 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2401 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2402 for (i=0; i<strlen(string); i++) {
2403 (*data)[2*i]=string[i];
2404 (*data)[2*i+1]='\0';
2409 if (!StrCaseCmp(value, "DsPresent")) {
2411 if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
2413 SIVAL(*data, 0, 0x01);
2418 if (!StrCaseCmp(value, "DNSMachineName")) {
2421 if (!get_mydnsfullname(hostname))
2422 return WERR_BADFILE;
2424 *needed = 2*(strlen(hostname)+1);
2425 if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
2427 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2428 for (i=0; i<strlen(hostname); i++) {
2429 (*data)[2*i]=hostname[i];
2430 (*data)[2*i+1]='\0';
2436 return WERR_BADFILE;
2439 /********************************************************************
2440 * spoolss_getprinterdata
2441 ********************************************************************/
2443 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2445 POLICY_HND *handle = &q_u->handle;
2446 UNISTR2 *valuename = &q_u->valuename;
2447 uint32 in_size = q_u->size;
2448 uint32 *type = &r_u->type;
2449 uint32 *out_size = &r_u->size;
2450 uint8 **data = &r_u->data;
2451 uint32 *needed = &r_u->needed;
2454 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2455 NT_PRINTER_INFO_LEVEL *printer = NULL;
2459 * Reminder: when it's a string, the length is in BYTES
2460 * even if UNICODE is negociated.
2465 *out_size = in_size;
2467 /* in case of problem, return some default values */
2472 DEBUG(4,("_spoolss_getprinterdata\n"));
2475 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2476 status = WERR_BADFID;
2480 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2482 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2483 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2486 if ( !get_printer_snum(p,handle, &snum) ) {
2487 status = WERR_BADFID;
2491 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2492 if ( !W_ERROR_IS_OK(status) )
2495 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2497 if ( strequal(value, "ChangeId") ) {
2499 *needed = sizeof(uint32);
2500 if ( (*data = (uint8*)talloc(p->mem_ctx, sizeof(uint32))) == NULL) {
2501 status = WERR_NOMEM;
2504 SIVAL( *data, 0, printer->info_2->changeid );
2508 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2511 if (*needed > *out_size)
2512 status = WERR_MORE_DATA;
2515 if ( !W_ERROR_IS_OK(status) )
2517 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2519 /* reply this param doesn't exist */
2522 if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
2524 free_a_printer( &printer, 2 );
2533 /* cleanup & exit */
2536 free_a_printer( &printer, 2 );
2541 /*********************************************************
2542 Connect to the client machine.
2543 **********************************************************/
2545 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2546 struct in_addr *client_ip, const char *remote_machine)
2548 ZERO_STRUCTP(the_cli);
2550 if(cli_initialise(the_cli) == NULL) {
2551 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2555 if ( is_zero_ip(*client_ip) ) {
2556 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2557 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2558 cli_shutdown(the_cli);
2562 if (ismyip(the_cli->dest_ip)) {
2563 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2564 cli_shutdown(the_cli);
2569 the_cli->dest_ip.s_addr = client_ip->s_addr;
2570 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2571 inet_ntoa(*client_ip) ));
2574 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2575 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) ));
2576 cli_shutdown(the_cli);
2580 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2581 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2583 cli_shutdown(the_cli);
2587 the_cli->protocol = PROTOCOL_NT1;
2588 cli_setup_signing_state(the_cli, lp_client_signing());
2590 if (!cli_negprot(the_cli)) {
2591 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2592 cli_shutdown(the_cli);
2596 if (the_cli->protocol != PROTOCOL_NT1) {
2597 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2598 cli_shutdown(the_cli);
2603 * Do an anonymous session setup.
2606 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2607 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2608 cli_shutdown(the_cli);
2612 if (!(the_cli->sec_mode & 1)) {
2613 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2614 cli_shutdown(the_cli);
2618 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2619 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) ));
2620 cli_shutdown(the_cli);
2625 * Ok - we have an anonymous connection to the IPC$ share.
2626 * Now start the NT Domain stuff :-).
2629 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2630 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)));
2631 cli_nt_session_close(the_cli);
2632 cli_ulogoff(the_cli);
2633 cli_shutdown(the_cli);
2640 /***************************************************************************
2641 Connect to the client.
2642 ****************************************************************************/
2644 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2645 uint32 localprinter, uint32 type,
2646 POLICY_HND *handle, struct in_addr *client_ip)
2651 * If it's the first connection, contact the client
2652 * and connect to the IPC$ share anonymously
2654 if (smb_connections==0) {
2655 fstring unix_printer;
2657 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2659 ZERO_STRUCT(notify_cli);
2661 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2664 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2665 /* Tell the connections db we're now interested in printer
2666 * notify messages. */
2667 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2671 * Tell the specific printing tdb we want messages for this printer
2672 * by registering our PID.
2675 if (!print_notify_register_pid(snum))
2676 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2680 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2683 if (!W_ERROR_IS_OK(result))
2684 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2685 dos_errstr(result)));
2687 return (W_ERROR_IS_OK(result));
2690 /********************************************************************
2692 * ReplyFindFirstPrinterChangeNotifyEx
2694 * before replying OK: status=0 a rpc call is made to the workstation
2695 * asking ReplyOpenPrinter
2697 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2698 * called from api_spoolss_rffpcnex
2699 ********************************************************************/
2701 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2703 POLICY_HND *handle = &q_u->handle;
2704 uint32 flags = q_u->flags;
2705 uint32 options = q_u->options;
2706 UNISTR2 *localmachine = &q_u->localmachine;
2707 uint32 printerlocal = q_u->printerlocal;
2709 SPOOL_NOTIFY_OPTION *option = q_u->option;
2710 struct in_addr client_ip;
2712 /* store the notify value in the printer struct */
2714 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2717 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2721 Printer->notify.flags=flags;
2722 Printer->notify.options=options;
2723 Printer->notify.printerlocal=printerlocal;
2725 if (Printer->notify.option)
2726 free_spool_notify_option(&Printer->notify.option);
2728 Printer->notify.option=dup_spool_notify_option(option);
2730 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2731 sizeof(Printer->notify.localmachine)-1);
2733 /* Connect to the client machine and send a ReplyOpenPrinter */
2735 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2737 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2738 !get_printer_snum(p, handle, &snum) )
2741 client_ip.s_addr = inet_addr(p->conn->client_address);
2743 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2744 Printer->notify.printerlocal, 1,
2745 &Printer->notify.client_hnd, &client_ip))
2746 return WERR_SERVER_UNAVAILABLE;
2748 Printer->notify.client_connected=True;
2753 /*******************************************************************
2754 * fill a notify_info_data with the servername
2755 ********************************************************************/
2757 void spoolss_notify_server_name(int snum,
2758 SPOOL_NOTIFY_INFO_DATA *data,
2759 print_queue_struct *queue,
2760 NT_PRINTER_INFO_LEVEL *printer,
2761 TALLOC_CTX *mem_ctx)
2766 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2768 data->notify_data.data.length = len;
2769 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2771 if (!data->notify_data.data.string) {
2772 data->notify_data.data.length = 0;
2776 memcpy(data->notify_data.data.string, temp, len);
2779 /*******************************************************************
2780 * fill a notify_info_data with the printername (not including the servername).
2781 ********************************************************************/
2783 void spoolss_notify_printer_name(int snum,
2784 SPOOL_NOTIFY_INFO_DATA *data,
2785 print_queue_struct *queue,
2786 NT_PRINTER_INFO_LEVEL *printer,
2787 TALLOC_CTX *mem_ctx)
2792 /* the notify name should not contain the \\server\ part */
2793 char *p = strrchr(printer->info_2->printername, '\\');
2796 p = printer->info_2->printername;
2801 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2803 data->notify_data.data.length = len;
2804 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2806 if (!data->notify_data.data.string) {
2807 data->notify_data.data.length = 0;
2811 memcpy(data->notify_data.data.string, temp, len);
2814 /*******************************************************************
2815 * fill a notify_info_data with the servicename
2816 ********************************************************************/
2818 void spoolss_notify_share_name(int snum,
2819 SPOOL_NOTIFY_INFO_DATA *data,
2820 print_queue_struct *queue,
2821 NT_PRINTER_INFO_LEVEL *printer,
2822 TALLOC_CTX *mem_ctx)
2827 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2829 data->notify_data.data.length = len;
2830 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2832 if (!data->notify_data.data.string) {
2833 data->notify_data.data.length = 0;
2837 memcpy(data->notify_data.data.string, temp, len);
2840 /*******************************************************************
2841 * fill a notify_info_data with the port name
2842 ********************************************************************/
2844 void spoolss_notify_port_name(int snum,
2845 SPOOL_NOTIFY_INFO_DATA *data,
2846 print_queue_struct *queue,
2847 NT_PRINTER_INFO_LEVEL *printer,
2848 TALLOC_CTX *mem_ctx)
2853 /* even if it's strange, that's consistant in all the code */
2855 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2857 data->notify_data.data.length = len;
2858 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2860 if (!data->notify_data.data.string) {
2861 data->notify_data.data.length = 0;
2865 memcpy(data->notify_data.data.string, temp, len);
2868 /*******************************************************************
2869 * fill a notify_info_data with the printername
2870 * but it doesn't exist, have to see what to do
2871 ********************************************************************/
2873 void spoolss_notify_driver_name(int snum,
2874 SPOOL_NOTIFY_INFO_DATA *data,
2875 print_queue_struct *queue,
2876 NT_PRINTER_INFO_LEVEL *printer,
2877 TALLOC_CTX *mem_ctx)
2882 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2884 data->notify_data.data.length = len;
2885 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2887 if (!data->notify_data.data.string) {
2888 data->notify_data.data.length = 0;
2892 memcpy(data->notify_data.data.string, temp, len);
2895 /*******************************************************************
2896 * fill a notify_info_data with the comment
2897 ********************************************************************/
2899 void spoolss_notify_comment(int snum,
2900 SPOOL_NOTIFY_INFO_DATA *data,
2901 print_queue_struct *queue,
2902 NT_PRINTER_INFO_LEVEL *printer,
2903 TALLOC_CTX *mem_ctx)
2908 if (*printer->info_2->comment == '\0')
2909 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2911 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2913 data->notify_data.data.length = len;
2914 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2916 if (!data->notify_data.data.string) {
2917 data->notify_data.data.length = 0;
2921 memcpy(data->notify_data.data.string, temp, len);
2924 /*******************************************************************
2925 * fill a notify_info_data with the comment
2926 * location = "Room 1, floor 2, building 3"
2927 ********************************************************************/
2929 void spoolss_notify_location(int snum,
2930 SPOOL_NOTIFY_INFO_DATA *data,
2931 print_queue_struct *queue,
2932 NT_PRINTER_INFO_LEVEL *printer,
2933 TALLOC_CTX *mem_ctx)
2938 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2940 data->notify_data.data.length = len;
2941 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2943 if (!data->notify_data.data.string) {
2944 data->notify_data.data.length = 0;
2948 memcpy(data->notify_data.data.string, temp, len);
2951 /*******************************************************************
2952 * fill a notify_info_data with the device mode
2953 * jfm:xxxx don't to it for know but that's a real problem !!!
2954 ********************************************************************/
2956 static void spoolss_notify_devmode(int snum,
2957 SPOOL_NOTIFY_INFO_DATA *data,
2958 print_queue_struct *queue,
2959 NT_PRINTER_INFO_LEVEL *printer,
2960 TALLOC_CTX *mem_ctx)
2964 /*******************************************************************
2965 * fill a notify_info_data with the separator file name
2966 ********************************************************************/
2968 void spoolss_notify_sepfile(int snum,
2969 SPOOL_NOTIFY_INFO_DATA *data,
2970 print_queue_struct *queue,
2971 NT_PRINTER_INFO_LEVEL *printer,
2972 TALLOC_CTX *mem_ctx)
2977 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2979 data->notify_data.data.length = len;
2980 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
2982 if (!data->notify_data.data.string) {
2983 data->notify_data.data.length = 0;
2987 memcpy(data->notify_data.data.string, temp, len);
2990 /*******************************************************************
2991 * fill a notify_info_data with the print processor
2992 * jfm:xxxx return always winprint to indicate we don't do anything to it
2993 ********************************************************************/
2995 void spoolss_notify_print_processor(int snum,
2996 SPOOL_NOTIFY_INFO_DATA *data,
2997 print_queue_struct *queue,
2998 NT_PRINTER_INFO_LEVEL *printer,
2999 TALLOC_CTX *mem_ctx)
3004 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3006 data->notify_data.data.length = len;
3007 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3009 if (!data->notify_data.data.string) {
3010 data->notify_data.data.length = 0;
3014 memcpy(data->notify_data.data.string, temp, len);
3017 /*******************************************************************
3018 * fill a notify_info_data with the print processor options
3019 * jfm:xxxx send an empty string
3020 ********************************************************************/
3022 void spoolss_notify_parameters(int snum,
3023 SPOOL_NOTIFY_INFO_DATA *data,
3024 print_queue_struct *queue,
3025 NT_PRINTER_INFO_LEVEL *printer,
3026 TALLOC_CTX *mem_ctx)
3031 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3033 data->notify_data.data.length = len;
3034 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3036 if (!data->notify_data.data.string) {
3037 data->notify_data.data.length = 0;
3041 memcpy(data->notify_data.data.string, temp, len);
3044 /*******************************************************************
3045 * fill a notify_info_data with the data type
3046 * jfm:xxxx always send RAW as data type
3047 ********************************************************************/
3049 void spoolss_notify_datatype(int snum,
3050 SPOOL_NOTIFY_INFO_DATA *data,
3051 print_queue_struct *queue,
3052 NT_PRINTER_INFO_LEVEL *printer,
3053 TALLOC_CTX *mem_ctx)
3058 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3060 data->notify_data.data.length = len;
3061 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3063 if (!data->notify_data.data.string) {
3064 data->notify_data.data.length = 0;
3068 memcpy(data->notify_data.data.string, temp, len);
3071 /*******************************************************************
3072 * fill a notify_info_data with the security descriptor
3073 * jfm:xxxx send an null pointer to say no security desc
3074 * have to implement security before !
3075 ********************************************************************/
3077 static void spoolss_notify_security_desc(int snum,
3078 SPOOL_NOTIFY_INFO_DATA *data,
3079 print_queue_struct *queue,
3080 NT_PRINTER_INFO_LEVEL *printer,
3081 TALLOC_CTX *mem_ctx)
3083 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3084 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3087 /*******************************************************************
3088 * fill a notify_info_data with the attributes
3089 * jfm:xxxx a samba printer is always shared
3090 ********************************************************************/
3092 void spoolss_notify_attributes(int snum,
3093 SPOOL_NOTIFY_INFO_DATA *data,
3094 print_queue_struct *queue,
3095 NT_PRINTER_INFO_LEVEL *printer,
3096 TALLOC_CTX *mem_ctx)
3098 data->notify_data.value[0] = printer->info_2->attributes;
3099 data->notify_data.value[1] = 0;
3102 /*******************************************************************
3103 * fill a notify_info_data with the priority
3104 ********************************************************************/
3106 static void spoolss_notify_priority(int snum,
3107 SPOOL_NOTIFY_INFO_DATA *data,
3108 print_queue_struct *queue,
3109 NT_PRINTER_INFO_LEVEL *printer,
3110 TALLOC_CTX *mem_ctx)
3112 data->notify_data.value[0] = printer->info_2->priority;
3113 data->notify_data.value[1] = 0;
3116 /*******************************************************************
3117 * fill a notify_info_data with the default priority
3118 ********************************************************************/
3120 static void spoolss_notify_default_priority(int snum,
3121 SPOOL_NOTIFY_INFO_DATA *data,
3122 print_queue_struct *queue,
3123 NT_PRINTER_INFO_LEVEL *printer,
3124 TALLOC_CTX *mem_ctx)
3126 data->notify_data.value[0] = printer->info_2->default_priority;
3127 data->notify_data.value[1] = 0;
3130 /*******************************************************************
3131 * fill a notify_info_data with the start time
3132 ********************************************************************/
3134 static void spoolss_notify_start_time(int snum,
3135 SPOOL_NOTIFY_INFO_DATA *data,
3136 print_queue_struct *queue,
3137 NT_PRINTER_INFO_LEVEL *printer,
3138 TALLOC_CTX *mem_ctx)
3140 data->notify_data.value[0] = printer->info_2->starttime;
3141 data->notify_data.value[1] = 0;
3144 /*******************************************************************
3145 * fill a notify_info_data with the until time
3146 ********************************************************************/
3148 static void spoolss_notify_until_time(int snum,
3149 SPOOL_NOTIFY_INFO_DATA *data,
3150 print_queue_struct *queue,
3151 NT_PRINTER_INFO_LEVEL *printer,
3152 TALLOC_CTX *mem_ctx)
3154 data->notify_data.value[0] = printer->info_2->untiltime;
3155 data->notify_data.value[1] = 0;
3158 /*******************************************************************
3159 * fill a notify_info_data with the status
3160 ********************************************************************/
3162 static void spoolss_notify_status(int snum,
3163 SPOOL_NOTIFY_INFO_DATA *data,
3164 print_queue_struct *queue,
3165 NT_PRINTER_INFO_LEVEL *printer,
3166 TALLOC_CTX *mem_ctx)
3168 print_status_struct status;
3170 print_queue_length(snum, &status);
3171 data->notify_data.value[0]=(uint32) status.status;
3172 data->notify_data.value[1] = 0;
3175 /*******************************************************************
3176 * fill a notify_info_data with the number of jobs queued
3177 ********************************************************************/
3179 void spoolss_notify_cjobs(int snum,
3180 SPOOL_NOTIFY_INFO_DATA *data,
3181 print_queue_struct *queue,
3182 NT_PRINTER_INFO_LEVEL *printer,
3183 TALLOC_CTX *mem_ctx)
3185 data->notify_data.value[0] = print_queue_length(snum, NULL);
3186 data->notify_data.value[1] = 0;
3189 /*******************************************************************
3190 * fill a notify_info_data with the average ppm
3191 ********************************************************************/
3193 static void spoolss_notify_average_ppm(int snum,
3194 SPOOL_NOTIFY_INFO_DATA *data,
3195 print_queue_struct *queue,
3196 NT_PRINTER_INFO_LEVEL *printer,
3197 TALLOC_CTX *mem_ctx)
3199 /* always respond 8 pages per minutes */
3200 /* a little hard ! */
3201 data->notify_data.value[0] = printer->info_2->averageppm;
3202 data->notify_data.value[1] = 0;
3205 /*******************************************************************
3206 * fill a notify_info_data with username
3207 ********************************************************************/
3209 static void spoolss_notify_username(int snum,
3210 SPOOL_NOTIFY_INFO_DATA *data,
3211 print_queue_struct *queue,
3212 NT_PRINTER_INFO_LEVEL *printer,
3213 TALLOC_CTX *mem_ctx)
3218 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3220 data->notify_data.data.length = len;
3221 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3223 if (!data->notify_data.data.string) {
3224 data->notify_data.data.length = 0;
3228 memcpy(data->notify_data.data.string, temp, len);
3231 /*******************************************************************
3232 * fill a notify_info_data with job status
3233 ********************************************************************/
3235 static void spoolss_notify_job_status(int snum,
3236 SPOOL_NOTIFY_INFO_DATA *data,
3237 print_queue_struct *queue,
3238 NT_PRINTER_INFO_LEVEL *printer,
3239 TALLOC_CTX *mem_ctx)
3241 data->notify_data.value[0]=nt_printj_status(queue->status);
3242 data->notify_data.value[1] = 0;
3245 /*******************************************************************
3246 * fill a notify_info_data with job name
3247 ********************************************************************/
3249 static void spoolss_notify_job_name(int snum,
3250 SPOOL_NOTIFY_INFO_DATA *data,
3251 print_queue_struct *queue,
3252 NT_PRINTER_INFO_LEVEL *printer,
3253 TALLOC_CTX *mem_ctx)
3258 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3260 data->notify_data.data.length = len;
3261 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3263 if (!data->notify_data.data.string) {
3264 data->notify_data.data.length = 0;
3268 memcpy(data->notify_data.data.string, temp, len);
3271 /*******************************************************************
3272 * fill a notify_info_data with job status
3273 ********************************************************************/
3275 static void spoolss_notify_job_status_string(int snum,
3276 SPOOL_NOTIFY_INFO_DATA *data,
3277 print_queue_struct *queue,
3278 NT_PRINTER_INFO_LEVEL *printer,
3279 TALLOC_CTX *mem_ctx)
3282 * Now we're returning job status codes we just return a "" here. JRA.
3289 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3292 switch (queue->status) {
3297 p = ""; /* NT provides the paused string */
3306 #endif /* NO LONGER NEEDED. */
3308 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3310 data->notify_data.data.length = len;
3311 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3313 if (!data->notify_data.data.string) {
3314 data->notify_data.data.length = 0;
3318 memcpy(data->notify_data.data.string, temp, len);
3321 /*******************************************************************
3322 * fill a notify_info_data with job time
3323 ********************************************************************/
3325 static void spoolss_notify_job_time(int snum,
3326 SPOOL_NOTIFY_INFO_DATA *data,
3327 print_queue_struct *queue,
3328 NT_PRINTER_INFO_LEVEL *printer,
3329 TALLOC_CTX *mem_ctx)
3331 data->notify_data.value[0]=0x0;
3332 data->notify_data.value[1]=0;
3335 /*******************************************************************
3336 * fill a notify_info_data with job size
3337 ********************************************************************/
3339 static void spoolss_notify_job_size(int snum,
3340 SPOOL_NOTIFY_INFO_DATA *data,
3341 print_queue_struct *queue,
3342 NT_PRINTER_INFO_LEVEL *printer,
3343 TALLOC_CTX *mem_ctx)
3345 data->notify_data.value[0]=queue->size;
3346 data->notify_data.value[1]=0;
3349 /*******************************************************************
3350 * fill a notify_info_data with page info
3351 ********************************************************************/
3352 static void spoolss_notify_total_pages(int snum,
3353 SPOOL_NOTIFY_INFO_DATA *data,
3354 print_queue_struct *queue,
3355 NT_PRINTER_INFO_LEVEL *printer,
3356 TALLOC_CTX *mem_ctx)
3358 data->notify_data.value[0]=queue->page_count;
3359 data->notify_data.value[1]=0;
3362 /*******************************************************************
3363 * fill a notify_info_data with pages printed info.
3364 ********************************************************************/
3365 static void spoolss_notify_pages_printed(int snum,
3366 SPOOL_NOTIFY_INFO_DATA *data,
3367 print_queue_struct *queue,
3368 NT_PRINTER_INFO_LEVEL *printer,
3369 TALLOC_CTX *mem_ctx)
3371 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3372 data->notify_data.value[1]=0;
3375 /*******************************************************************
3376 Fill a notify_info_data with job position.
3377 ********************************************************************/
3379 static void spoolss_notify_job_position(int snum,
3380 SPOOL_NOTIFY_INFO_DATA *data,
3381 print_queue_struct *queue,
3382 NT_PRINTER_INFO_LEVEL *printer,
3383 TALLOC_CTX *mem_ctx)
3385 data->notify_data.value[0]=queue->job;
3386 data->notify_data.value[1]=0;
3389 /*******************************************************************
3390 Fill a notify_info_data with submitted time.
3391 ********************************************************************/
3393 static void spoolss_notify_submitted_time(int snum,
3394 SPOOL_NOTIFY_INFO_DATA *data,
3395 print_queue_struct *queue,
3396 NT_PRINTER_INFO_LEVEL *printer,
3397 TALLOC_CTX *mem_ctx)
3404 t=gmtime(&queue->time);
3406 len = sizeof(SYSTEMTIME);
3408 data->notify_data.data.length = len;
3409 data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
3411 if (!data->notify_data.data.string) {
3412 data->notify_data.data.length = 0;
3416 make_systemtime(&st, t);
3419 * Systemtime must be linearized as a set of UINT16's.
3420 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3423 p = (char *)data->notify_data.data.string;
3424 SSVAL(p, 0, st.year);
3425 SSVAL(p, 2, st.month);
3426 SSVAL(p, 4, st.dayofweek);
3427 SSVAL(p, 6, st.day);
3428 SSVAL(p, 8, st.hour);
3429 SSVAL(p, 10, st.minute);
3430 SSVAL(p, 12, st.second);
3431 SSVAL(p, 14, st.milliseconds);
3434 struct s_notify_info_data_table
3440 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3441 print_queue_struct *queue,
3442 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3445 /* A table describing the various print notification constants and
3446 whether the notification data is a pointer to a variable sized
3447 buffer, a one value uint32 or a two value uint32. */
3449 static const struct s_notify_info_data_table notify_info_data_table[] =
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3473 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3474 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3475 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3476 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3496 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3497 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3498 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3499 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3500 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3503 /*******************************************************************
3504 Return the size of info_data structure.
3505 ********************************************************************/
3507 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3511 for (i = 0; i < sizeof(notify_info_data_table); i++)
3513 if ( (notify_info_data_table[i].type == type)
3514 && (notify_info_data_table[i].field == field) )
3516 switch(notify_info_data_table[i].size)
3518 case NOTIFY_ONE_VALUE:
3519 case NOTIFY_TWO_VALUE:
3524 /* The only pointer notify data I have seen on
3525 the wire is the submitted time and this has
3526 the notify size set to 4. -tpot */
3528 case NOTIFY_POINTER:
3531 case NOTIFY_SECDESC:
3537 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3542 /*******************************************************************
3543 Return the type of notify_info_data.
3544 ********************************************************************/
3546 static int type_of_notify_info_data(uint16 type, uint16 field)
3550 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3551 if (notify_info_data_table[i].type == type &&
3552 notify_info_data_table[i].field == field)
3553 return notify_info_data_table[i].size;
3559 /****************************************************************************
3560 ****************************************************************************/
3562 static int search_notify(uint16 type, uint16 field, int *value)
3566 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3567 if (notify_info_data_table[i].type == type &&
3568 notify_info_data_table[i].field == field &&
3569 notify_info_data_table[i].fn != NULL) {
3578 /****************************************************************************
3579 ****************************************************************************/
3581 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3583 info_data->type = type;
3584 info_data->field = field;
3585 info_data->reserved = 0;
3587 info_data->size = size_of_notify_info_data(type, field);
3588 info_data->enc_type = type_of_notify_info_data(type, field);
3595 /*******************************************************************
3597 * fill a notify_info struct with info asked
3599 ********************************************************************/
3601 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3602 snum, SPOOL_NOTIFY_OPTION_TYPE
3603 *option_type, uint32 id,
3604 TALLOC_CTX *mem_ctx)
3610 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3611 NT_PRINTER_INFO_LEVEL *printer = NULL;
3612 print_queue_struct *queue=NULL;
3614 type=option_type->type;
3616 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3617 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3618 option_type->count, lp_servicename(snum)));
3620 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3623 for(field_num=0; field_num<option_type->count; field_num++) {
3624 field = option_type->fields[field_num];
3626 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3628 if (!search_notify(type, field, &j) )
3631 if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3632 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3637 current_data = &info->data[info->count];
3639 construct_info_data(current_data, type, field, id);
3641 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3642 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3644 notify_info_data_table[j].fn(snum, current_data, queue,
3650 free_a_printer(&printer, 2);
3654 /*******************************************************************
3656 * fill a notify_info struct with info asked
3658 ********************************************************************/
3660 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3661 SPOOL_NOTIFY_INFO *info,
3662 NT_PRINTER_INFO_LEVEL *printer,
3663 int snum, SPOOL_NOTIFY_OPTION_TYPE
3664 *option_type, uint32 id,
3665 TALLOC_CTX *mem_ctx)
3671 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3673 DEBUG(4,("construct_notify_jobs_info\n"));
3675 type = option_type->type;
3677 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3678 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3679 option_type->count));
3681 for(field_num=0; field_num<option_type->count; field_num++) {
3682 field = option_type->fields[field_num];
3684 if (!search_notify(type, field, &j) )
3687 if((tid=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
3688 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3691 else info->data = tid;
3693 current_data=&(info->data[info->count]);
3695 construct_info_data(current_data, type, field, id);
3696 notify_info_data_table[j].fn(snum, current_data, queue,
3705 * JFM: The enumeration is not that simple, it's even non obvious.
3707 * let's take an example: I want to monitor the PRINTER SERVER for
3708 * the printer's name and the number of jobs currently queued.
3709 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3710 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3712 * I have 3 printers on the back of my server.
3714 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3717 * 1 printer 1 name 1
3718 * 2 printer 1 cjob 1
3719 * 3 printer 2 name 2
3720 * 4 printer 2 cjob 2
3721 * 5 printer 3 name 3
3722 * 6 printer 3 name 3
3724 * that's the print server case, the printer case is even worse.
3727 /*******************************************************************
3729 * enumerate all printers on the printserver
3730 * fill a notify_info struct with info asked
3732 ********************************************************************/
3734 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3735 SPOOL_NOTIFY_INFO *info,
3736 TALLOC_CTX *mem_ctx)
3739 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3740 int n_services=lp_numservices();
3742 SPOOL_NOTIFY_OPTION *option;
3743 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3745 DEBUG(4,("printserver_notify_info\n"));
3750 option=Printer->notify.option;
3755 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3756 sending a ffpcn() request first */
3761 for (i=0; i<option->count; i++) {
3762 option_type=&(option->ctr.type[i]);
3764 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3767 for (snum=0; snum<n_services; snum++)
3769 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3770 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3776 * Debugging information, don't delete.
3779 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3780 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3781 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3783 for (i=0; i<info->count; i++) {
3784 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3785 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3786 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3793 /*******************************************************************
3795 * fill a notify_info struct with info asked
3797 ********************************************************************/
3799 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3800 TALLOC_CTX *mem_ctx)
3803 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3806 SPOOL_NOTIFY_OPTION *option;
3807 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3809 print_queue_struct *queue=NULL;
3810 print_status_struct status;
3812 DEBUG(4,("printer_notify_info\n"));
3817 option=Printer->notify.option;
3823 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3824 sending a ffpcn() request first */
3829 get_printer_snum(p, hnd, &snum);
3831 for (i=0; i<option->count; i++) {
3832 option_type=&option->ctr.type[i];
3834 switch ( option_type->type ) {
3835 case PRINTER_NOTIFY_TYPE:
3836 if(construct_notify_printer_info(Printer, info, snum,
3842 case JOB_NOTIFY_TYPE: {
3843 NT_PRINTER_INFO_LEVEL *printer = NULL;
3845 count = print_queue_status(snum, &queue, &status);
3847 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3850 for (j=0; j<count; j++) {
3851 construct_notify_jobs_info(&queue[j], info,
3858 free_a_printer(&printer, 2);
3868 * Debugging information, don't delete.
3871 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3872 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3873 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3875 for (i=0; i<info->count; i++) {
3876 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3877 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3878 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3884 /********************************************************************
3886 ********************************************************************/
3888 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3890 POLICY_HND *handle = &q_u->handle;
3891 SPOOL_NOTIFY_INFO *info = &r_u->info;
3893 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3894 WERROR result = WERR_BADFID;
3896 /* we always have a NOTIFY_INFO struct */
3900 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3901 OUR_HANDLE(handle)));
3905 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3908 * We are now using the change value, and
3909 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3910 * I don't have a global notification system, I'm sending back all the
3911 * informations even when _NOTHING_ has changed.
3914 /* We need to keep track of the change value to send back in
3915 RRPCN replies otherwise our updates are ignored. */
3917 Printer->notify.fnpcn = True;
3919 if (Printer->notify.client_connected) {
3920 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3921 Printer->notify.change = q_u->change;
3924 /* just ignore the SPOOL_NOTIFY_OPTION */
3926 switch (Printer->printer_type) {
3927 case PRINTER_HANDLE_IS_PRINTSERVER:
3928 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3931 case PRINTER_HANDLE_IS_PRINTER:
3932 result = printer_notify_info(p, handle, info, p->mem_ctx);
3936 Printer->notify.fnpcn = False;
3942 /********************************************************************
3943 * construct_printer_info_0
3944 * fill a printer_info_0 struct
3945 ********************************************************************/
3947 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3951 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3952 counter_printer_0 *session_counter;
3953 uint32 global_counter;
3956 print_status_struct status;
3958 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3961 count = print_queue_length(snum, &status);
3963 /* check if we already have a counter for this printer */
3964 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3965 if (session_counter->snum == snum)
3969 /* it's the first time, add it to the list */
3970 if (session_counter==NULL) {
3971 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3972 free_a_printer(&ntprinter, 2);
3975 ZERO_STRUCTP(session_counter);
3976 session_counter->snum=snum;
3977 session_counter->counter=0;
3978 DLIST_ADD(counter_list, session_counter);
3982 session_counter->counter++;
3985 * the global_counter should be stored in a TDB as it's common to all the clients
3986 * and should be zeroed on samba startup
3988 global_counter=session_counter->counter;
3990 pstrcpy(chaine,ntprinter->info_2->printername);
3992 init_unistr(&printer->printername, chaine);
3994 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3995 init_unistr(&printer->servername, chaine);
3997 printer->cjobs = count;
3998 printer->total_jobs = 0;
3999 printer->total_bytes = 0;
4001 setuptime = (time_t)ntprinter->info_2->setuptime;
4002 t=gmtime(&setuptime);
4004 printer->year = t->tm_year+1900;
4005 printer->month = t->tm_mon+1;
4006 printer->dayofweek = t->tm_wday;
4007 printer->day = t->tm_mday;
4008 printer->hour = t->tm_hour;
4009 printer->minute = t->tm_min;
4010 printer->second = t->tm_sec;
4011 printer->milliseconds = 0;
4013 printer->global_counter = global_counter;
4014 printer->total_pages = 0;
4016 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4017 printer->major_version = 0x0005; /* NT 5 */
4018 printer->build_version = 0x0893; /* build 2195 */
4020 printer->unknown7 = 0x1;
4021 printer->unknown8 = 0x0;
4022 printer->unknown9 = 0x0;
4023 printer->session_counter = session_counter->counter;
4024 printer->unknown11 = 0x0;
4025 printer->printer_errors = 0x0; /* number of print failure */
4026 printer->unknown13 = 0x0;
4027 printer->unknown14 = 0x1;
4028 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4029 printer->unknown16 = 0x0;
4030 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4031 printer->unknown18 = 0x0;
4032 printer->status = nt_printq_status(status.status);
4033 printer->unknown20 = 0x0;
4034 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4035 printer->unknown22 = 0x0;
4036 printer->unknown23 = 0x6; /* 6 ???*/
4037 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4038 printer->unknown25 = 0;
4039 printer->unknown26 = 0;
4040 printer->unknown27 = 0;
4041 printer->unknown28 = 0;
4042 printer->unknown29 = 0;
4044 free_a_printer(&ntprinter,2);
4048 /********************************************************************
4049 * construct_printer_info_1
4050 * fill a printer_info_1 struct
4051 ********************************************************************/
4052 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4056 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4058 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4061 printer->flags=flags;
4063 if (*ntprinter->info_2->comment == '\0') {
4064 init_unistr(&printer->comment, lp_comment(snum));
4065 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4066 ntprinter->info_2->drivername, lp_comment(snum));
4069 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4070 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4071 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4074 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4076 init_unistr(&printer->description, chaine);
4077 init_unistr(&printer->name, chaine2);
4079 free_a_printer(&ntprinter,2);
4084 /****************************************************************************
4085 Free a DEVMODE struct.
4086 ****************************************************************************/
4088 static void free_dev_mode(DEVICEMODE *dev)
4093 SAFE_FREE(dev->private);
4098 /****************************************************************************
4099 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4100 should be valid upon entry
4101 ****************************************************************************/
4103 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4105 if ( !devmode || !ntdevmode )
4108 init_unistr(&devmode->devicename, ntdevmode->devicename);
4110 init_unistr(&devmode->formname, ntdevmode->formname);
4112 devmode->specversion = ntdevmode->specversion;
4113 devmode->driverversion = ntdevmode->driverversion;
4114 devmode->size = ntdevmode->size;
4115 devmode->driverextra = ntdevmode->driverextra;
4116 devmode->fields = ntdevmode->fields;
4118 devmode->orientation = ntdevmode->orientation;
4119 devmode->papersize = ntdevmode->papersize;
4120 devmode->paperlength = ntdevmode->paperlength;
4121 devmode->paperwidth = ntdevmode->paperwidth;
4122 devmode->scale = ntdevmode->scale;
4123 devmode->copies = ntdevmode->copies;
4124 devmode->defaultsource = ntdevmode->defaultsource;
4125 devmode->printquality = ntdevmode->printquality;
4126 devmode->color = ntdevmode->color;
4127 devmode->duplex = ntdevmode->duplex;
4128 devmode->yresolution = ntdevmode->yresolution;
4129 devmode->ttoption = ntdevmode->ttoption;
4130 devmode->collate = ntdevmode->collate;
4131 devmode->icmmethod = ntdevmode->icmmethod;
4132 devmode->icmintent = ntdevmode->icmintent;
4133 devmode->mediatype = ntdevmode->mediatype;
4134 devmode->dithertype = ntdevmode->dithertype;
4136 if (ntdevmode->private != NULL) {
4137 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4144 /****************************************************************************
4145 Create a DEVMODE struct. Returns malloced memory.
4146 ****************************************************************************/
4148 DEVICEMODE *construct_dev_mode(int snum)
4150 NT_PRINTER_INFO_LEVEL *printer = NULL;
4151 DEVICEMODE *devmode = NULL;
4153 DEBUG(7,("construct_dev_mode\n"));
4155 DEBUGADD(8,("getting printer characteristics\n"));
4157 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4160 if ( !printer->info_2->devmode ) {
4161 DEBUG(5, ("BONG! There was no device mode!\n"));
4165 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4166 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4170 ZERO_STRUCTP(devmode);
4172 DEBUGADD(8,("loading DEVICEMODE\n"));
4174 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4175 free_dev_mode( devmode );
4180 free_a_printer(&printer,2);
4185 /********************************************************************
4186 * construct_printer_info_2
4187 * fill a printer_info_2 struct
4188 ********************************************************************/
4190 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4193 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4195 print_status_struct status;
4197 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4200 count = print_queue_length(snum, &status);
4202 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4203 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4204 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4205 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4206 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4208 if (*ntprinter->info_2->comment == '\0')
4209 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4211 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4213 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4214 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4215 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4216 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4217 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4219 printer->attributes = ntprinter->info_2->attributes;
4221 printer->priority = ntprinter->info_2->priority; /* priority */
4222 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4223 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4224 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4225 printer->status = nt_printq_status(status.status); /* status */
4226 printer->cjobs = count; /* jobs */
4227 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4229 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4230 DEBUG(8, ("Returning NULL Devicemode!\n"));
4233 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4234 /* steal the printer info sec_desc structure. [badly done]. */
4235 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4236 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4237 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4238 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4241 printer->secdesc = NULL;
4244 free_a_printer(&ntprinter, 2);
4248 /********************************************************************
4249 * construct_printer_info_3
4250 * fill a printer_info_3 struct
4251 ********************************************************************/
4253 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4255 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4256 PRINTER_INFO_3 *printer = NULL;
4258 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4262 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4263 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4267 ZERO_STRUCTP(printer);
4269 printer->flags = 4; /* These are the components of the SD we are returning. */
4270 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4271 /* steal the printer info sec_desc structure. [badly done]. */
4272 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4276 * Set the flags for the components we are returning.
4279 if (printer->secdesc->owner_sid)
4280 printer->flags |= OWNER_SECURITY_INFORMATION;
4282 if (printer->secdesc->grp_sid)
4283 printer->flags |= GROUP_SECURITY_INFORMATION;
4285 if (printer->secdesc->dacl)
4286 printer->flags |= DACL_SECURITY_INFORMATION;
4288 if (printer->secdesc->sacl)
4289 printer->flags |= SACL_SECURITY_INFORMATION;
4292 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4293 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4294 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4297 free_a_printer(&ntprinter, 2);
4299 *pp_printer = printer;
4303 /********************************************************************
4304 * construct_printer_info_4
4305 * fill a printer_info_4 struct
4306 ********************************************************************/
4308 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4310 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4312 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4315 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4316 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4317 printer->attributes = ntprinter->info_2->attributes;
4319 free_a_printer(&ntprinter, 2);
4323 /********************************************************************
4324 * construct_printer_info_5
4325 * fill a printer_info_5 struct
4326 ********************************************************************/
4328 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4330 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4332 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4335 init_unistr(&printer->printername, ntprinter->info_2->printername);
4336 init_unistr(&printer->portname, ntprinter->info_2->portname);
4337 printer->attributes = ntprinter->info_2->attributes;
4339 /* these two are not used by NT+ according to MSDN */
4341 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4342 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4344 free_a_printer(&ntprinter, 2);
4349 /********************************************************************
4350 * construct_printer_info_7
4351 * fill a printer_info_7 struct
4352 ********************************************************************/
4354 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4356 char *guid_str = NULL;
4359 if (is_printer_published(print_hnd, snum, &guid)) {
4360 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4361 strupper_m(guid_str);
4362 init_unistr(&printer->guid, guid_str);
4363 printer->action = SPOOL_DS_PUBLISH;
4365 init_unistr(&printer->guid, "");
4366 printer->action = SPOOL_DS_UNPUBLISH;
4372 /********************************************************************
4373 Spoolss_enumprinters.
4374 ********************************************************************/
4376 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4380 int n_services=lp_numservices();
4381 PRINTER_INFO_1 *tp, *printers=NULL;
4382 PRINTER_INFO_1 current_prt;
4384 DEBUG(4,("enum_all_printers_info_1\n"));
4386 for (snum=0; snum<n_services; snum++) {
4387 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4388 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4390 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4391 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4392 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4393 SAFE_FREE(printers);
4398 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4400 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4406 /* check the required size. */
4407 for (i=0; i<*returned; i++)
4408 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4410 if (!alloc_buffer_size(buffer, *needed))
4411 return WERR_INSUFFICIENT_BUFFER;
4413 /* fill the buffer with the structures */
4414 for (i=0; i<*returned; i++)
4415 smb_io_printer_info_1("", buffer, &printers[i], 0);
4418 SAFE_FREE(printers);
4420 if (*needed > offered) {
4422 return WERR_INSUFFICIENT_BUFFER;
4428 /********************************************************************
4429 enum_all_printers_info_1_local.
4430 *********************************************************************/
4432 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4434 DEBUG(4,("enum_all_printers_info_1_local\n"));
4436 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4439 /********************************************************************
4440 enum_all_printers_info_1_name.
4441 *********************************************************************/
4443 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4447 DEBUG(4,("enum_all_printers_info_1_name\n"));
4449 if ((name[0] == '\\') && (name[1] == '\\'))
4452 if (is_myname_or_ipaddr(s)) {
4453 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4456 return WERR_INVALID_NAME;
4459 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4460 /********************************************************************
4461 enum_all_printers_info_1_remote.
4462 *********************************************************************/
4464 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4466 PRINTER_INFO_1 *printer;
4467 fstring printername;
4470 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4472 /* JFM: currently it's more a place holder than anything else.
4473 * In the spooler world there is a notion of server registration.
4474 * the print servers are registered on the PDC (in the same domain)
4476 * We should have a TDB here. The registration is done thru an
4477 * undocumented RPC call.
4480 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4485 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4486 slprintf(desc, sizeof(desc)-1,"%s", name);
4487 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4489 init_unistr(&printer->description, desc);
4490 init_unistr(&printer->name, printername);
4491 init_unistr(&printer->comment, comment);
4492 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4494 /* check the required size. */
4495 *needed += spoolss_size_printer_info_1(printer);
4497 if (!alloc_buffer_size(buffer, *needed)) {
4499 return WERR_INSUFFICIENT_BUFFER;
4502 /* fill the buffer with the structures */
4503 smb_io_printer_info_1("", buffer, printer, 0);
4508 if (*needed > offered) {
4510 return WERR_INSUFFICIENT_BUFFER;
4518 /********************************************************************
4519 enum_all_printers_info_1_network.
4520 *********************************************************************/
4522 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4526 DEBUG(4,("enum_all_printers_info_1_network\n"));
4528 /* If we respond to a enum_printers level 1 on our name with flags
4529 set to PRINTER_ENUM_REMOTE with a list of printers then these
4530 printers incorrectly appear in the APW browse list.
4531 Specifically the printers for the server appear at the workgroup
4532 level where all the other servers in the domain are
4533 listed. Windows responds to this call with a
4534 WERR_CAN_NOT_COMPLETE so we should do the same. */
4536 if (name[0] == '\\' && name[1] == '\\')
4539 if (is_myname_or_ipaddr(s))
4540 return WERR_CAN_NOT_COMPLETE;
4542 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4545 /********************************************************************
4546 * api_spoolss_enumprinters
4548 * called from api_spoolss_enumprinters (see this to understand)
4549 ********************************************************************/
4551 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4555 int n_services=lp_numservices();
4556 PRINTER_INFO_2 *tp, *printers=NULL;
4557 PRINTER_INFO_2 current_prt;
4559 for (snum=0; snum<n_services; snum++) {
4560 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4561 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4563 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4564 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4565 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4566 SAFE_FREE(printers);
4571 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4572 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4578 /* check the required size. */
4579 for (i=0; i<*returned; i++)
4580 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4582 if (!alloc_buffer_size(buffer, *needed)) {
4583 for (i=0; i<*returned; i++) {
4584 free_devmode(printers[i].devmode);
4586 SAFE_FREE(printers);
4587 return WERR_INSUFFICIENT_BUFFER;
4590 /* fill the buffer with the structures */
4591 for (i=0; i<*returned; i++)
4592 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4595 for (i=0; i<*returned; i++) {
4596 free_devmode(printers[i].devmode);
4598 SAFE_FREE(printers);
4600 if (*needed > offered) {
4602 return WERR_INSUFFICIENT_BUFFER;
4608 /********************************************************************
4609 * handle enumeration of printers at level 1
4610 ********************************************************************/
4612 static WERROR enumprinters_level1( uint32 flags, fstring name,
4613 NEW_BUFFER *buffer, uint32 offered,
4614 uint32 *needed, uint32 *returned)
4616 /* Not all the flags are equals */
4618 if (flags & PRINTER_ENUM_LOCAL)
4619 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4621 if (flags & PRINTER_ENUM_NAME)
4622 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4624 #if 0 /* JERRY - disabled for now */
4625 if (flags & PRINTER_ENUM_REMOTE)
4626 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4629 if (flags & PRINTER_ENUM_NETWORK)
4630 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4632 return WERR_OK; /* NT4sp5 does that */
4635 /********************************************************************
4636 * handle enumeration of printers at level 2
4637 ********************************************************************/
4639 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4640 NEW_BUFFER *buffer, uint32 offered,
4641 uint32 *needed, uint32 *returned)
4643 char *s = servername;
4645 if (flags & PRINTER_ENUM_LOCAL) {
4646 return enum_all_printers_info_2(buffer, offered, needed, returned);
4649 if (flags & PRINTER_ENUM_NAME) {
4650 if ((servername[0] == '\\') && (servername[1] == '\\'))
4652 if (is_myname_or_ipaddr(s))
4653 return enum_all_printers_info_2(buffer, offered, needed, returned);
4655 return WERR_INVALID_NAME;
4658 if (flags & PRINTER_ENUM_REMOTE)
4659 return WERR_UNKNOWN_LEVEL;
4664 /********************************************************************
4665 * handle enumeration of printers at level 5
4666 ********************************************************************/
4668 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4669 NEW_BUFFER *buffer, uint32 offered,
4670 uint32 *needed, uint32 *returned)
4672 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4676 /********************************************************************
4677 * api_spoolss_enumprinters
4679 * called from api_spoolss_enumprinters (see this to understand)
4680 ********************************************************************/
4682 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4684 uint32 flags = q_u->flags;
4685 UNISTR2 *servername = &q_u->servername;
4686 uint32 level = q_u->level;
4687 NEW_BUFFER *buffer = NULL;
4688 uint32 offered = q_u->offered;
4689 uint32 *needed = &r_u->needed;
4690 uint32 *returned = &r_u->returned;
4694 /* that's an [in out] buffer */
4695 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4696 buffer = r_u->buffer;
4698 DEBUG(4,("_spoolss_enumprinters\n"));
4705 * flags==PRINTER_ENUM_NAME
4706 * if name=="" then enumerates all printers
4707 * if name!="" then enumerate the printer
4708 * flags==PRINTER_ENUM_REMOTE
4709 * name is NULL, enumerate printers
4710 * Level 2: name!="" enumerates printers, name can't be NULL
4711 * Level 3: doesn't exist
4712 * Level 4: does a local registry lookup
4713 * Level 5: same as Level 2
4716 unistr2_to_ascii(name, servername, sizeof(name)-1);
4721 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4723 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4725 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4730 return WERR_UNKNOWN_LEVEL;
4733 /****************************************************************************
4734 ****************************************************************************/
4736 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4738 PRINTER_INFO_0 *printer=NULL;
4740 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4743 construct_printer_info_0(print_hnd, printer, snum);
4745 /* check the required size. */
4746 *needed += spoolss_size_printer_info_0(printer);
4748 if (!alloc_buffer_size(buffer, *needed)) {
4750 return WERR_INSUFFICIENT_BUFFER;
4753 /* fill the buffer with the structures */
4754 smb_io_printer_info_0("", buffer, printer, 0);
4759 if (*needed > offered) {
4760 return WERR_INSUFFICIENT_BUFFER;
4766 /****************************************************************************
4767 ****************************************************************************/
4769 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4771 PRINTER_INFO_1 *printer=NULL;
4773 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4776 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4778 /* check the required size. */
4779 *needed += spoolss_size_printer_info_1(printer);
4781 if (!alloc_buffer_size(buffer, *needed)) {
4783 return WERR_INSUFFICIENT_BUFFER;
4786 /* fill the buffer with the structures */
4787 smb_io_printer_info_1("", buffer, printer, 0);
4792 if (*needed > offered) {
4793 return WERR_INSUFFICIENT_BUFFER;
4799 /****************************************************************************
4800 ****************************************************************************/
4802 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4804 PRINTER_INFO_2 *printer=NULL;
4806 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4809 construct_printer_info_2(print_hnd, printer, snum);
4811 /* check the required size. */
4812 *needed += spoolss_size_printer_info_2(printer);
4814 if (!alloc_buffer_size(buffer, *needed)) {
4815 free_printer_info_2(printer);
4816 return WERR_INSUFFICIENT_BUFFER;
4819 /* fill the buffer with the structures */
4820 if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4821 free_printer_info_2(printer);
4826 free_printer_info_2(printer);
4828 if (*needed > offered) {
4829 return WERR_INSUFFICIENT_BUFFER;
4835 /****************************************************************************
4836 ****************************************************************************/
4838 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4840 PRINTER_INFO_3 *printer=NULL;
4842 if (!construct_printer_info_3(print_hnd, &printer, snum))
4845 /* check the required size. */
4846 *needed += spoolss_size_printer_info_3(printer);
4848 if (!alloc_buffer_size(buffer, *needed)) {
4849 free_printer_info_3(printer);
4850 return WERR_INSUFFICIENT_BUFFER;
4853 /* fill the buffer with the structures */
4854 smb_io_printer_info_3("", buffer, printer, 0);
4857 free_printer_info_3(printer);
4859 if (*needed > offered) {
4860 return WERR_INSUFFICIENT_BUFFER;
4866 /****************************************************************************
4867 ****************************************************************************/
4869 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4871 PRINTER_INFO_4 *printer=NULL;
4873 if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4876 if (!construct_printer_info_4(print_hnd, printer, snum))
4879 /* check the required size. */
4880 *needed += spoolss_size_printer_info_4(printer);
4882 if (!alloc_buffer_size(buffer, *needed)) {
4883 free_printer_info_4(printer);
4884 return WERR_INSUFFICIENT_BUFFER;
4887 /* fill the buffer with the structures */
4888 smb_io_printer_info_4("", buffer, printer, 0);
4891 free_printer_info_4(printer);
4893 if (*needed > offered) {
4894 return WERR_INSUFFICIENT_BUFFER;
4900 /****************************************************************************
4901 ****************************************************************************/
4903 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4905 PRINTER_INFO_5 *printer=NULL;
4907 if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4910 if (!construct_printer_info_5(print_hnd, printer, snum))
4913 /* check the required size. */
4914 *needed += spoolss_size_printer_info_5(printer);
4916 if (!alloc_buffer_size(buffer, *needed)) {
4917 free_printer_info_5(printer);
4918 return WERR_INSUFFICIENT_BUFFER;
4921 /* fill the buffer with the structures */
4922 smb_io_printer_info_5("", buffer, printer, 0);
4925 free_printer_info_5(printer);
4927 if (*needed > offered) {
4928 return WERR_INSUFFICIENT_BUFFER;
4934 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4936 PRINTER_INFO_7 *printer=NULL;
4938 if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4941 if (!construct_printer_info_7(print_hnd, printer, snum))
4944 /* check the required size. */
4945 *needed += spoolss_size_printer_info_7(printer);
4947 if (!alloc_buffer_size(buffer, *needed)) {
4948 free_printer_info_7(printer);
4949 return WERR_INSUFFICIENT_BUFFER;
4952 /* fill the buffer with the structures */
4953 smb_io_printer_info_7("", buffer, printer, 0);
4956 free_printer_info_7(printer);
4958 if (*needed > offered) {
4959 return WERR_INSUFFICIENT_BUFFER;
4965 /****************************************************************************
4966 ****************************************************************************/
4968 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4970 POLICY_HND *handle = &q_u->handle;
4971 uint32 level = q_u->level;
4972 NEW_BUFFER *buffer = NULL;
4973 uint32 offered = q_u->offered;
4974 uint32 *needed = &r_u->needed;
4975 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4979 /* that's an [in out] buffer */
4980 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4981 buffer = r_u->buffer;
4985 if (!get_printer_snum(p, handle, &snum))
4990 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4992 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4994 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4996 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4998 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5000 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5002 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5004 return WERR_UNKNOWN_LEVEL;
5007 /********************************************************************
5008 * fill a DRIVER_INFO_1 struct
5009 ********************************************************************/
5011 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5013 init_unistr( &info->name, driver.info_3->name);
5016 /********************************************************************
5017 * construct_printer_driver_info_1
5018 ********************************************************************/
5020 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5022 NT_PRINTER_INFO_LEVEL *printer = NULL;
5023 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5025 ZERO_STRUCT(driver);
5027 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5028 return WERR_INVALID_PRINTER_NAME;
5030 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5031 return WERR_UNKNOWN_PRINTER_DRIVER;
5033 fill_printer_driver_info_1(info, driver, servername, architecture);
5035 free_a_printer(&printer,2);
5040 /********************************************************************
5041 * construct_printer_driver_info_2
5042 * fill a printer_info_2 struct
5043 ********************************************************************/
5045 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5049 info->version=driver.info_3->cversion;
5051 init_unistr( &info->name, driver.info_3->name );
5052 init_unistr( &info->architecture, driver.info_3->environment );
5055 if (strlen(driver.info_3->driverpath)) {
5056 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5057 init_unistr( &info->driverpath, temp );
5059 init_unistr( &info->driverpath, "" );
5061 if (strlen(driver.info_3->datafile)) {
5062 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5063 init_unistr( &info->datafile, temp );
5065 init_unistr( &info->datafile, "" );
5067 if (strlen(driver.info_3->configfile)) {
5068 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5069 init_unistr( &info->configfile, temp );
5071 init_unistr( &info->configfile, "" );
5074 /********************************************************************
5075 * construct_printer_driver_info_2
5076 * fill a printer_info_2 struct
5077 ********************************************************************/
5079 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5081 NT_PRINTER_INFO_LEVEL *printer = NULL;
5082 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5084 ZERO_STRUCT(printer);
5085 ZERO_STRUCT(driver);
5087 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5088 return WERR_INVALID_PRINTER_NAME;
5090 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5091 return WERR_UNKNOWN_PRINTER_DRIVER;
5093 fill_printer_driver_info_2(info, driver, servername);
5095 free_a_printer(&printer,2);
5100 /********************************************************************
5101 * copy a strings array and convert to UNICODE
5103 * convert an array of ascii string to a UNICODE string
5104 ********************************************************************/
5106 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5114 DEBUG(6,("init_unistr_array\n"));
5125 v = ""; /* hack to handle null lists */
5128 /* hack to allow this to be used in places other than when generating
5129 the list of dependent files */
5132 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5136 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5138 /* add one extra unit16 for the second terminating NULL */
5140 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5141 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5149 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5154 /* special case for ""; we need to add both NULL's here */
5156 (*uni_array)[j++]=0x0000;
5157 (*uni_array)[j]=0x0000;
5160 DEBUGADD(6,("last one:done\n"));
5162 /* return size of array in uint16's */
5167 /********************************************************************
5168 * construct_printer_info_3
5169 * fill a printer_info_3 struct
5170 ********************************************************************/
5172 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5178 info->version=driver.info_3->cversion;
5180 init_unistr( &info->name, driver.info_3->name );
5181 init_unistr( &info->architecture, driver.info_3->environment );
5183 if (strlen(driver.info_3->driverpath)) {
5184 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5185 init_unistr( &info->driverpath, temp );
5187 init_unistr( &info->driverpath, "" );
5189 if (strlen(driver.info_3->datafile)) {
5190 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5191 init_unistr( &info->datafile, temp );
5193 init_unistr( &info->datafile, "" );
5195 if (strlen(driver.info_3->configfile)) {
5196 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5197 init_unistr( &info->configfile, temp );
5199 init_unistr( &info->configfile, "" );
5201 if (strlen(driver.info_3->helpfile)) {
5202 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5203 init_unistr( &info->helpfile, temp );
5205 init_unistr( &info->helpfile, "" );
5207 init_unistr( &info->monitorname, driver.info_3->monitorname );
5208 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5210 info->dependentfiles=NULL;
5211 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5214 /********************************************************************
5215 * construct_printer_info_3
5216 * fill a printer_info_3 struct
5217 ********************************************************************/
5219 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5221 NT_PRINTER_INFO_LEVEL *printer = NULL;
5222 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5224 ZERO_STRUCT(driver);
5226 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5227 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5228 if (!W_ERROR_IS_OK(status))
5229 return WERR_INVALID_PRINTER_NAME;
5231 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5232 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5237 * I put this code in during testing. Helpful when commenting out the
5238 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5239 * as win2k always queries the driver using an infor level of 6.
5240 * I've left it in (but ifdef'd out) because I'll probably
5241 * use it in experimentation again in the future. --jerry 22/01/2002
5244 if (!W_ERROR_IS_OK(status)) {
5246 * Is this a W2k client ?
5249 /* Yes - try again with a WinNT driver. */
5251 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5252 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5256 if (!W_ERROR_IS_OK(status)) {
5257 free_a_printer(&printer,2);
5258 return WERR_UNKNOWN_PRINTER_DRIVER;
5266 fill_printer_driver_info_3(info, driver, servername);
5268 free_a_printer(&printer,2);
5273 /********************************************************************
5274 * construct_printer_info_6
5275 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5276 ********************************************************************/
5278 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5284 memset(&nullstr, '\0', sizeof(fstring));
5286 info->version=driver.info_3->cversion;
5288 init_unistr( &info->name, driver.info_3->name );
5289 init_unistr( &info->architecture, driver.info_3->environment );
5291 if (strlen(driver.info_3->driverpath)) {
5292 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5293 init_unistr( &info->driverpath, temp );
5295 init_unistr( &info->driverpath, "" );
5297 if (strlen(driver.info_3->datafile)) {
5298 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5299 init_unistr( &info->datafile, temp );
5301 init_unistr( &info->datafile, "" );
5303 if (strlen(driver.info_3->configfile)) {
5304 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5305 init_unistr( &info->configfile, temp );
5307 init_unistr( &info->configfile, "" );
5309 if (strlen(driver.info_3->helpfile)) {
5310 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5311 init_unistr( &info->helpfile, temp );
5313 init_unistr( &info->helpfile, "" );
5315 init_unistr( &info->monitorname, driver.info_3->monitorname );
5316 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5318 info->dependentfiles = NULL;
5319 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5321 info->previousdrivernames=NULL;
5322 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5324 info->driver_date.low=0;
5325 info->driver_date.high=0;
5328 info->driver_version_low=0;
5329 info->driver_version_high=0;
5331 init_unistr( &info->mfgname, "");
5332 init_unistr( &info->oem_url, "");
5333 init_unistr( &info->hardware_id, "");
5334 init_unistr( &info->provider, "");
5337 /********************************************************************
5338 * construct_printer_info_6
5339 * fill a printer_info_6 struct
5340 ********************************************************************/
5342 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5343 fstring servername, fstring architecture, uint32 version)
5345 NT_PRINTER_INFO_LEVEL *printer = NULL;
5346 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5349 ZERO_STRUCT(driver);
5351 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5353 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5355 if (!W_ERROR_IS_OK(status))
5356 return WERR_INVALID_PRINTER_NAME;
5358 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5360 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5362 if (!W_ERROR_IS_OK(status))
5365 * Is this a W2k client ?
5369 free_a_printer(&printer,2);
5370 return WERR_UNKNOWN_PRINTER_DRIVER;
5373 /* Yes - try again with a WinNT driver. */
5375 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5376 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5377 if (!W_ERROR_IS_OK(status)) {
5378 free_a_printer(&printer,2);
5379 return WERR_UNKNOWN_PRINTER_DRIVER;
5383 fill_printer_driver_info_6(info, driver, servername);
5385 free_a_printer(&printer,2);
5386 free_a_printer_driver(driver, 3);
5391 /****************************************************************************
5392 ****************************************************************************/
5394 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5396 SAFE_FREE(info->dependentfiles);
5399 /****************************************************************************
5400 ****************************************************************************/
5402 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5404 SAFE_FREE(info->dependentfiles);
5408 /****************************************************************************
5409 ****************************************************************************/
5411 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5413 DRIVER_INFO_1 *info=NULL;
5416 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5419 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5420 if (!W_ERROR_IS_OK(status)) {
5425 /* check the required size. */
5426 *needed += spoolss_size_printer_driver_info_1(info);
5428 if (!alloc_buffer_size(buffer, *needed)) {
5430 return WERR_INSUFFICIENT_BUFFER;
5433 /* fill the buffer with the structures */
5434 smb_io_printer_driver_info_1("", buffer, info, 0);
5439 if (*needed > offered)
5440 return WERR_INSUFFICIENT_BUFFER;
5445 /****************************************************************************
5446 ****************************************************************************/
5448 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5450 DRIVER_INFO_2 *info=NULL;
5453 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5456 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5457 if (!W_ERROR_IS_OK(status)) {
5462 /* check the required size. */
5463 *needed += spoolss_size_printer_driver_info_2(info);
5465 if (!alloc_buffer_size(buffer, *needed)) {
5467 return WERR_INSUFFICIENT_BUFFER;
5470 /* fill the buffer with the structures */
5471 smb_io_printer_driver_info_2("", buffer, info, 0);
5476 if (*needed > offered)
5477 return WERR_INSUFFICIENT_BUFFER;
5482 /****************************************************************************
5483 ****************************************************************************/
5485 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5492 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5493 if (!W_ERROR_IS_OK(status)) {
5497 /* check the required size. */
5498 *needed += spoolss_size_printer_driver_info_3(&info);
5500 if (!alloc_buffer_size(buffer, *needed)) {
5501 free_printer_driver_info_3(&info);
5502 return WERR_INSUFFICIENT_BUFFER;
5505 /* fill the buffer with the structures */
5506 smb_io_printer_driver_info_3("", buffer, &info, 0);
5508 free_printer_driver_info_3(&info);
5510 if (*needed > offered)
5511 return WERR_INSUFFICIENT_BUFFER;
5516 /****************************************************************************
5517 ****************************************************************************/
5519 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5526 status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5527 if (!W_ERROR_IS_OK(status)) {
5531 /* check the required size. */
5532 *needed += spoolss_size_printer_driver_info_6(&info);
5534 if (!alloc_buffer_size(buffer, *needed)) {
5535 free_printer_driver_info_6(&info);
5536 return WERR_INSUFFICIENT_BUFFER;
5539 /* fill the buffer with the structures */
5540 smb_io_printer_driver_info_6("", buffer, &info, 0);
5542 free_printer_driver_info_6(&info);
5544 if (*needed > offered)
5545 return WERR_INSUFFICIENT_BUFFER;
5550 /****************************************************************************
5551 ****************************************************************************/
5553 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5555 POLICY_HND *handle = &q_u->handle;
5556 UNISTR2 *uni_arch = &q_u->architecture;
5557 uint32 level = q_u->level;
5558 uint32 clientmajorversion = q_u->clientmajorversion;
5559 NEW_BUFFER *buffer = NULL;
5560 uint32 offered = q_u->offered;
5561 uint32 *needed = &r_u->needed;
5562 uint32 *servermajorversion = &r_u->servermajorversion;
5563 uint32 *serverminorversion = &r_u->serverminorversion;
5564 Printer_entry *printer;
5567 fstring architecture;
5570 /* that's an [in out] buffer */
5571 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5572 buffer = r_u->buffer;
5574 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5576 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5577 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5578 return WERR_INVALID_PRINTER_NAME;
5582 *servermajorversion = 0;
5583 *serverminorversion = 0;
5585 fstrcpy(servername, get_server_name( printer ));
5586 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5588 if (!get_printer_snum(p, handle, &snum))
5593 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5595 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5597 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5599 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5602 /* apparently this call is the equivalent of
5603 EnumPrinterDataEx() for the DsDriver key */
5608 return WERR_UNKNOWN_LEVEL;
5611 /****************************************************************************
5612 ****************************************************************************/
5614 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5616 POLICY_HND *handle = &q_u->handle;
5618 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5621 DEBUG(3,("Error in startpageprinter printer handle\n"));
5625 Printer->page_started=True;
5629 /****************************************************************************
5630 ****************************************************************************/
5632 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5634 POLICY_HND *handle = &q_u->handle;
5637 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5640 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5644 if (!get_printer_snum(p, handle, &snum))
5647 Printer->page_started=False;
5648 print_job_endpage(snum, Printer->jobid);
5653 /********************************************************************
5654 * api_spoolss_getprinter
5655 * called from the spoolss dispatcher
5657 ********************************************************************/
5659 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5661 POLICY_HND *handle = &q_u->handle;
5662 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5663 uint32 *jobid = &r_u->jobid;
5665 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5669 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5670 struct current_user user;
5673 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5677 get_current_user(&user, p);
5680 * a nice thing with NT is it doesn't listen to what you tell it.
5681 * when asked to send _only_ RAW datas, it tries to send datas
5684 * So I add checks like in NT Server ...
5687 if (info_1->p_datatype != 0) {
5688 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5689 if (strcmp(datatype, "RAW") != 0) {
5691 return WERR_INVALID_DATATYPE;
5695 /* get the share number of the printer */
5696 if (!get_printer_snum(p, handle, &snum)) {
5700 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5702 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5704 /* An error occured in print_job_start() so return an appropriate
5707 if (Printer->jobid == -1) {
5708 return map_werror_from_unix(errno);
5711 Printer->document_started=True;
5712 (*jobid) = Printer->jobid;
5717 /********************************************************************
5718 * api_spoolss_getprinter
5719 * called from the spoolss dispatcher
5721 ********************************************************************/
5723 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5725 POLICY_HND *handle = &q_u->handle;
5727 return _spoolss_enddocprinter_internal(p, handle);
5730 /****************************************************************************
5731 ****************************************************************************/
5733 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5735 POLICY_HND *handle = &q_u->handle;
5736 uint32 buffer_size = q_u->buffer_size;
5737 uint8 *buffer = q_u->buffer;
5738 uint32 *buffer_written = &q_u->buffer_size2;
5740 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5743 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5744 r_u->buffer_written = q_u->buffer_size2;
5748 if (!get_printer_snum(p, handle, &snum))
5751 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5752 if (*buffer_written == -1) {
5753 r_u->buffer_written = 0;
5754 if (errno == ENOSPC)
5755 return WERR_NO_SPOOL_SPACE;
5757 return WERR_ACCESS_DENIED;
5760 r_u->buffer_written = q_u->buffer_size2;
5765 /********************************************************************
5766 * api_spoolss_getprinter
5767 * called from the spoolss dispatcher
5769 ********************************************************************/
5771 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5774 struct current_user user;
5776 WERROR errcode = WERR_BADFUNC;
5777 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5779 get_current_user(&user, p);
5782 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5786 if (!get_printer_snum(p, handle, &snum))
5790 case PRINTER_CONTROL_PAUSE:
5791 if (print_queue_pause(&user, snum, &errcode)) {
5795 case PRINTER_CONTROL_RESUME:
5796 case PRINTER_CONTROL_UNPAUSE:
5797 if (print_queue_resume(&user, snum, &errcode)) {
5801 case PRINTER_CONTROL_PURGE:
5802 if (print_queue_purge(&user, snum, &errcode)) {
5807 return WERR_UNKNOWN_LEVEL;
5813 /********************************************************************
5814 * api_spoolss_abortprinter
5815 * From MSDN: "Deletes printer's spool file if printer is configured
5817 ********************************************************************/
5819 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5821 POLICY_HND *handle = &q_u->handle;
5822 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5824 struct current_user user;
5825 WERROR errcode = WERR_OK;
5828 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5832 if (!get_printer_snum(p, handle, &snum))
5835 get_current_user( &user, p );
5837 print_job_delete( &user, snum, Printer->jobid, &errcode );
5842 /********************************************************************
5843 * called by spoolss_api_setprinter
5844 * when updating a printer description
5845 ********************************************************************/
5847 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5848 const SPOOL_PRINTER_INFO_LEVEL *info,
5849 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5851 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5852 struct current_user user;
5856 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5858 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5859 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5860 OUR_HANDLE(handle)));
5862 result = WERR_BADFID;
5866 /* NT seems to like setting the security descriptor even though
5867 nothing may have actually changed. */
5869 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5871 if (DEBUGLEVEL >= 10) {
5875 the_acl = old_secdesc_ctr->sec->dacl;
5876 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5877 PRINTERNAME(snum), the_acl->num_aces));
5879 for (i = 0; i < the_acl->num_aces; i++) {
5882 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5884 DEBUG(10, ("%s 0x%08x\n", sid_str,
5885 the_acl->ace[i].info.mask));
5888 the_acl = secdesc_ctr->sec->dacl;
5891 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5892 PRINTERNAME(snum), the_acl->num_aces));
5894 for (i = 0; i < the_acl->num_aces; i++) {
5897 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5899 DEBUG(10, ("%s 0x%08x\n", sid_str,
5900 the_acl->ace[i].info.mask));
5903 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5907 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5909 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5914 /* Work out which user is performing the operation */
5916 get_current_user(&user, p);
5918 /* Check the user has permissions to change the security
5919 descriptor. By experimentation with two NT machines, the user
5920 requires Full Access to the printer to change security
5923 if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5924 result = WERR_ACCESS_DENIED;
5928 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5935 /********************************************************************
5936 Canonicalize printer info from a client
5938 ATTN: It does not matter what we set the servername to hear
5939 since we do the necessary work in get_a_printer() to set it to
5940 the correct value based on what the client sent in the
5941 _spoolss_open_printer_ex().
5942 ********************************************************************/
5944 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5946 fstring printername;
5949 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5950 "portname=%s drivername=%s comment=%s location=%s\n",
5951 info->servername, info->printername, info->sharename,
5952 info->portname, info->drivername, info->comment, info->location));
5954 /* we force some elements to "correct" values */
5955 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5956 fstrcpy(info->sharename, lp_servicename(snum));
5958 /* make sure printername is in \\server\printername format */
5960 fstrcpy( printername, info->printername );
5962 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5963 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5967 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5968 global_myname(), p );
5970 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5971 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5978 /****************************************************************************
5979 ****************************************************************************/
5981 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5983 extern userdom_struct current_user_info;
5984 char *cmd = lp_addprinter_cmd();
5990 fstring remote_machine = "%m";
5992 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5994 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5995 cmd, printer->info_2->printername, printer->info_2->sharename,
5996 printer->info_2->portname, printer->info_2->drivername,
5997 printer->info_2->location, printer->info_2->comment, remote_machine);
5999 DEBUG(10,("Running [%s]\n", command));
6000 ret = smbrun(command, &fd);
6001 DEBUGADD(10,("returned [%d]\n", ret));
6010 /* Get lines and convert them back to dos-codepage */
6011 qlines = fd_lines_load(fd, &numlines);
6012 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6016 /* Set the portname to what the script says the portname should be. */
6017 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6018 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6020 /* Send SIGHUP to process group... is there a better way? */
6023 /* reload our services immediately */
6024 reload_services( False );
6027 file_lines_free(qlines);
6031 /********************************************************************
6032 * Called by spoolss_api_setprinter
6033 * when updating a printer description.
6034 ********************************************************************/
6036 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6037 const SPOOL_PRINTER_INFO_LEVEL *info,
6038 DEVICEMODE *devmode)
6041 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6042 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6047 DEBUG(8,("update_printer\n"));
6052 result = WERR_BADFID;
6056 if (!get_printer_snum(p, handle, &snum)) {
6057 result = WERR_BADFID;
6061 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6062 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6063 result = WERR_BADFID;
6067 DEBUGADD(8,("Converting info_2 struct\n"));
6070 * convert_printer_info converts the incoming
6071 * info from the client and overwrites the info
6072 * just read from the tdb in the pointer 'printer'.
6075 if (!convert_printer_info(info, printer, level)) {
6076 result = WERR_NOMEM;
6081 /* we have a valid devmode
6082 convert it and link it*/
6084 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6085 if (!convert_devicemode(printer->info_2->printername, devmode,
6086 &printer->info_2->devmode)) {
6087 result = WERR_NOMEM;
6092 /* Do sanity check on the requested changes for Samba */
6094 if (!check_printer_ok(printer->info_2, snum)) {
6095 result = WERR_INVALID_PARAM;
6099 /* FIXME!!! If the driver has changed we really should verify that
6100 it is installed before doing much else --jerry */
6102 /* Check calling user has permission to update printer description */
6104 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6105 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6106 result = WERR_ACCESS_DENIED;
6110 /* Call addprinter hook */
6111 /* Check changes to see if this is really needed */
6113 if ( *lp_addprinter_cmd()
6114 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6115 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6116 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6117 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6119 if ( !add_printer_hook(printer) ) {
6120 result = WERR_ACCESS_DENIED;
6125 * make sure we actually reload the services after
6126 * this as smb.conf could have a new section in it
6127 * .... shouldn't .... but could
6129 reload_services(False);
6133 * When a *new* driver is bound to a printer, the drivername is used to
6134 * lookup previously saved driver initialization info, which is then
6135 * bound to the printer, simulating what happens in the Windows arch.
6137 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6139 if (!set_driver_init(printer, 2))
6141 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6142 printer->info_2->drivername));
6145 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6146 printer->info_2->drivername));
6148 notify_printer_driver(snum, printer->info_2->drivername);
6152 * flag which changes actually occured. This is a small subset of
6153 * all the possible changes. We also have to update things in the
6157 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6158 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6159 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6160 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6162 notify_printer_comment(snum, printer->info_2->comment);
6165 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6166 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6167 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6168 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6170 notify_printer_sharename(snum, printer->info_2->sharename);
6173 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6176 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6179 pname = printer->info_2->printername;
6182 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6183 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6184 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6186 notify_printer_printername( snum, pname );
6189 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6190 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6191 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6192 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6194 notify_printer_port(snum, printer->info_2->portname);
6197 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6198 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6199 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6200 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6202 notify_printer_location(snum, printer->info_2->location);
6205 /* here we need to update some more DsSpooler keys */
6206 /* uNCName, serverName, shortServerName */
6208 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6209 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6210 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6211 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6212 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6214 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6215 global_myname(), printer->info_2->sharename );
6216 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6217 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6218 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6220 /* Update printer info */
6221 result = mod_a_printer(printer, 2);
6224 free_a_printer(&printer, 2);
6225 free_a_printer(&old_printer, 2);
6231 /****************************************************************************
6232 ****************************************************************************/
6233 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6234 const SPOOL_PRINTER_INFO_LEVEL *info)
6237 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6239 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6241 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6246 if (!get_printer_snum(p, handle, &snum))
6249 nt_printer_publish(Printer, snum, info7->action);
6253 return WERR_UNKNOWN_LEVEL;
6256 /****************************************************************************
6257 ****************************************************************************/
6259 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6261 POLICY_HND *handle = &q_u->handle;
6262 uint32 level = q_u->level;
6263 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6264 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6265 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6266 uint32 command = q_u->command;
6269 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6272 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6276 /* check the level */
6279 return control_printer(handle, command, p);
6281 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6282 if (!W_ERROR_IS_OK(result))
6285 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6288 return update_printer_sec(handle, level, info, p,
6291 return publish_or_unpublish_printer(p, handle, info);
6293 return WERR_UNKNOWN_LEVEL;
6297 /****************************************************************************
6298 ****************************************************************************/
6300 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6302 POLICY_HND *handle = &q_u->handle;
6303 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6306 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6310 if (Printer->notify.client_connected==True) {
6313 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6315 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6316 !get_printer_snum(p, handle, &snum) )
6319 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6322 Printer->notify.flags=0;
6323 Printer->notify.options=0;
6324 Printer->notify.localmachine[0]='\0';
6325 Printer->notify.printerlocal=0;
6326 if (Printer->notify.option)
6327 free_spool_notify_option(&Printer->notify.option);
6328 Printer->notify.client_connected=False;
6333 /****************************************************************************
6334 ****************************************************************************/
6336 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6338 /* that's an [in out] buffer (despite appearences to the contrary) */
6339 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6342 return WERR_INVALID_PARAM; /* this is what a NT server
6343 returns for AddJob. AddJob
6344 must fail on non-local
6348 /****************************************************************************
6349 ****************************************************************************/
6351 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6352 int position, int snum,
6353 NT_PRINTER_INFO_LEVEL *ntprinter)
6357 t=gmtime(&queue->time);
6359 job_info->jobid=queue->job;
6360 init_unistr(&job_info->printername, lp_servicename(snum));
6361 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6362 init_unistr(&job_info->username, queue->fs_user);
6363 init_unistr(&job_info->document, queue->fs_file);
6364 init_unistr(&job_info->datatype, "RAW");
6365 init_unistr(&job_info->text_status, "");
6366 job_info->status=nt_printj_status(queue->status);
6367 job_info->priority=queue->priority;
6368 job_info->position=position;
6369 job_info->totalpages=queue->page_count;
6370 job_info->pagesprinted=0;
6372 make_systemtime(&job_info->submitted, t);
6375 /****************************************************************************
6376 ****************************************************************************/
6378 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6379 int position, int snum,
6380 NT_PRINTER_INFO_LEVEL *ntprinter,
6381 DEVICEMODE *devmode)
6385 t=gmtime(&queue->time);
6387 job_info->jobid=queue->job;
6389 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6391 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6392 init_unistr(&job_info->username, queue->fs_user);
6393 init_unistr(&job_info->document, queue->fs_file);
6394 init_unistr(&job_info->notifyname, queue->fs_user);
6395 init_unistr(&job_info->datatype, "RAW");
6396 init_unistr(&job_info->printprocessor, "winprint");
6397 init_unistr(&job_info->parameters, "");
6398 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6399 init_unistr(&job_info->text_status, "");
6401 /* and here the security descriptor */
6403 job_info->status=nt_printj_status(queue->status);
6404 job_info->priority=queue->priority;
6405 job_info->position=position;
6406 job_info->starttime=0;
6407 job_info->untiltime=0;
6408 job_info->totalpages=queue->page_count;
6409 job_info->size=queue->size;
6410 make_systemtime(&(job_info->submitted), t);
6411 job_info->timeelapsed=0;
6412 job_info->pagesprinted=0;
6414 job_info->devmode = devmode;
6419 /****************************************************************************
6420 Enumjobs at level 1.
6421 ****************************************************************************/
6423 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6424 NT_PRINTER_INFO_LEVEL *ntprinter,
6425 NEW_BUFFER *buffer, uint32 offered,
6426 uint32 *needed, uint32 *returned)
6431 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6438 for (i=0; i<*returned; i++)
6439 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6443 /* check the required size. */
6444 for (i=0; i<*returned; i++)
6445 (*needed) += spoolss_size_job_info_1(&info[i]);
6447 if (!alloc_buffer_size(buffer, *needed)) {
6449 return WERR_INSUFFICIENT_BUFFER;
6452 /* fill the buffer with the structures */
6453 for (i=0; i<*returned; i++)
6454 smb_io_job_info_1("", buffer, &info[i], 0);
6459 if (*needed > offered) {
6461 return WERR_INSUFFICIENT_BUFFER;
6467 /****************************************************************************
6468 Enumjobs at level 2.
6469 ****************************************************************************/
6471 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6472 NT_PRINTER_INFO_LEVEL *ntprinter,
6473 NEW_BUFFER *buffer, uint32 offered,
6474 uint32 *needed, uint32 *returned)
6476 JOB_INFO_2 *info = NULL;
6479 DEVICEMODE *devmode = NULL;
6481 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6484 result = WERR_NOMEM;
6488 /* this should not be a failure condition if the devmode is NULL */
6490 devmode = construct_dev_mode(snum);
6492 for (i=0; i<*returned; i++)
6493 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6496 free_a_printer(&ntprinter, 2);
6499 /* check the required size. */
6500 for (i=0; i<*returned; i++)
6501 (*needed) += spoolss_size_job_info_2(&info[i]);
6503 if (*needed > offered) {
6505 result = WERR_INSUFFICIENT_BUFFER;
6509 if (!alloc_buffer_size(buffer, *needed)) {
6511 result = WERR_INSUFFICIENT_BUFFER;
6515 /* fill the buffer with the structures */
6516 for (i=0; i<*returned; i++)
6517 smb_io_job_info_2("", buffer, &info[i], 0);
6522 free_a_printer(&ntprinter, 2);
6523 free_devmode(devmode);
6531 /****************************************************************************
6533 ****************************************************************************/
6535 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6537 POLICY_HND *handle = &q_u->handle;
6538 uint32 level = q_u->level;
6539 NEW_BUFFER *buffer = NULL;
6540 uint32 offered = q_u->offered;
6541 uint32 *needed = &r_u->needed;
6542 uint32 *returned = &r_u->returned;
6544 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6546 print_status_struct prt_status;
6547 print_queue_struct *queue=NULL;
6549 /* that's an [in out] buffer */
6550 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6551 buffer = r_u->buffer;
6553 DEBUG(4,("_spoolss_enumjobs\n"));
6558 /* lookup the printer snum and tdb entry */
6560 if (!get_printer_snum(p, handle, &snum))
6563 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6564 if ( !W_ERROR_IS_OK(wret) )
6567 *returned = print_queue_status(snum, &queue, &prt_status);
6568 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6570 if (*returned == 0) {
6577 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6580 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6585 wret = WERR_UNKNOWN_LEVEL;
6588 free_a_printer( &ntprinter, 2 );
6592 /****************************************************************************
6593 ****************************************************************************/
6595 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6600 /****************************************************************************
6601 ****************************************************************************/
6603 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6605 POLICY_HND *handle = &q_u->handle;
6606 uint32 jobid = q_u->jobid;
6607 uint32 command = q_u->command;
6609 struct current_user user;
6611 WERROR errcode = WERR_BADFUNC;
6613 if (!get_printer_snum(p, handle, &snum)) {
6617 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6618 return WERR_INVALID_PRINTER_NAME;
6621 get_current_user(&user, p);
6624 case JOB_CONTROL_CANCEL:
6625 case JOB_CONTROL_DELETE:
6626 if (print_job_delete(&user, snum, jobid, &errcode)) {
6630 case JOB_CONTROL_PAUSE:
6631 if (print_job_pause(&user, snum, jobid, &errcode)) {
6635 case JOB_CONTROL_RESTART:
6636 case JOB_CONTROL_RESUME:
6637 if (print_job_resume(&user, snum, jobid, &errcode)) {
6642 return WERR_UNKNOWN_LEVEL;
6648 /****************************************************************************
6649 Enumerates all printer drivers at level 1.
6650 ****************************************************************************/
6652 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6657 fstring *list = NULL;
6659 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6660 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6664 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6666 ndrivers=get_ntdrivers(&list, architecture, version);
6667 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6673 if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6674 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6675 SAFE_FREE(driver_info_1);
6679 else driver_info_1 = tdi1;
6682 for (i=0; i<ndrivers; i++) {
6684 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6685 ZERO_STRUCT(driver);
6686 status = get_a_printer_driver(&driver, 3, list[i],
6687 architecture, version);
6688 if (!W_ERROR_IS_OK(status)) {
6692 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6693 free_a_printer_driver(driver, 3);
6696 *returned+=ndrivers;
6700 /* check the required size. */
6701 for (i=0; i<*returned; i++) {
6702 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6703 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6706 if (!alloc_buffer_size(buffer, *needed)) {
6707 SAFE_FREE(driver_info_1);
6708 return WERR_INSUFFICIENT_BUFFER;
6711 /* fill the buffer with the driver structures */
6712 for (i=0; i<*returned; i++) {
6713 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6714 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6717 SAFE_FREE(driver_info_1);
6719 if (*needed > offered) {
6721 return WERR_INSUFFICIENT_BUFFER;
6727 /****************************************************************************
6728 Enumerates all printer drivers at level 2.
6729 ****************************************************************************/
6731 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6736 fstring *list = NULL;
6738 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6739 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6743 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6745 ndrivers=get_ntdrivers(&list, architecture, version);
6746 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6752 if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6753 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6754 SAFE_FREE(driver_info_2);
6758 else driver_info_2 = tdi2;
6761 for (i=0; i<ndrivers; i++) {
6764 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6765 ZERO_STRUCT(driver);
6766 status = get_a_printer_driver(&driver, 3, list[i],
6767 architecture, version);
6768 if (!W_ERROR_IS_OK(status)) {
6772 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6773 free_a_printer_driver(driver, 3);
6776 *returned+=ndrivers;
6780 /* check the required size. */
6781 for (i=0; i<*returned; i++) {
6782 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6783 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6786 if (!alloc_buffer_size(buffer, *needed)) {
6787 SAFE_FREE(driver_info_2);
6788 return WERR_INSUFFICIENT_BUFFER;
6791 /* fill the buffer with the form structures */
6792 for (i=0; i<*returned; i++) {
6793 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6794 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6797 SAFE_FREE(driver_info_2);
6799 if (*needed > offered) {
6801 return WERR_INSUFFICIENT_BUFFER;
6807 /****************************************************************************
6808 Enumerates all printer drivers at level 3.
6809 ****************************************************************************/
6811 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6816 fstring *list = NULL;
6818 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6819 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6823 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6825 ndrivers=get_ntdrivers(&list, architecture, version);
6826 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6832 if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6833 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6834 SAFE_FREE(driver_info_3);
6838 else driver_info_3 = tdi3;
6841 for (i=0; i<ndrivers; i++) {
6844 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6845 ZERO_STRUCT(driver);
6846 status = get_a_printer_driver(&driver, 3, list[i],
6847 architecture, version);
6848 if (!W_ERROR_IS_OK(status)) {
6852 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6853 free_a_printer_driver(driver, 3);
6856 *returned+=ndrivers;
6860 /* check the required size. */
6861 for (i=0; i<*returned; i++) {
6862 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6863 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6866 if (!alloc_buffer_size(buffer, *needed)) {
6867 SAFE_FREE(driver_info_3);
6868 return WERR_INSUFFICIENT_BUFFER;
6871 /* fill the buffer with the driver structures */
6872 for (i=0; i<*returned; i++) {
6873 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6874 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6877 for (i=0; i<*returned; i++)
6878 SAFE_FREE(driver_info_3[i].dependentfiles);
6880 SAFE_FREE(driver_info_3);
6882 if (*needed > offered) {
6884 return WERR_INSUFFICIENT_BUFFER;
6890 /****************************************************************************
6891 Enumerates all printer drivers.
6892 ****************************************************************************/
6894 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6896 uint32 level = q_u->level;
6897 NEW_BUFFER *buffer = NULL;
6898 uint32 offered = q_u->offered;
6899 uint32 *needed = &r_u->needed;
6900 uint32 *returned = &r_u->returned;
6902 fstring *list = NULL;
6904 fstring architecture;
6906 /* that's an [in out] buffer */
6907 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6908 buffer = r_u->buffer;
6910 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6914 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6915 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6917 if ( !is_myname_or_ipaddr( servername ) )
6918 return WERR_UNKNOWN_PRINTER_DRIVER;
6922 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6924 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6926 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6930 return WERR_UNKNOWN_LEVEL;
6934 /****************************************************************************
6935 ****************************************************************************/
6937 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6939 form->flag=list->flag;
6940 init_unistr(&form->name, list->name);
6941 form->width=list->width;
6942 form->length=list->length;
6943 form->left=list->left;
6944 form->top=list->top;
6945 form->right=list->right;
6946 form->bottom=list->bottom;
6949 /****************************************************************************
6950 ****************************************************************************/
6952 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6954 uint32 level = q_u->level;
6955 NEW_BUFFER *buffer = NULL;
6956 uint32 offered = q_u->offered;
6957 uint32 *needed = &r_u->needed;
6958 uint32 *numofforms = &r_u->numofforms;
6959 uint32 numbuiltinforms;
6961 nt_forms_struct *list=NULL;
6962 nt_forms_struct *builtinlist=NULL;
6967 /* that's an [in out] buffer */
6968 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6969 buffer = r_u->buffer;
6971 DEBUG(4,("_spoolss_enumforms\n"));
6972 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6973 DEBUGADD(5,("Info level [%d]\n", level));
6975 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6976 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6977 *numofforms = get_ntforms(&list);
6978 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6979 *numofforms += numbuiltinforms;
6981 if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6985 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6990 /* construct the list of form structures */
6991 for (i=0; i<numbuiltinforms; i++) {
6992 DEBUGADD(6,("Filling form number [%d]\n",i));
6993 fill_form_1(&forms_1[i], &builtinlist[i]);
6996 SAFE_FREE(builtinlist);
6998 for (; i<*numofforms; i++) {
6999 DEBUGADD(6,("Filling form number [%d]\n",i));
7000 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7005 /* check the required size. */
7006 for (i=0; i<numbuiltinforms; i++) {
7007 DEBUGADD(6,("adding form [%d]'s size\n",i));
7008 buffer_size += spoolss_size_form_1(&forms_1[i]);
7010 for (; i<*numofforms; i++) {
7011 DEBUGADD(6,("adding form [%d]'s size\n",i));
7012 buffer_size += spoolss_size_form_1(&forms_1[i]);
7015 *needed=buffer_size;
7017 if (!alloc_buffer_size(buffer, buffer_size)){
7019 return WERR_INSUFFICIENT_BUFFER;
7022 /* fill the buffer with the form structures */
7023 for (i=0; i<numbuiltinforms; i++) {
7024 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7025 smb_io_form_1("", buffer, &forms_1[i], 0);
7027 for (; i<*numofforms; i++) {
7028 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7029 smb_io_form_1("", buffer, &forms_1[i], 0);
7034 if (*needed > offered) {
7036 return WERR_INSUFFICIENT_BUFFER;
7043 SAFE_FREE(builtinlist);
7044 return WERR_UNKNOWN_LEVEL;
7049 /****************************************************************************
7050 ****************************************************************************/
7052 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7054 uint32 level = q_u->level;
7055 UNISTR2 *uni_formname = &q_u->formname;
7056 NEW_BUFFER *buffer = NULL;
7057 uint32 offered = q_u->offered;
7058 uint32 *needed = &r_u->needed;
7060 nt_forms_struct *list=NULL;
7061 nt_forms_struct builtin_form;
7066 int numofforms=0, i=0;
7068 /* that's an [in out] buffer */
7069 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7070 buffer = r_u->buffer;
7072 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7074 DEBUG(4,("_spoolss_getform\n"));
7075 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7076 DEBUGADD(5,("Info level [%d]\n", level));
7078 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7079 if (!foundBuiltin) {
7080 numofforms = get_ntforms(&list);
7081 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7083 if (numofforms == 0)
7090 fill_form_1(&form_1, &builtin_form);
7093 /* Check if the requested name is in the list of form structures */
7094 for (i=0; i<numofforms; i++) {
7096 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7098 if (strequal(form_name, list[i].name)) {
7099 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7100 fill_form_1(&form_1, &list[i]);
7106 if (i == numofforms) {
7110 /* check the required size. */
7112 *needed=spoolss_size_form_1(&form_1);
7114 if (!alloc_buffer_size(buffer, buffer_size)){
7115 return WERR_INSUFFICIENT_BUFFER;
7118 if (*needed > offered) {
7119 return WERR_INSUFFICIENT_BUFFER;
7122 /* fill the buffer with the form structures */
7123 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7124 smb_io_form_1("", buffer, &form_1, 0);
7130 return WERR_UNKNOWN_LEVEL;
7134 /****************************************************************************
7135 ****************************************************************************/
7137 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7139 init_unistr(&port->port_name, name);
7142 /****************************************************************************
7143 ****************************************************************************/
7145 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7147 init_unistr(&port->port_name, name);
7148 init_unistr(&port->monitor_name, "Local Monitor");
7149 init_unistr(&port->description, "Local Port");
7150 port->port_type=PORT_TYPE_WRITE;
7154 /****************************************************************************
7156 ****************************************************************************/
7158 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7160 PORT_INFO_1 *ports=NULL;
7163 if (*lp_enumports_cmd()) {
7164 char *cmd = lp_enumports_cmd();
7171 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7173 DEBUG(10,("Running [%s]\n", command));
7174 ret = smbrun(command, &fd);
7175 DEBUG(10,("Returned [%d]\n", ret));
7179 /* Is this the best error to return here? */
7180 return WERR_ACCESS_DENIED;
7184 qlines = fd_lines_load(fd, &numlines);
7185 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7189 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7190 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7191 dos_errstr(WERR_NOMEM)));
7192 file_lines_free(qlines);
7196 for (i=0; i<numlines; i++) {
7197 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7198 fill_port_1(&ports[i], qlines[i]);
7201 file_lines_free(qlines);
7204 *returned = numlines;
7207 *returned = 1; /* Sole Samba port returned. */
7209 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7212 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7214 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7217 /* check the required size. */
7218 for (i=0; i<*returned; i++) {
7219 DEBUGADD(6,("adding port [%d]'s size\n", i));
7220 *needed += spoolss_size_port_info_1(&ports[i]);
7223 if (!alloc_buffer_size(buffer, *needed)) {
7225 return WERR_INSUFFICIENT_BUFFER;
7228 /* fill the buffer with the ports structures */
7229 for (i=0; i<*returned; i++) {
7230 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7231 smb_io_port_1("", buffer, &ports[i], 0);
7236 if (*needed > offered) {
7238 return WERR_INSUFFICIENT_BUFFER;
7244 /****************************************************************************
7246 ****************************************************************************/
7248 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7250 PORT_INFO_2 *ports=NULL;
7253 if (*lp_enumports_cmd()) {
7254 char *cmd = lp_enumports_cmd();
7263 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7264 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7266 path = lp_lockdir();
7268 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7269 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7272 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7273 ret = smbrun(command, &fd);
7274 DEBUGADD(10,("returned [%d]\n", ret));
7278 /* Is this the best error to return here? */
7279 return WERR_ACCESS_DENIED;
7283 qlines = fd_lines_load(fd, &numlines);
7284 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7288 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7289 file_lines_free(qlines);
7293 for (i=0; i<numlines; i++) {
7294 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7295 fill_port_2(&(ports[i]), qlines[i]);
7298 file_lines_free(qlines);
7301 *returned = numlines;
7307 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7310 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7312 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7315 /* check the required size. */
7316 for (i=0; i<*returned; i++) {
7317 DEBUGADD(6,("adding port [%d]'s size\n", i));
7318 *needed += spoolss_size_port_info_2(&ports[i]);
7321 if (!alloc_buffer_size(buffer, *needed)) {
7323 return WERR_INSUFFICIENT_BUFFER;
7326 /* fill the buffer with the ports structures */
7327 for (i=0; i<*returned; i++) {
7328 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7329 smb_io_port_2("", buffer, &ports[i], 0);
7334 if (*needed > offered) {
7336 return WERR_INSUFFICIENT_BUFFER;
7342 /****************************************************************************
7344 ****************************************************************************/
7346 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7348 uint32 level = q_u->level;
7349 NEW_BUFFER *buffer = NULL;
7350 uint32 offered = q_u->offered;
7351 uint32 *needed = &r_u->needed;
7352 uint32 *returned = &r_u->returned;
7354 /* that's an [in out] buffer */
7355 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7356 buffer = r_u->buffer;
7358 DEBUG(4,("_spoolss_enumports\n"));
7365 return enumports_level_1(buffer, offered, needed, returned);
7367 return enumports_level_2(buffer, offered, needed, returned);
7369 return WERR_UNKNOWN_LEVEL;
7373 /****************************************************************************
7374 ****************************************************************************/
7376 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7377 const SPOOL_PRINTER_INFO_LEVEL *info,
7378 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7379 uint32 user_switch, const SPOOL_USER_CTR *user,
7382 NT_PRINTER_INFO_LEVEL *printer = NULL;
7385 WERROR err = WERR_OK;
7387 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7388 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7392 ZERO_STRUCTP(printer);
7394 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7395 if (!convert_printer_info(info, printer, 2)) {
7396 free_a_printer(&printer, 2);
7400 /* check to see if the printer already exists */
7402 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7403 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7404 printer->info_2->sharename));
7405 free_a_printer(&printer, 2);
7406 return WERR_PRINTER_ALREADY_EXISTS;
7409 /* FIXME!!! smbd should check to see if the driver is installed before
7410 trying to add a printer like this --jerry */
7412 if (*lp_addprinter_cmd() ) {
7413 if ( !add_printer_hook(printer) ) {
7414 free_a_printer(&printer,2);
7415 return WERR_ACCESS_DENIED;
7419 /* use our primary netbios name since get_a_printer() will convert
7420 it to what the client expects on a case by case basis */
7422 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7423 printer->info_2->sharename);
7426 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7427 free_a_printer(&printer,2);
7428 return WERR_ACCESS_DENIED;
7431 /* you must be a printer admin to add a new printer */
7432 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7433 free_a_printer(&printer,2);
7434 return WERR_ACCESS_DENIED;
7438 * Do sanity check on the requested changes for Samba.
7441 if (!check_printer_ok(printer->info_2, snum)) {
7442 free_a_printer(&printer,2);
7443 return WERR_INVALID_PARAM;
7447 * When a printer is created, the drivername bound to the printer is used
7448 * to lookup previously saved driver initialization info, which is then
7449 * bound to the new printer, simulating what happens in the Windows arch.
7454 set_driver_init(printer, 2);
7458 /* A valid devmode was included, convert and link it
7460 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7462 if (!convert_devicemode(printer->info_2->printername, devmode,
7463 &printer->info_2->devmode))
7467 /* write the ASCII on disk */
7468 err = mod_a_printer(printer, 2);
7469 if (!W_ERROR_IS_OK(err)) {
7470 free_a_printer(&printer,2);
7474 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7475 /* Handle open failed - remove addition. */
7476 del_a_printer(printer->info_2->sharename);
7477 free_a_printer(&printer,2);
7478 return WERR_ACCESS_DENIED;
7481 update_c_setprinter(False);
7482 free_a_printer(&printer,2);
7487 /****************************************************************************
7488 ****************************************************************************/
7490 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7492 UNISTR2 *uni_srv_name = &q_u->server_name;
7493 uint32 level = q_u->level;
7494 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7495 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7496 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7497 uint32 user_switch = q_u->user_switch;
7498 SPOOL_USER_CTR *user = &q_u->user_ctr;
7499 POLICY_HND *handle = &r_u->handle;
7503 /* we don't handle yet */
7504 /* but I know what to do ... */
7505 return WERR_UNKNOWN_LEVEL;
7507 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7509 user_switch, user, handle);
7511 return WERR_UNKNOWN_LEVEL;
7515 /****************************************************************************
7516 ****************************************************************************/
7518 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7520 uint32 level = q_u->level;
7521 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7522 WERROR err = WERR_OK;
7523 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7524 struct current_user user;
7525 fstring driver_name;
7528 ZERO_STRUCT(driver);
7530 get_current_user(&user, p);
7532 if (!convert_printer_driver_info(info, &driver, level)) {
7537 DEBUG(5,("Cleaning driver's information\n"));
7538 err = clean_up_driver_struct(driver, level, &user);
7539 if (!W_ERROR_IS_OK(err))
7542 DEBUG(5,("Moving driver to final destination\n"));
7543 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7544 if (W_ERROR_IS_OK(err))
7545 err = WERR_ACCESS_DENIED;
7549 if (add_a_printer_driver(driver, level)!=0) {
7550 err = WERR_ACCESS_DENIED;
7554 /* BEGIN_ADMIN_LOG */
7557 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7558 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7559 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7562 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7563 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7564 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7570 * I think this is where he DrvUpgradePrinter() hook would be
7571 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7572 * server. Right now, we just need to send ourselves a message
7573 * to update each printer bound to this driver. --jerry
7576 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7577 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7582 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7583 * decide if the driver init data should be deleted. The rules are:
7584 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7585 * 2) delete init data only if there is no 2k/Xp driver
7586 * 3) always delete init data
7587 * The generalized rule is always use init data from the highest order driver.
7588 * It is necessary to follow the driver install by an initialization step to
7589 * finish off this process.
7592 version = driver.info_3->cversion;
7593 else if (level == 6)
7594 version = driver.info_6->version;
7599 * 9x printer driver - never delete init data
7602 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7607 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7608 * there is no 2k/Xp driver init data for this driver name.
7612 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7614 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7616 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7618 if (!del_driver_init(driver_name))
7619 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7622 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7624 free_a_printer_driver(driver1,3);
7625 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7632 * 2k or Xp printer driver - always delete init data
7635 if (!del_driver_init(driver_name))
7636 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7640 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7646 free_a_printer_driver(driver, level);
7650 /********************************************************************
7651 * spoolss_addprinterdriverex
7652 ********************************************************************/
7654 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7656 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7657 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7660 * we only support the semantics of AddPrinterDriver()
7661 * i.e. only copy files that are newer than existing ones
7664 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7665 return WERR_ACCESS_DENIED;
7667 ZERO_STRUCT(q_u_local);
7668 ZERO_STRUCT(r_u_local);
7670 /* just pass the information off to _spoolss_addprinterdriver() */
7671 q_u_local.server_name_ptr = q_u->server_name_ptr;
7672 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7673 q_u_local.level = q_u->level;
7674 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7676 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7679 /****************************************************************************
7680 ****************************************************************************/
7682 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7684 init_unistr(&info->name, name);
7687 /****************************************************************************
7688 ****************************************************************************/
7690 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7696 const char *short_archi;
7697 DRIVER_DIRECTORY_1 *info=NULL;
7699 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7700 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7702 /* check for beginning double '\'s and that the server
7705 pservername = servername;
7706 if ( *pservername == '\\' && strlen(servername)>2 ) {
7710 if ( !is_myname_or_ipaddr( pservername ) )
7711 return WERR_INVALID_PARAM;
7713 if (!(short_archi = get_short_archi(long_archi)))
7714 return WERR_INVALID_ENVIRONMENT;
7716 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7719 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7721 DEBUG(4,("printer driver directory: [%s]\n", path));
7723 fill_driverdir_1(info, path);
7725 *needed += spoolss_size_driverdir_info_1(info);
7727 if (!alloc_buffer_size(buffer, *needed)) {
7729 return WERR_INSUFFICIENT_BUFFER;
7732 smb_io_driverdir_1("", buffer, info, 0);
7736 if (*needed > offered)
7737 return WERR_INSUFFICIENT_BUFFER;
7742 /****************************************************************************
7743 ****************************************************************************/
7745 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7747 UNISTR2 *name = &q_u->name;
7748 UNISTR2 *uni_environment = &q_u->environment;
7749 uint32 level = q_u->level;
7750 NEW_BUFFER *buffer = NULL;
7751 uint32 offered = q_u->offered;
7752 uint32 *needed = &r_u->needed;
7754 /* that's an [in out] buffer */
7755 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7756 buffer = r_u->buffer;
7758 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7764 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7766 return WERR_UNKNOWN_LEVEL;
7770 /****************************************************************************
7771 ****************************************************************************/
7773 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7775 POLICY_HND *handle = &q_u->handle;
7776 uint32 idx = q_u->index;
7777 uint32 in_value_len = q_u->valuesize;
7778 uint32 in_data_len = q_u->datasize;
7779 uint32 *out_max_value_len = &r_u->valuesize;
7780 uint16 **out_value = &r_u->value;
7781 uint32 *out_value_len = &r_u->realvaluesize;
7782 uint32 *out_type = &r_u->type;
7783 uint32 *out_max_data_len = &r_u->datasize;
7784 uint8 **data_out = &r_u->data;
7785 uint32 *out_data_len = &r_u->realdatasize;
7787 NT_PRINTER_INFO_LEVEL *printer = NULL;
7789 uint32 biggest_valuesize;
7790 uint32 biggest_datasize;
7792 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7795 REGISTRY_VALUE *val = NULL;
7796 NT_PRINTER_DATA *p_data;
7797 int i, key_index, num_values;
7800 ZERO_STRUCT( printer );
7804 *out_max_data_len = 0;
7808 DEBUG(5,("spoolss_enumprinterdata\n"));
7811 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7815 if (!get_printer_snum(p,handle, &snum))
7818 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7819 if (!W_ERROR_IS_OK(result))
7822 p_data = &printer->info_2->data;
7823 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7828 * The NT machine wants to know the biggest size of value and data
7830 * cf: MSDN EnumPrinterData remark section
7833 if ( !in_value_len && !in_data_len && (key_index != -1) )
7835 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7837 biggest_valuesize = 0;
7838 biggest_datasize = 0;
7840 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7842 for ( i=0; i<num_values; i++ )
7844 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7846 name_length = strlen(val->valuename);
7847 if ( strlen(val->valuename) > biggest_valuesize )
7848 biggest_valuesize = name_length;
7850 if ( val->size > biggest_datasize )
7851 biggest_datasize = val->size;
7853 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7857 /* the value is an UNICODE string but real_value_size is the length
7858 in bytes including the trailing 0 */
7860 *out_value_len = 2 * (1+biggest_valuesize);
7861 *out_data_len = biggest_datasize;
7863 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7869 * the value len is wrong in NT sp3
7870 * that's the number of bytes not the number of unicode chars
7873 if ( key_index != -1 )
7874 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7879 /* out_value should default to "" or else NT4 has
7880 problems unmarshalling the response */
7882 *out_max_value_len=(in_value_len/sizeof(uint16));
7884 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7886 result = WERR_NOMEM;
7890 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7892 /* the data is counted in bytes */
7894 *out_max_data_len = in_data_len;
7895 *out_data_len = in_data_len;
7897 /* only allocate when given a non-zero data_len */
7899 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7901 result = WERR_NOMEM;
7905 result = WERR_NO_MORE_ITEMS;
7911 * - counted in bytes in the request
7912 * - counted in UNICODE chars in the max reply
7913 * - counted in bytes in the real size
7915 * take a pause *before* coding not *during* coding
7919 *out_max_value_len=(in_value_len/sizeof(uint16));
7920 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7922 result = WERR_NOMEM;
7926 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7930 *out_type = regval_type( val );
7932 /* data - counted in bytes */
7934 *out_max_data_len = in_data_len;
7935 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7937 result = WERR_NOMEM;
7940 data_len = (size_t)regval_size(val);
7941 memcpy( *data_out, regval_data_p(val), data_len );
7942 *out_data_len = data_len;
7946 free_a_printer(&printer, 2);
7950 /****************************************************************************
7951 ****************************************************************************/
7953 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7955 POLICY_HND *handle = &q_u->handle;
7956 UNISTR2 *value = &q_u->value;
7957 uint32 type = q_u->type;
7958 uint8 *data = q_u->data;
7959 uint32 real_len = q_u->real_len;
7961 NT_PRINTER_INFO_LEVEL *printer = NULL;
7963 WERROR status = WERR_OK;
7964 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7967 DEBUG(5,("spoolss_setprinterdata\n"));
7970 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7974 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7975 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7976 return WERR_INVALID_PARAM;
7979 if (!get_printer_snum(p,handle, &snum))
7983 * Access check : NT returns "access denied" if you make a
7984 * SetPrinterData call without the necessary privildge.
7985 * we were originally returning OK if nothing changed
7986 * which made Win2k issue **a lot** of SetPrinterData
7987 * when connecting to a printer --jerry
7990 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7992 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7993 status = WERR_ACCESS_DENIED;
7997 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7998 if (!W_ERROR_IS_OK(status))
8001 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8004 * When client side code sets a magic printer data key, detect it and save
8005 * the current printer data and the magic key's data (its the DEVMODE) for
8006 * future printer/driver initializations.
8008 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8010 /* Set devmode and printer initialization info */
8011 status = save_driver_init( printer, 2, data, real_len );
8013 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8017 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8018 type, data, real_len );
8019 if ( W_ERROR_IS_OK(status) )
8020 status = mod_a_printer(printer, 2);
8024 free_a_printer(&printer, 2);
8029 /****************************************************************************
8030 ****************************************************************************/
8032 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8034 POLICY_HND *handle = &q_u->handle;
8035 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8038 DEBUG(5,("_spoolss_resetprinter\n"));
8041 * All we do is to check to see if the handle and queue is valid.
8042 * This call really doesn't mean anything to us because we only
8043 * support RAW printing. --jerry
8047 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8051 if (!get_printer_snum(p,handle, &snum))
8055 /* blindly return success */
8060 /****************************************************************************
8061 ****************************************************************************/
8063 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8065 POLICY_HND *handle = &q_u->handle;
8066 UNISTR2 *value = &q_u->valuename;
8068 NT_PRINTER_INFO_LEVEL *printer = NULL;
8070 WERROR status = WERR_OK;
8071 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8074 DEBUG(5,("spoolss_deleteprinterdata\n"));
8077 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8081 if (!get_printer_snum(p, handle, &snum))
8084 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8085 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8086 return WERR_ACCESS_DENIED;
8089 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8090 if (!W_ERROR_IS_OK(status))
8093 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8095 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8097 if ( W_ERROR_IS_OK(status) )
8098 mod_a_printer( printer, 2 );
8100 free_a_printer(&printer, 2);
8105 /****************************************************************************
8106 ****************************************************************************/
8108 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8110 POLICY_HND *handle = &q_u->handle;
8111 FORM *form = &q_u->form;
8112 nt_forms_struct tmpForm;
8114 WERROR status = WERR_OK;
8115 NT_PRINTER_INFO_LEVEL *printer = NULL;
8118 nt_forms_struct *list=NULL;
8119 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8121 DEBUG(5,("spoolss_addform\n"));
8124 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8129 /* forms can be added on printer of on the print server handle */
8131 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8133 if (!get_printer_snum(p,handle, &snum))
8136 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8137 if (!W_ERROR_IS_OK(status))
8141 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8142 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8143 status = WERR_ACCESS_DENIED;
8147 /* can't add if builtin */
8149 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8150 status = WERR_ALREADY_EXISTS;
8154 count = get_ntforms(&list);
8156 if(!add_a_form(&list, form, &count)) {
8157 status = WERR_NOMEM;
8161 write_ntforms(&list, count);
8164 * ChangeID must always be set if this is a printer
8167 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8168 status = mod_a_printer(printer, 2);
8172 free_a_printer(&printer, 2);
8178 /****************************************************************************
8179 ****************************************************************************/
8181 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8183 POLICY_HND *handle = &q_u->handle;
8184 UNISTR2 *form_name = &q_u->name;
8185 nt_forms_struct tmpForm;
8187 nt_forms_struct *list=NULL;
8188 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8190 WERROR status = WERR_OK;
8191 NT_PRINTER_INFO_LEVEL *printer = NULL;
8193 DEBUG(5,("spoolss_deleteform\n"));
8196 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8200 /* forms can be deleted on printer of on the print server handle */
8202 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8204 if (!get_printer_snum(p,handle, &snum))
8207 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8208 if (!W_ERROR_IS_OK(status))
8212 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8213 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8214 status = WERR_ACCESS_DENIED;
8218 /* can't delete if builtin */
8220 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8221 status = WERR_INVALID_PARAM;
8225 count = get_ntforms(&list);
8227 if ( !delete_a_form(&list, form_name, &count, &status ))
8231 * ChangeID must always be set if this is a printer
8234 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8235 status = mod_a_printer(printer, 2);
8239 free_a_printer(&printer, 2);
8245 /****************************************************************************
8246 ****************************************************************************/
8248 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8250 POLICY_HND *handle = &q_u->handle;
8251 FORM *form = &q_u->form;
8252 nt_forms_struct tmpForm;
8254 WERROR status = WERR_OK;
8255 NT_PRINTER_INFO_LEVEL *printer = NULL;
8258 nt_forms_struct *list=NULL;
8259 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8261 DEBUG(5,("spoolss_setform\n"));
8264 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8268 /* forms can be modified on printer of on the print server handle */
8270 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8272 if (!get_printer_snum(p,handle, &snum))
8275 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8276 if (!W_ERROR_IS_OK(status))
8280 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8281 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8282 status = WERR_ACCESS_DENIED;
8286 /* can't set if builtin */
8287 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8288 status = WERR_INVALID_PARAM;
8292 count = get_ntforms(&list);
8293 update_a_form(&list, form, count);
8294 write_ntforms(&list, count);
8297 * ChangeID must always be set if this is a printer
8300 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8301 status = mod_a_printer(printer, 2);
8306 free_a_printer(&printer, 2);
8312 /****************************************************************************
8313 enumprintprocessors level 1.
8314 ****************************************************************************/
8316 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8318 PRINTPROCESSOR_1 *info_1=NULL;
8320 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8325 init_unistr(&info_1->name, "winprint");
8327 *needed += spoolss_size_printprocessor_info_1(info_1);
8329 if (!alloc_buffer_size(buffer, *needed))
8330 return WERR_INSUFFICIENT_BUFFER;
8332 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8336 if (*needed > offered) {
8338 return WERR_INSUFFICIENT_BUFFER;
8344 /****************************************************************************
8345 ****************************************************************************/
8347 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8349 uint32 level = q_u->level;
8350 NEW_BUFFER *buffer = NULL;
8351 uint32 offered = q_u->offered;
8352 uint32 *needed = &r_u->needed;
8353 uint32 *returned = &r_u->returned;
8355 /* that's an [in out] buffer */
8356 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8357 buffer = r_u->buffer;
8359 DEBUG(5,("spoolss_enumprintprocessors\n"));
8362 * Enumerate the print processors ...
8364 * Just reply with "winprint", to keep NT happy
8365 * and I can use my nice printer checker.
8373 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8375 return WERR_UNKNOWN_LEVEL;
8379 /****************************************************************************
8380 enumprintprocdatatypes level 1.
8381 ****************************************************************************/
8383 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8385 PRINTPROCDATATYPE_1 *info_1=NULL;
8387 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8392 init_unistr(&info_1->name, "RAW");
8394 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8396 if (!alloc_buffer_size(buffer, *needed))
8397 return WERR_INSUFFICIENT_BUFFER;
8399 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8403 if (*needed > offered) {
8405 return WERR_INSUFFICIENT_BUFFER;
8411 /****************************************************************************
8412 ****************************************************************************/
8414 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8416 uint32 level = q_u->level;
8417 NEW_BUFFER *buffer = NULL;
8418 uint32 offered = q_u->offered;
8419 uint32 *needed = &r_u->needed;
8420 uint32 *returned = &r_u->returned;
8422 /* that's an [in out] buffer */
8423 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8424 buffer = r_u->buffer;
8426 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8433 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8435 return WERR_UNKNOWN_LEVEL;
8439 /****************************************************************************
8440 enumprintmonitors level 1.
8441 ****************************************************************************/
8443 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8445 PRINTMONITOR_1 *info_1=NULL;
8447 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8452 init_unistr(&info_1->name, "Local Port");
8454 *needed += spoolss_size_printmonitor_info_1(info_1);
8456 if (!alloc_buffer_size(buffer, *needed))
8457 return WERR_INSUFFICIENT_BUFFER;
8459 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8463 if (*needed > offered) {
8465 return WERR_INSUFFICIENT_BUFFER;
8471 /****************************************************************************
8472 enumprintmonitors level 2.
8473 ****************************************************************************/
8475 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8477 PRINTMONITOR_2 *info_2=NULL;
8479 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8484 init_unistr(&info_2->name, "Local Port");
8485 init_unistr(&info_2->environment, "Windows NT X86");
8486 init_unistr(&info_2->dll_name, "localmon.dll");
8488 *needed += spoolss_size_printmonitor_info_2(info_2);
8490 if (!alloc_buffer_size(buffer, *needed))
8491 return WERR_INSUFFICIENT_BUFFER;
8493 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8497 if (*needed > offered) {
8499 return WERR_INSUFFICIENT_BUFFER;
8505 /****************************************************************************
8506 ****************************************************************************/
8508 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8510 uint32 level = q_u->level;
8511 NEW_BUFFER *buffer = NULL;
8512 uint32 offered = q_u->offered;
8513 uint32 *needed = &r_u->needed;
8514 uint32 *returned = &r_u->returned;
8516 /* that's an [in out] buffer */
8517 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8518 buffer = r_u->buffer;
8520 DEBUG(5,("spoolss_enumprintmonitors\n"));
8523 * Enumerate the print monitors ...
8525 * Just reply with "Local Port", to keep NT happy
8526 * and I can use my nice printer checker.
8534 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8536 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8538 return WERR_UNKNOWN_LEVEL;
8542 /****************************************************************************
8543 ****************************************************************************/
8545 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8546 NT_PRINTER_INFO_LEVEL *ntprinter,
8547 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8552 JOB_INFO_1 *info_1=NULL;
8554 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8556 if (info_1 == NULL) {
8560 for (i=0; i<count && found==False; i++) {
8561 if ((*queue)[i].job==(int)jobid)
8567 /* NT treats not found as bad param... yet another bad choice */
8568 return WERR_INVALID_PARAM;
8571 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8573 *needed += spoolss_size_job_info_1(info_1);
8575 if (!alloc_buffer_size(buffer, *needed)) {
8577 return WERR_INSUFFICIENT_BUFFER;
8580 smb_io_job_info_1("", buffer, info_1, 0);
8584 if (*needed > offered)
8585 return WERR_INSUFFICIENT_BUFFER;
8590 /****************************************************************************
8591 ****************************************************************************/
8593 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8594 NT_PRINTER_INFO_LEVEL *ntprinter,
8595 uint32 jobid, NEW_BUFFER *buffer, uint32 offered,
8602 DEVICEMODE *devmode = NULL;
8603 NT_DEVICEMODE *nt_devmode = NULL;
8605 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8607 ZERO_STRUCTP(info_2);
8609 if (info_2 == NULL) {
8614 for ( i=0; i<count && found==False; i++ )
8616 if ((*queue)[i].job == (int)jobid)
8622 /* NT treats not found as bad param... yet another bad
8624 ret = WERR_INVALID_PARAM;
8629 * if the print job does not have a DEVMODE associated with it,
8630 * just use the one for the printer. A NULL devicemode is not
8631 * a failure condition
8634 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8635 devmode = construct_dev_mode(snum);
8637 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8638 ZERO_STRUCTP( devmode );
8639 convert_nt_devicemode( devmode, nt_devmode );
8643 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8645 *needed += spoolss_size_job_info_2(info_2);
8647 if (!alloc_buffer_size(buffer, *needed)) {
8648 ret = WERR_INSUFFICIENT_BUFFER;
8652 smb_io_job_info_2("", buffer, info_2, 0);
8654 if (*needed > offered) {
8655 ret = WERR_INSUFFICIENT_BUFFER;
8662 /* Cleanup allocated memory */
8664 free_job_info_2(info_2); /* Also frees devmode */
8666 free_a_printer(&ntprinter, 2);
8671 /****************************************************************************
8672 ****************************************************************************/
8674 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8676 POLICY_HND *handle = &q_u->handle;
8677 uint32 jobid = q_u->jobid;
8678 uint32 level = q_u->level;
8679 NEW_BUFFER *buffer = NULL;
8680 uint32 offered = q_u->offered;
8681 uint32 *needed = &r_u->needed;
8682 WERROR wstatus = WERR_OK;
8683 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8686 print_queue_struct *queue = NULL;
8687 print_status_struct prt_status;
8689 /* that's an [in out] buffer */
8690 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8691 buffer = r_u->buffer;
8693 DEBUG(5,("spoolss_getjob\n"));
8697 if (!get_printer_snum(p, handle, &snum))
8700 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8701 if ( !W_ERROR_IS_OK(wstatus) )
8704 count = print_queue_status(snum, &queue, &prt_status);
8706 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8707 count, prt_status.status, prt_status.message));
8711 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8712 buffer, offered, needed);
8715 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8716 buffer, offered, needed);
8719 wstatus = WERR_UNKNOWN_LEVEL;
8724 free_a_printer( &ntprinter, 2 );
8729 /********************************************************************
8730 spoolss_getprinterdataex
8732 From MSDN documentation of GetPrinterDataEx: pass request
8733 to GetPrinterData if key is "PrinterDriverData".
8734 ********************************************************************/
8736 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8738 POLICY_HND *handle = &q_u->handle;
8739 uint32 in_size = q_u->size;
8740 uint32 *type = &r_u->type;
8741 uint32 *out_size = &r_u->size;
8742 uint8 **data = &r_u->data;
8743 uint32 *needed = &r_u->needed;
8744 fstring keyname, valuename;
8746 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8748 NT_PRINTER_INFO_LEVEL *printer = NULL;
8750 WERROR status = WERR_OK;
8752 DEBUG(4,("_spoolss_getprinterdataex\n"));
8754 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8755 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8757 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8758 keyname, valuename));
8760 /* in case of problem, return some default values */
8764 *out_size = in_size;
8767 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8768 status = WERR_BADFID;
8772 /* Is the handle to a printer or to the server? */
8774 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8775 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8776 status = WERR_INVALID_PARAM;
8780 if ( !get_printer_snum(p,handle, &snum) )
8783 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8784 if ( !W_ERROR_IS_OK(status) )
8787 /* check to see if the keyname is valid */
8788 if ( !strlen(keyname) ) {
8789 status = WERR_INVALID_PARAM;
8793 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8794 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8795 free_a_printer( &printer, 2 );
8796 status = WERR_BADFILE;
8800 /* When given a new keyname, we should just create it */
8802 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8804 if (*needed > *out_size)
8805 status = WERR_MORE_DATA;
8808 if ( !W_ERROR_IS_OK(status) )
8810 DEBUG(5, ("error: allocating %d\n", *out_size));
8812 /* reply this param doesn't exist */
8816 if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8817 status = WERR_NOMEM;
8827 free_a_printer( &printer, 2 );
8832 /********************************************************************
8833 * spoolss_setprinterdataex
8834 ********************************************************************/
8836 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8838 POLICY_HND *handle = &q_u->handle;
8839 uint32 type = q_u->type;
8840 uint8 *data = q_u->data;
8841 uint32 real_len = q_u->real_len;
8843 NT_PRINTER_INFO_LEVEL *printer = NULL;
8845 WERROR status = WERR_OK;
8846 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8851 DEBUG(4,("_spoolss_setprinterdataex\n"));
8853 /* From MSDN documentation of SetPrinterDataEx: pass request to
8854 SetPrinterData if key is "PrinterDriverData" */
8857 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8861 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8862 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8863 return WERR_INVALID_PARAM;
8866 if ( !get_printer_snum(p,handle, &snum) )
8870 * Access check : NT returns "access denied" if you make a
8871 * SetPrinterData call without the necessary privildge.
8872 * we were originally returning OK if nothing changed
8873 * which made Win2k issue **a lot** of SetPrinterData
8874 * when connecting to a printer --jerry
8877 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8879 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8880 return WERR_ACCESS_DENIED;
8883 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8884 if (!W_ERROR_IS_OK(status))
8887 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8888 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8890 /* check for OID in valuename */
8892 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8898 /* save the registry data */
8900 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8902 if ( W_ERROR_IS_OK(status) )
8904 /* save the OID if one was specified */
8906 fstrcat( keyname, "\\" );
8907 fstrcat( keyname, SPOOL_OID_KEY );
8910 * I'm not checking the status here on purpose. Don't know
8911 * if this is right, but I'm returning the status from the
8912 * previous set_printer_dataex() call. I have no idea if
8913 * this is right. --jerry
8916 set_printer_dataex( printer, keyname, valuename,
8917 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8920 status = mod_a_printer(printer, 2);
8923 free_a_printer(&printer, 2);
8929 /********************************************************************
8930 * spoolss_deleteprinterdataex
8931 ********************************************************************/
8933 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8935 POLICY_HND *handle = &q_u->handle;
8936 UNISTR2 *value = &q_u->valuename;
8937 UNISTR2 *key = &q_u->keyname;
8939 NT_PRINTER_INFO_LEVEL *printer = NULL;
8941 WERROR status = WERR_OK;
8942 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8943 pstring valuename, keyname;
8945 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8948 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8952 if (!get_printer_snum(p, handle, &snum))
8955 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8956 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8957 return WERR_ACCESS_DENIED;
8960 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8961 if (!W_ERROR_IS_OK(status))
8964 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8965 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8967 status = delete_printer_dataex( printer, keyname, valuename );
8969 if ( W_ERROR_IS_OK(status) )
8970 mod_a_printer( printer, 2 );
8972 free_a_printer(&printer, 2);
8977 /********************************************************************
8978 * spoolss_enumprinterkey
8979 ********************************************************************/
8982 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8985 fstring *keynames = NULL;
8986 uint16 *enumkeys = NULL;
8989 POLICY_HND *handle = &q_u->handle;
8990 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8991 NT_PRINTER_DATA *data;
8992 NT_PRINTER_INFO_LEVEL *printer = NULL;
8994 WERROR status = WERR_BADFILE;
8997 DEBUG(4,("_spoolss_enumprinterkey\n"));
9000 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9004 if ( !get_printer_snum(p,handle, &snum) )
9007 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9008 if (!W_ERROR_IS_OK(status))
9011 /* get the list of subkey names */
9013 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9014 data = &printer->info_2->data;
9016 num_keys = get_printer_subkeys( data, key, &keynames );
9018 if ( num_keys == -1 ) {
9019 status = WERR_BADFILE;
9023 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9025 r_u->needed = printerkey_len*2;
9027 if ( q_u->size < r_u->needed ) {
9028 status = WERR_MORE_DATA;
9032 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9033 status = WERR_NOMEM;
9039 if ( q_u->size < r_u->needed )
9040 status = WERR_MORE_DATA;
9043 free_a_printer( &printer, 2 );
9044 SAFE_FREE( keynames );
9049 /********************************************************************
9050 * spoolss_deleteprinterkey
9051 ********************************************************************/
9053 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9055 POLICY_HND *handle = &q_u->handle;
9056 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9058 NT_PRINTER_INFO_LEVEL *printer = NULL;
9062 DEBUG(5,("spoolss_deleteprinterkey\n"));
9065 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9069 /* if keyname == NULL, return error */
9071 if ( !q_u->keyname.buffer )
9072 return WERR_INVALID_PARAM;
9074 if (!get_printer_snum(p, handle, &snum))
9077 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9078 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9079 return WERR_ACCESS_DENIED;
9082 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9083 if (!W_ERROR_IS_OK(status))
9086 /* delete the key and all subneys */
9088 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9090 status = delete_all_printer_data( printer->info_2, key );
9092 if ( W_ERROR_IS_OK(status) )
9093 status = mod_a_printer(printer, 2);
9095 free_a_printer( &printer, 2 );
9101 /********************************************************************
9102 * spoolss_enumprinterdataex
9103 ********************************************************************/
9105 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9107 POLICY_HND *handle = &q_u->handle;
9108 uint32 in_size = q_u->size;
9111 NT_PRINTER_INFO_LEVEL *printer = NULL;
9112 PRINTER_ENUM_VALUES *enum_values = NULL;
9113 NT_PRINTER_DATA *p_data;
9115 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9120 REGISTRY_VALUE *val;
9125 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9128 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9133 * first check for a keyname of NULL or "". Win2k seems to send
9134 * this a lot and we should send back WERR_INVALID_PARAM
9135 * no need to spend time looking up the printer in this case.
9139 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9140 if ( !strlen(key) ) {
9141 result = WERR_INVALID_PARAM;
9145 /* get the printer off of disk */
9147 if (!get_printer_snum(p,handle, &snum))
9150 ZERO_STRUCT(printer);
9151 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9152 if (!W_ERROR_IS_OK(result))
9155 /* now look for a match on the key name */
9157 p_data = &printer->info_2->data;
9159 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9160 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9162 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9163 result = WERR_INVALID_PARAM;
9170 /* allocate the memory for the array of pointers -- if necessary */
9172 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9175 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9177 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9178 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9179 result = WERR_NOMEM;
9183 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9187 * loop through all params and build the array to pass
9188 * back to the client
9191 for ( i=0; i<num_entries; i++ )
9193 /* lookup the registry value */
9195 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9196 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9200 value_name = regval_name( val );
9201 init_unistr( &enum_values[i].valuename, value_name );
9202 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9203 enum_values[i].type = regval_type( val );
9205 data_len = regval_size( val );
9207 if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
9209 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9211 result = WERR_NOMEM;
9215 enum_values[i].data_len = data_len;
9217 /* keep track of the size of the array in bytes */
9219 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9222 /* housekeeping information in the reply */
9224 r_u->needed = needed;
9225 r_u->returned = num_entries;
9227 if (needed > in_size) {
9228 result = WERR_MORE_DATA;
9232 /* copy data into the reply */
9234 r_u->ctr.size = r_u->needed;
9235 r_u->ctr.size_of_array = r_u->returned;
9236 r_u->ctr.values = enum_values;
9242 free_a_printer(&printer, 2);
9247 /****************************************************************************
9248 ****************************************************************************/
9250 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9252 init_unistr(&info->name, name);
9255 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9256 UNISTR2 *environment,
9263 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9265 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9267 if (!get_short_archi(long_archi))
9268 return WERR_INVALID_ENVIRONMENT;
9270 if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9273 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9275 fill_printprocessordirectory_1(info, path);
9277 *needed += spoolss_size_printprocessordirectory_info_1(info);
9279 if (!alloc_buffer_size(buffer, *needed)) {
9281 return WERR_INSUFFICIENT_BUFFER;
9284 smb_io_printprocessordirectory_1("", buffer, info, 0);
9288 if (*needed > offered)
9289 return WERR_INSUFFICIENT_BUFFER;
9294 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9296 uint32 level = q_u->level;
9297 NEW_BUFFER *buffer = NULL;
9298 uint32 offered = q_u->offered;
9299 uint32 *needed = &r_u->needed;
9302 /* that's an [in out] buffer */
9303 spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9304 buffer = r_u->buffer;
9306 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9312 result = getprintprocessordirectory_level_1
9313 (&q_u->name, &q_u->environment, buffer, offered, needed);
9316 result = WERR_UNKNOWN_LEVEL;
9324 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9325 SPOOL_R_REPLYOPENPRINTER *r_u)
9327 DEBUG(5,("_spoolss_replyopenprinter\n"));
9329 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9334 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9335 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9337 DEBUG(5,("_spoolss_replycloseprinter\n"));